Start here →
AGENTS.md·SPEC_INDEX.md·ARCHITECTURE.md.
| Field | Value |
|---|---|
| Module id | page-routing-and-seo |
| Source path(s) | src/pages/, src/layouts/, src/lib/seo.ts, src/lib/sitemap*.ts |
| Doc kind | Module spec |
| Coverage score | 100% assessed 2026-07-24; 14/14 mandatory fields PRESENT, focused ASP route evidence added |
| Generated from | module-spec @ 0.2.1 |
| generated_by / approved_by / updated_at | codex (gpt-5.6) / repository owner MODIFIED-delta append approval / 2026-08-19 |
| Validation status | pass-with-warnings; validator claude-opus-4-8-1m (runtime independent of codex), target HEAD b9c7321ee3642bdb0137734e187a102a7f5de9be, assessed 2026-07-24; 0 Blocking, 0 Important, 0 Medium, 2 Minor; full suite environment-blocked (Node 24 + registry pending) |
Behavioral claims cite current route/config/test files. Preserved migration specs supplied route intent and acceptance cases, but do not override the Astro file tree.
| Source material | Scope | Decision | Disposition |
|---|---|---|---|
| Existing ASP listing specification | page behavior | verified/corrected | Current /asp-apps behavior is represented in requirements and routing flow |
| Current route tree and SEO tests | implementation/tests | authoritative | Requirements, public surface, error handling, test strategy |
Astro file-based routing under src/pages/ owns public pages, same-origin APIs, operational endpoints, authentication callbacks, media proxies, robots policy, and sitemap output. Shared layouts apply metadata and page chrome; src/lib/seo.ts centralizes title, description, canonical URL, and social-image construction.
Owns URL-to-handler mapping and indexable metadata for the current Astro application; it does not own external data normalization or browser interaction state.
Astro 6 SSR routes, TypeScript endpoint handlers, Astro layouts, Vitest route/SEO tests, Playwright higher-tier checks.
src/pages/
├── *.astro # public SSR pages
├── applications/[appId] # dynamic app detail
├── category/[category] # category listing
├── api/ # same-origin JSON/action routes
├── auth/ # App Hub OAuth
├── integration/ # native integration OAuth
└── sitemap*.ts, robots.txt.ts, ping.ts, getImage.ts
| File | Holds |
|---|---|
src/pages/ | Actual route existence and method handlers |
astro.config.mjs | SSR output, site origin, static sitemap and redirects |
src/lib/seo.ts | Metadata defaults and normalization |
src/pages/sitemap.xml.ts | Dynamic sitemap generation/cache/compression |
src/lib/sitemap-config.ts | Static page catalog |
src/lib/middleware/permanent-redirects.ts | Canonical 301 redirects |
| Contract ID | Type | Surface | Purpose | Compatibility | Detail | Root index |
|---|---|---|---|---|---|---|
page.catalog | HTTP | GET Astro page routes | Browse/search catalog | URL and redirect stability | src/pages/ | CONTRACTS.md |
seo.robots | HTTP | GET /robots.txt | Crawler policy | Text/status stability | src/pages/robots.txt.ts | CONTRACTS.md |
seo.sitemap | HTTP | GET /sitemap.xml | Discover public URLs | XML/gzip compatibility | src/pages/sitemap.xml.ts | CONTRACTS.md |
catalog.search | HTTP | GET /api/search | Server-side catalog search | Query/result compatibility | src/pages/api/search.ts | CONTRACTS.md |
Compatibility notes:
Synchronized catalog/category data, Redis, page layouts/components, SEO helpers, middleware redirects/security, and configured site host.
| ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Gaps | Confidence |
|---|---|---|---|---|---|---|
PAGE-R-001 | Astro MUST derive routes from src/pages/; dynamic parameters MUST be validated before data lookup. | Prevents invented routes and unsafe identifiers. | src/pages/applications/[appId].astro, src/pages/category/[category].astro | tests/unit/lib/listing-app.test.ts | none | PRESENT |
PAGE-R-002 | /asp-apps MUST render the ASP/agentic listing using current synchronized data and the shared listing layout. | Preserves the shipped listing contract without reviving legacy routing. | src/pages/asp-apps.astro, src/lib/fetch-synced-data.ts | playwright/tests/functional/navigation/collection-routes.spec.ts | none | PRESENT |
PAGE-R-003 | Page metadata MUST use centralized SEO defaults, bounded descriptions, absolute canonical/social URLs, and route-specific values. | Prevents inconsistent or invalid index metadata. | src/lib/seo.ts, src/layouts/BaseLayout.astro | tests/unit/lib/seo.test.ts, tests/unit/lib/seo-spec-constants-drift.test.ts | none | PRESENT |
PAGE-R-004 | Robots and sitemap output MUST exclude non-indexable auth/API/error/search surfaces and include current public static/dynamic URLs. | Keeps crawler output aligned with user-facing content. | astro.config.mjs, src/pages/robots.txt.ts, src/pages/sitemap.xml.ts | tests/unit/pages/robots-txt.test.ts, tests/unit/pages/sitemap-generation.test.ts | none | PRESENT |
PAGE-R-005 | Permanent legacy URLs MUST resolve through the centralized redirect definitions before normal route handling. | Maintains inbound-link compatibility. | src/lib/middleware/permanent-redirects.ts, src/middleware.ts | tests/unit/config/permanent-redirects.test.ts | none | PRESENT |
PAGE-R-006 [MODIFIED 2026-08-19, 2026-09-15] | /prebuilt-actions MUST render approved synchronized records and redirect to the current not-found route when none exist; sitemap output MUST include the listing and action detail URLs only while approved records exist. Legacy snapshot type aliases MUST pass through the same approval boundary before route or sitemap exposure, and the static fallback catalog MUST include /prebuilt-actions. | Keeps browsable and crawler-visible routes aligned with publishable upstream state, including during rolling deployments and degraded sitemap loading. | src/pages/prebuilt-actions.astro, src/pages/sitemap.xml.ts, src/lib/sitemap-config.ts, src/lib/prebuilt-actions.ts, src/lib/fetch-synced-data.ts | tests/unit/lib/prebuilt-actions.test.ts, tests/unit/lib/fetch-synced-data.test.ts, tests/unit/pages/sitemap-generation.test.ts | full route behavior covered by build/higher-tier navigation checks | PRESENT |
Routes are declarative files. Pages obtain server data before rendering and pass serializable initial state to islands. Static sitemap discovery is configured in Astro; the custom sitemap merges static pages with synchronized app/category URLs, normalizes/escapes them, caches the result, and serves compressed bytes when supported.
flowchart LR
Request --> Middleware --> Route["Astro route"]
Route --> Data["sync/SEO helpers"]
Data --> Render["layout + components"]
Render --> Response
Data --> Sitemap["XML generation/cache"]
| Operation group | Diagram | Failure coverage |
|---|---|---|
| SSR page | Page render | Missing data selects empty/404 behavior |
| Sitemap | Sitemap generation | Cache miss and unavailable data remain valid output paths |
sequenceDiagram
participant B as Browser
participant M as Middleware
participant P as Astro page
participant R as Redis/sync helpers
B->>M: GET page
M->>P: next()
P->>R: read normalized data
alt route entity exists
R-->>P: data
P-->>B: SSR HTML + metadata
else missing/invalid
R-->>P: null
P-->>B: 404/empty contract
end
sequenceDiagram
participant C as Crawler
participant S as Sitemap route
participant R as Redis/sync readers
C->>S: GET /sitemap.xml
S->>S: check process cache
alt cache miss
S->>R: read apps and categories
R-->>S: current snapshot or unavailable subset
S->>S: merge static/dynamic, normalize, escape, compress
end
S-->>C: XML or gzip XML
classDiagram
class AstroRoute
class Layout
class SeoHelpers
class SyncReaders
AstroRoute --> Layout
AstroRoute --> SeoHelpers
AstroRoute --> SyncReaders
src/pages/asp-apps.astro, src/lib/fetch-synced-data.ts./applications/:appId → identifier lookup → detail or not-found response. Evidence: src/pages/applications/[appId].astro.src/pages/robots.txt.ts, src/pages/sitemap.xml.ts.astro.config.mjs and robots/sitemap code.| Condition | Signal | Recovery |
|---|---|---|
| Invalid/missing dynamic ID | 404 or route-specific empty result | Correct URL; do not call upstream with unchecked ID |
| Search/index unavailable | API error/fallback result | Retry after sync; inspect sync health |
| Sitemap source unavailable | Valid response from available data | Regenerate after sync |
| Unknown route/probe | 404 from middleware/Astro | No retry unless URL corrected |
src/pages/, not the legacy API inventory.site is derived from configured host in astro.config.mjs; wrong environment host produces wrong canonicals.File-based routing keeps route ownership visible and build-checked, while custom sitemap generation accepts extra runtime complexity to include Redis-backed dynamic catalog URLs.
Unit-test SEO normalization, redirects, robots, sitemap escaping/deduplication/compression, and route helpers. Use build and visual/E2E suites for representative SSR routes and navigation.
| Behavior | Existing test evidence | Gap |
|---|---|---|
PAGE-R-003 | tests/unit/lib/seo.test.ts | none |
PAGE-R-004 | robots/sitemap unit suites | none |
PAGE-R-005 | permanent redirect tests | none |
| ASP listing SSR | playwright/tests/functional/navigation/collection-routes.spec.ts | none |
ARCHITECTURE.mdCONTRACTS.md.sdd/manifest.json