RiotML / Brand and Design System / foundation first
Search the Roger / λ

The Jolly Roger · foundation first

Hacker precise /
human happy.

A pragmatic design system for the RiotML ecosystem, migrated in the same order it asks other surfaces to follow: tokens first, typography second, layout third, components after that.

01Tokens define the contract
02Typography consumes tokens
03The site uses the system
Why

Language ecosystems accumulate dense surfaces: package indexes, generated API docs, changelogs, diagnostics, install flows, examples, and reference pages.

How

Use strong hierarchy, square geometry, exact spacing, visible structure, and real code. Prefer useful density over decoration.

/01 Foundation

Tokens first

A small box of values. Memorize them.

Tokens are the first migration layer. Every later decision pulls from these variables: color, type families, spacing, borders, and shadows. If a page needs an off-system value, the system probably needs a new token first.

/01 · Color

Cream, coal, and one red.

Paper carries reading. Ink carries structure. Riot Red is identity and urgent action. Mint, amber, and blue are semantic states, not decoration.

Paper #FFF8ED · Default reading surface
Paper-2 #F5ECDC · Recessed surface
Ink #151317 · Text, borders, structure
Coal #0E0D10 · Terminal and code
Riot #F5334D · Flag, identity, primary action
Mint #24C08D · Success state
Amber #F0B429 · Warning state
Blue #2777FF · References and links

/02 · Typography

Display mono. Code mono. Quiet sans.

Martian Mono is the system voice. JetBrains Mono is the code voice. Atkinson Hyperlegible carries longer prose.

DisplayMartian Mono · 800
Hoist the λ

Hero only. Pair with the red slash sparingly.

HeadingMartian Mono · 800
Modern package management for OCaml.

Page and section titles.

SubheadingMartian Mono · 700
Spawning actors costs microseconds.

Cards, component names, dense labels.

BodyAtkinson Hyperlegible · 400

Riot ships a single tool, a modern package registry, a multi-core actor runtime, and a standard library designed for real systems.

Long reading, explanations, docs prose.

MonoJetBrains Mono · 500
$ riot add httpaf
→ resolved 12 packages in 84ms

Code, CLI, package names, table numerics.

/03 · Spacing

5px unit. Eight common steps.

Layout snaps to the 5px scale. Type can be optical when it needs to be, but spacing should stay boring.

u1 5px
u2 10px
u3 15px
u4 20px
u5 25px
u8 40px
u12 60px
u16 80px

/04 · Edges and shadows

Square first. Hard shadows.

Depth comes from ink borders and solid offsets. Radius is an exception for inputs, not the house shape.

radius 0
radius 2
offset 4
offset 6

/05 · Layout

Sidebar, chapter, body.

The documentation shell uses a persistent left rail, a sticky chapter marker, and a constrained content column. Dense pages stay readable because the grid is predictable.

Shell260px navigation + flexible main
Content1080px max width, 30px mobile gutter
Chapter170px marker + body column
Section60px vertical padding, 1px rule

/06 · Elevation

Hard offsets, no blur.

Elevation is a drawing rule, not atmosphere. Primary surfaces use solid ink offsets. Soft shadows stay out of product UI.

2px
4px
6px
flat rule

/07 · Code

Terminal output is UI.

Diagnostics, commands, package names, paths, and numeric output use the mono channel. Color always means state.

λ riot fmt --check
ok 128 files formatted
json: {"event":"fmt.checked","files":128}

/08 · Accessibility

Useful density needs contrast.

The system can be compact because text, borders, focus, and state colors remain legible on every supported surface.

ContrastInk on paper for primary reading.
FocusUse visible ink or riot outlines, never glow only.
ColorState labels must not rely on color alone.
MotionHover movement is one or two pixels maximum.
/02 Articles

Rules for judgment

Short enough to stay in cache.

These are the rules every Riot surface has to live by: the website, registry, docs, CLI output, README badge, and release notes.

Dense by default

Riot surfaces carry package lists, version matrices, error logs, and dependency trees. Density is respect for an expert reader when hierarchy is clear.

UseTables, mono columns, inline metadata, tabular numbers.
SkipMarketing cards that hide the actual data.
TestCan a maintainer answer the question in one glance?
›_

Terminal-native

Install, build, test, publish, and debug happen in the terminal. CLI output and copyable commands are first-class design surfaces.

UseLambda prompts, aligned labels, fix commands, JSONL when piped.
SkipLong prose errors that bury the fix below the fold.
TestDoes it still read well in plain ASCII, no colors?

Excellent

Excellent means the obvious path is polished: first search, first install, first error, first generated doc page, and first copy-pasted example.

UseWorking examples, direct links, exact versions.
SkipPlaceholder screenshots and fake product chrome.
TestDoes this page help someone ship today?

Calm confidence

Riot can have an edge without becoming noisy. Red is a signal. Structure does most of the talking.

UseFew colors, crisp borders, deliberate red accents.
SkipOver-rounded shapes, gradients, mascot clutter.
TestDoes it feel sharp, useful, and trustworthy?
/03 Identity

The flag

A black flag with a white λ.

The lambda ties Riot to ML and functional programming. The flag gives the ecosystem its edge. On cream, the red offset is part of the mark, not a decorative shadow.

/A · Primary mark

RiotML · The Jolly Roger

/B · Context

Black flag with red offset is the default. On dark surfaces the flag inverts to paper. On red, the offset flips to paper so the silhouette stays crisp.

on cream
on coal
on amber
on red
/04 Components

Built from tokens and type

A handful of pieces. Used a lot.

Components are repeated decisions. Buttons, tables, diagnostics, pills, and callouts use the same token contract documented above.

Buttons

Square, command-shaped, imperative.

Package cards

Compact cards for recently published packages.

std@0.6.0

Datatypes, collections, IO, time, formats, crypto.

↓ 1.2M · today
krasny@0.2.1

Web framework on top of httpaf and the actor runtime.

↓ 98K · 1d

Diagnostics

Compiler errors are product surfaces.

error[R0087] Type mismatch in fold accumulator
  ┌─ src/main.ri:42:13
42 │ let total = items |> List.fold (+) "zero"^^^^^^ expected int, found string
help: change "zero" to 0

Tables

The natural form for registries and version matrices.

PackageVersionCategoryDownloads
std0.6.0core1,247K
http0.7.1net840K
krasny0.2.1web98K

Forms

Inputs are compact, labeled, and bordered in ink.

Commands

Copyable command strips for docs and install flows.

curl -sSL https://get.riot.ml | sh
riot add krasny http postgres

API rows

A dense row for generated docs and registry APIs.

Result.map('a -> 'b) -> ('a, 'e) t -> ('b, 'e) tstable
Package.searchquery:string -> package list promisebeta
Docs.renderartifact -> html resultstable

Callouts

A left rule, one label, one useful note.

Note

Use riot fmt. There is one style, and the formatter is part of the product surface.

Indexes

Module indexes should scan like a map, not a grid of teasers.

Release notes

Version, date, and exactly what changed.

0.6.0Static docs shell, package cards, and terminal diagnostics.
0.5.2Registry tables moved to the Jolly Roger density rules.
0.5.0First pass at voice rules for CLI output and agents.
/05 Applications

In the wild

Same system, different densities.

RiotML is declarative. pkgs.ml is table-first. docs.pkgs.ml is long-form reference. The flag and tokens make them feel like one ecosystem.

https://riot.ml

riot.ml

Many OCaml stacks.
/ One flies a flag.

One tool, a modern package registry, an actor runtime, and a stdlib that ships the common path.

std@0.6.0

Standard library surface for system work.

published today
kernel@0.0.18

Core abstractions shared across Riot.

updated 6h ago
https://pkgs.ml
pkgs.ml
1,247 packages
Total packages1,247
Downloads8.4M
Publishers309
Median publish1.8s
Package Version Description Category Downloads Updated
std 0.4.0 Standard library. Datatypes, collections, IO, time, formats. core 1,247,890 today
httpaf 0.7.1 Fast, low-allocation HTTP/1.1 server and client. net 840,221 2d
kernel 0.0.18 Core abstractions shared across the Riot ecosystem. core 620,498 6h
krasny 0.2.1-rc Web framework on top of httpaf and the actor runtime. web 98,114 1d
https://docs.pkgs.ml/p/kernel/0.0.18/Kernel/Result
RiotML Docs kernel / Kernel / Result v0.0.18

module · Kernel.Result

Result

Errors are values. Results carry them through pipelines, actor boundaries, and logs.

type ('a, 'e) t = Ok of 'a | Error of 'e
val map : ('a -> 'b) -> ('a, 'e) t -> ('b, 'e) t
Use let* for chains. Stop nesting binds when the next step can fail.
terminal surfaces

CLI

Plain text still carries the brand.

Prompts, aligned labels, diagnostic IDs, and fix commands should work without browser chrome.

λ riot publish --dry-run
ok package checked
package: krasny
version: 0.2.1
next: run riot publish
/06 Voice

How we sound

Plainspoken, technical, lightly opinionated.

One piece of pirate flavor per page is plenty. The rest is straight engineering: name the function, show the command, explain the tradeoff, move on.

Do

Direct, technical, present tense.

  • State the function in sentence one.
  • Use precise commands, package names, versions, and diagnostics.
  • Prefer direct maintainer language over stage copy.
  • Show the fix in the same surface as the error.

Don't

No stage copy. No hedging.

  • Do not hedge every line with maybe, try, or consider.
  • Do not use pirate flavor as a substitute for clarity.
  • Do not hide important registry or diagnostic data behind clicks.
  • Do not soften the system until it looks like generic docs.

Error voice

Name the problem first.

  • Name the package, source, requested symbol, and nearest fix.
  • Use "Riot could not..." when the tool failed.
  • Use "This package..." when the project shape is wrong.
  • End with one concrete edit, command, or docs link.

Agent-friendly voice

Stable labels. Copyable examples.

  • Use labels tools can parse: package, source, module, fix.
  • Prefer short structured paragraphs over clever prose.
  • Make examples runnable without hidden setup.
  • Avoid maybe, try, and should when the fix is known.

Rules of the deck

  1. Function in sentence one. If the first sentence does not say what the thing does, the rest is filler.
  2. Imperative for actions. Install Riot. Read the docs. Run riot fmt.
  3. Code first, prose second. If a snippet shows the idea, delete the extra prose.
  4. Numbers are mono. Versions, downloads, durations, error IDs, and counts.
  5. Do not apologize for opinions. The stack has a point of view. The brand does too.