183 lines
12 KiB
Markdown
183 lines
12 KiB
Markdown
# Content Site (Blog / Docs) — product specification
|
|
|
|
This is the contract the project is built against. It is written for the agent that scaffolds
|
|
the repository, but it doubles as the human-readable brief: every requirement below is meant to
|
|
be implementable and verifiable.
|
|
|
|
Values in angle brackets (`<Site name>`, `<content type>`, `<authoring>`) come from the
|
|
project-creation dialog and are recorded in the project record; replace them as you read.
|
|
`<content>` is blog, documentation or marketing pages; `<cms>` is the authoring approach
|
|
(Markdown/MDX, Contentful, Sanity or Notion).
|
|
|
|
## 1. Goal
|
|
|
|
A content site a real team could launch with: write structured entries in `<cms>`, have them
|
|
rendered as `<content>` pages with navigation, tags, authors and search, and publish a fast,
|
|
crawlable, shareable site. Content is stored against a **typed content model** and validated at
|
|
build time, so a malformed entry fails the build instead of shipping a broken page. It must be
|
|
**runnable end-to-end on day one** (even with seeded sample content), not a set of screens wired
|
|
together later.
|
|
|
|
Non-goals (do not build unless the must-have list says otherwise): multi-tenant CMS, comments,
|
|
subscriptions/paywalls, live collaborative editing, multi-language content.
|
|
|
|
## 2. Roles
|
|
|
|
| Role | Can do |
|
|
|------|--------|
|
|
| Reader | Anonymous. Browse the site, read entries, filter by tag/author, search, subscribe to the feed. |
|
|
| Author | Everything a reader can, plus create and edit their own entries (draft → in review). |
|
|
| Editor | Everything an author can, plus edit and review any entry, manage taxonomy and schedules, approve and publish. |
|
|
| Site admin | Everything an editor can, plus site configuration, navigation, roles, feeds and redirects. |
|
|
|
|
Reading is anonymous and never gated. Authoring happens in `<cms>` (for `Markdown / MDX`, in the
|
|
repository itself; for hosted CMSs, in that CMS UI) and only the publishing side is guarded by
|
|
roles. Provide a seeded author and editor for local development when the authoring approach has
|
|
a local backend.
|
|
|
|
## 3. Information architecture (routes)
|
|
|
|
Public site:
|
|
- `/` — home: hero/intro, latest or featured entries, section links.
|
|
- `/:section` — section index for one collection (e.g. `/blog`, `/docs`), with pagination.
|
|
- `/:section/:slug` — one entry: title, metadata (author, date, reading time), body, table of
|
|
contents, related entries.
|
|
- `/tags` and `/tags/:tag` — tag archive; `/authors/:author` — author archive; both paginated.
|
|
- `/search` — search over titles, tags and body, with a no-results state.
|
|
- `/404` — not-found page (and a real 404 status for unknown routes).
|
|
- Authoring preview where the chosen CMS provides one (draft preview URL for an unpublished
|
|
entry); otherwise a local preview route.
|
|
- Generated artifacts: `/sitemap.xml`, `/rss.xml` or `/atom.xml`, `/robots.txt`, and Open Graph
|
|
images (`/og/:section/:slug.png` or static equivalents).
|
|
|
|
When `<content>` is `Documentation`, the section index is the docs sidebar: entries are ordered
|
|
and grouped, and one document shows the same sidebar with the current page highlighted.
|
|
|
|
Admin (guarded by the editor/admin roles, only where the authoring approach has a local backend;
|
|
hosted CMSs keep this in the CMS UI):
|
|
- `/admin` — dashboard: draft/review queue and scheduled entries.
|
|
- `/admin/entries` — list, create, edit, preview and publish/unpublish entries.
|
|
- `/admin/taxonomy` — manage tags and authors.
|
|
- `/admin/site` — site config, navigation and redirects.
|
|
|
|
## 4. Data model
|
|
|
|
Minimum viable entities (add fields the requirements imply; keep them typed and validated):
|
|
|
|
- **ContentEntry** — slug, title, body (Markdown/MDX or a CMS reference), excerpt, type
|
|
(reference to a ContentType), tags[], author (reference), status (`draft` | `in_review` |
|
|
`scheduled` | `published` | `archived`), publishedAt, updatedAt, seo { title, description,
|
|
canonicalUrl?, image?, noindex }.
|
|
- **ContentType** — id/key, title, and `fields[]` (name, label, type, required, default) that
|
|
define the front-matter a `<content>` entry must carry; the schema entries are validated
|
|
against.
|
|
- **Author** — id, slug, name, bio, avatar, links[].
|
|
- **Tag** — id, slug, name, description, parentId? (categories are tags with children).
|
|
- **SiteConfig** — site name, base URL, locale, defaultSeo, and `navigation[]` (label, href,
|
|
order, children?) used for the header and the docs sidebar.
|
|
- **Relationship** — a typed edge between entries: `parent`/`child` for the docs sidebar tree,
|
|
`series` for an ordered series, `related` for hand-picked links.
|
|
|
|
The content model is the source of truth: front-matter missing a required field, an unknown
|
|
field, or a wrong type is a **build error**, with the offending file and field named. Document
|
|
the model so an author can add an entry without reading the renderer.
|
|
|
|
## 5. Key flows
|
|
|
|
1. **Author → publish.** An author adds a Markdown/MDX file (or creates an entry in `<cms>`)
|
|
with the required front-matter. A malformed entry fails validation with a clear message and
|
|
the build stops; a valid `draft` entry renders in preview only. The author marks it ready,
|
|
an editor reviews and publishes it, and it appears on the section index, the tag archive and
|
|
the feed with `publishedAt` set.
|
|
2. **Read.** A reader lands on the home page, opens a section, reads an entry; the table of
|
|
contents tracks the scroll position, related entries are listed below, and the document's
|
|
canonical URL and Open Graph metadata are present in the HTML head.
|
|
3. **Documentation navigation.** A reader in the docs section sees the ordered sidebar, moves
|
|
between sibling and child documents, and breadcrumbs show the path from the section root.
|
|
4. **Search.** A reader types a query on `/search` and gets ranked matches over current
|
|
published entries (client-side over an index for small sites, or a hosted search service);
|
|
an empty query shows recent entries and a no-results query shows a clear empty state.
|
|
5. **Schedule.** An editor sets a future `publishedAt` on an entry; it is `scheduled`, excluded
|
|
from production builds and the feed, and a rebuild at/after that time publishes it.
|
|
6. **Taxonomy and feeds.** The editor renames a tag; the tag archive, the entry pages and the
|
|
sitemap all reflect the change, and `sitemap.xml` and the feed stay valid.
|
|
|
|
## 6. Functional requirements
|
|
|
|
- **Authoring:** Markdown/MDX with front-matter, or entries authored in `<cms>`; code blocks
|
|
render with syntax highlighting; images and links resolve; the chosen CMS's preview is wired in
|
|
where it exists.
|
|
- **Typed validation:** entry front-matter is validated against its `ContentType` at build time;
|
|
a required field missing, an unknown field or a wrong type fails the build with the file,
|
|
field and expectation in the message.
|
|
- **Rendering:** table of contents generated from headings; reading time computed; breadcrumbs in
|
|
the docs layout; related content from series/related edges (fallback: shared tags).
|
|
- **Indexes:** section, tag and author archives are paginated with a stable page size and their
|
|
own metadata; pagination links are crawlable.
|
|
- **Search:** over titles, tags and body; client-side or hosted; no query sent to a third party
|
|
without the configuration saying so.
|
|
- **Feeds & discovery:** `rss.xml` (or `atom.xml`) built from published entries newest-first;
|
|
`sitemap.xml` covering every published route; `robots.txt` with the sitemap reference and
|
|
non-production hosts disallowed.
|
|
- **Metadata:** every route has a unique title and description and an absolute canonical URL;
|
|
Open Graph and Twitter card tags are emitted; JSON-LD (`Article`/`BlogPosting`,
|
|
`BreadcrumbList`, `WebSite`) is present where it applies.
|
|
- **Draft/scheduled exclusion:** `draft`, `in_review` and `scheduled` entries are excluded from
|
|
production builds, the sitemap and the feed; they are visible only in preview/local mode.
|
|
- **Seed data:** sample content (≥ 8 entries across ≥ 2 sections, ≥ 4 tags, ≥ 2 authors, one
|
|
draft and one scheduled entry) so the site is presentable on first run.
|
|
|
|
## 7. Non-functional requirements
|
|
|
|
This is the **SEO and performance** template, so these are hard requirements, not polish.
|
|
|
|
- **SEO:** semantic HTML (one `h1` per page, ordered headings), unique title/description per
|
|
route, absolute canonical URLs, a valid sitemap and feed, correct `hreflang`/locale if used,
|
|
and no indexable duplicate routes.
|
|
- **Performance:** static output where possible (pre-render every published route at build time);
|
|
a Lighthouse budget of LCP < 2.5 s and CLS < 0.1 on an article page; images optimised with
|
|
explicit width/height and lazy loading below the fold; no client JavaScript on non-interactive
|
|
pages (article, archives, 404); route-level code splitting only where interactivity needs it.
|
|
- **Accessibility (AA):** correct landmarks (`header`/`nav`/`main`/`footer`), heading order, alt
|
|
text on every meaningful image, labelled links and controls, visible focus, contrast at least
|
|
AA, keyboard-operable search and navigation.
|
|
- **Resilience:** explicit loading, empty and error states; a missing entry renders the 404 page
|
|
with a real 404 status, not an empty shell.
|
|
- **Observability:** build-time report of validation errors and skipped drafts; structured logs
|
|
for publish/build events; a health or build-status check for the deployed site.
|
|
- **Security:** no secrets in the repository; CMS tokens stay server-side and are documented in
|
|
`.env.example`; validate and cap CMS and search inputs.
|
|
|
|
## 8. Acceptance criteria (definition of done)
|
|
|
|
- [ ] Install, dev server, lint, typecheck, tests and production build all pass.
|
|
- [ ] A malformed front-matter entry (missing required field, unknown field or wrong type) **fails the build** with a message naming the file and field.
|
|
- [ ] `sitemap.xml` and `rss.xml`/`atom.xml` are generated, cover the published routes and validate against their schemas.
|
|
- [ ] Every route has a unique title, description and absolute canonical URL; Open Graph and JSON-LD are present.
|
|
- [ ] A static article page ships no client JavaScript and meets the LCP/CLS budget.
|
|
- [ ] Draft, in-review and scheduled entries never appear in the production build, sitemap or feed; preview still shows them.
|
|
- [ ] Search returns ranked results for published entries and has an explicit no-results state.
|
|
- [ ] Code highlighting, table of contents, reading time, related content and pagination work on seeded entries.
|
|
- [ ] Docs navigation (sidebar order, breadcrumbs, active highlight) works when `<content>` is documentation.
|
|
- [ ] Seeded sample content makes the site presentable immediately; `.env.example` documents every secret.
|
|
- [ ] README quickstart (install, run, build, env) is accurate; loading/empty/error states exist.
|
|
- [ ] Accessibility pass: landmarks, heading order, alt text, contrast AA, keyboard-operable search.
|
|
- [ ] CI runs install + lint + typecheck + tests + build.
|
|
|
|
## 9. Suggested build order
|
|
|
|
Follow this order and finish (and verify) a layer before starting the next:
|
|
|
|
1. **Scaffold** the chosen stack, install dependencies, get the dev server and the empty shell
|
|
running, and commit the skeleton.
|
|
2. **Content model + typed validation**: the `ContentType`/field schema, front-matter parsing and
|
|
the build-time validation that fails on a bad entry.
|
|
3. **Layouts + navigation**: base layout, section index, entry page, breadcrumbs, the docs sidebar
|
|
and taxonomy pages, rendered from seeded entries.
|
|
4. **SEO / feed / sitemap**: metadata per route, canonical URLs, JSON-LD, `sitemap.xml`,
|
|
`rss.xml`/`atom.xml`, `robots.txt`, Open Graph images, and draft/scheduled exclusion.
|
|
5. **Search & related content**: the search index or hosted search plus related/series links.
|
|
6. **Authoring workflow**: `<cms>` wiring and preview, roles, draft → review → publish, scheduling.
|
|
7. **Quality / performance**: tests for validation and rendering, static-output check, Lighthouse
|
|
budget, accessibility pass, CI, README and `.env.example`.
|