- TypeScript 97.9%
- CSS 1.4%
- JavaScript 0.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .openai | ||
| app | ||
| build | ||
| db | ||
| docs | ||
| drizzle | ||
| examples/d1 | ||
| public | ||
| tests | ||
| types | ||
| worker | ||
| .dev.vars.example | ||
| .gitignore | ||
| drizzle.config.ts | ||
| eslint.config.mjs | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
| worker-configuration.d.ts | ||
| wrangler.jsonc | ||
Arc Algebra
Arc Algebra is an adaptive algebra practice app built for durable learning. It runs as a vinext application on Cloudflare Workers, with D1 for accounts, sessions, progress, and review history.
Current product shape
- Adults create a username-and-password account without requiring an email.
- Every adult has their own learning profile and can optionally create child accounts.
- Children can sign in to their own learning profile but cannot create accounts, manage family settings, or change credentials.
- Adults can reveal or replace credentials for children they manage.
- Optional recovery email addresses support single-use, 15-minute password reset links through Cloudflare Email Service.
- Five active algebra templates generate reproducible questions from saved seeds: linear equations, factoring trinomials, function notation, completing the square, and absolute-value equations.
- Walkthroughs reveal detailed work successively while keeping earlier steps visible.
The backend schema still calls the managing account role parent. The UI calls
it an adult account because adults can learn with or without children. Renaming
the stored role is a future cleanup, not a current database requirement.
Question generation
app/questions.ts contains the native, constraint-driven template registry.
Each template owns:
- parameter selection from a deterministic seed;
- rejection constraints for trivial or unnatural variants;
- prompt, canonical answer, variation key, hints, and worked equations;
- an answer policy (
equivalentorexact).
The shared renderer omits incidental identity operations such as + 0, 1x,
and multiplication by one. MathLive remains the answer input, while the
CortexJS Compute Engine checks symbolic equivalence.
tests/question-generator.test.ts exercises 1,000 deterministic seeds for each
active template and includes a small fixed gallery for human review.
Authentication and data
Usernames are lowercase, globally unique, and 3–32 characters. Suggested usernames derive from the display name and end with four stable digits; the suggestion stops changing once the adult edits it. Availability checks are debounced by 400 ms, and creation still enforces uniqueness atomically.
Adult passwords require at least eight characters. Child passwords require at least four characters and have no other constraints. Login passwords use salted PBKDF2 hashes. Child passwords are also encrypted with AES-GCM so only the authenticated managing adult can reveal them. Adult passwords are never recoverable.
Sessions use HTTP-only, secure, same-site cookies with a rolling one-year lifetime. Login and recovery requests have modest D1-backed throttling. Changing a password revokes the affected sessions.
The D1 schema and migrations live in db/schema.ts and drizzle/. Migration
0001_parent_child_auth.sql intentionally starts from a fresh database and
discards the original demo data. Migration 0002_parent_learning_profiles.sql
adds learning profiles for adults.
Local setup
Prerequisites:
- Node.js 22.13 or newer
- npm
- Wrangler authentication only when working with remote Cloudflare resources
Install dependencies:
npm install
Copy .dev.vars.example to .dev.vars and replace the example values:
CREDENTIAL_ENCRYPTION_KEY=base64url-encoded-32-byte-key
RECOVERY_EMAIL_HMAC_KEY=long-random-secret
MAIL_FROM=noreply@your-verified-domain.example
APP_ORIGIN=http://localhost:3000
Generate a suitable credential key with Node:
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
Apply migrations to the fresh local D1 database:
npx wrangler d1 migrations apply site-creator-d1 --local
Start the app:
npm run dev
Verification
npm test
npx tsc --noEmit
npm run lint
npm test performs a production build, runs the 5,000-case generator quality
sweep, verifies the deterministic review gallery, and checks the Arc app entry
surface.
Cloudflare deployment
The production runtime uses a Worker with:
- a D1 binding named
DB; - a Cloudflare Email Service binding named
EMAIL; - encrypted secrets named
CREDENTIAL_ENCRYPTION_KEYandRECOVERY_EMAIL_HMAC_KEY; MAIL_FROMset to a sender on a verified domain;APP_ORIGINset to the production origin used in reset links.
Before deployment, create the production D1 database and replace the placeholder
database ID in wrangler.jsonc. Then configure the secrets, apply migrations
with --remote, verify the Email Service sender, and deploy the built Worker.
Do not commit .dev.vars or production secret values.
Useful commands
npm run dev— start local developmentnpm run build— create the production Worker buildnpm test— build and run the generator/application checksnpm run lint— run ESLintnpm run db:generate— generate a Drizzle migration after schema changes