feat(demo-app): demo.sonicjs.com app with auto-reseed#986
Open
lane711 wants to merge 19 commits into
Open
Conversation
New workspace app for the public demo at demo.sonicjs.com. Always runs the latest main and wipes + reseeds its data on every deploy and every 2 hours, so visitors can freely edit content without permanently changing anything. demo-app/: - 4 code-defined collections (blog_post, page, testimonial, faq) plus sample content and SVG media seeded to R2 - demo-login prefill plugin (admin@sonicjs.com / sonicjs!), gated to ENVIRONMENT=demo - demo-seed plugin: POST /__demo/reseed (bearer-token + env gated) and a "0 */2 * * *" cron, both sharing runReseed (full wipe-all -> R2 purge -> seed types/media/content -> re-activate login) - scripts/seed-demo.ts for local reseed via getPlatformProxy - README with operator provisioning + deploy steps CI: .github/workflows/deploy-demo.yml — on push to main, builds core, type-checks, applies D1 migrations, deploys, seeds admin, then reseeds. E2E: tests/e2e/82-demo-seed.spec.ts (DEMO_BASE_URL-gated). Core changes: - routes/auth.ts: the demo-login gate queried a `plugins` table that does not exist on greenfield (always threw -> prefill permanently dead). Repoint at the document-model plugin status (type_id='plugin', data.status='active'). - index.ts: export MediaDocumentService + MediaUploadMeta so the demo seed can upload media through the document model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add demo-app/src/plugins/demo-seed/__tests__/reseed.sqlite.test.ts — real SQLite coverage for runReseed via core's better-sqlite3 D1 shim + an in-memory R2 stub (closes the R10 gap; E2E 82 only covers the live path). Asserts summary counts, published-on-create, q_media_* generated columns, full-reset idempotency (second run wipes visitor edits and rebuilds 1:1), and the exact document row routes/auth.ts gates the demo-login prefill on. The test caught a real bug: ensureTypes seeded the 4 collection document_types with source:'user', which violates the document_types CHECK (source IN 'code','plugin','system'). INSERT OR IGNORE then silently dropped those rows. Masked in production (bootstrap registers the types as 'system' before reseed runs) but broke the fresh-DB fallback (local npm run seed:demo). Fixed to source:'system', matching autoRegisterCollectionDocumentTypes. - demo-app: add vitest devDep + test/test:watch scripts; exclude test files from the app tsc program (they are @ts-nocheck and run by vitest, and import core's shim from outside rootDir) - CI: run npm test --workspace=demo-app before deploy in deploy-demo.yml Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Provision sonicjs-demo D1 (dc87c94a), KV (91de57b1), R2 (sonicjs-demo-media) and deploy to Cloudflare Workers. demo.sonicjs.com custom domain registered; workers.dev live. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without this Better Auth derived base URL from the request, which caused session cookies to be scoped incorrectly on demo.sonicjs.com. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…BAC reseed
- Activate mediaPlugin by default in demo-app
- Export renderLoginPage + LoginPageData from @sonicjs-cms/core
- Short-circuit GET/HEAD /auth/login (no query) with a module-init pre-rendered
constant (LOGIN_HTML) — bypasses entire Hono stack (bootstrap D1 queries,
Better Auth session lookup, demo-login D1 query). Cold load: 10s → 0.12s.
Edge-cached via Cache-Control: public, s-maxage=600; version-scoped key
(_v=SONICJS_VERSION) auto-busts on deploy. Security: never caches
app.fetch response — would replay session cookies cross-user.
- Add Bootstrap KV fast-path: _bootstrap:v{SONICJS_VERSION} in CACHE_KV;
subsequent cold starts do 1 KV read instead of 8+ serial D1 queries.
- Add Smart Placement (wrangler.toml) to co-locate Worker with D1.
- Add 28 BLOG_HERO_IMAGES to seed/assets/images.ts; register as media_asset
documents on every reseed (R2 objects survive reseed under blog/ prefix).
- Add RBAC user role assignments to reseed step 7 so admin/editor can access
portal after 2h data reset (requireRbac reads rbac_user_roles docs, not
auth_user.role).
- Add E2E spec 95-login-page-cache.spec.ts pinning no-Set-Cookie, public-
cacheable, dynamic-fallthrough, and POST end-to-end invariants.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add "Upload blog hero images to R2" step between Worker deploy and health-check. Loops over www/public/images/blog/*/hero.png and puts each under blog/<slug>/hero.png in sonicjs-demo-media. Idempotent — re-uploads keep bucket in sync when images change. Runs before reseed so mediaSvc.createFromUpload finds objects already in R2. Also: add www/public/images/blog/** to path filter (image changes trigger redeploy), bump timeout to 25 min for 28 uploads. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without --remote, wrangler targets the local R2 emulator instead of the production bucket. CI runners have no local wrangler dev server, so this would silently succeed locally but fail in CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…strap Without defaultActive:true the plugin manifest-registry entry wasn't picked up by PluginBootstrapService, so no plugins DB row was created and the admin UI showed Media Manager as uninstalled even though mediaPlugin was wired in demoPlugins. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
demo-app was added as a workspace but package-lock.json was not regenerated, causing `npm ci` to fail in CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The lock file at HEAD was generated with npm 11 (Node 24) and had an exact pin `"better-sqlite3": "12.11.1"` in the packages/core section, but packages/core/package.json has the range `^12.10.0`. This inconsistency caused npm ci (Node 22 / npm 10) to report `Missing: better-sqlite3@12.11.1 from lock file`. Regenerated with `npm install --package-lock-only` on Node 22 / npm 10 (same as CI). packages/core section now has `"^12.10.0"` (range), matching the pattern on main that passes CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
npm install --package-lock-only on macOS only includes darwin-arm64 rollup binary. CI (Ubuntu x64) needs @rollup/rollup-linux-x64-gnu. Copied all 24 missing platform entries from main's lock file (same rollup@4.62.2 version). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…behavior Three issues fixed: 1. admin-content-docbacked + api-content-crud: tests expected COUNT=2 after publish, but versioning=false causes publish() to delete the old published row (pure-history purge at documents.ts:336-345). Correct assertion is 1. 2. media_asset showing in content dropdowns: duplicate registration in document-types-seed.ts overwrote the first entry's internal:true flag. Removed duplicate; merged public:read and publish grant into the canonical first registration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…post - Add versioning: true to blog_post document type so publish() preserves old versions instead of deleting them (matches main's 6b96827) - Revert toBe(1) → toBe(2) in admin-content-docbacked and api-content-crud integration tests to match versioning=true behavior - Quarantine 6 email-plugin hook/route tests written for a different API design (matches main's 6b96827 quarantine) - Fix email-service-singleton import path in 5 email plugin test files: services/email-service-singleton → services/email/email-service-singleton (matches main's 76ffca2) All 111 test files now pass (7 skipped via quarantine). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolve conflicts: - package-lock.json: take main (CI now uses npm install, not npm ci) - migrations-bundle.ts: regenerated after taking main's version - manifest-registry.ts: keep branch timestamp (newer) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ions admin-layout-catalyst: Users/Plugins/Settings are now admin-only (b5383b9). Tests using baseData (no user) no longer render them. Add adminData fixture with role=admin for tests that assert on admin-only menu items. admin-users-profile: PUT /admin/users/:id now calls RbacService.getRoles() for dynamic role validation (f8310b2). Add the getRoles mock response at call 0 and update prepare-call count assertion from 2 → 3. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both branches fixed the same test (admin-only menu items need admin user). Kept main's inline approach, removed redundant adminData fixture. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both branches fixed the same RbacService.getRoles() prepare-call count.
Kept main's comment wording ("Only 3 prepare calls").
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shallow clones (fetch-depth:1) have no HEAD~1. The pull_request_target branch already fell back to HEAD~1 but without || echo "", causing exit 128 when that also fails. Add 2>/dev/null || echo "" guard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
New workspace app for the public demo at demo.sonicjs.com. Always runs the latest
mainand wipes + reseeds its data on every deploy and every 2 hours, so visitors can freely edit content, upload media, and explore the admin without permanently changing anything.What's included
blog_post,page,testimonial,faq— plus sample content and SVG media assets seeded to R2.admin@sonicjs.com/sonicjs!via thedemo-loginplugin, hard-gated toENVIRONMENT=demo.demo-seedplugin exposesPOST /__demo/reseed(bearer-token + env gated) and a0 */2 * * *cron, both sharing onerunReseed(full wipe-all → R2 purge → seed types/media/content → re-activate login)..github/workflows/deploy-demo.yml: on push tomain, build core → type-check → reseed integration test → migrate → deploy → seed admin → reseed.npm run seed:demo(getPlatformProxy →runReseed).Tests
demo-app/src/plugins/demo-seed/__tests__/reseed.sqlite.test.ts— better-sqlite3 D1 shim + in-memory R2 stub; asserts summary counts, published-on-create,q_media_*generated columns, full-reset idempotency, and the exactroutes/auth.tsdemo-login gate query. Runs in CI before deploy.tests/e2e/82-demo-seed.spec.ts— credential prefill, seeded public API, reseed-endpoint auth (skipped unlessDEMO_BASE_URLis set).This integration test caught a real bug:
ensureTypesseeded the 4 collectiondocument_typeswithsource:'user', which violates thedocument_typesCHECK (code|plugin|system) —INSERT OR IGNOREsilently dropped the rows. Masked in production (bootstrap registers the types first) but broke the fresh-DB fallback. Fixed tosource:'system'.Core changes (outside demo-app)
routes/auth.ts— the demo-login gate queried apluginstable that doesn't exist on greenfield (always threw → prefill permanently dead). Repointed at the document-model plugin status (type_id='plugin',data.status='active').index.ts— exportMediaDocumentService+MediaUploadMetaso the demo seed can upload media through the document model.Before first deploy (operator)
Fill
REPLACE_WITH_*D1/KV ids indemo-app/wrangler.toml;wrangler secret put BETTER_AUTH_SECRET DEMO_SEED_TOKEN; addCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID/DEMO_SEED_TOKENto GitHub Actions secrets. Steps indemo-app/README.md.🤖 Generated with Claude Code