Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ version: 2
# updates, when enabled in the repository settings, do not follow this schedule.
updates:
- package-ecosystem: npm
target-branch: dev
directory: /
schedule:
interval: monthly
Expand Down Expand Up @@ -38,6 +39,7 @@ updates:
update-types:
- version-update:semver-major
- package-ecosystem: nuget
target-branch: dev
# Dependabot expands ProCoderJi.slnx here, covering the API and test projects
# together so shared .NET packages can move in one reviewed pull request.
directory: /backend
Expand All @@ -56,6 +58,7 @@ updates:
- minor
- patch
- package-ecosystem: github-actions
target-branch: dev
directory: /
schedule:
interval: monthly
Expand Down
24 changes: 24 additions & 0 deletions .github/scripts/branch-policy.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import assert from "node:assert/strict";
import test from "node:test";
import { branchPolicy } from "./check-branch-policy.mjs";

const repository = "procoderji-com/procoderji";
const check = (base, head, sourceRepository = repository) => branchPolicy({ base, head, sourceRepository, repository });

test("contributors and bots can send changes to dev", () => {
assert.equal(check("dev", "feat/student-experience", "contributor/procoderji"), null);
assert.equal(check("dev", "dependabot/npm_and_yarn/example"), null);
});

test("main accepts only the canonical dev branch", () => {
assert.equal(check("main", "dev"), null);
assert.ok(check("main", "feat/student-experience"));
assert.ok(check("main", "dependabot/npm_and_yarn/example"));
assert.ok(check("main", "dev", "contributor/procoderji"));
});

test("unknown or absent targets do not silently pass", () => {
assert.ok(check("release/1.0", "dev"));
assert.ok(check(undefined, undefined));
assert.ok(branchPolicy({ base: "main", head: "dev" }));
});
26 changes: 26 additions & 0 deletions .github/scripts/check-branch-policy.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { pathToFileURL } from "node:url";

export function branchPolicy({ base, head, sourceRepository, repository }) {
if (!base || !head || !sourceRepository || !repository) return "Pull-request branch metadata is incomplete.";
if (base === "dev") return null;
if (base === "main" && head === "dev" && sourceRepository === repository) return null;
if (base === "main") {
return "Production PRs must promote this repository's dev branch. Send feature and dependency PRs to dev first.";
}
return "Contributions target dev; production promotions target main.";
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const failure = branchPolicy({
base: process.env.PR_BASE,
head: process.env.PR_HEAD,
sourceRepository: process.env.PR_SOURCE_REPOSITORY,
repository: process.env.TARGET_REPOSITORY,
});
if (failure) {
console.error(failure);
process.exitCode = 1;
} else {
console.log("Branch policy passed.");
}
}
2 changes: 1 addition & 1 deletion .github/workflows/backend-containers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
- 'vercel.backend.json'
- '.github/workflows/backend-containers.yml'
push:
branches: [main]
branches: [dev, main]
paths:
- 'backend/**'
- 'shared/**'
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/branch-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Branch policy

on:
pull_request:
types: [opened, synchronize, reopened, edited, ready_for_review]

permissions:
contents: read

jobs:
branch-policy:
name: Branch policy
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Check out proposed policy
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Test branch policy
run: node --test .github/scripts/branch-policy.test.mjs

- name: Enforce contribution and promotion targets
env:
PR_BASE: ${{ github.event.pull_request.base.ref }}
PR_HEAD: ${{ github.event.pull_request.head.ref }}
PR_SOURCE_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }}
TARGET_REPOSITORY: ${{ github.repository }}
run: node .github/scripts/check-branch-policy.mjs
48 changes: 46 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ name: CI
on:
pull_request:
push:
branches: [main]
branches: [dev, main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
# Cancel stale PR checks, but never interrupt a push run during a deployment.
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
verify:
Expand Down Expand Up @@ -40,6 +41,9 @@ jobs:
- name: Unit tests
run: npm test

- name: Deployment gate tests
run: node --test scripts/*.test.mjs

- name: Production build
run: npm run build

Expand Down Expand Up @@ -148,3 +152,43 @@ jobs:
ConnectionStrings__Platform: 'Host=localhost;Port=5432;Database=procoderji_test;Username=postgres;Password=postgres'
PublicOrigin: http://localhost:3000
run: dotnet run --project backend/src/ProCoderJi.Api --configuration Release --no-build --no-launch-profile -- --migrate

deploy:
name: Deploy checked branch
permissions:
contents: read
deployments: write
needs: [verify, site-quality, backend]
if: github.event_name == 'push' && github.repository == 'procoderji-com/procoderji' && (github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main')
runs-on: ubuntu-24.04
timeout-minutes: 20
environment:
name: ${{ github.ref_name == 'main' && 'production' || 'staging' }}
url: ${{ vars.PUBLIC_ORIGIN }}
concurrency:
group: deploy-${{ github.ref_name }}
cancel-in-progress: false
steps:
- name: Check out checked commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: 24

- name: Install deployment CLI
run: npm install --global vercel@65.14.0

- name: Deploy backend, verify storage, then deploy frontend
env:
VERCEL_ORG_ID: ${{ vars.VERCEL_ORG_ID }}
VERCEL_FRONTEND_PROJECT_ID: ${{ vars.VERCEL_FRONTEND_PROJECT_ID }}
VERCEL_BACKEND_PROJECT_ID: ${{ vars.VERCEL_BACKEND_PROJECT_ID }}
PUBLIC_ORIGIN: ${{ vars.PUBLIC_ORIGIN }}
BACKEND_ORIGIN: ${{ vars.BACKEND_ORIGIN }}
VERCEL_FRONTEND_TOKEN: ${{ secrets.VERCEL_FRONTEND_TOKEN }}
VERCEL_BACKEND_TOKEN: ${{ secrets.VERCEL_BACKEND_TOKEN }}
run: node scripts/deploy-vercel.mjs
18 changes: 18 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Repository guidance

Read `CONTRIBUTING.md` before making changes. Contributions target `dev`;
production promotions follow `docs/branching-and-releases.md`.

For UI work, follow `design-system/MASTER.md` and reuse the shared brand and
action styles. Keep real student activity distinct from interactive samples.
Verify keyboard navigation and narrow layouts alongside the relevant checks.

<!-- BEGIN:nextjs-agent-rules -->

## This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.

This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.

<!-- END:nextjs-agent-rules -->
17 changes: 12 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ fork as `origin`, and continue from the same checkout.

## Start a branch

Update your local `main` before starting a new change:
Update your local `dev` before starting a new change:

```bash
git switch main
git fetch upstream
git merge --ff-only upstream/main
git push origin main
git switch dev
git merge --ff-only upstream/dev
git push origin dev
git switch -c feat/describe-the-change
```

Expand Down Expand Up @@ -120,10 +120,17 @@ git commit -m "Describe the change"
git push -u origin <your-branch-name>
```

Open a pull request from your fork branch to `procoderji-com/procoderji:main`. Fill in the
Open a pull request from your fork branch to `procoderji-com/procoderji:dev`. Fill in the
template, link a related issue when one exists, explain the resulting behavior, and list the
checks you ran.
Include screenshots for visible UI changes and sources or permissions for learning content.
For interface changes, follow the [design system](design-system/MASTER.md): use the shared
brand, typography, buttons and colour tokens, and check both keyboard and mobile navigation.

`dev` is the integration/staging branch; `main` is production. Feature and dependency changes
go through `dev`. Maintainers promote the canonical `dev` branch to `main` after staging checks;
contributors do not send feature branches directly to `main`. See the
[branch and deployment workflow](docs/branching-and-releases.md).

Respond to review feedback and keep the branch up to date when needed. Maintainers review
student value, correctness, accessibility, and maintenance cost before merging. A proposed
Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

# ProCoderJii Learning Hub

### Practise for campus placements. Understand your answers. Build a study habit.
### For the semester. For what’s next.

A student learning workspace with original practice questions, explanations, and saved progress.
A student learning brand bringing together course resources, placement practice, games,
portfolios, concept videos and community. This repository builds the open-source web platform.

[Website](https://procoderji.com) · [Documentation](docs/README.md) · [Roadmap](https://github.com/procoderji-com/procoderji/issues/22) · [Good first issues](https://github.com/procoderji-com/procoderji/issues?q=is%3Aissue%20is%3Aopen%20label%3A%22good%20first%20issue%22) · [Report a bug](https://github.com/procoderji-com/procoderji/issues/new?template=bug_report.yml) · [Propose a question](https://github.com/procoderji-com/procoderji/issues/new?template=practice_question.yml)

Expand All @@ -21,8 +22,18 @@ A student learning workspace with original practice questions, explanations, and
> [!NOTE]
> This is an early student-product foundation. Four practice topics contain 24 original multiple-choice questions. Practice and browser-saved progress work without login. An optional ASP.NET Core backend provides Google sign-in, account progress, and private portfolio drafts. The portfolio editor, two themes, Markdown import, and public-page support are implemented; public publishing is off by default pending deployment configuration. Billing and checkout are not enabled. Course notes, guides, and job listings are awaiting published content.

![ProCoderJii homepage with a placement practice sample](docs/images/homepage.png)

<details>
<summary>Student learning workspace</summary>

![Guest learning workspace before the first session](docs/images/learning-workspace.png)

</details>

Interface contributions follow the [design system](design-system/MASTER.md), with shared
navigation, self-hosted typography, keyboard access and responsive layouts.

See the [product roadmap](docs/product-roadmap.md) for student validation, content growth, and future monetization work.

## Contents
Expand Down
8 changes: 8 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ is distributed. Preserve applicable package licenses and component notices when
frontend archive or image, and inspect that actual artifact against the upstream terms. The
backend-only container does not bundle the Next.js image-processing dependencies.

## DM Sans

Copyright 2014 The DM Sans Project Authors (https://github.com/googlefonts/dm-fonts).

The self-hosted font in `public/fonts/dm-sans-variable.ttf` is distributed under the
[SIL Open Font License 1.1](public/fonts/OFL.txt). Its full notice is included alongside
the font. See [the source and usage notes](public/fonts/README.md).

## UI/UX Pro Max

Source: [nextlevelbuilder/ui-ux-pro-max-skill](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill)
Expand Down
44 changes: 44 additions & 0 deletions design-system/MASTER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ProCoderJii interface

ProCoderJii is a student learning brand, spanning notes, placement practice, games, videos,
community and portfolios. The interface should feel like a useful study desk, with clear
choices and readable content. It must not imply hiring guarantees or invent social proof.

## Direction

UI/UX Pro Max's Swiss Modernism guidance informs the grid, hierarchy, restrained decoration
and keyboard accessibility. Use an editorial opening on the public site and compact,
functional layouts in the student workspace. The existing gold brand remains an accent.

| Token | Value | Use |
| ------------- | --------- | ------------------------------------------- |
| Paper | `#f8f7f2` | Page background |
| Surface | `#ffffff` | Forms, reading and practice |
| Ink | `#242b25` | Headings and primary text |
| Secondary ink | `#60685d` | Supporting text |
| Forest | `#345443` | Links, primary actions, selected navigation |
| Gold | `#edc76e` | Small highlights and warm-up activities |
| Rule | `#dedfd5` | Quiet dividers and input boundaries |

DM Sans is self-hosted under the SIL Open Font License. Georgia provides occasional editorial
display headings; the workspace keeps sans-serif headings. Body text is at least 16px for
reading and form inputs. Small labels supplement, never replace, visible field labels.

## Patterns

- One clear primary action per section. Prefer content rows and dividers over repeated cards.
- Desktop public navigation is shared across public pages. Mobile navigation has visible
controls, an expanded state, Escape dismissal and focus restoration.
- Learning navigation stays consistent between practice, account and portfolio editing.
- Progress displays real saved values, with useful empty states; homepage samples are labelled
as samples and do not impersonate saved activity.
- Notes keep branch/semester URLs and readable document layouts. Games keep their original
controls and feedback. Portfolio drafts remain private until explicit publication.
- Avoid animated backgrounds, gradient text, glass effects, floating decorations and invented
testimonials, rankings, company affiliations or activity counts.

## Verification

Check 375px, 768px, 1024px and 1440px layouts; keyboard focus and mobile menu; practice feedback;
notes navigation; portfolio preview; reading contrast; reduced motion; and existing browser/SEO
checks. Stage changes through `dev`; production uses the reviewed promotion workflow.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ synchronization is a separate capability; paid billing is future work.
| Import a portfolio from a text template | [Markdown import](portfolio-markdown.md), [template](../public/templates/portfolio.md) |
| Work on portfolio fields, policy, publication, or storage | [Shared rules](../shared/portfolio/README.md), [Portfolio API](portfolio-api.md) |
| Configure production hosting and the site domain | [Deployment](deployment.md) |
| Contribute to dev, test staging and promote a production release | [Branches and releases](branching-and-releases.md) |
| Run the API and choose a database with Docker | [Containers](containers.md) |
| Configure the selected hosted PostgreSQL database | [Neon setup](neon.md) |
| Report a vulnerability privately | [Security policy](../SECURITY.md) |
Expand Down
Loading
Loading