view .claude/skills/zenbu-personal-site/SKILL.md @ 264:04fee26ecce0

add authenticated JRPG conversation platform Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 07:34:12 -0700
parents b401627fc49e
children 056790c4fb0d
line wrap: on
line source

---
name: zenbu-personal-site
description: Use this skill when updating the mrjunejune personal website, blog, resume, tools, notes/editor APIs, uploads, PWA assets, or deployment bundle.
---

# Mrjunejune Personal Site

Use this skill for `mrjunejune/`, the personal website served by a C backend.

## Structure

- `mrjunejune/main.c`: C web server, routes, APIs, S3 upload URL generation, editor persistence, media conversion, WebSocket chat.
- `mrjunejune/src/`: static site source files and HTML templates.
- `mrjunejune/src/parts/`: shared HTML includes used by `{{...}}` template placeholders.
- `mrjunejune/src/public/`: public assets, PWA files, media, generated JS, icons, resume PDF.
- Zenbu UI assets are copied from `//design_system:components` and
  `//design_system:styles` into `src/public/design-system/` by Bazel. Do not
  hand-copy or fork shared component files.
- Preserve the site's established transparent content and plain header/icon
  presentation. Use `appearance="plain"` when shared behavior is useful, and
  do not introduce cards, shadows, borders, or surfaces without a concrete UX
  reason.
- Every site-owned `zen-button` declares an `xs` / `sm` / `md` / `lg` / `xl`
  size. Site CSS must consume inherited `--zenbu-control-*` aliases plus
  `--zenbu-sys-padding-*` and typography roles instead of hardcoding control
  padding or height.
- New site CSS uses `--zenbu-sys-*` semantic roles. Do not consume
  `--zenbu-ref-color-*` or add new `--zen-*` compatibility-token usage.
- `mrjunejune/test/`: integration tests and snapshots.
- `mrjunejune/BUILD`: Bazel build, bundle, asset movement, and test-visible filegroups.
- `mrjunejune/.config` and `.config.development`: server configuration. Do not commit secrets.
- The JRPG chat is a production route. Seobeo owns conversation CRUD and POST
  SSE, Deita stores turns, and a Bazel-managed Python Copilot SDK sidecar uses a
  loopback LiteLLM `github_copilot` provider. Never use a virtualenv or pip
  install workflow.

## How rendering works

Handlers allocate a response body from `Dowa_Arena`, render an HTML file with `Seobeo_Render_Html_FilePath`, and return a response map:

```c
Seobeo_Request_Entry *resp = NULL;
char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
Seobeo_Render_Html_FilePath(final_body, "/tools/index.html", arena);
Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
return resp;
```

The simple template renderer replaces `{{...}}` tokens with file contents loaded through `Seobeo_Web_LoadFile`.

Before adding or changing HTML controls, read
`design_system/wiki/HTML_AUTHORING.md` and `PRIMITIVE_MAP.md`. Every authored
interactive control must have exactly one appropriate Zenbu owner while
retaining its native element underneath.

## Routes and features

Existing route areas include:

- Home, resume, tools, markdown-to-HTML, file converter, blog, talk/chat, notes, and editor pages.
- Redirect helpers built with `CREATE_REDIRECT_HANDLER`.
- File/media conversion APIs using `ffmpeg` and temporary files under `/tmp`.
- S3 presigned upload URL API using `Authorization: Bearer <token>`.
- Editor save/load APIs backed by `deita` SQLite.
- WebSocket chat broadcasting through seobeo WebSocket server APIs.

When adding pages, add the HTML/CSS/JS under `src/`, register a route in `main.c`, and update tests/snapshots if the route should be covered.

## Build and test

```bash
bazel build //mrjunejune:mrjunejune_server
bazel build //mrjunejune:mrjunejune_server_bundle
bazel test //mrjunejune/test:integration_test
bazel test //mrjunejune/test:theme_and_webp_test
```

The JRPG browser acceptance is sharded by concern:

- `//mrjunejune/test:jrpg_core_test`
- `//mrjunejune/test:jrpg_jrpg_test`
- `//mrjunejune/test:jrpg_routing_test`
- `//mrjunejune/test:jrpg_hls_test`

`//mrjunejune/test:theme_and_webp_test` is the aggregate `test_suite`; Bazel
runs its shards in parallel. Keep future slow browser scenarios in the narrowest
independent shard, or create another shard rather than extending one serial
test process. Give every shard its own port, temporary database, and fixture
state.

Run the complete local inference stack with:

```bash
export GITHUB_COPILOT_TOKEN_DIR="$HOME/.local/state/mrjunejune/inference/litellm-copilot"
bazel run //mrjunejune/inference:litellm_proxy -- \
  --authenticate \
  --token-dir "$GITHUB_COPILOT_TOKEN_DIR"

LITELLM_MASTER_KEY='<local proxy key>' \
  MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE=1 \
  bazel run //mrjunejune:run_inference_stack
```

Use `bazel run //mrjunejune:run_inference_stack -- --mock` for deterministic
UI development through the real Seobeo, Deita, inference bridge, and SSE path
without Copilot authentication or a LiteLLM key. Mock stream scenarios are
maintained as `!command` event scripts in
`mrjunejune/inference/mock_responses.json`; custom event types pass through
Seobeo to the page's `mjj-jrpg-stream-event`.

## Production-minded checklist

- Use Dowa's fixed-width aliases and `boolean`/`TRUE`/`FALSE` in first-party C
  instead of introducing `<stdint.h>` `_t` types or `<stdbool.h>` `bool`.
- Keep auth-protected APIs strict: missing auth should be `401`, invalid token `403`, malformed JSON/input `400`, unavailable DB/S3/ffmpeg `500`.
- Never hardcode secrets. Read configuration from `.config` or environment wiring already used by the Bazel target.
- For uploads and downloads, validate filenames and content lengths before touching `/tmp`.
- For binary responses, set `content-length` and avoid string-only operations on body bytes.
- If a route is part of the public website, add or update snapshot coverage in `mrjunejune/test`.
- Keep PWA changes consistent across `manifest.json`, `sw.js`, icons, and `PWA_SETUP.md`.
- Site themes use `data-zen-theme` with Auto, Paper, Ink, Playful, and
  Cyberpunk states.
  Preserve the More Sugar font aliases and keep theme-specific values in shared
  design-system tokens rather than branching inside components.
- Reuse `seobeo`, `dowa`, `deita`, `s3`, and `markdown_converter` instead of adding parallel implementations.