docs(33-12): complete the demo, summercms.io and bm plan

SUMMARY with the smoke output, the 33-14 hand-off (pins, linking, rome
steps) and the demo's /pl/ finding; deferred items and two WINDOWS
entries.
This commit is contained in:
Jakub Zych
2026-11-04 18:12:25 +01:00
parent 298c81d701
commit 81c81c0c7d
3 changed files with 474 additions and 3 deletions

View File

@@ -1,10 +1,10 @@
---
schema_version: 1
open_count: 25
open_count: 27
waived_count: 0
fixed_count: 8
total_count: 33
last_updated: 2026-11-04T15:03:28.619Z
total_count: 35
last_updated: 2026-11-04T17:10:14.144Z
---
# Broken Windows Ledger
@@ -48,6 +48,8 @@ last_updated: 2026-11-04T15:03:28.619Z
| 31 | 33 | deviation | models/settings/fields.yaml | | sm-sitemap-plugin: News sources is a taglist with custom tags and no options (values listed by the news_sources partial, server-checked) because cabana taglist options are a fixed YAML list and form extensions take no taglist; switch to options from the article types and categories once the framework offers per-request taglist options | open | | 2026-11-04T11:42:13.158Z | |
| 32 | 33 | deviation | controllers/issues/config_filter.yaml | | sm-seo-plugin: the Site audit status filter cannot default to Open (cabana list filters have no default value), so the list shows ignored issues too, badged Ignored; GET /_seo/api/v1/issues and seo_list_issues default to status open; set the default once cabana filters accept one | open | | 2026-11-04T15:03:28.372Z | |
| 33 | 33 | deviation | controllers/issues/_issue_details.htm | | sm-seo-plugin: P7 shows Open the page and the Rich Results Test as labelled addresses, not links, because the partial allowlist keeps only same-origin hrefs; make them links once partials may carry an external link (new tab) | open | | 2026-11-04T15:03:28.619Z | |
| 34 | 33 | deviation | vue-demo-app/nuxt.config.ts | | 33-12: the demo serves Polish by cookie at one address (no_prefix), but the CMS names /pl/... alternates and sitemap addresses, which answer 404; i18n strategy decision before 33-14 applies the demo patches | open | | 2026-11-04T17:10:13.946Z | |
| 35 | 33 | todo | sm-sitemap-plugin/classes/rebuild.go | | 33-12: additional addresses are not de-duplicated against content records (migrated /, /blog, /faq listed twice on rome-like data); the demo DEPLOY step works around it | open | | 2026-11-04T17:10:14.144Z | |
````json
[
@@ -479,6 +481,32 @@ last_updated: 2026-11-04T15:03:28.619Z
"recorded_at": "2026-11-04T15:03:28.619Z",
"resolved_at": null,
"milestone": "v1.0"
},
{
"id": 34,
"kind": "deviation",
"phase": "33",
"file": "vue-demo-app/nuxt.config.ts",
"line": null,
"description": "33-12: the demo serves Polish by cookie at one address (no_prefix), but the CMS names /pl/... alternates and sitemap addresses, which answer 404; i18n strategy decision before 33-14 applies the demo patches",
"status": "open",
"reason": "",
"recorded_at": "2026-11-04T17:10:13.946Z",
"resolved_at": null,
"milestone": "v1.0"
},
{
"id": 35,
"kind": "todo",
"phase": "33",
"file": "sm-sitemap-plugin/classes/rebuild.go",
"line": null,
"description": "33-12: additional addresses are not de-duplicated against content records (migrated /, /blog, /faq listed twice on rome-like data); the demo DEPLOY step works around it",
"status": "open",
"reason": "",
"recorded_at": "2026-11-04T17:10:14.144Z",
"resolved_at": null,
"milestone": "v1.0"
}
]
````

View File

@@ -0,0 +1,412 @@
---
phase: 33-seo-output-audit-and-content
plan: 12
subsystem: apps
tags: [seo, sitemap, nuxt, vue-seo-layer, demo, summercms-io, bm, noindex, patches]
requires:
- phase: 33-03..33-06
provides: sitemap index and files, SEO plugin page registry, site answer, JSON-LD graph, breadcrumbs
- phase: 33-07..33-09
provides: vue-seo-layer v0.2.0 (resolve, root files, build guard, noindex routes, route report, components) and the journal, menu and faq layers on it
- phase: 33-11
provides: WebP variants (purego linking note)
provides:
- "33-12-sm-demo-app.patch: Journal (tag_pages false), sitemap (site_url) and SEO (route_report_token) config, nginx without sitemap locations, env templates, DEPLOY.md SEO steps, deploy/seo-pages.csv, TestSEOOutput, scripts/smoke-seo.sh, scripts/smoke.sh and check-deploy.sh on the new format"
- "33-12-vue-demo-app.patch: seo.noindexRoutes ['/p/**', '/presentations/**'], page meta instead of hand-written robots, SeoSitemapLink in the footer, @nuxtjs/seo keys removed, SSR resolve through /api/__seo__"
- "33-12-vue-summercmsio-app.patch: changelog on seo: { cms: false, htmlSitemap: false } and 12 new expectation lines"
- "33-12-sm-summercmsio-app.patch: the empty note (no change beyond the pin bumps)"
- "33-12-local-wiring.md: worktrees, go.work, pnpm overrides, run variables, checks and cleanup for 33-13 and 33-14"
- "sm-bm-app bd7ee84: robots.txt Disallow, robots meta, X-Robots-Tag in nginx, scripts/check-noindex.sh (D-72)"
affects: [33-13, 33-14]
actuals:
tokens: 30000
tasks: 3
commits: 2
plan_head_before: 617e15d
plan_head_after: 298c81d701c697e77cc7b4b5e8639f07f87a98e2
tech-stack:
added: []
patterns:
- "Release patches from scratch worktrees: git add -N for new files, git diff --binary over an explicit path list, so the wiring (go.work, plugins.gen.go, pnpm overrides and lockfile) never enters a patch"
- "Scratch Nuxt wiring with pnpm 12 overrides in pnpm-workspace.yaml (link: to the sibling layers, applied at every depth)"
- "An SEO smoke run against a site: CMS head checks, a sitemap crawl through the site with duplicate and noindex detection, a redirect and a 404 created and removed through the SEO API"
key-files:
created:
- .planning/phases/33-seo-output-audit-and-content/33-12-sm-demo-app.patch
- .planning/phases/33-seo-output-audit-and-content/33-12-vue-demo-app.patch
- .planning/phases/33-seo-output-audit-and-content/33-12-sm-summercmsio-app.patch
- .planning/phases/33-seo-output-audit-and-content/33-12-vue-summercmsio-app.patch
- .planning/phases/33-seo-output-audit-and-content/33-12-local-wiring.md
- ../sm-bm-app/frontend/public/robots.txt
- ../sm-bm-app/scripts/check-noindex.sh
modified:
- ../sm-bm-app/frontend/index.html
- ../sm-bm-app/deploy/nginx/bm.jakubzych.com.conf
- ../sm-bm-app/DEPLOY.md
- ../sm-bm-app/README.md
- .planning/phases/33-seo-output-audit-and-content/deferred-items.md
- .planning/WINDOWS.md
key-decisions:
- "The demo keeps its cookie-based Polish (D-13). Moving to /pl/ prefixes is a Rule 4 change and goes to 33-14 as a decision; smoke-seo.sh reports the /pl/ 404s as WARN lines (SMOKE_SEO_STRICT=1 fails on them)"
- "Demo sitemaps go through Nuxt: nginx drops = /sitemap.xml and = /sitemap.xsl and gets no /_sitemap or /_seo location, and check-deploy.sh refuses one. robots.txt stays on the Go port"
- "The demo resolves client-side navigations through the Nuxt server (public.seo.apiBase /api/__seo__), so /_seo stays unrouted"
- "Registry page titles: deploy/seo-pages.csv restores 'SummerCMS Demo' (/) and 'FAQ' (/faq), which the registry would otherwise derive as 'Home' and 'Faq'"
- "sm-bm-app's check-noindex.sh builds the frontend into a temp outDir, so the committed build in the jz.bm plugin submodule is not touched"
requirements-completed: [SC-1, SC-2, D-72, D-70, D-23, D-97, D-33, D-22, D-30, D-34]
coverage:
- id: D1
description: "The demo stack on local links serves a Journal post with the CMS title, one canonical, one JSON-LD @graph, hreflang and breadcrumbs, /sitemap.xml as an index whose files answer through the layer, a 301 from an SEO plugin redirect, noindex on /p/** and the auth pages, the reported routes in the registry and a 404 in the 404 log"
requirement: SC-1
verification:
- kind: e2e
ref: "SMOKE_SEO_API=http://127.0.0.1:8120 bash scripts/smoke-seo.sh http://127.0.0.1:3020 (smoke-seo: ok, 29 ok lines, 9 WARN)"
status: pass
human_judgment: false
- id: D2
description: "The demo build passes the D-70 guard with seo.noindexRoutes and fails without the line"
requirement: D-70
verification:
- kind: automated_ui
ref: "pnpm exec nuxt build in the vue-demo-app worktree: exit 0 with the line, exit 1 '[vue-seo-layer] indexable routes must render on the server (D-70): /p/**, /presentations/**' without it"
status: pass
human_judgment: false
- id: D3
description: "TestSEOOutput (Docker): sitemap index and file on the public origin, no tag address and /blog/tag/releases not_found with tag_pages false, site answer, post resolve with @graph and breadcrumbs, route report with route_report_token"
requirement: SC-2
verification:
- kind: integration
ref: "go test -tags summercms_mcp -run TestSEOOutput -count=1 . (pass; fails without config/golem15.journal.yaml)"
status: pass
human_judgment: false
- id: D4
description: "summercms.io's changelog on seo.cms false keeps its titles, one canonical, one graph and makes no resolve call; landing generate, unit tests and marketplace smoke pass"
requirement: D-97
verification:
- kind: e2e
ref: "pnpm run build:changelog && pnpm run test:changelog (smoke-ssr: ok (89 checks)); pnpm run generate; pnpm test (82 pass, 0 fail); pnpm run test:marketplace (30 checks)"
status: pass
human_judgment: false
- id: D5
description: "sm-bm-app has no indexable page: robots.txt Disallow, robots meta, X-Robots-Tag in both server blocks and the location with its own add_header"
requirement: D-72
verification:
- kind: unit
ref: "bash ../sm-bm-app/scripts/check-noindex.sh (check-noindex: ok; three negative runs fail)"
status: pass
human_judgment: false
- id: D6
description: "Patches apply cleanly to the live HEADs"
verification:
- kind: other
ref: "git apply --check of all four patches (sm-summercmsio-app with --allow-empty)"
status: pass
human_judgment: false
- id: D7
description: "The demo's noindex set covers only browser-only or private routes (D-70 values prohibition); subscriptions is marked signed-in per P33-48 although its plan list is visible to visitors"
requirement: D-70
verification: []
human_judgment: true
rationale: "Whether /subscriptions (plans shown to visitors, subscribing needs an account) counts as a signed-in page is a product judgement for Jakub at 33-14's release checkpoint"
duration: 50min
completed: 2026-11-04
status: complete
---
# Phase 33 Plan 12: Demo, summercms.io and bm on the Phase 33 stack Summary
**The demo runs end to end on local links: CMS head, one graph, breadcrumbs, the sitemap index through vue-seo-layer, a CMS redirect enforced by Nuxt, D-70/D-23 noindex. Release patches for the demo and summercms.io apply to the current HEADs, and bm is noindexed by file, meta and header. The run also found that the demo's cookie-based Polish leaves 8 of 23 sitemap addresses (all `/pl/...`) answering 404.**
## Performance
- **Duration:** about 50 min (16:25Z to 17:15Z)
- **Tasks:** 3 of 3
- **Files:**
- four patches and a wiring note in the phase directory;
- six files in sm-bm-app;
- deferred-items.md and WINDOWS.md.
## Ports and wiring
Ports:
- Go `127.0.0.1:8120`. dev.sh uses 8097; the other port avoids a clash with a running dev stack.
- Nuxt `127.0.0.1:3020`.
- Scratch Postgres `127.0.0.1:55561` (container `sm-demo-pg-scratch33`, now removed).
- 33-13's Nuxt `3016` and its two worktrees were not touched.
33-12-local-wiring.md has every command.
The plan's Task 1 verify line uses the default `SMOKE_SEO_API=http://127.0.0.1:8097`. This run needs `SMOKE_SEO_API=http://127.0.0.1:8120`.
## Accomplishments
### Task 1: tracer, demo end to end on local links
The tracer gate passed: `<verify>` was re-run after the fixes, and it ended `smoke-seo: ok`.
**Setup:**
- worktrees under `../../scratch-33`;
- a scratch go.work with sm-journal-plugin, sm-sitemap-plugin, sm-seo-plugin and the framework replace;
- pnpm 12 overrides for the four layers;
- `summer build`;
- a fresh Postgres, then `migrate`, `admin:create` and `demo:seed` (posts with categories and Polish translations);
- `SUMMER_ENV=production` with local overrides, so the staging lock does not mask the noindex checks;
- `sitemap:rebuild`;
- the `seo-pages.csv` import.
**Final smoke** (`$S/smoke-seo-final.txt`):
```
ok /blog/welcome-to-summercms answers 200
ok /blog/welcome-to-summercms has one ld+json script
ok /blog/welcome-to-summercms ld+json is one @graph
ok /blog/welcome-to-summercms has one canonical
ok /blog/welcome-to-summercms has 3 hreflang links
ok /blog/welcome-to-summercms has nav.seo-breadcrumbs (2 links)
ok /blog/welcome-to-summercms title is the CMS title (Welcome to SummerCMS)
ok /blog/welcome-to-summercms X-Robots-Tag is the CMS's (index, follow)
ok alternate /blog/welcome-to-summercms answers 200
WARN alternate /pl/blog/welcome-to-summercms answers 404
ok /sitemap.xml is a sitemap index (application/xml)
ok /sitemap-authors-1.xml answers a urlset through the site
WARN sitemap address /pl/blog/author/summercms-team answers 404
ok /sitemap-categories-1.xml answers a urlset through the site
WARN sitemap address /pl/blog/category/uncategorized answers 404 (and news, guides)
ok /sitemap-pages-1.xml answers a urlset through the site
ok /sitemap-posts-1.xml answers a urlset through the site
WARN sitemap address /pl/blog/welcome-to-summercms answers 404 (and the other three posts)
ok 23 sitemap addresses fetched, 8 not 200
ok no address is listed twice in the sitemaps
ok /robots.txt names the sitemap index
ok /p/smoke-seo (200) sends X-Robots-Tag: noindex, nofollow
ok /presentations/new (200) sends X-Robots-Tag: noindex, nofollow
ok /login (200) sends X-Robots-Tag: noindex, nofollow
ok /register (200) sends X-Robots-Tag: noindex, nofollow
ok /account/security (200) sends X-Robots-Tag: noindex, nofollow
ok /login has the robots meta noindex, nofollow
ok / (200) links the HTML sitemap in the footer
ok /sitemap lists /blog/welcome-to-summercms
ok /smoke-seo-old-1793811624-4025853 answers 301 to /blog/welcome-to-summercms (SEO plugin redirect 4)
ok the registry lists the reported routes: / /blog /chat /contact /faq /forum /quizzes
ok /smoke-seo-missing-1793811625-4025853 answers 404
ok /smoke-seo-missing-1793811625-4025853 reached the 404 log (entry 12)
smoke-seo: ok
```
**Negative run** on rome-like sitemap data (the migrated additional addresses `/` and `/subscriptions`), which the smoke must catch:
```
FAIL sitemap address /subscriptions answers X-Robots-Tag: noindex, nofollow
FAIL addresses listed more than once in the sitemaps: /
```
### Task 2: release patches
**33-12-sm-demo-app.patch** (13 files):
- config:
- `config/golem15.journal.yaml` (new, `tag_pages: false`);
- `config/golem15.sitemap.yaml` (new, `site_url: https://demo.summercms.io`);
- `config/golem15.seo.yaml` (`route_report_token: ""` from the environment).
- deploy files:
- `deploy/env.example` and `deploy/site.env.example`: SEO tokens and the `NUXT_SEO_*` bases; `NUXT_PUBLIC_SITE_URL` and `NUXT_PUBLIC_SITEMAP_URL` dropped, since nothing reads them;
- `deploy/nginx/demo.summercms.io.conf`: `= /sitemap.xml` and `= /sitemap.xsl` dropped;
- `deploy/seo-pages.csv` (new).
- DEPLOY.md:
- the overview, the one-time setup with the SEO tokens, and the rewritten SEO section;
- the "Before" and "After the first release with Phase 33" steps (the token append refuses when a key exists and was dry-run twice; the additional-address cleanup and the CSV import were tested on the scratch backend);
- the smoke-seo.sh usage.
- README.md.
- `scripts/check-deploy.sh`: refuses `/_seo`, `/_sitemap` and `/sitemap*` locations.
- `scripts/smoke.sh`:
- runs `sitemap:rebuild` and checks the index on Go and, through the site, `/sitemap.xml`, `sitemap-posts-1.xml` and `/robots.txt`;
- starts the site with `NUXT_SEO_API_BASE`;
- replaces the deck check that relied on nuxt-site-config's `window.__NUXT_SITE_CONFIG__` with the empty-app-root and `X-Robots-Tag` check.
- `scripts/smoke-seo.sh` (new, 0755).
- `seo_output_test.go` (new).
**33-12-vue-demo-app.patch** (18 files):
- nuxt.config.ts:
- `site`, `robots`, `linkChecker` and `public.sitemapUrl` removed;
- `seo: { noindexRoutes: ['/p/**', '/presentations/**'] }`;
- `runtimeConfig.seo.apiBase` and `public.seo.apiBase: '/api/__seo__'`.
- Page meta, per P33-48:
- `seo: { robots: 'noindex, nofollow' }` on login, register, connect and link-admin;
- `requiresAuth: true` on account/security, subscriptions, friends, call/[conversation] and forum/t/[id];
- `seo: { robots: 'noindex' }` on quizzes/[slug] (login required) and roadmap (a redirect only);
- the robots value dropped from the three /presentations pages (noindexRoutes covers them).
- The footer's XML sitemap link is replaced by `<SeoSitemapLink />`, and the unused `footer.sitemap` labels are dropped.
- The patch adds no `useSeoMeta(` line with a robots value.
**33-12-vue-summercmsio-app.patch:**
- `changelog/nuxt.config.ts`: `seo: { cms: false, htmlSitemap: false }`;
- `changelog/testing/expect.txt`: 12 lines, covering title, canonical ×1, ld+json ×1, h1 ×1, no breadcrumbs, 404 for /sitemap and /mapa-strony, and `resolves * 0`.
The card and heading markup needed no expectation change: the app overrides PostCard, PostList and IndexHeader, so the layer's new card markup does not reach it.
**33-12-sm-summercmsio-app.patch:** the single note line. It needs `git apply --check --allow-empty` (see Deviations).
**Results:**
- demo:
- build passes, and fails without the noindexRoutes line;
- `go vet ./...`, `go test -short ./...` and `go test -tags summercms_mcp -count=1 ./...` (Docker) pass;
- `scripts/smoke.sh bin/demo` ends `smoke: ok`;
- `scripts/check-deploy.sh` ends `check-deploy: ok`;
- `pnpm test` gives 225/225.
- summercms.io:
- `test:changelog` gives 89 checks;
- `generate` passes;
- `pnpm test` gives 82 pass, 0 fail;
- `test:marketplace` gives 30 checks;
- Go `go test ./...` passes on the wiring.
**Cleanup:** the four worktrees were removed with `git worktree remove --force` after the patch commits. The demo worktree was recreated once for the TestSEOOutput fix and removed again. `git worktree list` shows only the main checkouts. The scratch Postgres and both servers are stopped. Ports 8120, 3020 and 55561 are free.
### Task 3: sm-bm-app (D-72)
- **Changes:**
- `frontend/public/robots.txt`;
- the robots meta in `frontend/index.html`;
- `add_header X-Robots-Tag "noindex, nofollow" always;` in both server blocks and in `location = /prezentacje/AW_tematy-prezentacji.html`;
- `scripts/check-noindex.sh`;
- DEPLOY.md, "Search engines (noindex)";
- one README line.
- **Check:** `check-noindex: ok`. Removing the header from the port-80 server, the header from the location, or the meta each fails with its own line.
- **Commit:** bd7ee84 on master, local, not pushed.
- **sm-bm-app `.planning`:** there were no other-session `.planning` changes to preserve; `git status --short .planning` was empty before and after.
## Task Commits
| Repo | Commit | Message |
|------|--------|---------|
| summercms.go | e1d5110 | docs(33-12): app patches for the release |
| summercms.go | 298c81d | docs(33-12): demo patch tags a post in TestSEOOutput |
| sm-bm-app | bd7ee84 | feat: keep the app out of search engines (noindex, Disallow) |
## Decisions Made
See `key-decisions` in the frontmatter. The main one: the demo's /pl/ problem is reported, not fixed (Rule 4).
## Deviations from Plan
### Auto-fixed and plan-shape deviations
**1. [Rule 1 - Bug] TestSEOOutput's tag check was vacuous**
- **Found during:** Task 2, after the first patch commit.
- **Issue:** demo:seed creates no tag, so the test passed without `config/golem15.journal.yaml` too.
- **Fix:** the test tags the seeded post and requires `/blog/tag/releases` to resolve `not_found`. Without the config the test fails: `resolves "ok", want not_found`.
- **Commit:** 298c81d. The patch was regenerated and re-checked.
**2. [Rule 1 - Bug] The live run never served `config/golem15.journal.yaml`**
- **Found during:** cleanup.
- **Issue:** the first manually started Go process kept port 8120, because its pid file recorded the subshell's pid. The later restarts could not bind the port. The local stack therefore served the config as it was at the first start, plus the env overrides.
- **Effect:** every smoke result stands, because none depends on the files added later. `tag_pages: false` is proven by TestSEOOutput only.
**3. [Rule 3 - Blocking] The release smoke depended on nuxt-site-config**
- **Issue:** `scripts/smoke.sh` used `window.__NUXT_SITE_CONFIG__` to prove the deck page renders in the browser only. That module left with @nuxtjs/seo.
- **Fix:** replaced by the empty `#__nuxt` root and the declared `X-Robots-Tag`. The smoke also starts the site with `NUXT_SEO_API_BASE` and checks the new sitemap format.
**4. [Rule 2 - Missing] Registry pages lose their titles**
- **Issue:** the route report creates registry pages named from their path ("Home", "Faq").
- **Fix:** `deploy/seo-pages.csv` and a DEPLOY import step bring back "SummerCMS Demo" and "FAQ", as P33-50 does for 33-13's site. Tested: the import applied with 2 changed and 0 refused, and the titles showed at once.
**5. [Rule 2 - Missing] Migrated sitemap addresses on rome**
- **Issue:** on rome the old sitemap definition becomes additional addresses (`/`, `/blog`, `/faq`, `/subscriptions`). That gives duplicates and a noindex address in the sitemap.
- **Fix:** DEPLOY.md's "After the first release" removes them through `PUT /_sitemap/api/v1/settings` (tested on the scratch backend). smoke-seo.sh now fails on duplicates and on noindex addresses.
**6. [Rule 2 - Missing] HTML sitemap pages on summercms.io's changelog**
- **Issue:** the layer registered `/sitemap` and `/mapa-strony` pages, which only answer 404 there.
- **Fix:** `htmlSitemap: false` next to `cms: false`. The expectations pin both 404s.
**7. Plan assumption: the empty patch**
- **Plan:** "git apply treats it as an empty patch".
- **Actual:** plain `git apply --check` answers `error: No valid patches in input (allow with "--allow-empty")`, exit 128. With `--allow-empty` it exits 0.
- **For 33-14:** use the flag or skip the file.
**8. Scope additions to the demo patch**
- **Added beyond the plan's list:** check-deploy.sh, smoke.sh, README.md, `deploy/env.example`, `deploy/site.env.example`, `deploy/seo-pages.csv` and `config/golem15.journal.yaml`.
- **Why:** each was needed for the new format or for correct output.
**9. P33-48 followed for `/subscriptions`**
- **What:** the page gets `requiresAuth: true`, as P33-48 says. The plan list is visible to visitors.
- **Open:** whether that is "signed-in" is listed as D7 (human judgement) for 33-14's checkpoint.
### Auth gates
None.
## Issues Encountered
**The demo's cookie-based Polish** (deferred-items.md, WINDOWS #34). The demo serves Polish from a cookie at one address, but the CMS names `/pl/…` addresses, which affects three outputs:
- hreflang;
- the sitemaps: 8 of 23 addresses, all 404;
- the Polish visitor's head: English CMS title over a Polish body.
Fixing it means moving the demo to `prefix_except_default`, which reverses D-13. **33-14 or Jakub must decide this before the demo patches are applied.**
Other findings, all in deferred-items.md:
- **Sitemap duplicates** (WINDOWS #35): the sitemap plugin does not de-duplicate additional addresses against content records.
- **Noindex additional addresses:** an additional address the site serves noindex stays listed.
- **Tag pattern in the site answer:** the SEO site answer lists `journal-tag` with `tag_pages: false` (a drift warning at every start).
- **Duplicate type export:** vue-journal-layer warns `Duplicated imports "JournalImageVariant"` on every build.
**Local quirks** (in the wiring note):
- the admin login throttle (5 a minute);
- `cp` is interactive in this shell (`/bin/cp -f`);
- `go build ./...` in sm-summercmsio-app drops a binary in the repository root (that is the untracked `sm-summercmsio-app` file in the live checkout);
- the secret-read guard blocks `.env` files, so the run variables lived in `$S/demo-run.vars` and were deleted at cleanup.
## For 33-14
**Pins:**
- sm-demo-app:
- go.mod requires and submodule pointers for sm-journal-plugin, sm-sitemap-plugin and sm-seo-plugin (all three move together, because the SEO plugin needs the sitemap `contract`), plus summercms v0.6.1;
- then `summer build` (plugins.gen.go), then apply 33-12-sm-demo-app.patch.
- vue-demo-app: pins vue-journal-layer v0.8.0, vue-menu-layer v0.5.0 and vue-faq-layer v0.5.0. vue-seo-layer comes in through them; add a direct pin if the layers' `link:` dependency becomes a git pin. Then apply 33-12-vue-demo-app.patch.
- sm-summercmsio-app: summercms v0.6.1 and sm-journal-plugin (submodule and require). Skip the empty patch, or apply it with `--allow-empty`.
- vue-summercmsio-app: vue-journal-layer v0.8.0, then apply 33-12-vue-summercmsio-app.patch. The changelog still gets @nuxtjs/seo from the landing ('..'), so the canonical and graph stay single.
- sm-bm-app:
- robots.txt and the meta reach rome only after `npm --prefix frontend run build` is committed in the jz.bm plugin repository (`jakub/sm-bm-plugin`, `plugins/jz/bm/public`), pushed, and the pointer bumped. 33-12 committed only in sm-bm-app.
- The nginx header is inserted into the live vhost by hand (DEPLOY.md, "Search engines (noindex)").
**Linking decision:**
- **Demo:** `scripts/build.sh` builds the release with `CGO_ENABLED=0` and no `nodynamic`, which gives a dynamically linked binary (checked: "dynamically linked"; with `-tags summercms_mcp,nodynamic` "statically linked").
- **summercms.io:** `scripts/build.sh` uses `CGO_ENABLED=0`, and the scratch build is "dynamically linked".
- **grzybyfunkcjonalne:** `CGO_ENABLED=0` as well (not built here).
- **DEPLOY.md:** both the demo's and summercms.io's say "(linux/amd64, static)". Add `nodynamic` or change that line.
**Rome steps:**
- the "Before" and "After the first release with Phase 33" blocks in the demo's DEPLOY.md: SEO tokens, NUXT_SEO bases, the vhost without the sitemap locations, clearing the additional addresses, `sitemap:rebuild`, the seo-pages.csv import;
- `journal:image-variants` once per site with Journal (33-11).
**Release-note items:**
- **Demo:** sitemap index and per-type files served by the site; `/sitemap.xsl` gone; noindex on decks and auth/signed-in pages; HTML sitemap link in the footer; page titles from the SEO plugin.
- **summercms.io:** changelog on the new journal layer with the SEO layer off.
- **bm:** noindex everywhere.
## Known Stubs
None. Two items are open (not stubs) and are in deferred-items.md and WINDOWS: the demo's `/pl/` WARN lines and the sitemap duplicates.
## Threat Flags
| Flag | File | Description |
|------|------|-------------|
| threat_flag: credential-handling | sm-demo-app scripts/smoke-seo.sh | Logs in as an admin to create and delete a redirect and a 404 log entry. The password is read from a file or the environment and passed through stdin and a temp file under mktemp, never argv; the token goes through `-H @file`; it logs out at exit. The default password is scripts/dev.sh's local admin. |
| threat_flag: secret-file-edit | sm-demo-app DEPLOY.md | The "Before the first release" block appends tokens to .env and site.env on rome and deletes two unused keys. It prints no value and refuses when a key exists. |
## Self-Check: PASSED
- FOUND: 33-12-sm-demo-app.patch, 33-12-vue-demo-app.patch, 33-12-sm-summercmsio-app.patch, 33-12-vue-summercmsio-app.patch, 33-12-local-wiring.md (phase directory)
- FOUND: ../sm-bm-app/frontend/public/robots.txt, ../sm-bm-app/scripts/check-noindex.sh
- FOUND commits: e1d5110, 298c81d (summercms.go), bd7ee84 (sm-bm-app)
- `git apply --check` passes for all four patches against the live HEADs (the empty one with `--allow-empty`)
- `bash ../sm-bm-app/scripts/check-noindex.sh` gives `check-noindex: ok`
- `grep -c noindexRoutes 33-12-vue-demo-app.patch` gives 1
- No scratch worktree of this plan remains, and none of this plan's processes are listening

View File

@@ -97,3 +97,34 @@ Out-of-scope discoveries logged during execution; not fixed in the plan that fou
status: open
- **Possible fix:** record the original's size for files without variants (for example a row with width 0), and skip them in `featuredFiles`.
- **Why deferred:** cheap and rare (featured images are usually wider than 480 px).
## From 33-12 (demo, summercms.io and bm on local links)
- **The demo's Polish addresses answer 404 (sm-demo-app, decision needed before 33-14 applies the demo patches).** The demo serves Polish from a cookie at the same address (vue-demo-app `i18n.strategy: 'no_prefix'`, D-13 of the demo). The Journal, sitemap and SEO plugins give every non-default locale a `/<code>` prefix (sm-journal-plugin README, "Every resolved record carries alternates…"). So the CMS answers have three consequences on the demo:
- every post, category and author page carries `<link rel="alternate" hreflang="pl" href="…/pl/blog/…">`;
- the sitemaps list 8 of 23 addresses under `/pl/…`, and each of those answers 404;
- a visitor with the Polish cookie gets the English CMS title and description over a Polish body, because the resolve goes by address and answers `en`.
`scripts/smoke-seo.sh` prints these as WARN lines; with `SMOKE_SEO_STRICT=1` they fail.
status: open
- **Possible fix:** move the demo to `strategy: 'prefix_except_default'` (Polish at `/pl/…`, the HTML sitemap path `/pl/mapa-strony`, locale-aware links in the demo's pages and LanguageSwitcher). The other way is a framework, Journal and SEO option for "every locale at one address", which would give the site no hreflang at all.
- **Why deferred:** it reverses a recorded demo decision and changes every Polish URL of the demo (Rule 4); 33-12 runs without a human.
- **Additional addresses are not de-duplicated against content records (sm-sitemap-plugin).** On a database migrated from the old definition (rome), migration `202610280002` copies its url items (`/`, `/blog`, `/faq`, `/subscriptions`) into the additional addresses. Once the route report has put `/`, `/blog` and `/faq` into the page registry, `sitemap-pages-1.xml` lists each of them twice. The demo patch's DEPLOY.md removes the copied addresses after the first release. sm-grzybyfunkcjonalne-app's companion items (33-13) can meet the same case.
status: open
- **Possible fix:** in `classes.Rebuild`, skip an additional address whose absolute URL a content type already lists, or report the overlap on the settings screen.
- **Why deferred:** a plugin change in sm-sitemap-plugin, outside 33-12's repositories; the demo works around it in its deploy steps.
- **An additional address that the site serves noindex stays in the sitemap (sm-sitemap-plugin, sm-seo-plugin).** The SEO filter judges the CMS's effective SEO only, while `requiresAuth` and `seo.robots` page meta (D-23) live in Nuxt. A page marked that way and also listed as an additional address (the demo's migrated `/subscriptions`) appears in the sitemap with `X-Robots-Tag: noindex, nofollow`. smoke-seo.sh fails on it, and the demo's DEPLOY.md removes the address.
status: open
- **Possible fix:** the route report also sends the noindex static paths (as `noindex` entries), and the filter leaves them out of the sitemaps.
- **Why deferred:** a contract change across vue-seo-layer and sm-seo-plugin.
- **The site answer lists the `journal-tag` pattern while `golem15.journal.tag_pages` is false (sm-seo-plugin).** `classes/site.go` adds every content type's pattern. vue-seo-layer then logs `[vue-seo-layer] drift: the CMS's journal-tag URLs (/blog/tag/:slug) match no Nuxt route` at every start of the demo, although tag paths no longer resolve (TestSEOOutput).
status: open
- **Possible fix:** leave out a type whose descriptor resolves no URL (the Journal could report tag pages off on its descriptor).
- **Why deferred:** log noise only; a plugin change outside 33-12.
- **`Duplicated imports "JournalImageVariant"` on every build of an app with vue-journal-layer (vue-journal-layer).** The type is declared in `app/utils/srcset.ts` and re-exported from `app/utils/types.ts`, both auto-imported.
status: open
- **Possible fix:** drop the re-export from `types.ts`, or move the interface to `types.ts` only.
- **Why deferred:** a warning only; a layer change, best done before the v0.8.0 tag in 33-14.
- **Both DEPLOY.md files call the binary "static" (sm-demo-app, sm-summercmsio-app).** Once the apps require the new sm-journal-plugin, their `CGO_ENABLED=0` release builds are dynamically linked (`file bin/demo`: "dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2"). With `-tags nodynamic` they are static again. Checked in 33-12 on both scratch builds.
status: open
- **Possible fix:** 33-14 decides per app: add `nodynamic` to `scripts/build.sh` (and summer.yaml `build.tags`), or change the DEPLOY.md table to "dynamically linked (glibc)".
- **Why deferred:** the linking decision is 33-14's (33-11).