Add Plannotator Workspaces waitlist (page + worker + CI)#771
Merged
Conversation
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>
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>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces Plannotator Workspaces — the hosted team layer waitlist — as a new page on the marketing site backed by a new Cloudflare Worker + D1 backend.
What's new
/workspaces/marketing page: two-column conversion layout on desktop (hero + form siblings, both top-aligned); single-column on mobile reordered ashero → form → info → bannersso the CTA is reachable without scrolling past the long info section.apps/waitlist-service/: Cloudflare Worker that accepts signup submissions and writes to a D1 (SQLite) waitlist table.POST /signup— Turnstile-verified, honeypot-protected, per-IP/day rate-limited.GET /admin/{count,list}— bearer-token gated (ADMIN_TOKEN).tsc --noEmitclean.deploy-waitlistjob added to.github/workflows/deploy.yml, mirroringdeploy-paste. Uses the existingCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDrepo secrets — no new config.Already done out-of-band
The Cloudflare side has been provisioned manually so this PR's worker job won't be doing first-time setup work:
plannotator-waitlistcreated (id pinned inwrangler.toml)note,is_contributorcolumns)ADMIN_TOKENandTURNSTILE_SECRET_KEYsecrets uploaded viawrangler secret puthttps://plannotator-waitlist.plannotator.workers.devand end-to-end-curl-testedThe merge will trigger an idempotent
wrangler deployfrom CI, which is what we want for ongoing changes.Production verification needed
Local form testing on
localhost:3003was blocked by Cloudflare Turnstile error 110200 ("domain not allowed") — the widget's allowlist only includesplannotator.ai. Addinglocalhost/127.0.0.1to the widget's hostnames in the CF dashboard would fix dev testing, but for now we're verifying directly against production after merge.Test plan
https://plannotator.ai/workspaces/wrangler d1 execute plannotator-waitlist --remote --command="SELECT email, company, team_size, note, is_contributor, created_at FROM waitlist ORDER BY created_at DESC LIMIT 5"GET /admin/listwithout token → 401; with token → 200Notes on legacy data shape
The earlier iteration of this work briefly captured
name/role/tools/use_cases. Those columns remain in thewaitlisttable for forward-compat (zero rows in production yet), but the new validator no longer accepts them and the worker writes empty strings/NULLs to those columns. A follow-up destructive migration can drop the unused columns whenever convenient.Generated with Devin