Skip to content

Commit 93e8b5d

Browse files
Add Plannotator Workspaces waitlist (page + worker + CI) (#771)
* 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>
1 parent 4db7fcc commit 93e8b5d

21 files changed

Lines changed: 2159 additions & 3 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
- 'apps/marketing/**'
99
- 'apps/portal/**'
1010
- 'apps/paste-service/**'
11+
- 'apps/waitlist-service/**'
1112
- 'packages/**'
1213
workflow_dispatch:
1314
inputs:
@@ -21,6 +22,7 @@ on:
2122
- marketing
2223
- portal
2324
- paste
25+
- waitlist
2426

2527
permissions:
2628
contents: read
@@ -32,6 +34,7 @@ jobs:
3234
marketing: ${{ steps.changes.outputs.marketing }}
3335
portal: ${{ steps.changes.outputs.portal }}
3436
paste: ${{ steps.changes.outputs.paste }}
37+
waitlist: ${{ steps.changes.outputs.waitlist }}
3538
steps:
3639
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3740

@@ -54,13 +57,19 @@ jobs:
5457
else
5558
echo "paste=false" >> $GITHUB_OUTPUT
5659
fi
60+
if [[ "${{ inputs.target }}" == "all" || "${{ inputs.target }}" == "waitlist" ]]; then
61+
echo "waitlist=true" >> $GITHUB_OUTPUT
62+
else
63+
echo "waitlist=false" >> $GITHUB_OUTPUT
64+
fi
5765
else
5866
# For push events, check what changed
5967
git fetch origin ${{ github.event.before }} --depth=1 2>/dev/null || true
6068
6169
MARKETING_CHANGED=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} 2>/dev/null | grep -E '^(apps/marketing/|packages/)' || true)
6270
PORTAL_CHANGED=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} 2>/dev/null | grep -E '^(apps/portal/|packages/)' || true)
6371
PASTE_CHANGED=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} 2>/dev/null | grep -E '^apps/paste-service/' || true)
72+
WAITLIST_CHANGED=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} 2>/dev/null | grep -E '^apps/waitlist-service/' || true)
6473
6574
if [[ -n "$MARKETING_CHANGED" ]]; then
6675
echo "marketing=true" >> $GITHUB_OUTPUT
@@ -79,6 +88,12 @@ jobs:
7988
else
8089
echo "paste=false" >> $GITHUB_OUTPUT
8190
fi
91+
92+
if [[ -n "$WAITLIST_CHANGED" ]]; then
93+
echo "waitlist=true" >> $GITHUB_OUTPUT
94+
else
95+
echo "waitlist=false" >> $GITHUB_OUTPUT
96+
fi
8297
fi
8398
8499
deploy-marketing:
@@ -178,3 +193,27 @@ jobs:
178193
env:
179194
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
180195
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
196+
197+
deploy-waitlist:
198+
needs: detect-changes
199+
if: needs.detect-changes.outputs.waitlist == 'true'
200+
runs-on: ubuntu-latest
201+
permissions:
202+
contents: read
203+
environment: production
204+
steps:
205+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
206+
207+
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
208+
with:
209+
bun-version: latest
210+
211+
- name: Install dependencies
212+
run: bun install
213+
214+
- name: Deploy to Cloudflare
215+
working-directory: apps/waitlist-service
216+
run: npx wrangler deploy
217+
env:
218+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
219+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ opencode.json
5252
plannotator-local
5353
# Local research/reference docs (not for repo)
5454
/reference/
55+
/Plannotator Waitlist Signup/
5556
# Local goal setup packages generated by the setup-goal skill.
5657
/goals/
5758
*.bun-build

apps/marketing/src/components/Nav.astro

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import ModeToggleIsland from './ModeToggleIsland.tsx';
44
const currentPath = Astro.url.pathname;
55
const isDocsActive = currentPath.startsWith('/docs/');
66
const isBlogActive = currentPath.startsWith('/blog/');
7+
const isWorkspacesActive = currentPath.startsWith('/workspaces/');
78
---
89
<nav class="fixed top-0 left-0 right-0 h-12 flex items-center justify-between px-6 bg-background/80 backdrop-blur-sm border-b border-border/30 z-50">
910
<div class="flex items-center gap-2">
@@ -33,6 +34,17 @@ const isBlogActive = currentPath.startsWith('/blog/');
3334
Blog
3435
</a>
3536
<span class="text-muted-foreground/50">|</span>
37+
<a
38+
href="/workspaces/"
39+
class:list={[
40+
'transition-colors inline-flex items-center gap-1',
41+
isWorkspacesActive ? 'text-foreground font-medium' : 'text-muted-foreground hover:text-foreground',
42+
]}
43+
>
44+
Workspaces
45+
<span class="text-[0.6875rem] px-1 py-px rounded bg-primary/15 text-primary border border-primary/30 leading-none">soon</span>
46+
</a>
47+
<span class="text-muted-foreground/50">|</span>
3648
<a
3749
href="https://github.com/backnotprop/plannotator"
3850
target="_blank"

apps/marketing/src/layouts/Base.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import '../styles/global.css';
4545
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
4646
<link href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
4747
<noscript><style>.landing-reveal{opacity:1!important;transform:none!important}</style></noscript>
48+
<slot name="head" />
4849
</head>
4950
<body class="min-h-screen antialiased">
5051
<slot />

apps/marketing/src/pages/index.astro

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,33 @@ import AnnoReplace from '../components/landing/AnnoReplace.astro';
404404
</div>
405405
</section>
406406

407+
<!-- Workspaces teaser -->
408+
<section class="workspaces-cta-band py-14 px-8 border-t border-border/30 landing-reveal">
409+
<div class="relative z-10 max-w-2xl mx-auto text-center">
410+
<span class="workspaces-cta-pill mb-4">
411+
<span class="w-1.5 h-1.5 rounded-full bg-primary"></span>
412+
Plannotator Workspaces · waitlist
413+
</span>
414+
<h2 class="font-display text-xl sm:text-2xl font-semibold tracking-tight mb-3">
415+
Turn agent plans and code reviews into <span class="text-primary">shared team knowledge</span>.
416+
</h2>
417+
<p class="text-sm text-muted-foreground leading-relaxed mb-5 max-w-[52ch] mx-auto">
418+
Workspaces is the hosted layer for teams &mdash; shared plans,
419+
review history, integrations, and verification standards. The
420+
local plugin stays free &amp; open source.
421+
</p>
422+
<a
423+
href="/workspaces/"
424+
class="hero-cta-btn inline-flex items-center gap-2 px-4 py-2 rounded-lg border border-border text-sm text-foreground font-medium hover:bg-muted/50 transition-colors"
425+
>
426+
Join the waitlist
427+
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
428+
<path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" />
429+
</svg>
430+
</a>
431+
</div>
432+
</section>
433+
407434
<!-- Final CTA -->
408435
<section class="py-16 px-8 border-t border-border/30 bg-card/30">
409436
<div class="text-center">

0 commit comments

Comments
 (0)