Files
open-design/.gitignore
T
c732084b23 feat: newsletter subscribe (landing entry + onboarding email capture) (#3575)
* feat: add newsletter subscribe entry points (landing + client)

Add a "Subscribe to our newsletter" form on the marketing landing page
(bottom section + dismissable bottom-right popup) and a matching popup in
the desktop client. Emails POST to a new /subscribe Cloudflare Pages
Function that writes to KV (idempotent via sha256(email)), with CORS for
the cross-origin client. i18n covers all locales; analytics fire a
newsletter_signup event.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* chore: refine newsletter copy to product-name title

Drop the frequency promise ("weekly") and the abstract "Design
intelligence" wording in favor of the product-name title "The Open Design
newsletter", and change the eyebrow label to "Stay updated" so it no longer
echoes the title. Updated across the landing page and all client locales.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* chore: ease landing newsletter popup trigger to 50% scroll / 10s

Lower the bottom-right popup trigger from 60% scroll / 25s to 50% / 10s so
it surfaces a bit sooner without interrupting the hero LCP.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* refactor(web): move newsletter signup from popup into onboarding

The desktop client's newsletter popup only mounted on the main entry view,
so first-run users (who land on onboarding) never saw it. Replace it with an
optional email field on the onboarding "About you" step instead — a more
natural, less interruptive moment to capture an address.

- Add an optional email input to the About-you step; on finish, a valid
  address is POSTed to the subscribe endpoint fire-and-forget (a slow or
  failing request never blocks completing onboarding).
- Endpoint is configurable via NEXT_PUBLIC_NEWSLETTER_URL, defaulting to the
  marketing site so dev can point at a local wrangler instance.
- Remove the NewsletterPopup component, its mount, styles, and popup-only
  analytics/i18n keys.
- Track only a boolean newsletter_opt_in on the onboarding click — the email
  address itself is never sent to analytics.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* chore(landing): mirror newsletter section into canonical template

The newsletter section/popup was added to apps/landing-page/app/page.tsx
and globals.css but the source-of-truth example.html was left stale, so
future landing/template work would regenerate against a homepage missing
the subscription entry point. Mirror the section + popup markup, styles,
and signup script into design-templates/open-design-landing/example.html
to restore lockstep per apps/landing-page/AGENTS.md.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

* refactor(web): make newsletter its own onboarding step (3rd)

Promote the newsletter email from a cramped field under the About-you
dropdowns to a dedicated third onboarding step ("Stay updated"), giving it
room for a heading + explainer. Also removes the design-system creation step
from onboarding (the home sidebar entry to create a design system is
unchanged).

- steps array is now Connect / About you / Stay updated; the progress bar
  uses a 3-column grid so all three sit on one row.
- Email submit + completion now fire from the third step.
- Drop the onboarding design-system branches and their now-unused helpers
  (designItems, designSource, deriveOnboardingSourceType); a completion no
  longer carries a DS request.
- Add 'newsletter' to the onboarding analytics area/step-name enums.
- zh-CN copy: 了解你 / 订阅更新 / 获取最新动态 / 邮箱地址(选填)/ 完成.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* fix(landing): avoid logging subscriber PII when KV binding is missing

The subscribe fallback logged the full record (raw email + referer) to
provider logs whenever NEWSLETTER_SUBSCRIBERS was unbound, turning a
deploy-time misconfiguration into a privacy leak with no operator signal.
Log only non-PII metadata (hashed key, source, country) via console.warn
so the missing binding is loud without exposing the address.

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

* chore(i18n): rename zh-CN onboarding step 3 to 获取最新动态

"订阅更新" read awkwardly as the step label; use 获取最新动态. zh-CN only.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

* refactor(web): drop dead onboarding design-system renderer prop

The newsletter step replaced the step-3 design-system surface in first-run
onboarding, leaving `renderDesignSystemCreation` typed but never destructured
or rendered in OnboardingView. Remove the stale prop through the
App -> EntryView -> EntryShell -> OnboardingView chain and document that
first-run design-system creation is intentionally no longer part of
onboarding (still reachable via the design-system-create route and the
Design Systems tab).

Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code)

* feat: sync newsletter subscribers to Resend

---------

Co-authored-by: qiongyu1999 <2694684348@qq.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-06-05 08:51:29 +00:00

84 lines
1.8 KiB
Plaintext

node_modules/
dist/
out/
.next/
.next-*/
.tmp/
.DS_Store
*.log
/OpenDesign.exe
.vite
.astro/
.wrangler/
.vscode
# Local runtime data — auto-created by the daemon on first start.
# Holds app.sqlite (project metadata), projects/<id>/ (per-project artifacts,
# the agent's CWD), and artifacts/ (one-off renders). Never commit.
.od
.od-e2e
test-results
playwright-report
e2e/.od-data
e2e/playwright-report
e2e/reports/html
e2e/reports/playwright-html-report
e2e/reports/test-results
e2e/reports/results.json
e2e/reports/junit.xml
e2e/reports/latest.md
e2e/ui/.od-data
e2e/ui/reports
e2e/ui/test-results
apps/web/playwright/
# Legacy folder name from before the rename; keep ignored so existing
# clones don't accidentally stage stale runtime data.
.ocd
tsconfig.tsbuildinfo
**/.claude-sessions/*
.cursor/
.agents/
.opencode/
.claude/*
# Exception: od-contribute skill ships with the repo so the OD app can mount it
# for non-coder contributors. Personal Claude state (sessions, settings, etc.) stays ignored.
!.claude/skills/
.claude/skills/*
!.claude/skills/od-contribute/
!.claude/commands/
.claude/commands/*
!.claude/commands/od-contribute.md
.codex/
.deepseek/
.antigravitycli/
# Commander task scratchpad; keep local task notes out of git by default.
.task/
task.md
specs/change/active
.ralph/
docs/superpowers/
# Nix and direnv
.direnv/
.envrc
# Local secrets (PostHog keys, BYOK creds for local testing, etc.)
.env.local
.env.*.local
# Local design assistant context
.impeccable.md
# Landing-page preview thumbnails — regenerated by CI from
# `skills/<slug>/example.html` and `templates/live-artifacts/<slug>/`
# on every deploy. Should not be committed (~70MB of PNGs).
apps/landing-page/public/previews/
# Ad-hoc local e2e scripts and their screenshots
e2e/scripts/test-fal-webui.ts
e2e/scripts/fal-webui-*.png
growth/**