feat(menu-plugin): data-driven admin sidebar navigation#940
Open
lane711 wants to merge 155 commits into
Open
Conversation
feat: merge v3 document model architecture into main
- hono: ^4.12.18 → ^4.12.26 (security fixes in 4.12.25: CORS, body-limit, serve-static path traversal, AWS Lambda Set-Cookie, Lambda@Edge header) - vitest: ^4.0.5 → ^4.1.9 (root, packages/core) - @vitest/coverage-v8: ^4.0.5 → ^4.1.9 (root, packages/core) - my-sonicjs-app vitest: ^2.1.8 → ^4.1.9 (align with root) - postcss: 8.5.6 → 8.5.15 (transitive, lockfile) - qs: 6.15.0 → 6.15.2 (transitive, lockfile) - shell-quote: 1.8.3 → 1.8.4 (transitive, lockfile) Closes PRs: #918, #862, #851, #849, #843, #840, #839, #837 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
page_blocks was registered in the sample app but has no place in a base install. Replaced with e2e_test collection that covers all field types (string, slug, textarea, number, boolean, date, datetime, user, media, select, radio, lexical, object/flat, array/blocks) so E2E specs have a stable test fixture without polluting the starter experience. Updated 10 E2E specs to reference e2e_test / E2E Test instead of page_blocks / Page Blocks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…with-e2e-test-collection refactor: replace page_blocks with e2e_test collection
…onsolidate chore(deps): consolidate all dependabot dependency updates
…o-resolve-error fix(create-app): bump compatibility_date to fix crypto import error on npm run dev
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uncement docs(marketing): v3 beta Discord announcement and blog post
…mp, simplify post-install output (#925) - Remove prompt for example blog collection; always include it - Fix admin seed crash: Date.now() → new Date() for Drizzle timestamp_ms columns - Move Cloudflare resource creation to optional "Deploy to Cloudflare" section; only show migration/seed steps when they actually failed
…r local dev - Rewrite generated seed-admin.ts to use raw SQL (bypass Drizzle schema mismatch with auth_user columns missing from migration) - Create auth_account record so Better Auth credential login works - Use PBKDF2 via Web Crypto for password hashing (matches auth system) - Auto-generate .dev.vars with BETTER_AUTH_SECRET on project creation (missing secret caused 500 on every auth request) - Add --admin-email / --admin-password flags for non-interactive use - Replace wrangler resource commands in success output with npm run deploy
Per-developer Claude Code settings should not be shared. settings.local.json contained machine-specific rules and shared auto-approve allowlists. Untrack it so each dev keeps their own local copy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move v3.0.0-beta.3 entry from under "Version 2.x" into "Version 3.x" - Add "Version 3.x" section to changelog sidebar nav - Fix JWT default lifetime: 24h → 30d (matches DEFAULT_JWT_EXPIRES_IN_SECONDS) - Fix stale comment labeling v3.0.0-beta.3 entry as v2.19.0 on homepage
… by default (#927) - Switch blog_post content field from quill to lexical - Update blog_post schema: name, slug, author type (user), remove stale fields - Set core-cache defaultActive to false (only lexical should be on by default) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Resource creation runs before npm install, so wrangler isn't in node_modules/.bin/ yet. Users running via npx also won't have a global wrangler binary. Fall back to `npx wrangler` in both cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add deploy-stats.yml CI workflow (triggers on packages/stats/** or packages/core/src/** changes to main + workflow_dispatch) - Build core, type-check, then wrangler deploy --env production - Add deploy:production script to packages/stats - Add deploy:stats convenience script to root package.json - Update wrangler compatibility_date to 2025-05-05 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- rehype.mjs: guard parentNode.properties before set — mdxJsxFlowElement nodes (inline code in JSX <li>/<span>) have no properties object, causing "Cannot set properties of undefined (setting 'language')" - blog/[slug]/page.tsx: pass Callout to compileMDX components map — blog posts using <Callout> crashed with "Expected component Callout to be defined"
…934) * fix(www): resolve build errors blocking deploy - rehype.mjs: guard parentNode.properties before set — mdxJsxFlowElement nodes (inline code in JSX <li>/<span>) have no properties object, causing "Cannot set properties of undefined (setting 'language')" - blog/[slug]/page.tsx: pass Callout to compileMDX components map — blog posts using <Callout> crashed with "Expected component Callout to be defined" * chore(www): upgrade next and opennextjs-cloudflare for Next 16 compat next: 16.2.1 → 16.2.9 @opennextjs/cloudflare: 1.18.0 → 1.19.11 1.18.0 couldn't bundle next-server.js with Next 16 (missing shims for node-environment, node-polyfill-crypto, etc). 1.19.11 adds Next 16 support and requires next >= 16.2.3.
- plugins/page.mdx: add Example Plugin under Core Plugins section - plugins/development/page.mdx: callout + reference section for example plugin - blog: building-your-first-sonicjs-plugin tutorial covering all extension points Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /plugins/example page: full reference covering file structure, two-phase boot, /example/* routing rationale, factory pattern, configSchema settings, moods collection, hooks, data seeding, customization, and removal - plugins/core/page.mdx: Example Plugin section in feature grid, sections array, and body with key patterns table + removal snippet Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- plugins/page.mdx: add buttons → /plugins/example + blog post - plugins/development/page.mdx: add buttons → /plugins/example + blog post - blog post: replace plain /plugins/development link with /plugins/example first Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…/blog/... Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: plugin wirePlugins() has no bootstrapComplete guard, so a static-asset request (favicon, etc.) can fire onBoot before bootstrapMiddleware has run autoRegisterCollectionDocumentTypes. D1 local enforces the FK on documents.type_id — the seed INSERT fails with SQLITE_CONSTRAINT_FOREIGNKEY, gets swallowed by the catch, and the once-guard means it never retries. Fix: INSERT OR IGNORE the example document_type row inside the seed try-block before the COUNT check. Idempotent when the row already exists; races bootstrap safely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings tab now defaults as active when a plugin has user-configurable settings. Info and Activity follow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removing a field from configSchema had no effect on stored settings — the field persisted in the DB blob and kept appearing in the admin UI. Two fixes: 1. POST /admin/plugins/:id/configure: replace the naive spread-merge with schema-aware merge that only carries forward non-schema keys (internal `_`-prefixed keys like `_routes`) from existing settings. Schema-removed fields are pruned on next save. 2. GET /admin/plugins/:id (legacy settings page): filter `enrichedSettings` to schema-defined + `_`-prefixed keys before passing to the template, so stale stored keys never render in the UI. Fixes: #972 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
onBoot populated pluginOptions once at isolate warm-up; admin UI saves
updated settings to DB but the in-memory cache was never refreshed, so
GET /example always returned the stale boot-time values.
Fix: read greeting/defaultName from DB per-request via PluginService.getPlugin
in a getPluginSettings() helper, parallel with getRandomMood. The stale
options param is removed from createExampleApiRoutes.
Also fixes greeting being declared in configSchema but never used in the
response (was hardcoded). Now uses ${settings.greeting}.
Applies to both my-sonicjs-app and packages/create-app starter template.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Reflects the settings-not-saved bug fix shipped in #975. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rom GitHub Scaffolded plugin files are ejected copies — npm install updates @sonicjs-cms/core but leaves plugin source untouched. This script fetches the latest files from the canonical starter template on GitHub main and overwrites the local copies. Usage: npm run update:plugin # update example plugin npm run update:plugin -- example # explicit npm run update:plugin -- example --dry-run Ships in both my-sonicjs-app and packages/create-app starter template so new projects get the script at scaffold time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n pages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er (#976) - Search bar filters all columns including JSON data fields via LIKE - Search term persists across pagination, sort, and page-size changes - JSON/long text cells render as clickable links opening a modal viewer - Modal shows syntax-highlighted pretty-printed JSON with copy button - Closes on backdrop click, close button, or Escape key - E2E spec 91 covers search input, URL params, clear, modal open/close Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- MediaDocumentService.list() now runs a parallel COUNT(*) with the same WHERE filters and returns `total` in MediaListResult - Admin media route uses `total` for totalFiles and fixes hasNextPage (was capped at page size 24 instead of real library total) - Media selector search input: add missing `name="search"` attr so the typed term is actually sent with the HTMX request - Add hx-swap="outerHTML" + hx-select="#media-selector-grid" to prevent the full panel (search box + grid) from nesting inside the grid on each keystroke Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Conflicts: - wrangler.toml: kept branch DB config - admin-plugin-settings.template.ts: merged hasUserSettings/defaultTab from main with settingsTabContent support from branch Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
core-menuplugin — registersmenu_itemdocument type (no new tables), seeds 4 system nav items (Content, Collections, Users, Settings) idempotently on boot, and reconciles plugin-declared menu entries from bothdefinePlugin({ menu: [...] })andmanifest.jsonadminMenufields<!-- ADMIN_SIDEBAR_NAV_ITEMS -->marker) — hardcoded items remain as fallback when DB unavailable/admin/menuadmin UI for CRUD, visibility toggle, and drag-free move-up/down reordering; locked fields prevent admins from breaking system/plugin itemsArchitecture
env.DB.prepare().bind()/db.batch()— no Drizzle (R1)tenant_id = 'default'throughout (R3)q_*generated columns:q_menu_parent,q_menu_visible,q_menu_source,q_menu_plugin_idmenu-icons.tsconsolidates 30 heroicons used across admin sidebarTest plan
npx vitest run src/__tests__/services/menu-repository.sqlite.test.ts→ 7/7 pass (real-SQLite)npx tsc --noEmit→ 0 errorsbetter-authmodule warnings only)82-menu-management.spec.ts— run withnpm run setup:db && npm run devthennpx playwright test tests/e2e/82-menu-management.spec.ts🤖 Generated with Claude Code