# AlphaBeta Studio — full documentation for LLMs and agents AlphaBeta Studio is a free, open-source, fully client-side web application for designing original typefaces and exporting them as real, installable font files. Source: https://github.com/moji-ux/font-studio ## What the app does 1. **Compose** — the home page (`/`) offers character-set presets (Basic Latin, Uppercase only, Farsi/Persian with presentation forms for proper RTL joining, and more) plus an **import card**: drop a `.alphabeta.json` project file that brings its own character set — any Unicode script (Latin, Persian, Japanese, Greek, mixed). Picking a preset or importing a file creates the working project. 2. **Refine** — the studio (`/studio`) shows a glyph grid. Per glyph you can: drop an SVG or PNG drawing onto a cell (raster images are auto-vectorized), open the bezier editor to drag anchors and control handles, add/delete points, and adjust advance width and side bearings. Project-wide tools: "fill" populates every glyph from a donor font (bundled or user-imported), and "distort" applies jitter / smooth / roughen / inflate / skew at an adjustable intensity. 3. **Ship** — the export page (`/export`) sets family name, style name and designer, then builds OTF, TTF, or WOFF2 files in the browser (opentype.js + wawoff2). Nothing is uploaded; there is no server. Projects autosave to browser storage and round-trip as portable JSON files with the extension `.alphabeta.json` — specified below so an agent can generate one programmatically. Users import them from the landing page (click or drag-and-drop on the import card) or the studio actions menu. Projects can also be SHARED. Two link forms: - **Short links** `/f/` — the compressed payload is stored server-side (Vercel Blob + Upstash Redis); the page shows a specimen, view/open counts, and an "open in studio" button. Slugs default to the font name and are rename-able by the share's creator (proven by an edit token issued at creation); renamed-away slugs keep resolving as aliases. Shared fonts appear in the landing-page gallery with search and trending/new/most-viewed ordering. - **Fragment links** `/studio#p=2:…` — the whole compressed project in the URL fragment; fully serverless fallback. Share API (also usable by agents): `POST /api/shares` with `{"payload": "", "previewSvg"?: ""}` → `{slug, id, editToken, url}` (server-side validation decodes the payload through the same path as file import); `GET /api/shares/` → metadata; `GET /api/shares//payload` → the bytes; `PATCH /api/shares/` with `{newSlug, editToken}` → rename; `GET /api/showcase?q=&sort=trending|new|views&limit=&offset=` → the gallery feed. --- ## The `.alphabeta.json` project file format (version 2) A project file is a single UTF-8 JSON document: ```json { "kind": "alphabeta-studio.project", "version": 2, "project": { ... } } ``` - `kind` (string, REQUIRED) — must be exactly `"alphabeta-studio.project"`. - `version` (number, REQUIRED) — must be `2`. There is no other version. - `project` (object, REQUIRED) — the payload, described next. ### `project` object | Field | Type | Required | Notes | |--------------|------------------|----------|-------| | `name` | string | no | Font family name (defaults to "Untitled"). | | `styleName` | string | no | e.g. "Regular", "Bold" (defaults to "Regular"). | | `designer` | string | no | Credited in exported font metadata. | | `charset` | number[] | no | Unicode codepoints (decimal) in glyph-grid display order. **Any codepoints whatsoever** — the app's presets impose no restriction. Carries ordering and undrawn placeholder cells. Glyphs keyed outside it are still imported (appended in codepoint order); omit it and the charset derives from the glyph keys. | | `metrics` | object | no | See Metrics; per-field defaults. | | `glyphs` | object | YES | Map keyed by decimal codepoint string (e.g. `"19968"` for 一). See Glyph. | | `preview` | object | no | `{ "text", "sizePx", "trackingEm" }` — the live preview banner. Defaults to a sample built from the project's own characters. | ### Metrics All values in font units on a `unitsPerEm` grid. Defaults: ```json { "unitsPerEm": 1000, "ascender": 800, "descender": -200, "capHeight": 700, "xHeight": 500 } ``` `descender` is NEGATIVE (distance below the baseline). Keep `ascender - descender ≈ unitsPerEm` for well-behaved line spacing. ### Glyph Each entry in `glyphs`: ```json { "commands": [ ... ], "advanceWidth": 600, "leftSideBearing": 50 } ``` - `commands` (array, REQUIRED) — the outline; see Commands. An empty array means the glyph is not drawn yet (excluded from font export, except the space character, which is always exported width-only). - `advanceWidth` (number, optional, default 600) — horizontal advance. - `leftSideBearing` (number, optional, default 50). That is the whole glyph shape — no statuses, ids, or undo stacks exist in the file format. ### Commands — the outline format `commands` is a flat array of absolute path commands. Allowed shapes: ```json { "type": "M", "x": 0, "y": 0 } { "type": "L", "x": 0, "y": 0 } { "type": "C", "x1": 0, "y1": 0, "x2": 0, "y2": 0, "x": 0, "y": 0 } { "type": "Q", "x1": 0, "y1": 0, "x": 0, "y": 0 } { "type": "Z" } ``` Coordinate system — the part agents most often get wrong: - **Font units, not pixels**: an em square spans `unitsPerEm` units (1000 by default). - **Y points UP**: the baseline is `y = 0`; capitals typically span `y = 0` to `y = capHeight` (700); descenders dip to negative y (≥ `descender`, −200); CJK glyphs conventionally fill roughly −80…700. This is the OPPOSITE of SVG screen coordinates — if converting from an SVG `d` string, flip Y first. - **X grows right** from `x = 0`; keep the outline roughly within `0 … advanceWidth`. - Every contour starts with `M` and should end with `Z`. Multiple contours per glyph are fine (the two stems and crossbar of an H, the box and window of 口). - Fill rule is **nonzero**: counters (the hole in O, the window of 口) must wind in the OPPOSITE direction from the outer contour, or they will be filled solid. Same-direction overlapping contours union. - Arcs are not supported — approximate them with `C` (cubic) segments. ### Script notes - **Any Unicode works.** Grid cells label themselves with the literal character (あ, Ω, 字); exported fonts use standard PostScript names where they exist and `uniXXXX` otherwise. - **Right-to-left**: Arabic-block codepoints lay out RTL automatically in the preview. Farsi charsets should include the presentation forms (U+FB50–U+FEFF) used by the app's Farsi preset so exported fonts join correctly; the preview applies contextual shaping automatically. ### Validation behaviour on import Forgiving about content: missing optional fields get defaults, an empty cell is synthesized for any charset codepoint without a glyph entry, and glyphs outside the charset are appended rather than dropped. Strict about the envelope: wrong `kind`, any `version` other than `2`, or a non-object `project` are rejected with an error message. ### Minimal complete example (Japanese) A project containing 一 (a drawn bar), 口 (box with a correctly-wound counter window), and a space — importable as-is: ```json { "kind": "alphabeta-studio.project", "version": 2, "project": { "name": "Agent Mincho", "charset": [19968, 21475, 32], "glyphs": { "19968": { "commands": [ { "type": "M", "x": 60, "y": 300 }, { "type": "L", "x": 660, "y": 300 }, { "type": "L", "x": 660, "y": 380 }, { "type": "L", "x": 60, "y": 380 }, { "type": "Z" } ], "advanceWidth": 720 }, "21475": { "commands": [ { "type": "M", "x": 80, "y": 0 }, { "type": "L", "x": 640, "y": 0 }, { "type": "L", "x": 640, "y": 620 }, { "type": "L", "x": 80, "y": 620 }, { "type": "Z" }, { "type": "M", "x": 180, "y": 100 }, { "type": "L", "x": 180, "y": 520 }, { "type": "L", "x": 540, "y": 520 }, { "type": "L", "x": 540, "y": 100 }, { "type": "Z" } ], "advanceWidth": 720 }, "32": { "commands": [], "advanceWidth": 300 } }, "preview": { "text": "一口 一口", "sizePx": 96, "trackingEm": 0 } } } ``` This exact file is downloadable at `/skills/alphabeta-project/example.alphabeta.json`, and an agent-skill version of this spec at `/skills/alphabeta-project/SKILL.md`. --- ## Language charset templates Ready-to-import templates for 16 languages — each is a valid v2 project file with a comprehensive character set for the language, an empty glyph map, and a native preview sentence. Importing one yields a ready-to-draw grid. Every template is also a card on the app's landing page, paired with a bundled default font (subset Noto fonts, OFL-licensed) so picking it there starts the project with all glyphs filled in that font. Machine- readable index: `/templates/index.json`. | Template | File | Codepoints | Covers | |---|---|---|---| | English · Latin | `/templates/english.alphabeta.json` | 159 | printable ASCII + Latin-1 diacritics | | Mandarin Chinese · Han | `/templates/chinese.alphabeta.json` | 125 | ~100 most frequent hanzi + ideographic punctuation | | Hindi · Devanagari | `/templates/hindi.alphabeta.json` | 101 | vowels, consonants, matras, virama, danda, digits | | Spanish · Latin | `/templates/spanish.alphabeta.json` | 111 | ASCII + áéíóúüñ + ¿¡ | | French · Latin | `/templates/french.alphabeta.json` | 129 | ASCII + full diacritics, œ/æ, «» | | Arabic · Arabic | `/templates/arabic.alphabeta.json` | 201 | letters, tashkeel, digits + Presentation Forms-B | | Bengali · Bengali | `/templates/bengali.alphabeta.json` | 84 | full block essentials incl. khanda-ta, ড়/ঢ়/য় | | Portuguese · Latin | `/templates/portuguese.alphabeta.json` | 119 | ASCII + ãõç and accent set | | Russian · Cyrillic | `/templates/russian.alphabeta.json` | 163 | А–я + Ё/ё + ASCII + «» | | Urdu · Arabic | `/templates/urdu.alphabeta.json` | 248 | Urdu alphabet + digits + Forms-A/B contextual forms | | Farsi · Arabic (Persian) | `/templates/farsi.alphabeta.json` | 202 | 33 Persian letters + hamza variants, diacritics, Forms-A/B | | Japanese · Kana + Kanji | `/templates/japanese.alphabeta.json` | 235 | full hiragana + katakana, ideographic punctuation, starter kanji | | Korean · Hangul | `/templates/korean.alphabeta.json` | 117 | compatibility jamo + common-word syllables | | German · Latin | `/templates/german.alphabeta.json` | 104 | ASCII + ÄÖÜäöüß + „quotes“ | | Vietnamese · Latin (extended) | `/templates/vietnamese.alphabeta.json` | 223 | ASCII + full tone-marked vowel set (U+1EA0–1EF9) | | Greek · Greek | `/templates/greek.alphabeta.json` | 87 | monotonic alphabet with tonos/dialytika | To build templates for OTHER languages, follow the per-script-family recipes (Latin diacritics, Cyrillic outliers, the four required layers of Arabic-script sets, Indic block structure, CJK frequency subsets) in the skill at `/skills/alphabeta-language-templates/SKILL.md`. Universal rules: charset order = grid display order; the preview sentence must only use codepoints present in the charset; name the project ` ·