Skip to content

feat(v1.7b): static pages + navigation manager + legal seeder (closes #32)#39

Merged
thunpisit merged 1 commit into
mainfrom
feat/v1.7b-pages-nav
Apr 30, 2026
Merged

feat(v1.7b): static pages + navigation manager + legal seeder (closes #32)#39
thunpisit merged 1 commit into
mainfrom
feat/v1.7b-pages-nav

Conversation

@thunpisit

Copy link
Copy Markdown
Contributor

Summary

Closes #32. v1.7b — second half of the IA milestone. With v1.7a (media folders + reusable blocks + cookie consent + legal templates) merged earlier, this completes v1.7.

Pages

  • New `pages` + `page_localizations` tables (schema landed in v1.7a's migration 0005, sit empty until now).
  • Public catch-all `(www)/[locale]/[...slug]` — SvelteKit prefers more-specific routes, so `/[locale]/blog` and `/[locale]/blog/[slug]` win; the catch-all only fires for static pages.
  • Three soft templates (`default` / `landing` / `legal`) swap the public wrapper.
  • Reuses v1.6 `` (canonical + hreflang + OG + Twitter Card) and v1.7a `expandBlocks` so `{{block:cta-newsletter}}` works inside pages too.
  • CMS: `/cms/pages` (list), `/cms/pages/new`, `/cms/pages/[id]` (edit). Shared `PageForm.svelte` modeled on `ArticleForm`.
  • Sitemap now lists pages alongside articles in each per-locale sitemap.

Navigation manager

  • `ContentProvider` gains menu + item CRUD.
  • `/cms/navigation` auto-bootstraps two stock menus (`primary`, `footer`) on first load. Per-locale labels stored as JSON. Items target an article / category / tag / page / custom URL. Position-based ordering with up/down buttons.
  • `loadNavigation()` pre-fetches menus + slug lookup tables; `navItemHref()` resolves each item to a final URL with O(1) lookups.
  • (www) layout server load surfaces `data.nav.{primary,footer}` as render-ready arrays. Header iterates primary; footer iterates footer.

Legal seeder

  • `seedLegalPages(content, authorId)` embeds Privacy + Cookie policy markdown, prefills `[Site Name]` from `site_settings`, creates draft Pages with the `legal` template. Idempotent (skips existing slugs).
  • "Seed legal templates" button on the empty state of `/cms/pages`.
  • New pages always start as drafts. Operator must review before publishing.

Sidebar

Two new entries (editor+ gated): Pages, Navigation.

i18n

23 new keys (EN + TH).

Test plan

  • `pnpm build` succeeds
  • `paraglide-js compile` succeeds
  • `svelte-check` clean (only pre-existing paraglide-server noise)
  • After deploy: `/cms/pages` is empty → click "Seed legal templates" → 2 draft pages appear
  • Edit one of them, mark published, save → visit `/{locale}/privacy-policy` → renders with the `legal` wrapper, full SEO meta
  • `/cms/navigation` shows two stock tabs (primary, footer) with no items → add a custom URL item → see it appear in the public header
  • Insert `{{block:hello}}` into a page body (after creating a block called `hello` in /cms/blocks) → page renders the block content
  • `curl /sitemap-en.xml` includes the new published page

🤖 Generated with Claude Code

…32)

Second half of v1.7. With v1.7a (media folders + reusable blocks +
cookie consent + legal templates) merged earlier, this completes the
v1.7 milestone.

Pages
-----
- ContentProvider: getPage / getPageBySlug / listPages / createPage /
  updatePage / deletePage. Soft scheduled-publishing semantics
  identical to articles (status='published' AND publishedAt <= now).
- Public: (www)/[locale]/[...slug] catch-all. SvelteKit prefers the
  more-specific /[locale]/blog and /[locale]/blog/[slug] routes so
  the catch-all only triggers for static pages. Three soft templates
  (default, landing, legal) swap the public wrapper.
- Reuses v1.6 <Seo> + v1.7a expandBlocks, so canonical + hreflang +
  Open Graph + Article-style JSON-LD all just work, and {{block:key}}
  shortcodes expand inside pages too.
- CMS: /cms/pages (list), /cms/pages/new, /cms/pages/[id] (edit).
  Shared PageForm.svelte modeled on ArticleForm.
- Sitemap: per-locale sitemap now lists pages in addition to
  articles, with hreflang siblings only for locales with real content.

Navigation manager
------------------
- ContentProvider: listMenus / getMenuByKey / createMenu / deleteMenu
  / createNavigationItem / updateNavigationItem /
  deleteNavigationItem / reorderNavigationItems.
- /cms/navigation auto-bootstraps two stock menus (primary, footer)
  on first load. Per-locale labels stored as JSON. Items target one
  of article / category / tag / page / custom URL. Position-based
  ordering with up/down buttons (true drag-drop trees deferred).
- $lib/server/content/navigation.ts: loadNavigation() pre-fetches
  the menus + the slug lookup tables in one pass; navItemHref()
  resolves each item to a final URL with O(1) lookups.
- (www) layout server load consumes loadNavigation() and surfaces
  data.nav.{primary,footer} as render-ready arrays. Header iterates
  primary; footer iterates footer.

Legal seeder
------------
- $lib/server/content/legal-seed.ts: seedLegalPages(content,
  authorId) embeds the privacy + cookie policy templates, prefills
  [Site Name] from site_settings, and creates draft Pages with the
  'legal' template. Idempotent: skips slugs that already exist.
- /cms/pages empty state shows a "Seed legal templates" button that
  invokes the seeder. New pages start as drafts (never auto-publish)
  with explicit "review before publishing" copy on the success
  banner.

Sidebar
-------
- Two new entries: Pages and Navigation, both gated to editor+.

i18n: 23 new keys (EN + TH). cms_pages_*, cms_navigation_*,
cms_pages_seed_legal, cms_pages_seeded.

Closes #32 (full v1.7 — both halves merged).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@thunpisit thunpisit merged commit d653e42 into main Apr 30, 2026
1 check passed
@thunpisit thunpisit deleted the feat/v1.7b-pages-nav branch April 30, 2026 00:42
thunpisit added a commit to codustry/khaopad-example that referenced this pull request Apr 30, 2026
…am PR codustry#39) (#6)

Cherry-picks upstream PR codustry#39 (closes codustry#32). v1.7 schema (migration
0005) was already applied to live D1 in v1.7a.

i18n: 23 new keys field-merged into messages/en.json + th.json
(example-specific copy preserved).

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.

v1.7 — Pages, navigation, and asset organization

1 participant