Website for the AI meets SDLC seminar, held 13 October 2026 at Marsio Saastamoinen Foundation Stage, Espoo, Finland.
The site is built with Gustwind and HTMLisp, styled with Tailwind CSS, and
deployed as a Cloudflare Worker with static assets. The production domain is
sdlcai.org.
- Node 24 or newer. The repository includes
.node-versionfor Cloudflare Workers Builds and local version managers. - npm
- Wrangler access to the Cloudflare account for Worker, D1, R2, and Turnstile setup.
site/layouts/index.html: main page markup and client-side behavior.site/tailwind.css: font faces, Tailwind theme variables, and global styles.assets/: logo, favicon, fonts, and referenced media.worker/index.ts: Cloudflare Worker, interest form endpoint, and scheduled backups.migrations/: D1 schema.scripts/: local helper scripts for dotenv, backup decryption, and build verification.docs/cloudflare.md: Cloudflare provisioning, secrets, backup, and deployment notes.
Install dependencies:
npm installRun the Gustwind development server:
npm startBuild the static site:
npm run buildServe the generated build locally:
npm run serveFormat and validate:
npm run format
npm run format:check
npm run validateCopy .env.example to .env, set a local EMAIL_ENCRYPTION_KEY, then generate
Wrangler's .dev.vars:
npm run dev:envApply the local D1 migration:
npm run db:migrate:localRun the Worker locally:
npm run worker:devworker:dev builds the site, verifies that build/index.html exists, and then
starts Wrangler.
The interest form stores submissions in Cloudflare D1. Email, name, and organization are encrypted before insert, and a keyed email hash is stored for deduplication. Plaintext contact details are not stored in D1 or R2.
Scheduled backups export encrypted D1 rows to R2. A latest-backup manifest stores a hash of the encrypted rows so unchanged scheduled runs do not write duplicate backup objects.
Decrypt a downloaded backup with:
EMAIL_ENCRYPTION_KEY=... npm run interests:decrypt -- backup.jsonExport contact details for follow-up email from production D1 with:
EMAIL_ENCRYPTION_KEY=... npm run --silent interests:export -- --remote > contacts.csvThe export script also supports local D1 and downloaded backups:
EMAIL_ENCRYPTION_KEY=... npm run --silent interests:export -- --local
EMAIL_ENCRYPTION_KEY=... npm run --silent interests:export -- --input backup.json
EMAIL_ENCRYPTION_KEY=... npm run --silent interests:export -- --remote --format jsonDeploy through Cloudflare Workers Builds or locally with:
npm run deploySee Cloudflare setup for provisioning, secrets, backup, and deployment notes.