# Project: a kid's tinycoders site

This project deploys to **tinycoders.ai**, where it'll be served at `<kid>.tinycoders.dev`.

## Hard constraints

This site must be **fully static**. The deployer will reject anything else.

Allowed:
- Plain HTML, CSS, JavaScript files
- Static assets (images, fonts, sounds) bundled into the project
- Astro, Vite, or Next.js with `output: 'export'`

Not allowed:
- Next.js API routes, server actions, middleware, or `getServerSideProps`
- Any backend code, databases, or environment-secret-driven server logic
- Server-side image optimization (use `unoptimized: true` for `next/image`)
- Websockets, SSR, edge functions

If asked to add a backend feature, refuse and suggest a static alternative
(precomputed JSON file baked into the build at build time, etc.).

## Content Security Policy — read this carefully

Deployed sites are served with a **strict CSP**. Code that works locally will silently
break in production if it violates these rules. Generate code that complies *up front* —
do not rely on the kid to debug a blank page.

The exact policy applied to every HTML response:

```
default-src 'self';
img-src 'self' data: blob:;
media-src 'self' data: blob:;
style-src 'self' 'unsafe-inline';
script-src 'self';
font-src 'self' data:;
connect-src 'self';
frame-ancestors 'none';
base-uri 'self';
form-action 'self'
```

What this means in practice — **follow these or the site will break in production:**

- **No inline `<script>` blocks.** `script-src 'self'` blocks them. Put all JS in
  separate `.js` files and load them with `<script src="./app.js"></script>`.
- **No inline event handlers.** `onclick="..."`, `onload="..."`, `onsubmit="..."`,
  etc. are all blocked. Use `addEventListener` from a `.js` file instead.
- **No `javascript:` URLs.** Use a real handler attached via `addEventListener`.
- **No `eval`, `new Function(...)`, or string-form `setTimeout`/`setInterval`.**
  These are blocked by default CSP and will throw at runtime.
- **No external scripts or libraries from CDNs.** `<script src="https://cdn..."></script>`,
  the Tailwind Play CDN, jsdelivr, unpkg, cdnjs — all blocked. Bundle libraries
  into the build (npm install + import) or copy the file into the project.
- **No external fonts via `<link>`.** Google Fonts (`fonts.googleapis.com`) and any
  other third-party font host is blocked. Use local font files (woff2 in the
  project) and `@font-face`, or rely on system fonts (`font-family: system-ui, ...`).
- **No external stylesheets.** `<link rel="stylesheet" href="https://...">` is
  blocked. Bundle CSS locally.
- **No `fetch()` / `XMLHttpRequest` / WebSocket to other origins.** `connect-src 'self'`
  means the browser will refuse network calls to anywhere except the kid's own
  subdomain. No public APIs, no third-party services, no analytics, no Firebase.
  If you need data, bake it into a JSON file at build time.
- **No `<iframe>` embeds from other sites.** No YouTube embeds, no Spotify embeds,
  no CodePen embeds — `default-src 'self'` blocks the frame source.
- **Images, audio, and video** can use local files, `data:` URIs, or `blob:` URLs.
  External image hosts are blocked.
- **Inline `<style>` blocks and `style="..."` attributes ARE allowed** (style-src
  includes `'unsafe-inline'`). Stylesheets are the one place inline content works.

Quick rule of thumb: if the URL in your HTML/CSS/JS doesn't start with `./`, `/`,
`data:`, or `blob:`, it will probably be blocked. When in doubt, bundle it locally.

## Mobile friendly

Most kids and parents will view the site on a phone. Every generated site must:

- Include `<meta name="viewport" content="width=device-width, initial-scale=1">` in
  the `<head>` of every HTML page.
- Use responsive layout (CSS Grid, Flexbox, or `clamp()` for type) — no fixed
  pixel widths that overflow a 360px-wide phone screen.
- Use tap-friendly hit targets (buttons and links at least ~44x44 CSS pixels).
- Use readable type on small screens (body text ≥ 16px so iOS doesn't zoom on
  focus; headings scale up from there).
- Avoid hover-only interactions — anything important must work on tap.
- Test mentally at 360px wide before declaring the layout done.

## Audience

The site is being built by an elementary-school kid (with parent help). All
generated content should be:

- Kid-appropriate (no mature themes, scary content, or explicit language)
- Friendly, encouraging, and visually playful — bright colors, big text, clear navigation
- **Free of personal information.** Never include the kid's full name, age, school,
  address, phone number, photo of their face, or other identifiers — even if mentioned
  in the prompt. Use a nickname or first-name-only at most. tinycoders is directed to
  children and treats personal info conservatively to comply with COPPA.

## Tone for generated copy

- Warm, encouraging, and a little silly is great
- Avoid sarcasm, snark, or anything that punches down
- Big readable type, generous spacing, high contrast

## Deploy

```
npx tinycoders deploy
```

This uploads the build output. The parent then clicks **Approve** in their
tinycoders dashboard to push it live.
