docs(16): capture phase context

This commit is contained in:
Jakub Zych
2026-10-07 19:53:58 +02:00
parent 40a2a6584c
commit ece31c3426
4 changed files with 236 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
# Phase 16: grzybyfunkcjonalne.pl on reusable blog views - Context
**Gathered:** 2026-10-07
**Status:** Ready for planning
<domain>
## Phase Boundary
grzybyfunkcjonalne.pl gets a new Nuxt frontend built the same way as `vue-summercmsio-app`. Its styling is based on the current arsha theme but refreshed. It reads Journal content from the Phase 15 `/_journal/api/v1`, and the Go binary (`sm-grzybyfunkcjonalne-app`) stays headless. The blog views (Journal pages, components and API client) live in a reusable Nuxt layer, so a later blog (golem15.com, a summercms.io blog) can mount them with its own content and styling.
The phase ends with the site **deploy-ready on staging** on the same server as the PHP site. The production nginx/DNS switch is a separate operational step after the phase.
Out of scope: porting the Winter arsha/Twig theme or a Go server-side template engine; the menu, FAQ, sitemanager, blocks and sitemap plugin ports; the contact and newsletter forms; an English locale; changes to `sm-journal-plugin`'s API contract (Phase 15 D-14). `summercms.go` is touched only if a framework feature turns out to be missing.
</domain>
<decisions>
## Implementation Decisions
### Rendering approach (user-stated before discussion)
- **D-01:** Build a new Nuxt theme following summercms standards (the `vue-summercmsio-app` setup: Nuxt 4, `@nuxtjs/i18n`, `@nuxtjs/seo`, `@nuxt/fonts`, pnpm, node `--test`). The styling is based on grzybyfunkcjonalne but refreshed, not a pixel copy of arsha/Bootstrap. Go stays headless. No Go `html/template` theme layer and no Twig port. — **Reversibility:** costly — every public page is a Nuxt page that consumes the Journal JSON API.
### Reuse shape
- **D-02:** The reusable blog views are a **Nuxt layer** in a new repo `vue-journal-layer` (`git.golem15.com/golem15/vue-journal-layer`). Site apps consume it with `extends`. — **Reversibility:** costly — later blogs build on the layer's structure.
- **D-03:** The layer ships a **neutral base design driven by CSS custom-property tokens** (colors, fonts, spacing, radii). It looks clean on its own. Site apps override the tokens and can override any layer component. The refreshed grzyby design lives in the site app, not in the layer.
- **D-04:** Distribution is a **pnpm git dependency** with a pinned tag: `git+https://git.golem15.com/golem15/vue-journal-layer.git#<tag>`, with the commit locked in `pnpm-lock.yaml`. There is no npm registry and no submodule for the layer. (`git.golem15.com` is Gitea 1.25.4, and a public repo needs no auth.) Local development uses `pnpm link` or a `link:../vue-journal-layer` override. A release is a git tag.
- **D-05:** The layer owns these Journal views and their data access: post list with pagination (successor of `journalPosts`, with sort and page size configurable), single post (successor of `journalPost`: rendered markdown, featured image, meta, related/random posts like `randomPosts`), category and tag listings, the author page (successor of `journalAuthor`), and the RSS feed link. It also owns a typed client for `/_journal/api/v1` (anonymous GET routes only).
- **D-06:** Route paths in the layer must be configurable or overridable by the app, because grzyby uses specific PHP URLs (D-15) that another blog may not want.
### Render & deploy
- **D-07:** **SSR**: `nuxt build` runs as a Node server, with `routeRules` swr/ISR caching so a newly published post shows up without a rebuild and pages stay full HTML for SEO. Unlike summercms.io (`nuxt generate` embedded in the binary), this site runs two processes: the Go binary and the Nuxt Node server. — **Reversibility:** costly — deploy scripts, supervisor and nginx topology depend on it.
- **D-08:** The Nuxt app is a new repo `vue-grzybyfunkcjonalne-app`, mounted as a **submodule in `sm-grzybyfunkcjonalne-app`**, the same way `vue-summercmsio-app` is mounted in `sm-summercmsio-app`.
- **D-09:** The admin is exposed on the site domain at **`/gfadmin`** (set with `backend.uri: /gfadmin` in the host config; cabana supports this without a framework change). nginx routes `/gfadmin` and `/_journal` (plus media/storage paths) to Go and everything else to Nuxt. PHP used `/backend`; the new path is intentional.
- **D-10:** Deploy target is the **same server as the PHP site**. Staging runs next to the live Winter install. The later cutover switches nginx, and the Winter install stays as the rollback.
### Non-Journal content
- **D-11:** The homepage marketing content (hero, about, why-us, CTA and the other sitemanager blocks, `content/blocks/*`, `content/homepage`, `content/blog` headers, the kontakt page content) moves **into the Nuxt app repo** as components plus i18n/markdown, with the current Polish copy carried over. The sitemanager `enable_*` toggles are dropped, and the design decides which sections stay. No sitemanager or blocks plugin port.
- **D-12:** The main menu (`g15_menu`) becomes typed config in the app, and the FAQ (`g15_faq` slug `what-mushrooms-can-give-you`) becomes static i18n/markdown content in the app. Both get proper plugins later; todos `menu-plugin-port.md` and `faq-plugin-port.md` were added.
- **D-13:** SEO and sitemap use **`@nuxtjs/seo` in the layer**: per-post meta, OG tags, canonical, robots (honor the per-page `robots_noindex` equivalents), and `sitemap.xml` generated from `/_journal/api/v1` plus the app's static pages. This replaces `eagle_seo` and `Golem15.Sitemap` for this site. `sm-sitemap-plugin` stays on the backlog.
- **D-14:** The contact and newsletter forms are **dropped**. The kontakt page shows contact details and an email link only, and the newsletter stays in backlog 999.1. No new Go endpoints.
### URLs, i18n, migration, cutover
- **D-15:** **The PHP public URLs stay identical**: `/`, `/blog` (with pagination), `/blog/:post`, `/autor/:author`, `/kontakt`, `/:category` (root-level catch-all, where known static routes take precedence), plus `/404` and `/error` behavior. Research must enumerate the real live URLs (including the pagination query/segment form and `trwaja-prace`) so none are lost. — **Reversibility:** one-way — search-indexed URLs; changing them later needs a 301 map.
- **D-16:** **Polish only, i18n-ready**: `@nuxtjs/i18n` is wired in the layer and the app, the layer ships pl and en UI strings, and the site serves `pl` without a URL prefix. A later blog can enable more locales.
- **D-17:** Content migration uses the Phase 15 **`journal:import-posts`** command fed by a PHP Journal export (the PHP repo already has `journal-export/*.json`), plus copying featured images and media into Go storage. Research must check that the export format matches the importer, and that slugs, authors, categories, tags, published dates and media references survive; it must flag gaps rather than patch over them.
- **D-18:** **The phase stops at staging.** grzybyfunkcjonalne content runs end to end on staging (Go + Nuxt + imported posts) on the PHP site's server, with a smoke check that hits every old URL. The production switch is not a plan in this phase. Success criterion 1 counts as met once the site is served by SummerCMS on staging.
### Claude's Discretion
- Plan count and split, subject to the plan-count checkpoint and "unit tests are the last plan" (the layer gets Vitest or `node --test` tests, and app-local Go code gets Go tests).
- How the layer exposes route configuration (`app.config`, runtime config or pages override) and token names.
- How markdown renders on the Nuxt side (render server-side from the API's markdown or HTML field, whichever the Phase 15 API returns), with sanitization consistent with Journal's XSS rules.
- Exact swr/ISR TTLs, supervisor/nginx config and scripts layout, modeled on `sm-summercmsio-app/deploy` and `scripts/`.
- Whether the refreshed visual direction gets a `/gsd-ui-phase` UI-SPEC before planning (recommended, not required).
- Run the security-review agent only if new Go endpoints or auth surface appear. None are planned.
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Roadmap and prior decisions
- `.planning/ROADMAP.md` § Phase 16 — goal, repos, success criteria
- `.planning/phases/15-journal-plugin/15-CONTEXT.md` — Journal API contract (D-14), host app layout (D-18–D-23), what Phase 16 inherits
- `.planning/phases/15-journal-plugin/15-VERIFICATION.md`, `15-UAT.md` — what actually shipped in Phase 15
- `.planning/notes/core-plugins-own-repos.md` — repo naming and submodule mount pattern
- `.planning/todos/pending/menu-plugin-port.md`, `faq-plugin-port.md` — follow-ups created by D-12
- `.planning/todos/pending/sitemap-plugin-port.md` — stays deferred (D-13)
### Journal API (consumed by the layer)
- `../sm-journal-plugin/` — the Go plugin: routes and README for `/_journal/api/v1`
- `/media/nvme/dev/golem15/fonoteka/plugins/golem15/journal/API.md` — request/response contract (frozen SHA `02110eb`)
### SummerCMS Nuxt standards (pattern to copy)
- `../sm-summercmsio-app/README.md` — host + Nuxt submodule layout, build and deploy scripts
- `../sm-summercmsio-app/vue-summercmsio-app/` — Nuxt 4 setup: `nuxt.config.ts`, i18n, seo, fonts, tests
- `../sm-summercmsio-app/deploy/`, `scripts/` — nginx/supervisor/smoke precedents (adapt for SSR, D-07)
### Host application
- `../sm-grzybyfunkcjonalne-app/` — `summer.yaml`, `config/`, `go.work`, plugins `golem15.{user,translate,journal}`
- `modules/cabana/README.md` § Configuration — `backend.uri` (D-09)
### Legacy PHP site (styling, content and URL source, read-only)
- `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/themes/arsha/pages/` — page URLs and component settings (D-15)
- `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/themes/arsha/layouts/default.htm`, `partials/`, `assets/` — visual baseline for the refresh
- `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/themes/arsha/content/`, `config/fields.yaml`, `lang/pl/` — homepage, blocks and kontakt copy (D-11)
- `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/plugins/golem15/faq`, `plugins/golem15/menu` — FAQ and menu data to inline (D-12)
- `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/journal-export/` — existing post export (D-17)
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- `vue-summercmsio-app`: a working Nuxt 4 + `@nuxtjs/i18n` 10 + `@nuxtjs/seo` 5 + `@nuxt/fonts` config and `node --test` setup to copy for the layer and the app.
- `sm-summercmsio-app` scripts: `build.sh`, `smoke.sh`, `check-deploy.sh` and `deploy/` (nginx, supervisor, `.env` template). Adapt them from static/embedded to SSR plus a Go upstream.
- `sm-journal-plugin` `/_journal/api/v1`: posts, `posts/{slug}`, categories, tags and rss. The layer's only data source.
- `journal:import-posts` / `journal:export-posts` (Phase 15 D-13) for the content migration.
- cabana `backend.uri` for `/gfadmin`.
### Established Patterns
- Naming: `sm-<name>-app` host, `vue-<name>-app` frontend submodule. The new shared frontend repo is `vue-journal-layer`.
- Framework-neutral READMEs: the layer README must not name grzybyfunkcjonalne (use `blog` / `acme`).
- `go vet` and `go test ./...` stay green in every Go repo touched. Unit tests are the last plan.
### Integration Points
- New repos: `vue-journal-layer` (shared) and `vue-grzybyfunkcjonalne-app` (site, submodule of `sm-grzybyfunkcjonalne-app`).
- `sm-grzybyfunkcjonalne-app`: `backend.uri: /gfadmin`, CORS/limiter config for the Nuxt server origin if needed, media serving, build/deploy scripts for two processes.
- Staging server = the PHP site's server: nginx vhost for staging, supervisor entries for Go and Nuxt.
</code_context>
<specifics>
## Specific Ideas
- "We will create new nuxt theme, per summercms standards, styling based on grzybyfunkcjonalne, but refreshed."
- The admin path must be `/gfadmin`.
- The user asked whether the layer could come straight from git.golem15.com the way PHP Composer VCS repos do. Yes: a pnpm git dependency, with no registry setup.
- Menu and FAQ plugins will be needed later; they are recorded as todos and are not part of this phase.
</specifics>
<deferred>
## Deferred Ideas
- `sm-menu-plugin` port (todo `menu-plugin-port.md`)
- `sm-faq-plugin` port (todo `faq-plugin-port.md`)
- Sitemanager/blocks plugin port for editor-managed homepage sections
- Contact form via a Go endpoint, and the newsletter signup (backlog 999.1)
- English locale for grzybyfunkcjonalne.pl
- Production cutover (nginx switch on the PHP server, Winter kept as rollback): an operational step after the phase
### Reviewed Todos (not folded)
- `sitemap-plugin-port.md`: superseded for this site by `@nuxtjs/seo` sitemap (D-13); stays on the backlog for a site that needs editor-defined sitemaps.
- `nest-framework-packages-under-modules.md`, `2026-10-01-benchmark-the-application-on-wintercms-vs-summercms.md`, `2026-10-07-translate-messages-as-nuxt-i18n-json-editor.md`: keyword matches only, not this phase.
</deferred>
---
*Phase: 16-grzybyfunkcjonalne-pl-on-reusable-blog-views*
*Context gathered: 2026-10-07*

View File

@@ -0,0 +1,72 @@
# Phase 16: grzybyfunkcjonalne.pl on reusable blog views - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-10-07
**Phase:** 16-grzybyfunkcjonalne-pl-on-reusable-blog-views
**Areas discussed:** Reuse shape, Render & deploy, Non-Journal content, URLs/i18n/cutover
---
## Pre-discussion
While the arsha theme was being scouted, the user cut the research short: "we will create new nuxt theme, per summercms standards, styling based on grzybyfunkcjonalne, but refreshed." That settled the rendering approach before any gray areas were presented (no Go template engine, no Twig port).
## Reuse shape
| Option | Description | Selected |
|--------|-------------|----------|
| Nuxt layer repo | `vue-journal-layer` consumed with `extends` | ✓ |
| Starter template | Copy per blog | |
| One configurable app | Branding set by config | |
| Option | Description | Selected |
|--------|-------------|----------|
| Neutral base + tokens | CSS custom properties, the app overrides them | ✓ |
| Headless only | Unstyled | |
| Full grzyby design | Layer carries the grzyby look | |
Distribution: the user asked what the npm option would need and whether git.golem15.com could be used the way Composer VCS repos are. git.golem15.com turned out to be Gitea 1.25.4, and the options were explained again.
| Option | Description | Selected |
|--------|-------------|----------|
| pnpm git dependency | `git+https://…#tag`, lockfile-pinned, no setup | ✓ |
| Gitea npm registry | `.npmrc`, a token and a publish step | |
| Git submodule + path extends | ssu-managed | |
Views in the layer (multi): post list + pagination, single post, category + tag listings, author page + RSS link (all selected).
## Render & deploy
| Option | Description | Selected |
|--------|-------------|----------|
| SSR + cached routes | Node server, swr/ISR | ✓ |
| Prerender + rebuild on publish | Same as summercms.io | |
| Prerender shell + client fetch | Weak SEO | |
App repo: submodule in the host app (✓) vs a standalone repo.
Admin access: "1, but we'll need /gfadmin for backend". The admin is exposed on the site domain at `/gfadmin`.
Server: the same server as the PHP site (✓) vs the summercms.io server vs deciding later.
## Non-Journal content
Homepage: in the Nuxt app repo (✓) vs a sitemanager/blocks plugin vs Journal posts.
FAQ & menu: "Static in the app, we'll need menu and faq plugins in future so add migrating these to todo". Todos were created.
SEO/sitemap: `@nuxtjs/seo` in the layer (✓) vs porting `sm-sitemap-plugin`.
Forms: contact info only, forms dropped (✓) vs a Go contact endpoint vs research first.
## URLs, i18n, cutover
URLs: keep the PHP URLs identical (✓) vs moving categories vs a new scheme with a 301 map.
Locales: Polish only, i18n-ready (✓) vs pl + en.
Migration: `journal:import-posts` + media copy (✓) vs a DB script vs letting research decide.
Cutover: stop at staging (✓) vs a production cutover inside the phase.
## Claude's Discretion
Plan split, layer route configuration mechanism, markdown rendering, cache TTLs, deploy script layout, whether to run a UI-SPEC first.
## Deferred Ideas
The menu, FAQ and sitemanager/blocks plugin ports; the contact form and newsletter; an English locale; the production cutover.

View File

@@ -0,0 +1,10 @@
---
title: Port the FAQ plugin as sm-faq-plugin so FAQs become editable
date: 2026-10-07
priority: medium
area: sm-faq-plugin
---
Phase 16 ships the grzybyfunkcjonalne.pl FAQ (`g15_faq` slug `what-mushrooms-can-give-you`) as static i18n/markdown content in the Nuxt app. Later blogs need editors to manage FAQs, so port `Golem15.Faq` 1:1 as its own `sm-faq-plugin` repo (see `.planning/notes/core-plugins-own-repos.md`): models, admin screens and a public read API by slug.
Reference: `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/plugins/golem15/faq` and the theme partials `themes/arsha/partials/g15_faq/` and `g15_faq_whyus/`. When it lands, move the grzybyfunkcjonalne FAQ out of the app into the plugin.

View File

@@ -0,0 +1,10 @@
---
title: Port the menu plugin as sm-menu-plugin so blog menus become editable
date: 2026-10-07
priority: medium
area: sm-menu-plugin
---
Phase 16 hardcodes the grzybyfunkcjonalne.pl main menu as typed config in the Nuxt app, replacing the `g15_menu` component. Later blogs need editors to manage menus again, so port `Golem15.Menu` 1:1 as its own `sm-menu-plugin` repo (see `.planning/notes/core-plugins-own-repos.md`): models, admin screens and a public read API that the shared `vue-journal-layer` (or a sibling layer) can consume.
Reference: `/media/nvme/dev/golem15/grzybyfunkcjonalne.pl/plugins/golem15/menu` and the theme partial `themes/arsha/partials/g15_menu/default.htm` (nested link entries, target, css_class, active state). When it lands, move the grzybyfunkcjonalne menu from app config into the plugin.