Skip to content

feat(web): seed the landing demo workspace for first-time /app?demo=1 visitors (0384) - #609

Merged
crs48 merged 2 commits into
mainfrom
claude/nostalgic-morse-acc684
Jul 21, 2026
Merged

feat(web): seed the landing demo workspace for first-time /app?demo=1 visitors (0384)#609
crs48 merged 2 commits into
mainfrom
claude/nostalgic-morse-acc684

Conversation

@crs48

@crs48 crs48 commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

Exploration 0384 made Try the app — free, no account the landing page's single primary CTA — but it dropped first-time visitors into an empty workspace. This wires the curated LANDING_SEED_PROFILE into apps/web so a visitor arriving from the landing CTA opens a lived-in demo workspace instead.

How it works

  • The site's try-style CTAs (Hero, TheApp, GetStarted) now link to /app?demo=1. The hero's generic Use the app door stays plain /app, preserving a blank-workspace entry.
  • use-boot-sequence captures the demo param at boot (before the router sees the URL), persists the intent to sessionStorage — so it survives a mid-onboarding reload — and strips the param, mirroring the hub-session.ts pattern.
  • Once authenticated, <DemoSeed /> (inside XNetProvider, next to BundledPluginInstaller) runs maybeRunDemoSeed, which dynamic-imports the seed and runs runSeed({ store, ...LANDING_SEED_PROFILE }) against the app's own store/worker.

Fresh-profile guard

The seed runs only on an explicit demo signal and a profile with no user content: it counts nodes via the storage adapter, discounting infrastructure schemas (SEED_EXCLUDED_SCHEMA_IDS + PluginSchema — every fresh profile gets bundled-plugin install records before the seed can run). One node in any other schema vetoes the seed, so a returning user who follows a shared /app?demo=1 link is never touched. The pending flag is consumed on either outcome; a thrown seed error leaves it set so a reload retries (the seed is idempotent).

Plumbing

  • @xnetjs/devtools gains a ./seed subpath export — the root barrel is a prod stub (devtools are compiled out of production), and the seed chunk is dynamic-imported only on demo entry so the main bundle doesn't grow. devtools is changeset-ignored, so no changeset.
  • Root vitest.config.ts gets the matching subpath alias before the bare devtools alias (same precedent as @xnetjs/data/database).

Testing

  • New apps/web/src/boot/demo-seed.test.ts (7 tests): signal capture/strip for both search and hash-routed URLs, seed-once semantics, the existing-user-content veto, and infrastructure-only profiles still counting as fresh.
  • devtools seed suite (27), LinkifiedText/linkify (30), and views property tests (6) all green.
  • Live verified (vite 5199 + Playwright): /app?demo=1 → onboarding → workspace auto-populates ([demo-seed] populated the landing demo workspace, pages/databases/chats/CRM all present), and the seeded Tasks Tracker database view renders its 6 rows with zero console errors — the str.replace-on-non-string crash from the formula/rollup cells is confirmed fixed on this branch (LinkifiedText/linkify guards + views/properties/text coercion, fix(views): don't crash database views on formula/rollup cell values #460).

🤖 Generated with Claude Code

@crs48
crs48 temporarily deployed to pr-609 July 20, 2026 23:59 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

✓ Changelog fragment found — thanks!

xNet Test and others added 2 commits July 20, 2026 17:01
… visitors (0384)

The landing page's 'Try the app' CTAs now link to /app?demo=1. Boot
captures the signal into sessionStorage (stripping the param), and once
the store is ready <DemoSeed /> runs the curated LANDING_SEED_PROFILE —
but only for a fresh profile: any node outside the infrastructure set
(seed-excluded system schemas + bundled-plugin install records) vetoes
the seed, so a returning user's workspace is never auto-seeded.

- @xnetjs/devtools gains a ./seed subpath export (the root barrel is a
  prod stub, and the seed chunk is dynamic-imported only on demo entry)
- vitest root config gets the matching subpath alias (before the bare
  devtools alias, per the @xnetjs/data/database precedent)
- fresh-profile guard covered by apps/web/src/boot/demo-seed.test.ts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 force-pushed the claude/nostalgic-morse-acc684 branch from efe6889 to eddc488 Compare July 21, 2026 00:01
@crs48
crs48 temporarily deployed to pr-609 July 21, 2026 00:01 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Jul 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

No visual differences detected in the changed UI.

CI run

github-actions Bot added a commit that referenced this pull request Jul 21, 2026
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #609.

github-actions Bot added a commit that referenced this pull request Jul 21, 2026
@crs48
crs48 merged commit 1a02ee4 into main Jul 21, 2026
21 of 24 checks passed
@crs48
crs48 deleted the claude/nostalgic-morse-acc684 branch July 21, 2026 00:25
github-actions Bot added a commit that referenced this pull request Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant