mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
93e8b5dfcf
* Add Plannotator Workspaces waitlist (page + worker + CI) Marketing - New /workspaces/ page: hero+form sibling layout on desktop; mobile reorders to hero -> form -> info -> banners so the CTA is reachable on the first scroll. Uses the marketing site tokens/fonts and the existing border-x editorial column. Theme-aware via the cookie. - Adds a "head" slot to Base.astro for per-page <head> additions. - Nav: new "Workspaces" link with a "soon" pill. - Landing: small Workspaces CTA band before the final install CTA. Waitlist worker (apps/waitlist-service) - Cloudflare Worker + D1 (SQLite). Mirrors the paste-service layout. - Endpoints: POST /signup (Turnstile-protected, rate-limited, honeypot), GET /health, GET /admin/count, GET /admin/list gated by Bearer ADMIN_TOKEN. - Validation: required email + company + team_size; optional note + is_contributor; honeypot field; freemail-aware company auto-inference. - D1 schema includes a non-destructive 001 migration that adds note and is_contributor columns. 19/19 validation unit tests pass; tsc clean. CI - Adds a deploy-waitlist job to .github/workflows/deploy.yml mirroring paste-service. Uses the existing CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID secrets, so no new repo config is required. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Force light mode on /workspaces/ The page is designed and signed off in light. Override the saved theme cookie via a head-slot inline script that adds the `.light` class before paint. Base.astro's cookie reader only adds the class (never removes), so any saved-dark preference can't undo this. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
38 lines
1.3 KiB
SQL
38 lines
1.3 KiB
SQL
-- Plannotator Workspaces waitlist
|
|
--
|
|
-- Authoritative schema for from-scratch deploys. The current production
|
|
-- schema is this file PLUS the migrations under `migrations/` (already
|
|
-- applied). For a fresh database, this file alone is sufficient.
|
|
--
|
|
-- Run with: bun run db:migrate (remote) or db:migrate:local (local dev)
|
|
|
|
CREATE TABLE IF NOT EXISTS waitlist (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
|
-- `name` is no longer collected by the form. Kept NOT NULL with an empty
|
|
-- string default so the live D1 schema (which has NOT NULL with no default)
|
|
-- can be brought into line via the 002 migration without losing rows.
|
|
name TEXT NOT NULL DEFAULT '',
|
|
company TEXT,
|
|
company_inferred INTEGER NOT NULL DEFAULT 0,
|
|
team_size TEXT,
|
|
note TEXT,
|
|
is_contributor INTEGER NOT NULL DEFAULT 0,
|
|
ip TEXT,
|
|
country TEXT,
|
|
user_agent TEXT,
|
|
referer TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_waitlist_created_at ON waitlist(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_waitlist_company ON waitlist(company);
|
|
|
|
-- Per-IP daily rate-limit counter, prunable on a schedule.
|
|
CREATE TABLE IF NOT EXISTS rate_limit (
|
|
ip TEXT NOT NULL,
|
|
day TEXT NOT NULL,
|
|
hits INTEGER NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (ip, day)
|
|
);
|