Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .agents/skills/testing-learninglab/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description: How to run and end-to-end test the LearningLab worksheet generator
- Root and server deps require Node **>=22.12** — run `source ~/.nvm/nvm.sh && nvm use 22` in every shell before npm/npx (the default node may be older).
- `server` is a root npm **workspace** and has no own lockfile: install with `npm install` at the repo root (this also installs server deps), then `npm install` in `server/client`. Root `npm install` may rewrite the `engines.node` metadata in the tracked root `package-lock.json` — check `git diff package-lock.json` and `git checkout -- package-lock.json` if it is only that.
- Static checks that should pass: root `npm run build` (client), `cd server && npx tsc --noEmit && npx eslint .` (eslint 10 flat config; warnings are pre-existing, only errors matter), `cd server/client && npx tsc --noEmit`.
- Duplicated serverless copies of the endpoints: `api/generate-worksheet.js` (Vercel-style, CommonJS) and `functions/api/generate-worksheet.js` (Cloudflare Pages, ESM `onRequestPost`). Real production is Cloudflare Pages: static client + `functions/api/*`.
- Serverless copy of the endpoint: `functions/api/generate-worksheet.js` (Cloudflare Pages, ESM `onRequestPost`). Real production is Cloudflare Pages: static client + `functions/api/*`. Tests: `npm test` at the root (Cloudflare function via `test/*.test.mjs` with stubbed `fetch`, server via `server/src/**/*.test.ts`).

## Ports / wiring gotcha
In dev the client does **not** use the vite `/api` proxy: `server/client/src/config/constants.ts` hardcodes `http://localhost:3001` for non-production mode (in production mode the bundle uses a same-origin empty baseUrl). So the Express server must listen on **3001** (`PORT=3001`) and `CORS_ORIGIN` must be `http://localhost:5173`, otherwise the UI shows "Unable to connect to server".
Expand Down
16 changes: 8 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# Copy this file to server/.env (the Express server loads server/.env, not the repo root).

# OpenAI API Configuration
OPENAI_API_KEY=your_openai_api_key_here

# Server Configuration
PORT=3000
PORT=3001
NODE_ENV=development

# Security
CORS_ORIGIN=http://localhost:5173

# API Rate Limiting (Optional - defaults are secure)
# Positive integers; the defaults shown apply when unset.
# General API rate limiting (15 minutes window)
GENERAL_RATE_LIMIT_WINDOW_MS=900000
GENERAL_RATE_LIMIT_MAX_REQUESTS=100
# GENERAL_RATE_LIMIT_WINDOW_MS=900000
# GENERAL_RATE_LIMIT_MAX_REQUESTS=100

# Worksheet generation rate limiting (1 hour window)
WORKSHEET_RATE_LIMIT_WINDOW_MS=3600000
WORKSHEET_RATE_LIMIT_MAX_REQUESTS=10

# Request size limits (bytes)
MAX_REQUEST_SIZE=1024
# WORKSHEET_RATE_LIMIT_WINDOW_MS=3600000
# WORKSHEET_RATE_LIMIT_MAX_REQUESTS=10
6 changes: 5 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ updates:
# typescript-eslint does not support TypeScript 7 yet.
- dependency-name: "typescript"
update-types: ["version-update:semver-major"]
# Track the Node 22 runtime (engines / .node-version / vercel.json).
# Track the Node 22 runtime (engines / .node-version).
- dependency-name: "@types/node"
update-types: ["version-update:semver-major"]
# Client has its own lockfile (not part of the workspace).
Expand All @@ -28,3 +28,7 @@ updates:
ignore:
- dependency-name: "typescript"
update-types: ["version-update:semver-major"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
24 changes: 13 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
Expand All @@ -14,9 +17,11 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false

- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: .node-version
cache: npm
Expand All @@ -31,8 +36,8 @@ jobs:
run: npm ci
working-directory: server/client

- name: Typecheck server
run: npx tsc --noEmit
- name: Typecheck server (incl. tests)
run: npx tsc --noEmit -p tsconfig.eslint.json
working-directory: server

- name: Lint server
Expand All @@ -43,26 +48,23 @@ jobs:
run: npx tsc --noEmit
working-directory: server/client

- name: Test (Cloudflare function + server)
run: npm test

- name: Build client
run: npm run build

- name: Build server
run: npx tsc
working-directory: server

- name: Serverless handlers load
run: |
node -e "const h = require('./api/generate-worksheet.js'); if (typeof h !== 'function') process.exit(1)"
node --input-type=module -e "import('./functions/api/generate-worksheet.js').then(m => { if (typeof m.onRequestPost !== 'function') process.exit(1) })"
env:
OPENAI_API_KEY: ci-dummy

- name: Production smoke test
run: |
NODE_ENV=production PORT=3001 OPENAI_API_KEY=ci-dummy node server/dist/index.js &
for i in $(seq 1 20); do curl -sf localhost:3001/api/health && break; sleep 1; done
curl -sf localhost:3001/api/health
curl -sf localhost:3001/ | grep -q '<div id="root"'
curl -sf -o /dev/null localhost:3001/favicon.svg
code=$(curl -s -o /dev/null -w '%{http_code}' -X POST localhost:3001/api/generate-worksheet -H 'content-type: application/json' -d '{"gradeLevel":"99th","topic":"x"}')
test "$code" = "400"
kill %1
11 changes: 1 addition & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ node_modules/
/build
/server/dist
/client/dist
.next/
.vercel/

# Next.js specific
learninglab-nextjs/node_modules/
learninglab-nextjs/.next/
learninglab-nextjs/.vercel/
learninglab-nextjs/dist/

# Logs
logs
Expand Down Expand Up @@ -54,8 +46,7 @@ coverage/
npm-debug.log*

# Local development
.serverless/
.serverless_plugins/
.wrangler/

# IDE
*.sublime-workspace
Expand Down
57 changes: 0 additions & 57 deletions .vercelignore

This file was deleted.

Loading
Loading