Riot’s Jolly Roger

The flag and surface system for RiotML: one voice across web, CLI, docs, packages, diagnostics, and releases.

What is Jolly Roger?

Jolly Roger is Riot’s design system. In many ways, it is our very own pirate flag: it describes the values this stack, and all the supporting systems around it, lives and dies by.

In this document you'll find everything we use to design Riot, from its CLI surface, to the way our docs and pkgs.ml look, to the voice we use to write prose and code.

Optimize for Developer Joy

I get joy out of building good software. Especially when it works, but even more so when it looks beautiful and runs fast.

Every interaction with Riot should make information clear, feedback actionable, and iteration fast. Put commands near claims, examples near explanations, and recovery paths near failures.

Joy does not mean everything is soft, friendly, or simplified until it becomes useless. Riot can be sharp. It can be loud. It can be opinionated. It can say no.

In Practice

  • When running CLI commands, there is always prompt feedback with the right amount of information to understand what is going on. The output should say what Riot is doing, what changed, what succeeded, and what still needs attention without turning every command into a wall of logs.
  • When something goes wrong, there is always a clear next step to take. The user should know how to fix it, where to look deeper, how to report the issue, or what command to run next.
  • When searching for things, results should bring back adjacent information that helps the user find exactly what they want faster: package names, versions, docs status, freshness, owners, related modules, and enough context to make the next click obvious.

Design as One Piece

Riot is one piece, not many. The compiler, runtime, actor model, package manager, docs generator, registry, test runner, formatter, diagnostics, install scripts, standard library, and website should feel like parts of the same whole.

Make the preferred path obvious. A golden path is not a prison; it is the route designed, tested, documented, and supported end to end. The design system should make those paths visible: install this, run this, add this package, read these docs, fix this error, publish this way.

The core model is not up for committee redesign. Riot does not need formatter knobs, old-tool compatibility as identity, or every surface assembled from unrelated options.

In Practice

  • The same tokens drive the design-system page, component demos, docs mock, registry mock, and CLI surfaces.
  • The table of contents follows the same section order as the document.
  • The hero, footer, docs, and registry examples all use one voice and one visual grammar.

Build for Shipping

Riot exists so you can ship real software. The design system should help people understand, install, try, build, test, publish, debug, and keep going.

The Riot path is: make it work, learn whether it is the right thing, make it beautiful, make it fast where it needs to be fast, and keep shipping.

Do not reward performative complexity, academic posturing, elaborate setup rituals, or pages that brand and decorate without moving the builder forward.

In Practice

  • Buttons use imperative labels like Install, Read, Add, and Publish.
  • Copyable commands stay close to install, fix, and publish explanations.
  • Application rules name the task, required information, traps to avoid, and primary components.

Human-led, agent-ready

Riot is designed by humans. Taste matters. Authority matters. Judgment matters.

Use stable anchors, stable headings, stable field labels, package names, source paths, version numbers, error codes, copyable commands, structured metadata, explicit next steps, and short examples that agents can reuse safely.

AI-friendly does not mean vague chat UX, autopilot magic, generated slop, or letting the AI own the taste. The captain is human.

In Practice

  • The page rail exposes durable section anchors, not every tiny component variant.
  • Tables include captions and labels so the content degrades cleanly into text.
  • Agent-ready voice examples use stable fields like package, source, wanted, and fix.

Trust Builders With Power

Riot trusts you with powerful tools. The stack should be approachable, but it should not be timid.

Make power legible: show code, signatures, generated artifacts, runtime behavior, unsafe boundaries, platform caveats, what the tool did, and how to go deeper.

Do not hide powerful concepts behind soft language. Power tools need visible edges.

In Practice

  • Code blocks show real commands and structured output instead of decorative terminal chrome.
  • Callouts use explicit warning, danger, success, and note variants when the reader needs a stronger signal.
  • Docs examples expose signatures and module context instead of hiding the machinery.

Voice & Writing

How Riot sounds across all surfaces: from the CLI to the web.

Riot’s Jolly Roger has a distinct sound: direct, opinionated, helpful, and joyful. We speak our mind out loud, respectfully and candidly.

Our users are smart, and we acknowledge that, but they also have a job to do. Detours for the sake of it are not worth their time. We do not expect them to know everything or keep every detail fresh in mind.

When designing interfaces for the Riot ecosystem, use this voice as a practical tool. It should make documentation easier to scan, CLI output easier to trust, error messages easier to recover from, and product surfaces easier to act on.

Be Direct

Just say the thing. Riot copy should be clear of fluff. We would rather make a sentence obviously wrong than make it hard to see whether it is wrong.

Bad
You may want to consider checking whether dependency resolution encountered an issue.
Good
Riot could not resolve std. Run riot add std.

Be Opinionated

Do not be afraid to state the preferred path or the preferred way of doing something. It might not be exactly what every user wants, and that is okay. Do not try to offer solutions for everyone all of the time.

Bad
Riot supports many project layouts depending on your preference.
Good
Put packages in packages/. Riot looks there first, and every generated command assumes that layout.

Be Helpful

Always provide contextual help and next steps to unblock developers. Remember, they are not here to marvel at the tool; they are here to ship. Help them ship.

Bad
Build failed.
Good
Build failed in packages/std. Run riot test std --failed, or open the diagnostic above for the exact file and fix.

Be Joyful

Feel empowered to be bold and laugh, then relentlessly fix everything that removes joy: friction, slowness, bugginess, vague feedback, and dead ends.

Bad
Operation completed successfully.
Good
Formatted 128 files. Nothing else to fix.

Agent-ready

Being agent-friendly means that everything we build must have a clear, structured way of being used by an agent rather than a human. That may be an llms.txt file, uniform --json flags, stable anchors, predictable labels, or machine-readable output.

Do not hide the messy details of data or errors, but remember that agents do not think the way you expect them to. A little context engineering can go a long way.

Bad
Something went wrong while resolving dependencies.
Good text
package: std source: packages/app/riot.toml wanted: std found: no matching dependency fix: riot add std
Better JSON
{
  "event": "dependency.resolve.failed",
  "package": "std",
  "source": "packages/app/riot.toml",
  "wanted": "std",
  "found": null,
  "fix": "riot add std"
}

Coding voice

Perhaps a surprising aspect of the Jolly Roger is that it applies to how we write code too. The same voice becomes code that is understandable, malleable, correct, and fast, in that order.

Understandability

Code is read more than it is written, so it must be structured, documented, named, and designed to be understandable. There are many ways to achieve correctness, refactorability, and performance, but we should be willing to balance them to keep code understandable. If we cannot understand it, it does not matter how fast, correct, or modular it is.

Malleability

Code should be built to change. In today’s agentic development world, making code easier to evolve also makes correctness and performance easier to improve.

Correctness

Code should be built to be correct, even at the expense of performance. We use the tools at our disposal: unit tests, properties, fuzzing, sanitizers, and clear contracts.

Performance

Code should be fast, and it should be aware of its performance model and cost.


Foundations

Every design system needs a visual foundation to build on. Riot’s Jolly Roger picks one that abides by our principles: it is direct, it has no fluff, it optimizes for readability, and it stays cohesive from top to bottom.

Grid

Five pixels, everywhere.

The Jolly Roger grid is based around a 5px unit. This unit makes the math easy, and it gives the whole system a consistent sense of rhythm across rows, gaps, controls, examples, and page structure.

Five pixels is small enough to tune dense interfaces and large enough to remember. It keeps spacing choices deliberate without forcing every visual decision into a rigid machine.

The unit is most visible in repeated structure: compact rows, controls, card padding, nested examples, and the space between labels and the values they describe.

single block
three units
value rhythm
u1 5px
u2 10px
u3 15px
u4 20px
u5 25px
u6 30px
u8 40px
u10 50px

Colors

Legibility first. Signals second. Vibes last.

Color is as important as spacing for visual rhythm. It helps readers identify information quickly: mint for success, Riot Red for identity and primary actions, ink and paper for ease of reading.

Riot’s colors are optimized for legibility and clear signaling of intent. Most surfaces should be paper, ink, and line work. Red, mint, amber, and blue appear when the interface needs to name a state, an action, a reference, or a risk.

Color never carries meaning alone. A successful action still needs a label. A warning still needs text. A primary action still needs a clear verb.

Paper #FFF8ED · Reading surface

Use it as the default page and prose background.

Paper-2 #F5ECDC · Recessed surface

Use it for soft contrast, inset areas, and quiet grouping.

Ink #151317 · Text and structure

Use it for body text, headings, borders, and stable UI structure.

Coal #0E0D10 · Code gravity

Use it for terminal surfaces and the darkest moments of contrast.

Riot #EF233C · Identity and action

Use it for the flag, primary actions, danger, and decisive emphasis.

Mint #24C08D · Success

Use it when something completed, resolved, passed, or became safe.

Amber #F0B429 · Caution

Use it for warnings, partial states, and things that need attention.

Blue #2777FF · Reference

Use it for links, references, and navigable technical objects.

Typography

Readable, technical, and still alive.

Typography carries hierarchy, tone, and long-term maintainability. We choose type that improves readability without losing character.

The display face gives Riot’s Jolly Roger its authored voice. The body face makes long explanations sustainable. The coding face keeps commands, paths, signatures, values, and machine-readable examples precise.

The system should be recognizable in light and dark contexts, but the rules stay narrow: use display for titles and labels, body for prose, and code for code.

Hero display / page hero

Use for the first-screen title of a major product, system, or surface. One per page.

Riot’s Jolly Roger
H1 section title

Use for the primary title of a page or long-form document section.

Foundations
H2 major subsection

Use when a section needs a clear second-level chapter break.

Grid
H3 component title

Use for components, examples, principles, and local content groups.

Value rhythm
H4 small heading

Use for compact labels that still need to read as headings.

In Practice
H5 minor heading

Use inside dense cards, forms, tables, and application examples.

Error states
H6 micro heading

Use only when hierarchy is already established and space is tight.

Package metadata
Subtitle supporting title text

Use below a title when the reader needs context before the body copy begins.

How Riot sounds across every surface.
Paragraph body prose

Use for doctrine, docs prose, explanations, and contextual help.

Long explanations should be comfortable to read without making dense technical pages feel padded or generic.
Button action label

Use concise, imperative text for actions. The label should say what happens next.

Add Read Cancel Source Install Riot Read the docs Publish package
Label interface label

Use for form labels, table captions, callout labels, and local UI structure.

Package nameDocs statusUpdatedOwnerError codeSource path
Code code and terminal

Use for commands, paths, JSON, versions, signatures, and terminal output.

riot add std
Metadata compact data

Use for nearby facts that help a reader evaluate an object quickly.

Display face

Martian Mono carries the authored Riot voice. Use it for titles, navigation, labels, buttons, and interface chrome.

Body face

Atkinson Hyperlegible carries explanations. Use it for paragraphs, doctrine, documentation, and longer help text.

Code face

JetBrains Mono carries machine-readable detail. Use it for code, commands, JSON, signatures, versions, and terminal output.

Light surfaces

Use ink on paper for long reading. Riot Red is allowed for a title accent, a primary action, or a piece of real emphasis.

Dark surfaces

Use paper on coal for terminals and code-heavy blocks. Keep red, mint, amber, and blue as syntax or state, not decoration.


Components

Reusable primitives with Riot judgment.

Components are repeated decisions. Buttons, tables, forms, inputs, badges, callouts, cards, and code should look like the same system and carry the same voice.

Buttons

Direct, compact, imperative actions.

Button variant rules
Variant Use for Example
Primary One main action on the surface.
Default A secondary action with normal weight.
Dark A technical or source-adjacent action.
Ghost A quiet command-shaped action.
Small Compact toolbars and dense forms.

Tables

Let users scan and compare dense structured information.

Package metadata comparison
Package Version Docs Owner Updated
std0.6.0readycoretoday
kernel0.0.18readycore2d
krasny0.2.1partialweb1d
Benchmark comparison
Run Mean P95 Delta
baseline42 ms68 ms0%
current37 ms54 ms-12%

Forms

Group controls by the decision they support.

Fields keep labels close to values so compact forms still scan cleanly.

Version values stay mono and exact.

Short fields read like configuration, not marketing copy.

Inputs

Compact, labeled, bordered in ink.

Use placeholders for examples, not hidden labels.

Textareas follow the same border, type, and spacing rules as inputs.

Badges

Small status and metadata markers.

Badge variant rules
Variant Use for Example
Default Neutral categories and tags. stdlib
Solid Strong version or status metadata. v0.6.0
Riot Identity, risk, or attention. unstable
Mint Readiness, success, passing checks. stable
Amber Caution, beta state, review needed. beta

Callouts

Interrupt only when the information changes what the reader should do.

Cards

Use cards for one bounded object. Do not use cards to replace comparison tables.

Docs report

One object, one status, one next action. Cards frame a thing; they should not hide data that wants rows.

Build surface review

Use status cards for repeated summaries, settings groups, and focused previews.

Code

Code examples are product UI.

Code snippet
λ riot fmt --check
ok 128 files formatted
Structured output
package: std
source:  src/lib.ri
fix:     riot add std

In the wild

Real surfaces governed by the system.

Each application names the surface, the reader's task, the required information, the traps to avoid, and the components that carry it.

https://riot.ml
PurposeMake people think: this might be the ML stack I wanted.
Must showThe stack, a real command, real code, and the path to install, learn, and ship.
AvoidStartup SaaS air, vague positioning, and technical proof buried below chrome.
Primary componentsButtons, cards, code, and callouts.

riot.ml

Many OCaml stacks.
/ One flies a flag.

The Riot website makes the stack legible fast. Show the command, the stack, and the path to install, learn, and ship.

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
PurposeHelp users find, compare, evaluate, and install packages.
Must showName, version, docs status, freshness, owner, install command, and compatibility context.
AvoidDecorative cards when comparison is the task.
Primary componentsTables, badges, forms, inputs, and callouts.
pkgs.ml
1,247 packages
Total packages1,247
Downloads8.4M
Publishers309
Median publish1.8s
Registry package comparison
Package Version Description Category Downloads Updated
std 0.4.0 Standard library. Datatypes, collections, IO, time, formats. core 1,247,890 today
kernel 0.0.18 Core abstractions shared across the Riot ecosystem. core 840,221 2d
serde 0.3.0 Schema-driven serialization helpers for Riot data. format 620,498 6h
krasny 0.2.1-rc Web framework on top of Riot’s actor runtime. web 98,114 1d
https://docs.pkgs.ml/p/kernel/0.0.18/Kernel/Result
PurposeHelp readers understand generated API documentation without losing orientation.
Must showPackage, version, module, breadcrumbs, search, local navigation, signatures, examples, and stability markers.
AvoidDecorative chrome around generated reference material.
Primary componentsTables, cards, code, callouts, and badges.
Riot Docs kernel / Kernel / Result v0.0.18

module · Kernel.Result

Result

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

Signature
type ('a, 'e) t = Ok of 'a | Error of 'e
val map : ('a -> 'b) -> ('a, 'e) t -> ('b, 'e) t
terminal surfaces
PurposeTell the user what happened and what to do next in plain text.
Must showStatus, package, version, source when relevant, diagnostic IDs, and copyable next commands.
AvoidNoisy success output, fake terminal theater, and prose that breaks scripts.
Primary componentsCode, badges, tables, and callouts.

CLI

Plain text still carries the brand.

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

CLI output
λ riot publish --dry-run
ok package checked
package: krasny
version: 0.2.1
next: run riot publish
https://pkgs.ml/not-found
PurposeTurn a dead end into a recovery path.
Must showProblem, context, possible cause, fix, and fallback.
AvoidCute dead ends, jokes instead of recovery, and errors with no next action.
Primary componentsCallouts, code, buttons, and badges.

Error pages

Useful dead ends.

Error pages are diagnostics in web form. Explain what failed, whether it is local or remote, and what the user can do next.

Anatomy
problem: package not found
context: registry search
possible cause: misspelled package name
fix: search for krasny
fallback: publish a new package