---
name: oysterun-website-authoring
description: Use when an Oysterun worker or agent needs to author a repo-local static website or HTML report that Host serves from an agent folder through .oysterun/site and the canonical /sites/<agent_id>/ route, without running CCStockWorkEnv, a localhost web server, browser/MCP, Mail, scheduler, or Host lifecycle commands.
metadata:
  short-description: Author Oysterun static sites
---

# Oysterun Website Authoring

Use this skill when a route asks you to create or update a static Oysterun website, report site, dashboard, or browser-facing HTML deliverable for an agent folder.

This is the repo-local Codex version of the CCStockWorkEnv site-authoring pattern. It keeps the useful authoring contract and removes any dependency on real CCStockWorkEnv commands or global skills.

Canonical product skill source lives at `skills/oysterun-website-authoring/`. The repo-local Codex mirror at `.codex/skills/oysterun-website-authoring/` and the Host packaged asset at `host-service/assets/product-skills/oysterun-website-authoring/` are generated mirrors. Run `node tool_scripts/sync_product_skills_to_codex.mjs` after changing this skill and `node tool_scripts/check_product_skill_mirrors.mjs` before review.

## Guardrails

- Do not run CCStockWorkEnv, scheduler, Mail runtime, browser/MCP, Host restart, served refresh, dependency install, staging, commit, snapshot, merge, or push unless the active route explicitly asks for that work.
- Do not require `vite`, `python -m http.server`, `npx serve`, Django, or any localhost server for the final Oysterun user flow.
- Do not tell users to open `file://` URLs or fixed-IP report URLs.
- Do not print tokens, cookies, passwords, auth headers, or raw credential material.
- Fail fast when the target agent folder, agent id, source body, or required page path is missing.
- Keep browser-facing files inside the target agent folder's configured website root.
- Put downloadable non-site outputs under `.oysterun/artifacts/`, not inside `.oysterun/site/`, unless they are intentionally served as raw site assets.

## Current Host Contract

- Shared agent config: `.oysterun/config.json`
- Local private overrides: `.oysterun/local.json`
- Default website root: `.oysterun/site`
- Shared website config keys: `web.root` and `web.access`
- Supported `web.access` values: `owner_only`, `password`, `public`
- Canonical browser route: `/sites/<agent_id>/...`
- Required entry page: `.oysterun/site/index.html`
- The website belongs to the `agent_id`, not one session, and remains available while the agent folder and site files exist.

Use `owner_only` unless a route explicitly asks for public or password-protected access.

## Preferred Structure

```text
agent-folder/
  .oysterun/
    config.json
    local.json
    site/
      index.html
      assets/
        app.css
        app.js
      reports/
        daily.html
    artifacts/
      exports/
        daily.csv
      reports/
        daily.pdf
```

## Helper

The bundled helper performs deterministic static checks and optional scaffolding. It uses only Node standard library APIs and does not call Host. In repo-local Codex tasks, the mirrored helper path is:

```bash
node .codex/skills/oysterun-website-authoring/scripts/site_author.mjs <command> [args]
```

When Host injects this skill into a live session, the helper path is:

```bash
node .claude/skills/oysterun-website-authoring/scripts/site_author.mjs <command> [args]
```

Commands:

```bash
node .codex/skills/oysterun-website-authoring/scripts/site_author.mjs validate \
  --agent-folder /absolute/path/to/agent-folder \
  --agent-id <agent_id>
```

```bash
node .codex/skills/oysterun-website-authoring/scripts/site_author.mjs manifest \
  --agent-folder /absolute/path/to/agent-folder \
  --agent-id <agent_id>
```

```bash
node .codex/skills/oysterun-website-authoring/scripts/site_author.mjs init \
  --agent-folder /absolute/path/to/agent-folder \
  --agent-id <agent_id> \
  --access owner_only
```

`init` creates `.oysterun/config.json`, `.oysterun/site/`, `.oysterun/site/assets/`, and a minimal `.oysterun/site/index.html` only when a route explicitly authorizes site source changes.

## Authoring Workflow

1. Confirm the target agent folder and agent id from the active route or Host metadata.
2. Inspect `.oysterun/config.json` if it exists.
3. If `web.root` is absent, use `.oysterun/site`; if `web.access` is absent, use `owner_only`.
4. Write the website under the resolved site root:
   - `index.html` is mandatory.
   - CSS, JS, images, and fonts should live under `assets/`.
   - Report pages should live under `reports/` and be linked from `index.html`.
5. Use relative links and relative asset paths inside the site.
6. Keep source file preview paths separate from browser routes. `.oysterun/site/index.html` is a source path; `/sites/<agent_id>/` is the browser route.
7. Validate locally with the helper before reporting completion.

## Phone-First Requirements

- Design for a 375px-wide phone viewport first, then enhance desktop.
- Every HTML page should include:

```html
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
```

- Keep controls tap-friendly, generally at least `44x44` CSS pixels.
- Do not depend on hover-only interactions.
- Avoid fixed-width layouts that cause horizontal overflow.
- Put wide tables, charts, code blocks, and dense content inside explicit scrollable regions.
- Include mobile-friendly metadata such as `theme-color` when useful.
- Do not claim offline support, installability, or service-worker behavior unless implemented.

## Completion Output

When reporting a completed site authoring task, include:

- site root, usually `.oysterun/site`
- browser entry route as plain text or a Markdown link, for example `/sites/<agent_id>/`
- report browser links when report pages exist
- source HTML paths as plain resolvable paths when file preview is useful
- artifact paths under `.oysterun/artifacts/` when downloads were created
- validation command results, with secrets omitted

Do not wrap `/sites/<agent_id>/...` browser routes in backticks when they should be clickable in chat.
