# Oysterun Static Content V2 Contract

This directory owns canonical author input for Oysterun Blog and Tutorial.
It is outside `static/site/`, so raw fragments are never deployed as pages.

The root `AGENTS.md` definition of **Agent files** applies here. This file
specializes static-content authoring only; it does not replace the root
definition, precedence, ownership, or edit-authority rules.

## Repository Lifecycle

Read and follow:

```text
docs/routec/dev/repository_branch_release_workflow.md
```

After the accepted `develop` bootstrap, static-site source and article bundles
move through dedicated worktrees based on `develop` and land through its normal
review path. Site-only commits may be deployed independently after site
validation and explicit production authorization; they do not move npm
dist-tags, `beta`, or `main`. Never commit a site-only update to the frozen
Beta release snapshot.

Before the bootstrap readiness receipt is accepted, do not start new site work
from the legacy Beta or RouteCMain branch. Include any already accepted
pre-bootstrap site candidate in the bounded integration inventory. After
bootstrap, inclusion in a later beta release remains a separate Owner freeze
decision.

Follow the executable contract in:

```text
docs/routec/dev/static_site_content_workflow.md
docs/routec/dev/examples/static_site_content_v2/blog/
docs/routec/dev/examples/static_site_content_v2/tutorial/
```

## Ownership

An authoring Agent owns only one V2 bundle:

```text
<slug>/
  content.json
  zh/article.html
  en/article.html
  assets/
    cover.<png|jpg|jpeg|webp|svg>
    article.css
    interactive/<component-id>/
```

The fragment root is exactly one `<div data-oysterun-article-body>`. Do not
author a doctype, `html`, `head`, `body`, site header, primary nav, `main`,
footer, H1, global CSS, or shared-page JavaScript. Oysterun renders those from
one shared shell.

A cover is optional. Canonical Docs sources omit synthetic covers; Blog may
include a meaningful cover or use the renderer's clean no-cover fallback. When
present, the cover is local, decoded, 16:9, at least 1200x675, and has localized
`cover_alt`; when absent, omit both `cover_image` and every `cover_alt`.
Article CSS is optional; every selector must start with
`[data-oysterun-article-body]`.

Use semantic HTML, inline SVG, tables, native media, and approved YouTube
embeds for ordinary content. Custom JavaScript or Canvas is allowed only
through the declared `assets/interactive/<component-id>/` contract. The
renderer creates the iframe with exactly `sandbox="allow-scripts"`; the shared
fragment must retain a meaningful semantic fallback.

## Application Interface

```bash
npm run site:content:init -- --type blog --slug <slug> --output <agent-folder>
npm run site:content:validate -- --bundle <agent-folder>/<slug>
npm run site:content:preview -- --bundle <agent-folder>/<slug> --host 127.0.0.1 --port 0
npm run site:content:import -- --bundle <agent-folder>/<slug> --state draft --dry-run
npm run site:content:import -- --bundle <agent-folder>/<slug> --state draft --apply
```

Use `--type tutorial` for Tutorial. Init creates the exact bundle at
`<agent-folder>/<slug>`. Preview renders the whole site and separates the
exact draft route from a noindex published/index projection.

Import defaults to dry-run, rejects dirty repositories and collisions, and
never changes state, stages, commits, promotes, deploys, or cleans. Production
publication and deployment require separate explicit Owner authorization.

Never store credentials, private Host URLs, local paths, private notes, or
unreleased secrets in a bundle. Never stage unrelated files.
