CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Val Town HTTP service that renders Japanese rail station number badges as SVG/PNG. Covers JR East square badges and Tokyo subway circular badges in the style of Wikipedia's JRSN/TSSN/JRLS/TSLS templates.

Development

This is a Val Town project — no build step, no package.json, no node_modules. Deno runtime with strict TypeScript.

  • Push changes: vt push
  • Stream logs: vt tail
  • Open in browser: vt browse

There are no tests or lint scripts configured.

Notion Integration

A Notion API token is stored in .env (git-ignored and vt-ignored). The token is used to populate a Notion database of Japanese rail stations/lines. The DB has three tables: Stations, Lines, and StationLine (join table with Station, Line, and Stop number). Badge PNGs from this API are used as Notion page icons.

Architecture

main.ts is the entry point (default export HTTP handler). Request flow:

  1. main.ts — URL routing, query param parsing, format dispatch (SVG/PNG/HTML), docs page generation
  2. badge.tsrenderBadgeSVG({style, line, number?, size?, color?, tlc?}) dispatches to the correct SVG renderer based on style ("jre"/"tssn") and presence of number
  3. colors.tsLINE_COLORS maps 100+ line codes to hex colors; getColor() resolves with optional override
  4. render.tssvgToPng() converts SVG strings to PNG using @resvg/resvg-wasm with Inter font from CDN

URL Patterns

/jre/{line}.{svg|png|html}           — square line symbol (JRLS)
/jre/{line}/{number}.{svg|png|html}  — square station badge (JRSN)
/tssn/{line}.{svg|png|html}          — circle line symbol (TSLS)
/tssn/{line}/{number}.{svg|png|html} — circle station badge (TSSN)

Query params: ?size= (default 30), ?color= (hex override), ?tlc= (three-letter code, JRE station badges only).

Badge Proportional Math

All dimensions are relative to size S. When modifying badge renderers, maintain these ratios from the Wikipedia templates:

  • JRSN (square+number): border S/10, content S*9/10, border-radius S/20
  • TSSN (circle+number): border S/8, content diameter S*3/4, outer radius fills viewBox (S/2)
  • JRLS (square only): same frame as JRSN, centered text S/2
  • TSLS (circle only): border S*6/25, content diameter S*13/25, outer radius S/2