---
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.
- `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.

## 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`.

## 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
```

Use the debug server when investigating routing or networking:

```bash
bazel build //mrjunejune:mrjunejune_server_debug -c dbg
```

## 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, and Playful 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.
