commit 4eed701419e28a65b7a7dc05483a77cb6c9c0f04 Author: lilleman Date: Sun Jun 14 11:45:30 2026 +0200 Scaffold Docker-only Node 24 + TypeScript EJS web backend diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3a7b2df --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +node_modules +npm-debug.log +*.log +.DS_Store +html-css-foundation diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5742681 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.claude +.DS_Store +*.log +node_modules diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..0410e11 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +; Pin exact versions on install — `npm install ` saves "1.2.3", not "^1.2.3". +save-exact=true diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..784e6ad --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,38 @@ +# AGENTS.md + +Guidance for AI agents and contributors working in this repo. Read `README.md` for +commands and layout. + +## Project priorities (do not erode) + +1. **Simplicity** — prefer the smallest, most readable solution. +2. **Few dependencies** — the only runtime dep is `ejs`. Prefer the Node standard + library. Justify any new dependency; do not add frameworks. +3. **Strict TypeScript** — `tsconfig.json` is strict (incl. `noUncheckedIndexedAccess`, + `exactOptionalPropertyTypes`, `verbatimModuleSyntax`). Keep it that way. + +## Docker only — no host tooling + +**Everything** (install, typecheck, test, run, build, deploy) goes through Docker / +Docker Compose. **Never run `node`, `npm`, or `tsc` on the host.** + +```bash +docker compose up # dev server, live reload +docker compose run --rm web npm run typecheck # strict type check +docker compose run --rm web npm test # tests +docker compose -f docker-compose.yml up --build -d # production +``` + +## Rules + +- Node 24 runs `.ts` directly (type stripping). Keep all TypeScript **erasable** + (`erasableSyntaxOnly` is on): no `enum`, `namespace`, parameter properties, or + decorators. Import local modules with their `.ts` extension. +- **No build step** and no compiled artifacts — do not add a bundler or `tsc` emit. +- Before finishing a change, run the typecheck and tests above; both must pass. +- Tests use the built-in `node --test` runner — no test framework dependency. +- English everywhere. Keep code comments short and information-dense. +- Pin all dependencies and Docker images to exact, human-readable **semantic + versions** — never ranges (`^`, `~`) and never digests/hashes. npm deps are kept + exact by `.npmrc` (`save-exact=true`) + `npm ci`; the base image by tag (e.g. + `node:24.16.0-alpine3.24`). diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..569ff00 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +# Node 24 runs TypeScript directly (type stripping) — no build step. +# Pinned to an exact, human-readable version (node / alpine). +FROM node:24.16.0-alpine3.24 + +WORKDIR /app + +# Reproducible install from the committed lockfile. Dev deps (typescript, types) +# are kept so `npm run typecheck` / `npm test` work in the same image. +COPY package.json package-lock.json .npmrc ./ +RUN npm ci + +COPY . . + +ENV PORT=3000 +EXPOSE 3000 +CMD ["node", "src/server.ts"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..3b4249a --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# Plainpages + +A minimal **Node.js 24 + TypeScript** web backend that serves server-rendered HTML +(via **EJS** templates), CSS, and static files. + +Priorities: **simplicity, few dependencies, strict TypeScript type checking.** +Development and deployment are **entirely Docker / Docker Compose based — no other +tooling is required** (no local Node, npm, or `tsc`). + +The only runtime dependency is `ejs`. Node 24 runs the TypeScript sources directly +(type stripping), so there is **no build step** and no compiled output. + +## Requirements + +- Docker +- Docker Compose + +That's it. Do not install or run Node/npm on the host — use the commands below. + +## Development + +```bash +docker compose up # http://localhost:3000, live reload via `node --watch` +``` + +`docker compose up` merges `compose.override.yml`, which mounts the source +and restarts the server on change. + +## Type check & tests + +```bash +docker compose run --rm web npm run typecheck # strict tsc --noEmit +docker compose run --rm web npm test # node --test +``` + +## Production / deployment + +```bash +docker compose -f compose.yml up --build -d # base config only, no source mount +``` + +## Layout + +``` +src/server.ts Entry point — starts the HTTP server (reads PORT, default 3000) +src/app.ts Request routing + EJS rendering +src/static.ts Static file serving with path-traversal protection +views/ EJS templates (index, 404, partials/) +public/ Static assets served under /public/ (css/, favicon, robots.txt) +``` + +## Extending + +- **New page:** add a route in `src/app.ts` and a template in `views/`. +- **Static asset:** drop it in `public/`; it is served at `/public/`. +- **New dependency:** `docker compose run --rm web npm install ` (updates + `package.json` + `package-lock.json`), then rebuild with `docker compose build`. + Keep dependencies minimal — prefer the Node standard library. + +All versions are pinned to **exact, human-readable semantic versions** (no ranges, +no digests): deps via `.npmrc` (`save-exact=true`) and the committed lockfile +(`npm ci`), and the Node base image by tag in the `Dockerfile` +(e.g. `node:24.16.0-alpine3.24`). + +`html-css-foundation/` holds the raw HTML/CSS design reference; it is not served and +is meant to be converted into EJS templates and `public/` assets over time. diff --git a/compose.override.yml b/compose.override.yml new file mode 100644 index 0000000..8bc9788 --- /dev/null +++ b/compose.override.yml @@ -0,0 +1,10 @@ +# Development overrides, merged automatically by `docker compose up`. +# Mounts the source for live editing and restarts on change via `node --watch`. +services: + web: + command: node --watch src/server.ts + environment: + NODE_ENV: development + volumes: + - .:/app + - /app/node_modules diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..576abb9 --- /dev/null +++ b/compose.yml @@ -0,0 +1,10 @@ +# Base / production config. Run alone with: docker compose -f docker-compose.yml up +# Plain `docker compose up` also merges docker-compose.override.yml for development. +services: + web: + build: . + ports: + - "3000:3000" + environment: + NODE_ENV: production + restart: unless-stopped diff --git a/html-css-foundation/App Shell.html b/html-css-foundation/App Shell.html new file mode 100644 index 0000000..03797d2 --- /dev/null +++ b/html-css-foundation/App Shell.html @@ -0,0 +1,735 @@ + + + + + +App Shell — Template + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ +
+
People
+
+ +
+ + +
+ + +
+ +
+ + +
+ Status +
+ + + +
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+ Tags + +
+ + + + + +
+
+ +
+ +
+ Joined + +
+ + + + + + +
+
+
+ + +
+
+ Applied + Team: Engineering + Tag: On-call + Joined: 2026 + Clear all +
+ +
+ +
+ + +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
People in the directory
+ + + + + + + + TeamStatus + + Actions
Mara Delgado[email protected]AdminEngineeringActive2 min ago + +
Soren Vance[email protected]MemberDesignIdle3 hours ago + +
Priya Nair[email protected]AdminOperationsActivejust now + +
Eli Brandt[email protected]ViewerSalesSuspended6 days ago + +
Tomas Lindqvist[email protected]MemberEngineeringInvited + +
Hana Osei[email protected]MemberDesignActive21 min ago + +
Rafael Costa[email protected]AdminOperationsIdle1 hour ago + +
Wen Li[email protected]ViewerSalesActive44 min ago + +
Nadia Farouk[email protected]MemberEngineeringSuspended12 days ago + +
Otto Berg[email protected]MemberDesignInvited + +
Greta Holm[email protected]AdminOperationsActive8 min ago + +
Yusuf Demir[email protected]ViewerSalesIdle5 hours ago + +
+
+ + +
+ 1–12 of 1,284 +
+ +
+ +
+
+
+ +
+ +
+
+ + + diff --git a/html-css-foundation/Auth.html b/html-css-foundation/Auth.html new file mode 100644 index 0000000..f4c96a9 --- /dev/null +++ b/html-css-foundation/Auth.html @@ -0,0 +1,216 @@ + + + + + +Sign in — Console + + + + + + + + +
+
+ +
+ + Console +
+ + +
+
+
+

Sign in

+

Welcome back. Enter your details to continue.

+
+ + +
+
    + +
  • +
  • +
  • +
+
or
+
+ +
+
+ +
+ + +
+
+ +
+
+ + Forgot password? +
+
+ + +
+
+ + + + +
+ +

Don't have an account? Create one

+
+
+ + +
+
+
+

Create account

+

Get started — it only takes a minute.

+
+ +
+
    +
  • +
  • +
  • +
+
or
+
+ +
+ +
+
+ + Optional +
+
+ + +
+
+ +
+ +
+ + +
+ +
+ +
+ +
+ + +
+ Use 8 or more characters. + +
+ + +
+ +

Already have an account? Sign in

+
+
+ + +
+
+
+ Back to sign in +

Reset password

+

Enter your email and we'll send you a reset link.

+
+ + +
+ +
Check your emailIf an account exists for that address, a reset link is on its way.
+
+ + +
+
+ +
+ + +
+
+ + +
+ +

Remembered it? Sign in

+
+
+ +
+
+ + +
+ Preview +
+ + + +
+ + + +
+
+ + + +
+
+ +
+
+ + + +
+
+
+ + + diff --git a/html-css-foundation/auth.css b/html-css-foundation/auth.css new file mode 100644 index 0000000..3805c1f --- /dev/null +++ b/html-css-foundation/auth.css @@ -0,0 +1,232 @@ +/* ============================================================= + Auth flow — login / register / forgot password + Built on the shared tokens in styles.css. Pure HTML/CSS: + - screens switch via :target (no JS) + - SSO is a config section toggled by a class/checkbox; providers + are a