Files
pocket-pascal/AGENTS.md
dtoro 3785d08e97 Initial commit: installable PWA hello world
React + TypeScript + Tailwind v4 + shadcn/ui frontend (client), Express +
better-sqlite3 backend (server) in a pnpm workspace. Includes vite-plugin-pwa
manifest, service worker, and iOS install meta tags. GET /api/hello increments a
visit counter in SQLite; backend serves the built client in production.
2026-08-03 22:45:19 +02:00

6.0 KiB

AGENTS.md — How to work in this project

A guide for AI agents (and humans) contributing to Pocket Pascal, a small installable PWA with a React/shadcn frontend and an Express + SQLite backend.

1. Overview

  • Frontend (client/): Vite + React + TypeScript, Tailwind CSS v4, shadcn/ui, vite-plugin-pwa for the service worker + web manifest.
  • Backend (server/): Express + TypeScript (tsx in dev, tsc for the production build) with better-sqlite3 as the database.
  • Workspace: a single pnpm workspace with two packages: client and server.

Runtime model

  • Dev: run pnpm dev from the repo root. It starts both packages in parallel. The Vite dev server (default http://localhost:5173) proxies /api/* to the backend (http://localhost:3001), so there are no CORS issues.
  • Prod / install test: run pnpm build && pnpm start. The backend serves the built client from client/dist (static files + SPA fallback), so a single process on http://localhost:3001 serves the whole app. This is the easiest way to test PWA "Add to Home Screen".

2. Prerequisites

  • Node.js >= 22 (developed on Node 22).
  • pnpm (developed on 10.25). The root package.json pins the version via packageManager.

better-sqlite3 ships a native module. It is listed under pnpm.onlyBuiltDependencies in the root package.json, so a normal pnpm install compiles/fetches it automatically. If it ever fails to load, run pnpm rebuild better-sqlite3 (or from its .pnpm dir: npx prebuild-install -r node).

3. First-time setup

pnpm install

4. Common commands

Run these from the repo root:

Command What it does
pnpm dev Start client + backend in parallel (concurrently).
pnpm build Build the server (tsc) then the client (tsc -b && vite build).
pnpm start Run the production server (node server/dist/index.js).
pnpm lint Lint every workspace package.
pnpm typecheck Type-check every workspace package (tsc).

Run these against a single package with the filter flag, e.g.:

pnpm --filter client dev
pnpm --filter server dev
pnpm --filter client build

5. Project layout

pocket-pascal/
├─ package.json            # workspace root + orchestration scripts
├─ pnpm-workspace.yaml     # packages: client, server
├─ AGENTS.md
├─ README.md
├─ client/                 # Vite + React + Tailwind v4 + shadcn/ui (PWA)
│  ├─ components.json      # shadcn config
│  ├─ pwa-assets.config.ts # @vite-pwa/assets-generator config
│  ├─ vite.config.ts       # react + tailwind + pwa + /api proxy + "@" alias
│  └─ src/
│     ├─ App.tsx           # Hello World UI (fetches /api/hello)
│     ├─ lib/api.ts        # typed fetch helpers
│     ├─ lib/utils.ts      # cn() helper (shadcn)
│     └─ components/ui/    # shadcn components live here
└─ server/                 # Express + better-sqlite3 (ESM, TypeScript)
   ├─ .env.example
   └─ src/
      ├─ index.ts          # express app; serves client/dist in prod
      ├─ db.ts             # opens SQLite, creates schema, exposes helpers
      └─ routes/hello.ts   # GET /api/hello

6. Conventions

  • Language: TypeScript everywhere. The server is ESM ("type": "module").
  • Path alias (client): @/* maps to client/src/* (configured in tsconfig.json, tsconfig.app.json, and vite.config.ts). Prefer @/components/..., @/lib/....
  • API contract: all backend endpoints are prefixed with /api (e.g. GET /api/hello, GET /api/health). The frontend calls them with relative URLs (fetch("/api/hello")) so the Vite proxy and the prod static server both work without extra config.
  • Environment: the backend reads process.env.PORT (default 3001). See server/.env.example.
  • Styling: Tailwind v4 + shadcn theme tokens (CSS variables in client/src/index.css). Use shadcn primitives; reach for cn() in @/lib/utils when composing classes.

7. Database

  • The SQLite file lives at server/data/app.db (auto-created on first run; the whole server/data/ directory is gitignored).
  • There is no migration tool. Schema changes use idempotent statements (CREATE TABLE IF NOT EXISTS ...) in server/src/db.ts, which runs on boot.
  • The demo visits table has a single enforced row (id = 1) holding a counter that GET /api/hello increments.

8. Adding a shadcn/ui component

Run from the client/ directory (it reads components.json):

cd client
pnpm dlx shadcn@latest add <component>   # e.g. card, input, dialog

The component is written to client/src/components/ui/. shadcn was initialized with the neutral base color and the base-nova style.

9. Regenerating PWA icons

Icons are generated from client/public/icon.svg via @vite-pwa/assets-generator:

cd client
pnpm dlx @vite-pwa/assets-generator        # uses pwa-assets.config.ts

Outputs land in client/public/ (pwa-*.png, maskable-icon-*.png, apple-touch-icon-*.png). The manifest in vite.config.ts references them.

10. PWA / install notes

  • iOS Safari needs the meta tags already in client/index.html (apple-mobile-web-app-capable, apple-touch-icon, etc.) and a valid icon set.
  • Service worker + manifest are produced by vite-plugin-pwa. To verify installability: pnpm build && pnpm start, open http://localhost:3001, then DevTools → Application → Manifest / Service Workers. Real-device install off localhost requires HTTPS.

11. Before you finish a change

Always run, from the repo root:

pnpm typecheck
pnpm lint
pnpm build

Then sanity-check pnpm dev (or pnpm build && pnpm start) end to end.