Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
982ea88
fix: correct false claims, repair quiz state, and split the bundle
SamirWagle Oct 20, 2026
b06bd39
feat: repair question bank, add design system, quiz engine and learne…
SamirWagle Oct 20, 2026
a8a410a
fix: correct the adaptive-practice difficulty target and sweep quiz d…
SamirWagle Oct 20, 2026
1165cdf
feat: add Cloudflare D1 schema and Workers API with server-side exam …
SamirWagle Oct 20, 2026
280e619
feat: add the typed backend client, gated off until a backend exists
SamirWagle Oct 20, 2026
652bd10
fix: apply the adjudicated answer keys, confirm the exam format at 12…
SamirWagle Oct 20, 2026
a97df8b
fix: reconcile the D1 schema with the Workers API, and stop publishing
SamirWagle Oct 20, 2026
69d7367
feat: AI-drafted explanations, badged as unreviewed, with a review pi…
SamirWagle Oct 20, 2026
1c600e9
feat: host the quiz engine in the four quiz pages
SamirWagle Oct 21, 2026
3bdeed7
feat: classify questions into syllabus sub-chapters, offline and dete…
SamirWagle Oct 21, 2026
cd67a12
feat: implement the three scheduled jobs the crons were firing into
SamirWagle Oct 22, 2026
583b402
docs: add the Cloudflare deployment runbook, and a content exporter i…
SamirWagle Oct 22, 2026
70f20a7
fix: the mock templates were seeding a 45-minute paper for a 120-minu…
SamirWagle Oct 22, 2026
8a91b84
chore: point wrangler at the provisioned D1 database and the deployed…
SamirWagle Oct 22, 2026
34c0757
feat: connect the frontend to the Worker, starting with the session
SamirWagle Oct 22, 2026
0ceb7d2
feat: take chapter question counts from the API, keeping the local ma…
SamirWagle Oct 22, 2026
53f14f7
docs: exact click-by-click for the Google OAuth setup
SamirWagle Oct 22, 2026
8e96ec7
feat: bottom navigation for phones, and put Mock Tests in the nav at all
SamirWagle Oct 22, 2026
8604d91
refactor: remove the 214 App.css rules that can never match
SamirWagle Oct 22, 2026
2a097d0
docs: correct the Google guide for the console rename
SamirWagle Oct 22, 2026
45cead9
chore: keep credentials out of the tree by default
SamirWagle Oct 22, 2026
9f78a53
fix: a half-configured Google app no longer takes the whole API down
SamirWagle Oct 22, 2026
a0be506
feat: make the whole stack runnable locally, Google sign-in included
SamirWagle Oct 22, 2026
ff0ae10
feat: add Continue with Google to the sign-in page
SamirWagle Oct 22, 2026
eff528e
feat: privacy policy and terms of use, describing what the code actua…
SamirWagle Oct 23, 2026
afb0c87
Merge branch 'main' into feat/platform-rebuild-phase-0
SamirWagle Oct 23, 2026
eb3f864
fix: the login page was unreachable from the landing page
SamirWagle Oct 23, 2026
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
97 changes: 97 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Bug report
description: Something in the app behaves differently from what it should.
labels: [bug]
body:
- type: markdown
attributes:
value: |
For a wrong answer key, a duplicated question or a broken question,
please use **Question error report** instead — it asks for the chapter
and index needed to find the row.

- type: textarea
id: what-happened
attributes:
label: What happened
description: What you saw, in one or two sentences.
validations:
required: true

- type: textarea
id: expected
attributes:
label: What you expected instead
validations:
required: true

- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: Numbered steps starting from a fresh page load.
placeholder: |
1. Open /app/practice
2. Pick Chapter 3
3. Answer the first question
4. ...
validations:
required: true

- type: input
id: url
attributes:
label: Page or route
placeholder: /app/practice/topic/book-ch3
validations:
required: false

- type: dropdown
id: area
attributes:
label: Which part of the app
options:
- Landing page
- Dashboard
- Practice (chapter / topic / quick / custom)
- Mock tests
- Study hub
- Flashcards
- Bookmarks
- Progress
- Profile / Settings
- Not sure
validations:
required: true

- type: input
id: environment
attributes:
label: Device and browser
description: >
Please be specific. A large share of users are on entry-level Android
over mobile data, and several bugs only appear there.
placeholder: Android 11, Chrome 120, 3G
validations:
required: true

- type: textarea
id: console
attributes:
label: Console errors
description: >
Open DevTools (or `chrome://inspect` on Android) and paste anything red.
render: text
validations:
required: false

- type: checkboxes
id: progress-loss
attributes:
label: Did this lose study progress?
description: >
All progress lives in this browser's `localStorage`. There is no account
and no server copy, so lost progress cannot be recovered — these reports
are triaged first.
options:
- label: Yes, saved progress, bookmarks or quiz history disappeared
required: false
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Question or idea to discuss first
url: https://github.com/SamirWagle/EngineeringLisenseProject/discussions
about: Not sure it is a bug or a feature yet? Start here.
59 changes: 59 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Feature request
description: Propose something the app should do that it does not do yet.
labels: [enhancement]
body:
- type: textarea
id: problem
attributes:
label: What problem does this solve for someone studying for the NEC exam
description: >
Describe the situation you are in when you need this, not the feature.
The strongest requests come from someone who hit a wall while revising.
validations:
required: true

- type: textarea
id: proposal
attributes:
label: What you would like it to do
validations:
required: true

- type: textarea
id: alternatives
attributes:
label: What you do instead today
description: The workaround, if there is one.
validations:
required: false

- type: dropdown
id: scope
attributes:
label: Does this need a server
description: >
The app is currently frontend-only: all data is static JSON and all
state is in this browser's `localStorage`. Anything needing an account,
sync across devices, or a leaderboard depends on the backend work that
is still in progress, and will be scheduled behind it.
options:
- No, it can work entirely in the browser
- Yes, it needs accounts or cross-device sync
- Not sure
validations:
required: true

- type: checkboxes
id: constraints
attributes:
label: Constraints you have considered
options:
- label: >
It does not meaningfully grow the initial page download. CI fails
above 180 kB of gzipped initial-load JavaScript, because much of the
audience is on entry-level Android over 3G.
required: false
- label: It works offline, or degrades cleanly without a network.
required: false
- label: I would be willing to open a PR for this.
required: false
86 changes: 86 additions & 0 deletions .github/ISSUE_TEMPLATE/question_error.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Question error report
description: A question has the wrong answer, bad options, or is a duplicate.
title: '[question] '
labels: [question-bank]
body:
- type: markdown
attributes:
value: |
A wrong answer key teaches the wrong thing, so these are the highest
priority reports in the project.

Before filing, it helps to know that `scripts/validate-questions.mjs`
already catches several classes of defect automatically, and that
questions it proved unanswerable are listed in
`frontend/src/data/quarantine.json` and withheld from practice. If the
question you hit is already in that file, there is nothing to report —
though a suggested correction is very welcome.

`docs/question-format.md` explains the data format and every failure
mode the validator checks.

- type: dropdown
id: chapter
attributes:
label: Chapter
description: Shown in the practice header, and in the URL as `book-chN`.
options:
- ch1
- ch2
- ch3
- ch4
- ch5
- ch6
- ch7
- ch8
- ch9
- ch10
- Not sure
validations:
required: true

- type: textarea
id: stem
attributes:
label: The question text
description: >
Copy it exactly. This is what we search the JSON for, so an exact copy
locates the row faster than anything else.
render: text
validations:
required: true

- type: dropdown
id: defect
attributes:
label: What is wrong with it
options:
- The marked correct answer is wrong
- Two or more options are identical
- No option is correct
- More than one option is correct
- The question text is cut off or incomplete
- It is a duplicate of another question
- Typo or formatting only
- Other
validations:
required: true

- type: textarea
id: correction
attributes:
label: What it should be
description: >
Which option is actually correct, and ideally why — a textbook section,
a formula, or a past paper. A correction with a source can be applied
directly; one without needs independent verification first.
validations:
required: true

- type: markdown
attributes:
value: |
**Note on option order.** Options are deliberately reordered before they
are shown to you, because the authored bank has a severe answer-position
bias. "Option B is marked correct but it should be C" is therefore
ambiguous — please quote the option *text*, not its letter or number.
60 changes: 60 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!--
Three sections, all required. Write them yourself — the point of the third one
is to prove the diff is understood, which a generated summary cannot do.
Delete these comments before submitting.
-->

## What changed and why

<!--
What this PR does, and the problem it solves. Link the issue if there is one
(`Closes #123`). If it changes behaviour a student will notice, say what they
will see.
-->

## How it was tested

<!--
Name the commands you ran and what they said. "Tested" without a command is not
tested.

cd frontend
npx tsc -b
npm run lint
npx vitest run
npm run build
node ../.github/scripts/bundle-budget.mjs

And, for any change touching frontend/public/data/books/ or the question loader:

node scripts/validate-questions.mjs

Paste the relevant output. For a UI change, a screenshot at a narrow viewport
(360px wide) is worth more than one at desktop width.
-->

## Explain the diff in your own words

<!--
Walk through the change file by file: what each edit does and why that approach
rather than the obvious alternative. Call out anything you are unsure about, and
anything a reviewer should look at hardest.
-->

---

### Checklist

- [ ] `npx tsc -b`, `npm run lint`, `npx vitest run` and `npm run build` all pass locally
- [ ] `node scripts/validate-questions.mjs` passes — required if this touches question data or the loader
- [ ] Initial-load JS is still within budget (the `Frontend` CI job prints the number)
- [ ] No new `eslint-disable`, `@ts-ignore`, `@ts-expect-error` or skipped test; if there is one, the PR explains why
- [ ] `frontend/src/data/bookChapters.generated.ts` is regenerated and committed, if chapter JSONs changed
- [ ] The README and `docs/` still describe what the code actually does

### If this changes question data

- [ ] Every row has `correct_option_index` **1-based** and `correct_option` matching the text at that index exactly
- [ ] No duplicate option text within a question, and no duplicate stems against the existing bank
- [ ] The correct answer is not always in the same position — see `docs/question-format.md`
- [ ] Any ids removed from `frontend/src/data/quarantine.json` have had their underlying rows actually fixed
Loading
Loading