GUIDE.md
1,757 words · 8 min read · 35 diagrams
title
Authoring guide for Stillcurrent
audience
LLMs that write documents for this viewer
renderer
GitHub-flavoured Markdown + Mermaid 11.16
updated
2026-10-04

Authoring guide for Stillcurrent#

You are writing a Markdown document that will be opened in a custom viewer. The viewer renders GitHub-flavoured Markdown, draws Mermaid diagrams, highlights code and styles everything itself. Follow this guide exactly: anything outside it either renders as plain text or breaks the page's styling.

important

The viewer owns all colours, fonts, line styles and layout of diagrams. Never set colours, themes, fonts or curve styles in Markdown or Mermaid. Write content and structure only.

1. Output contract#

  • Produce one Markdown document, UTF-8, with .md extension when saved as a file.

  • When you deliver the document inside a chat reply, wrap the whole document in a fence of four backticks with the language markdown, so the triple-backtick fences inside it survive:

    Text
    ````markdown
    ---
    title: …
    ---
    # …
    ```mermaid
    …
    ```
    ````
  • When you write it to a file, do not wrap it in any outer fence.

  • Do not add commentary before or after the document unless asked.

2. Document skeleton#

Use this order:

  1. Frontmatter (optional but recommended): a YAML block at the very top. The viewer shows it as a small properties card above the title.
  2. One H1 (#): the document title. Use exactly one.
  3. Summary: one or two plain sentences saying what the document is and who it is for.
  4. Sections as H2 (##), subsections as H3 (###). Go no deeper than H4.
Markdown
---
title: Posting a sales invoice
status: draft
owner: Accounting team
updated: 2026-10-04
tags: [posting, ledger, outbox]
---

# Posting a sales invoice

How a sales invoice moves from draft to the general ledger, for backend developers.

## Request path

…

Frontmatter rules#

  • Use only key: value lines, inline lists key: [a, b, c], or a key followed by - item lines.
  • Nested objects are not supported; they are flattened. Keep values short (they sit in a narrow card).
  • Lists render as small chips, so tags and owners work well as lists.

How headings behave#

  • H1, H2 and H3 appear in the Contents sidebar. Write headings as short, specific noun phrases, because they double as navigation.
  • Every H2 gets a divider line above it, so H2s mark major sections. Do not use H2 for a single short paragraph.
  • Do not number headings by hand ("1.", "2.") unless the order is meaningful to the reader.

3. Supported Markdown#

Element Syntax Notes
Paragraphs blank line between blocks Single line breaks inside a paragraph are joined; do not hard-wrap for layout.
Emphasis *italic*, **bold**, ~~strike~~ Use bold sparingly, for key terms.
Inline code `code` For identifiers, paths, commands, config keys.
Lists - or 1. Nest with two or four spaces. Use numbered lists only when order matters.
Task lists - [ ] and - [x] Rendered as checkboxes (read-only).
Blockquote > text For quotations. For notes and warnings use callouts (section 4).
Tables GitHub pipe tables See section 5.
Code blocks triple-backtick fence with a language See section 6.
Mermaid ```mermaid fence See sections 11 to 13.
Horizontal rule --- on its own line Rarely needed; H2s already draw dividers.
Links [text](https://…), [text](#heading-slug) See section 7.
Keyboard keys <kbd>Ctrl</kbd> Allowed inline HTML.
Highlight <mark>text</mark> Allowed inline HTML; use rarely.
Line break in a table cell <br> The only reliable way to break a line inside a cell.

4. Callouts#

Use GitHub-style alerts. The marker must be alone on the first line of the blockquote, in capitals:

Markdown
> [!NOTE]
> Background the reader should know.

> [!TIP]
> A better or faster way to do something.

> [!IMPORTANT]
> Something the reader must not miss.

> [!WARNING]
> Something that can cause problems.

> [!CAUTION]
> Something that can cause data loss or security issues.
  • Only these five types exist. Any other marker ([!INFO], [!DANGER]) renders as a plain quote.
  • Use at most one callout per section. Callouts lose their effect when everything is a callout.

5. Tables#

  • Always include the header row and the separator row.
  • Align numbers to the right with --:. Text stays left-aligned (---).
  • Header cells are shown in small capitals, so keep them to one to three words.
  • Wide tables scroll sideways inside their frame. Still, prefer five columns or fewer.
  • Do not put block content (lists, code blocks) in cells. Use <br> for a line break.
  • Escape a literal pipe inside a cell as \|.
Markdown
| Account           | Purpose            |    Debit |   Credit |
| ----------------- | ------------------ | -------: | -------: |
| 1400 Receivables  | `sales.receivable` | 1,190.00 |          |
| 8400 Revenue 19 % | `sales.revenue`    |          | 1,000.00 |

6. Code blocks#

  • Always put a language tag after the opening fence. The viewer shows it as the block's label and uses it for syntax colouring.
  • Use text for output, logs or anything that is not code.
  • Keep blocks under about 40 lines. Show the relevant part, not whole files.
  • Do not put line numbers or $ prompts inside the code unless the reader needs them.

Languages with syntax colouring (tag, then common aliases):

bash (sh, shell), c, cpp, csharp (cs), css, diff, go, graphql, ini (toml), java, javascript (js, jsx), json, kotlin (kt), less, lua, makefile, markdown (md), objectivec, perl, php, plaintext (text), python (py), r, ruby (rb), rust (rs), scss, sql, swift, typescript (ts, tsx), vbnet, xml (html, svg), yaml (yml).

Other tags (for example dart, dockerfile, http) still display with their label, just without colours.

  • External links must be absolute: https://…. They open in a new tab.
  • Link to a heading in the same document with its slug: [see Containers](#level-2-containers).
  • Slug rules (GitHub style): lowercase, punctuation removed, spaces become hyphens, letters in any script are kept. A repeated heading gets -2, -3.
    • ## Level 2: Containers → #level-2-containers
    • ### Why not REST? → #why-not-rest
  • Inside a project, link to another document of the same project by its file name: [see the ledger rules](ledger-rules.md) or [steps](./posting-flow.md#steps). The match ignores case, .md may be left out, and spaces can be written as %20. These links open that document (also on a shared project page).
  • Links to any other files (../other.md, folder/a.md, or a file that isn't in the project) cannot be opened in the viewer. Avoid them, or also name the file in the text.

8. Images#

  • Images from relative paths (./img/a.png) are not shown; the viewer displays a placeholder with the alt text.
  • Only https:// images and images embedded as data:image/… URIs display. Anything else (http://, relative paths) shows the placeholder.
  • Prefer a Mermaid diagram over an image whenever the picture is a diagram.
  • Always write meaningful alt text: ![Invoice states from draft to void](…).

9. Multilingual text and right-to-left scripts#

  • Each block (paragraph, list item, table cell, heading) picks its own direction from its first letter. Arabic, Persian and Hebrew paragraphs render right to left automatically.
  • Keep each language in its own paragraph or list item. A short foreign word inside a sentence is fine.
  • Do not add dir attributes or Unicode direction marks.

10. Not supported: do not use#

  • Math or LaTeX ($…$, $$…$$, \(...\)): shown as raw text. Write formulas in inline code or plain words.
  • Footnotes ([^1]), definition-list shorthand, custom containers (:::note), wiki links ([[Page]]), emoji shortcodes (:tada:).
  • Raw HTML beyond <kbd>, <mark>, <br>, <sub>, <sup>, <details>/<summary>. Scripts, styles, iframes and event attributes are removed.
  • Inline styles or colour HTML (<span style="color:…">, <font>).
  • PlantUML, Graphviz/DOT, ASCII-art diagrams. Use Mermaid.
  • Emoji as section markers or bullets.

11. Mermaid: rules for every diagram#

Write each diagram in its own fence:

Markdown
```mermaid
flowchart LR
  A[Draft] -->|post| B[Posted]
```

Styling is the viewer's job#

The viewer applies the reader's chosen diagram colour, light or dark theme, the page typeface, rounded connector corners and its own spacing. Therefore:

  • Never start a diagram with %%{init: …}%% or a --- config block.
  • Never use style, linkStyle, classDef … fill/stroke/color, class X someClass for colour, themeVariables, UpdateElementStyle or UpdateRelStyle.
  • Never set curve, fonts or sizes.
  • Express emphasis with words, stereotypes (<<interface>>) or grouping (subgraph, boundaries), not colour.

The viewer also animates direction: small pulses travel along every one-way connector toward its arrowhead (readers can turn this off). So give each arrow the direction you mean, and use a line without an arrowhead (---, --) or a two-headed arrow where there is no single direction. Never draw an arrow just for decoration.

Size and readability#

  • Keep one idea per diagram: about 15 nodes or fewer, 20 connectors or fewer. Split larger systems into several diagrams.
  • Put one sentence before each diagram saying what it shows. The diagram card shows only its type ("Flowchart", "Sequence"), not a caption.
  • Labels: short noun phrases for boxes, short verb phrases for arrows (one to four words).
  • Readers can zoom, pan and expand diagrams, so wide diagrams are acceptable. Prefer LR for pipelines and TB for hierarchies.

Supported diagram types (Mermaid 11.16)#

Purpose First line
Flow, process, architecture sketch flowchart LR / flowchart TB
Calls over time between parties sequenceDiagram
Types, interfaces, relations classDiagram
Lifecycle, status machine stateDiagram-v2
Database tables erDiagram
Software architecture (C4) C4Context, C4Container, C4Component, C4Dynamic, C4Deployment
Schedule gantt
Proportions pie
Trends xychart-beta
Two-axis positioning quadrantChart
Hierarchy of ideas mindmap
Events in order timeline
Branching history gitGraph
User experience steps journey
Flows with quantities sankey-beta
Requirements requirementDiagram
Columns of work items kanban
Fixed-grid block layout block-beta
Network packet fields packet-beta
Cloud/service layout architecture-beta
Comparing scores across dimensions radar-beta
Nested quantities treemap-beta
Overlapping sets venn-beta
Root causes (fishbone) ishikawa-beta
File or folder tree treeView-beta
Process with owners per lane swimlane-beta LR
Event modeling eventmodeling
Strategy map wardley-beta
Problem domains cynefin-beta
Grammar (syntax diagram) railroad-ebnf-beta

Section 17 shows a working example of every type.

Syntax pitfalls that cause errors#

Flowchart:

  • Node IDs are single words: orderSvc[Order service]. Never use the bare word end as an ID (use done or End).
  • Quote labels that contain punctuation: A["Validate (strict)"], B["Cost: 1,190 €"].
  • Line break inside a label: A["First line<br/>second line"].
  • Edge labels: A -->|calls| B or A -- calls --> B.
  • After a link, do not start an ID with lowercase o or x (A---oB draws a circle end). Use readable IDs.
  • Subgraphs: subgraph billing [Billing] … end.

Sequence:

  • Declare participants first: participant S as SalesService, actor U as User.
  • Solid call ->>, dashed reply -->>, notes Note over A,B: text.
  • Blocks: alt / else / end, opt, loop, par / and. Every block needs its end.
  • Do not use ; or # inside message text. Write #59; for a semicolon and #35; for # if you must.
  • autonumber on its own line numbers the messages.

Class:

  • Members: +String name, methods: +post(PostingRequest r) PostingResult.
  • Generics use tildes: List~PostingLine~, Map~String,Object~.
  • Static $ and abstract * go after the member: +of(String code)$ DocumentType.
  • Relations: inheritance <|--, realisation <|.., composition *--, aggregation o--, association -->, dependency ..>. Cardinality: Order "1" *-- "many" Line.

State:

  • Use stateDiagram-v2, start and end with [*]: [*] --> Draft, Void --> [*].
  • Transition labels: Draft --> Posted : post.

ER:

  • CUSTOMER ||--o{ INVOICE : receives.

  • Attributes go inside braces after the entity name, one per line, as type name with optional PK, FK or UK:

    Text
    INVOICE {
      uuid id PK
      string number
      date issued
    }

Gantt:

  • Always set dateFormat YYYY-MM-DD. Each task needs an id or a dependency: Build API :api, 2026-10-05, 10d, Tests :after api, 5d.

12. Class diagrams: stereotypes the viewer styles#

Put the stereotype as the first line inside the class body. The viewer recognises these words and styles them consistently:

Stereotype Use for Look
<<interface>> interfaces, ports coloured border and title
<<record>> value objects, DTOs, Java records tinted fill
<<enumeration>> enums tinted fill
<<entity>> aggregates, persisted entities dark border
<<abstract>> abstract base classes dotted border
<<plugin>> optional, later-phase or third-party parts dashed amber border
<<service>> or anything else implementations default look
classDiagram
  direction LR
  class PostingEngine {
    <<interface>>
    +post(PostingRequest r) PostingResult
  }
  class DefaultPostingEngine {
    <<service>>
    -resolveAccounts(PostingRequest r) Resolved
  }
  class Side {
    <<enumeration>>
    DEBIT
    CREDIT
  }
  PostingEngine <|.. DefaultPostingEngine
  DefaultPostingEngine ..> Side

13. C4 model diagrams#

The viewer gives C4 diagrams special treatment. It colours people, systems, containers and components as shades of the reader's diagram colour (external elements in grey). It reroutes every relationship as a right-angled connector that goes around boxes, places labels in free space, and widens the gaps to fit the labels.

Which diagram for which level#

C4 level Mermaid keyword Show
1. System context C4Context people and systems around the one system in scope
2. Containers C4Container deployable/runnable parts inside the system boundary
3. Components C4Component the parts inside one container
4. Code classDiagram the classes behind one component (Mermaid has no C4 code type)
Runtime flow C4Dynamic numbered interactions for one scenario
Infrastructure C4Deployment nodes and where containers run

Elements#

  • People: Person(alias, "Label", "Description"), Person_Ext(...).
  • Systems: System, SystemDb, SystemQueue, System_Ext, SystemDb_Ext, SystemQueue_Ext.
  • Containers: Container(alias, "Label", "Technology", "Description"), plus ContainerDb, ContainerQueue, Container_Ext, ContainerDb_Ext, ContainerQueue_Ext.
  • Components: Component(alias, "Label", "Technology", "Description"), plus ComponentDb, ComponentQueue, Component_Ext, …
  • Boundaries: Enterprise_Boundary(alias, "Label") { … }, System_Boundary(…) { … }, Container_Boundary(…) { … }, Boundary(…) { … }.
  • Deployment: Deployment_Node(alias, "Label", "Type") { … }.

Relationships#

  • Rel(from, to, "Label", "Technology"). The technology argument is optional.
  • BiRel(a, b, "Label") for two-way relationships.
  • Rel_U, Rel_D, Rel_L, Rel_R are accepted but have no visible effect, because the viewer routes all connectors itself. Plain Rel is preferred.
  • Connect elements to elements. Do not point a relationship at a boundary alias.
  • Labels: a verb phrase of one to four words ("Reads and writes", "Sends webhooks"). Put protocols in the technology argument ("JDBC", "HTTPS"). Avoid very long single words; the gap between boxes grows to fit the longest word.

Layout: you control it through declaration order#

Mermaid places C4 elements in rows, in the order you declare them. Elements outside boundaries are drawn first, then each boundary's contents. Use this to get a clean picture:

  • Declare elements in reading order: people first, then the system or boundary in scope, then external systems.
  • Put elements that talk to each other next to each other in the order. Short connectors stay straight; distant ones need bends.
  • End the diagram with UpdateLayoutConfig($c4ShapeInRow="N", $c4BoundaryInRow="1"):
    • N = 2 for Context and Container diagrams with up to six elements.
    • N = 3 for Component diagrams with up to nine components.
  • Keep each diagram to about nine elements. Split a busy container into two component diagrams.
  • Descriptions: ten words or fewer. They wrap inside the box.
  • Strings use double quotes and must not contain double quotes. Parentheses, colons and slashes inside the quotes are fine.

Complete C4 example (Level 2)#

C4Container
  Person(accountant, "Accountant", "Posts invoices")
  System_Ext(erp, "Customer ERP", "REST client")
  System_Boundary(saas, "Accounting SaaS") {
    Container(web, "Web app", "TypeScript, React", "Document, ledger and report screens")
    Container(app, "Application", "Java 21, Spring Boot", "Modular monolith with the REST API")
    ContainerDb(db, "Database", "PostgreSQL", "One schema per module")
    ContainerQueue(outbox, "Event outbox", "Table and relay", "Delivers events after commit")
  }
  Rel(accountant, web, "Uses", "HTTPS")
  Rel(web, app, "Calls", "JSON/HTTPS")
  Rel(erp, app, "Calls", "REST")
  Rel(app, db, "Reads and writes", "JDBC")
  Rel(app, outbox, "Writes events", "same transaction")
  Rel(outbox, erp, "Sends webhooks", "HTTPS")
  UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")

14. Writing style#

  • Write for a busy reader: the point first, details after.
  • Short paragraphs (two to four sentences). One idea per paragraph.
  • Prefer a table to a long list of "X: value" lines, and a list to a long sentence with many commas.
  • Use active voice and concrete names ("PostingEngine writes the ledger", not "the ledger is written").
  • Define each abbreviation once, at first use.

15. Checklist before you deliver#

  • Exactly one H1; sections are H2; nothing deeper than H4.
  • Frontmatter, if present, is at the very top and uses flat key: value lines.
  • Every code fence has a language tag; every fence is closed.
  • Every Mermaid diagram starts directly with its type keyword. No %%{init}%%, no styles, no colours.
  • Every diagram has one sentence before it explaining what it shows.
  • Flowchart labels with punctuation are quoted; no node is called end.
  • Sequence messages contain no ; or #; every alt, loop, opt, par has an end.
  • C4: elements declared in reading order, plain Rel, short labels, UpdateLayoutConfig at the end, nine elements or fewer.
  • Callouts use one of the five GitHub types, marker alone on its first line.
  • No math, footnotes, relative images, raw styling HTML or emoji headings.
  • In chat, the whole document is wrapped in a four-backtick markdown fence.

16. Template#

Copy this and replace the content:

Markdown
---
title: <Document title>
status: draft
owner: <Team or person>
updated: <YYYY-MM-DD>
tags: [<tag>, <tag>]
---

# <Document title>

<One or two sentences: what this document covers and for whom.>

> [!NOTE]
> <Optional context the reader needs before starting.>

## Overview

<Short explanation.>

<One sentence describing the diagram below.>

```mermaid
flowchart LR
  request[Request] --> validate["Validate input"]
  validate --> process[Process]
  process --> store[(Database)]
```

## <Section>

| Item   | Meaning       | Value |
| ------ | ------------- | ----: |
| <name> | <description> |  0.00 |

```java
// <the relevant lines only>
```

## Open questions

- [ ] <Question or decision still open>

One working example of every diagram type the viewer draws, so you can see how each one looks in your colour and theme. Each block follows the rules above; copy one as a starting point. Open Source on any card to see its Mermaid text. Types marked beta are new in Mermaid and may change in a later version; prefer the stable types for documents that must last.

Flowchart#

How a sales invoice moves from draft to the ledger.

flowchart LR
  draft[Draft invoice] --> check{"Valid?"}
  check -->|yes| post[Post to ledger]
  check -->|no| fix[Return to author]
  fix --> draft
  post --> ledger[(Ledger)]
  post --> notify([Notify customer])

Sequence diagram#

The calls made when an accountant posts an invoice.

sequenceDiagram
  autonumber
  actor U as Accountant
  participant S as SalesService
  participant T as TaxEngine
  participant L as Ledger
  U->>S: Post invoice
  S->>T: Calculate tax
  T-->>S: Tax lines
  alt Period open
    S->>L: Write entries
    L-->>S: Entry ids
    S-->>U: Posted
  else Period closed
    S-->>U: Rejected
  end

Class diagram#

The posting engine and the request it accepts. Section 12 lists the stereotypes the viewer styles.

classDiagram
  class PostingEngine {
    <<interface>>
    +post(PostingRequest r) PostingResult
  }
  class DefaultPostingEngine {
    -resolveAccounts(PostingRequest r) Resolved
  }
  class PostingRequest {
    <<record>>
    +UUID companyId
    +List~PostingLine~ lines
  }
  class PostingLine {
    <<record>>
    +Money amount
    +Side side
  }
  PostingEngine <|.. DefaultPostingEngine
  DefaultPostingEngine ..> PostingRequest
  PostingRequest "1" *-- "many" PostingLine

State diagram#

The lifecycle of an invoice, with payment as a nested state.

stateDiagram-v2
  [*] --> Draft
  Draft --> Posted : post
  Draft --> Cancelled : cancel
  Posted --> Paid : payment received
  Posted --> Void : void
  state Paid {
    [*] --> Partial
    Partial --> Settled : final payment
  }
  Paid --> [*]
  Void --> [*]
  Cancelled --> [*]

Entity relationship diagram#

The tables behind invoicing.

erDiagram
  CUSTOMER ||--o{ INVOICE : receives
  INVOICE ||--|{ INVOICE_LINE : contains
  PRODUCT ||--o{ INVOICE_LINE : "appears on"
  CUSTOMER {
    uuid id PK
    string name
    string vat_number UK
  }
  INVOICE {
    uuid id PK
    uuid customer_id FK
    string number
    date issued
  }
  INVOICE_LINE {
    uuid id PK
    uuid invoice_id FK
    uuid product_id FK
    decimal amount
  }
  PRODUCT {
    uuid id PK
    string sku UK
  }

C4: system context#

Who uses the system and which systems it depends on. Section 13 has the container level and the C4 layout rules.

C4Context
  Person(accountant, "Accountant", "Posts invoices")
  System(saas, "Accounting SaaS", "Ledger, sales and reports")
  System_Ext(bank, "Bank", "Statement feeds")
  System_Ext(mail, "Email service", "Delivers invoices")
  Rel(accountant, saas, "Uses", "HTTPS")
  Rel(saas, bank, "Imports statements from")
  Rel(saas, mail, "Sends email through", "SMTP")
  UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")

C4: components#

The parts inside the sales API container.

C4Component
  Container_Boundary(api, "Sales API") {
    Component(ctrl, "Invoice controller", "Spring MVC", "REST endpoints")
    Component(svc, "Posting service", "Java", "Validates and posts")
    Component(repo, "Invoice repository", "JPA", "Reads and writes invoices")
  }
  ContainerDb(db, "Ledger DB", "PostgreSQL", "Invoices and entries")
  Rel(ctrl, svc, "Calls")
  Rel(svc, repo, "Uses")
  Rel(repo, db, "Reads and writes", "JDBC")
  UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")

C4: dynamic#

The numbered steps of one scenario: posting an invoice.

C4Dynamic
  Person(user, "Accountant", "Posts invoices")
  Container(web, "Web app", "React", "Invoice screens")
  Container(api, "Sales API", "Java", "Posting rules")
  ContainerDb(db, "Ledger DB", "PostgreSQL", "Entries")
  Rel(user, web, "Clicks Post")
  Rel(web, api, "Posts invoice", "JSON/HTTPS")
  Rel(api, db, "Writes entries", "JDBC")
  UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")

C4: deployment#

Where the containers run.

C4Deployment
  Deployment_Node(eu, "EU region", "Cloud") {
    Deployment_Node(k8s, "Kubernetes cluster", "Managed") {
      Container(api, "Sales API", "Java", "Posting rules")
    }
    Deployment_Node(pg, "Managed PostgreSQL", "Service") {
      ContainerDb(db, "Ledger DB", "PostgreSQL 17", "Entries")
    }
  }
  Rel(api, db, "Reads and writes", "TLS")
  UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")

Architecture (beta)#

Services and data stores in one cloud region, with icons.

architecture-beta
  group eu(cloud)[EU region]
  service web(internet)[Web app] in eu
  service api(server)[Sales API] in eu
  service db(database)[Ledger DB] in eu
  service files(disk)[Exports] in eu
  web:R --> L:api
  api:R --> L:db
  api:B --> T:files

Block diagram#

Parts placed on a fixed grid.

block-beta
  columns 3
  web["Web app"] api["Sales API"] worker["Worker"]
  space:3
  db[("Ledger DB")] queue[["Outbox"]] mail["Email"]
  web --> api
  api --> db
  api --> queue
  queue --> worker
  worker --> mail

Requirement diagram#

Requirements and the element that satisfies them.

requirementDiagram

  requirement post_once {
    id: 1
    text: An invoice posts exactly once
    risk: high
    verifymethod: test
  }

  functionalRequirement audit_trail {
    id: 2
    text: Every posting is traceable
    risk: medium
    verifymethod: inspection
  }

  element posting_engine {
    type: service
  }

  posting_engine - satisfies -> post_once
  posting_engine - satisfies -> audit_trail

Git graph#

A feature branch merged back into main.

gitGraph
  commit id: "init"
  branch tax-engine
  checkout tax-engine
  commit id: "tax rules"
  commit id: "tests"
  checkout main
  commit id: "hotfix"
  merge tax-engine
  commit id: "release"

Gantt chart#

The plan for the next release.

gantt
  title Invoicing v2
  dateFormat YYYY-MM-DD
  section Build
    Posting API     :api, 2026-10-05, 10d
    Tax engine      :tax, after api, 7d
  section Release
    Beta            :beta, after tax, 5d
    General release :milestone, ga, after beta, 0d

Timeline#

Milestones in order.

timeline
  title Ledger platform
  2024 : Single-tenant ledger
  2025 : Multi-tenant SaaS : Bank feeds
  2026 : Public API : MCP server for agents

User journey#

How an accountant feels at each step, scored 1 to 5.

journey
  title Posting a month-end invoice
  section Prepare
    Open draft: 4: Accountant
    Check tax lines: 3: Accountant
  section Post
    Post invoice: 5: Accountant, System
    Send to customer: 4: System

Mind map#

The areas of the product.

mindmap
  root((Invoicing))
    Sales
      Quotes
      Invoices
      Credit notes
    Ledger
      Posting
      Periods
    Integrations
      Bank feeds
      Email

Kanban#

Work in progress.

kanban
  todo[To do]
    t1[Credit notes API]
    t2[Bank feed retries]
  doing[In progress]
    t3[Tax engine v2]
  shipped[Done]
    t4[MCP server]

Pie chart#

Share of invoices by status.

pie title Invoices by status
  "Paid" : 62
  "Posted" : 23
  "Draft" : 11
  "Void" : 4

XY chart#

Invoices posted per month, as bars with a trend line.

xychart-beta
  title "Invoices posted per month"
  x-axis [Jan, Feb, Mar, Apr, May, Jun]
  y-axis "Invoices" 0 --> 1400
  bar [620, 710, 890, 940, 1120, 1260]
  line [620, 710, 890, 940, 1120, 1260]

Quadrant chart#

Technical debt placed by effort and impact.

quadrantChart
  title Technical debt
  x-axis Low effort --> High effort
  y-axis Low impact --> High impact
  quadrant-1 Plan carefully
  quadrant-2 Do first
  quadrant-3 Fill-in work
  quadrant-4 Skip
  Tax rules cache: [0.25, 0.8]
  Retry queue: [0.4, 0.62]
  Legacy PDF export: [0.8, 0.35]
  Old admin UI: [0.75, 0.15]

Sankey (beta)#

Where revenue goes. One source,target,value row per flow.

sankey-beta
Sales,Revenue,820
Services,Revenue,310
Revenue,Salaries,520
Revenue,Hosting,140
Revenue,Profit,470

Radar chart (beta)#

Service quality today against the target, on a 0 to 5 scale.

radar-beta
  title Service quality
  axis perf["Performance"], rel["Reliability"], sec["Security"], cost["Cost"], dx["Developer experience"]
  curve today["Today"]{3, 4, 4, 2, 3}
  curve target["Target"]{4, 5, 5, 3, 4}
  max 5
  min 0

Treemap (beta)#

Monthly cost, nested by area.

treemap-beta
"Monthly cost"
    "Compute"
        "API": 420
        "Workers": 180
    "Data"
        "PostgreSQL": 310
        "Backups": 60
    "Email": 40

Packet (beta)#

The fields of a TCP header, by bit position.

packet-beta
  title TCP header
  0-15: "Source port"
  16-31: "Destination port"
  32-63: "Sequence number"
  64-95: "Acknowledgment number"
  96-99: "Data offset"
  100-105: "Reserved"
  106-111: "Flags"
  112-127: "Window"

Venn diagram (beta)#

Overlap between two groups of users.

venn-beta
  set api["API users"]:120
  set ui["Web users"]:300
  union api,ui:45

Ishikawa (fishbone) (beta)#

Possible causes of late invoices, by category.

ishikawa-beta
    Late invoices
    Process
        Manual approval step
        Month-end backlog
    Systems
        Tax engine timeouts
        Bank feed delays
    People
        Missing training
    Data
        Wrong customer emails

Tree view (beta)#

A folder structure.

treeView-beta
├── src/
│   ├── invoices/
│   │   ├── post.ts
│   │   └── tax.ts
│   └── index.ts
├── package.json
└── README.md

Swimlanes (beta)#

Who does each step of an order.

swimlane-beta LR
  subgraph Customer
    Browse[Browse catalogue]
    Pay[Pay]
  end
  subgraph Warehouse
    Pick[Pick items]
    Ship[Ship order]
  end
  subgraph Finance
    Invoice[Raise invoice]
  end
  Browse --> Pay
  Pay --> Pick
  Pick --> Ship
  Pay --> Invoice

Event modeling (beta)#

A screen, the command it sends and the event that results.

eventmodeling

tf 01 ui CartUI
tf 02 cmd AddItem
tf 03 evt ItemAdded

Wardley map (beta)#

Components placed by visibility to the user and by evolution.

wardley-beta
title Invoicing
anchor Accountant [0.95, 0.9]
component "Invoice screens" [0.8, 0.65]
component "Posting rules" [0.6, 0.45] (build)
component "Tax engine" [0.45, 0.6] (buy)
component Database [0.25, 0.85] (outsource)
Accountant -> "Invoice screens"
"Invoice screens" -> "Posting rules"
"Posting rules" -> "Tax engine"
"Posting rules" -> Database

Cynefin (beta)#

Sorting incident work by how well the problem is understood.

cynefin-beta
  title Incident response
  complex
    "Investigate root cause"
  complicated
    "Analyse slow queries"
  clear
    "Restart worker"
  chaotic
    "Page on-call"
  confusion
    "Unknown failure"

Railroad (beta)#

The grammar of an invoice number, in EBNF.

railroad-ebnf-beta
title "Invoice number"

number = prefix "-" year "-" digits ;
prefix = "INV" | "CRN" ;
year = digit digit digit digit ;
digits = digit { digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;