Deterministic, preset-driven flow diagrams for reporting guidelines (PRISMA 2020, CONSORT 2010, STROBE; MOOSE / ARRIVE planned).
A small TypeScript package that generates publication-quality flow diagrams from a structured data file. Source-of-truth is YAML / JSON / CSV — your choice — and outputs are SVG / drawio / Mermaid / PDF / PNG, all produced from the same in-memory layout with zero external runtime dependencies.
Built as a 2026-stack alternative to the R/Shiny PRISMA2020 package: no R runtime, no .shinyapps.io cold-starts, no Graphviz dependency, byte-deterministic output suitable for git diff and CI.
The official PRISMA 2020 R package is excellent science but inconvenient infrastructure: it requires R, depends on Graphviz/DiagrammeR for layout, and produces output that's hard to embed outside R Markdown. For a reporting-guideline diagram — which is essentially a fixed-shape DAG with a handful of count fields — that's overkill.
FlowDoc separates three concerns:
- Data layer — a flat key/value document (YAML/JSON/CSV) you author by hand or generate from your reference manager
- Engine layer — preset-agnostic, deterministic grid layout + Manhattan edge routing
- Render layer — SVG primary, drawio for further hand-editing, Mermaid for GitHub/Notion embeds
Adding a new guideline (CONSORT, STROBE, …) means writing one preset file. The engine doesn't change.
| PRISMA 2020 | CONSORT 2010 | STROBE |
|---|---|---|
| Systematic review | Parallel-group RCT | Cohort participant flow |
examples/prisma-review.yaml |
examples/consort-trial.yaml |
examples/strobe-cohort.yaml |
Each cell renders the same LaidOutDiagram to all five output formats — pick the one you need: .svg / .pdf / .png / .drawio / .mmd.
npm install
npm run buildThis produces dist/ and a runnable CLI at bin/flowdoc.mjs.
# Create a blank PRISMA 2020 template
node bin/flowdoc.mjs init --preset prisma-2020 -o review.yaml
# Validate it (checks types + flow accounting invariants)
node bin/flowdoc.mjs validate review.yaml
# Render to SVG
node bin/flowdoc.mjs render review.yaml -o fig1.svg
# Export to other formats
node bin/flowdoc.mjs export review.yaml --format drawio -o fig1.drawio
node bin/flowdoc.mjs export review.yaml --format mermaid -o fig1.mmd
# Convert between IO formats (auto-detected by extension)
node bin/flowdoc.mjs convert review.yaml -o review.csv
node bin/flowdoc.mjs convert review.csv -o review.jsonA complete worked example is in examples/prisma-review.yaml together with the rendered prisma-review.svg, prisma-review.drawio, and prisma-review.mmd.
flowdoc init [--preset ID] [--format yaml|json|csv] [-o FILE]
flowdoc validate <FILE>
flowdoc render <FILE> -o <OUT.svg> [--no-watermark] [--no-metadata] [--generated-at ISO]
flowdoc export <FILE> --format svg|drawio|mermaid|pdf|png -o <OUT> [--generated-at ISO]
flowdoc convert <IN> -o <OUT> # format detected from extensions
flowdoc presets [list | show ID]
flowdoc --version
All three formats roundtrip losslessly through the same in-memory FlowDocument. CSV→YAML→SVG is byte-identical to YAML→SVG (verified in test/cli.test.mjs).
$schema: https://flowdoc.dev/schema/v1
preset: prisma-2020
metadata:
title: "A systematic review of X on Y"
authors: [Lin W, Chen Y]
doi: "10.xxxx/xxxx"
data:
db_records: 1240
registry_records: 82
duplicates_removed: 312
records_screened: 965
records_excluded: 702
reports_sought: 263
reports_assessed: 251
exclusion_reasons:
- { reason: "Wrong population", n: 48 }
- { reason: "Wrong outcome", n: 36 }
studies_included: 89
reports_of_included_studies: 98
# ... see examples/prisma-review.yaml for the full field listSame shape as YAML, 1:1 mapping. Useful for programmatic pipelines.
field,value
$preset,prisma-2020
$title,"A systematic review of X on Y"
$authors,"Lin W;Chen Y"
$doi,10.xxxx/xxxx
db_records,1240
registry_records,82
exclusion_reasons,"Wrong population:48;Wrong outcome:36"
studies_included,89$-prefixed fields are metadata ($preset, $title, $authors, $doi, $date, $language, $notes). Any field starting with exclusion_reasons is parsed as a reason:n;reason:n;… list. Other fields are scalars.
import {
parseYaml, validate, layout, renderSvg, exportDiagram, getPreset,
} from "flowdoc";
const doc = parseYaml(yamlSource);
const preset = getPreset(doc.preset);
const result = validate(doc, preset);
if (!result.valid) throw new Error(result.issues[0].message);
const diagram = layout(doc, preset);
const svg = renderSvg(diagram, { generatedAt: "2026-04-25T00:00:00Z" });
const drawio = exportDiagram(diagram, "drawio");
const mermaid = exportDiagram(diagram, "mermaid");validate(doc, preset) runs two passes:
- Schema — checks each field's type (
number/string/exclusion_reasons) against the preset'sfieldsdeclarations. Required fields missing → error. Unknown fields → warning. - Flow accounting — each preset declares invariants like
records_screened = db_records + registry_records − duplicates_removed − automation_excluded − other_prescreen_removed. Imbalances are reported as warnings (not errors) because real-world systematic reviews sometimes have unexplained discrepancies.
PRISMA 2020 invariants currently checked: SCREEN_IN, SCREEN_OUT, SOUGHT_OUT, OTHER_SOUGHT_OUT, INCLUDED_BALANCE.
Same FlowDocument + same preset → byte-identical SVG (when --generated-at is fixed). Useful for:
git diffon rendered figures- CI visual-regression testing
- reproducible supplementary materials
The engine never calls Graphviz or any layout algorithm with non-deterministic ordering. Coordinates come from a fixed grid + per-row dynamic height computed from text wrapping, both pure functions.
Three layers:
- Software DOI — register the repository with Zenodo. On every GitHub release, Zenodo mints a new DOI.
CITATION.cffand.zenodo.jsonin this repo support that workflow. - Preset citation — each preset embeds the appropriate guideline citation. PRISMA 2020 cites Page MJ et al., BMJ 2021;372:n71 (DOI: 10.1136/bmj.n71). View with
flowdoc presets show prisma-2020. - Per-figure metadata — each rendered SVG embeds RDF metadata (
<dc:title>,<dc:identifier>with DOI,<dc:creator>, preset id+version, generation timestamp). PDF exporters that preserve SVG metadata carry this through.
Suggested Methods sentence:
Flow diagrams were generated with FlowDoc v0.1.1 (DOI: 10.5281/zenodo.19858610; concept DOI: 10.5281/zenodo.19858609) following the PRISMA 2020 statement (Page et al., 2021, DOI: 10.1136/bmj.n71).
- Create
src/presets/<id>/index.tsexporting aPresetobject withfields,nodes,edges,sections,grid, andinvariants. - Register it in
src/presets/index.ts. - Add tests under
test/.
The PRISMA 2020 preset (src/presets/prisma-2020/index.ts, ~200 lines) is the reference implementation.
npm test # 80 tests across IO, validation, layout, exporters, template, CLI, matrixCoverage includes: YAML/JSON/CSV roundtrips, CSV escaping, type validation, flow-accounting invariants, layout determinism, no-overlap, SVG metadata embedding, drawio XML well-formedness, Mermaid output, and end-to-end CLI smoke tests.
If you use FlowDoc in your work, please cite it:
@software{lin2026flowdoc,
author = {Lin, Hsieh-Ting},
title = {{FlowDoc}: Deterministic flow diagrams for reporting guidelines},
year = {2026},
url = {https://github.com/htlin222/flowdoc},
version = {0.1.1},
doi = {10.5281/zenodo.19858609},
license = {MIT}
}AMA format
Lin H-T. FlowDoc: Deterministic flow diagrams for reporting guidelines. Version 0.1.1. Zenodo; 2026. doi:10.5281/zenodo.19858609
APA format
Lin, H.-T. (2026). FlowDoc: Deterministic flow diagrams for reporting guidelines (Version 0.1.1) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.19858609
csl/american-medical-association.csl and csl/apa.csl are bundled for use with Quarto / Pandoc citation processors.
MIT — see LICENSE. Copyright (c) 2026 Hsieh-Ting Lin.
| Format | Type | Determinism | Notes |
|---|---|---|---|
| SVG | text | byte-identical with --generated-at |
primary, embeds RDF metadata |
| drawio | text | byte-identical apart from creation date | uncompressed mxGraphModel, hand-editable |
| Mermaid | text | byte-identical | GitHub / Notion native rendering |
| binary | byte-identical with --generated-at |
PDF 1.4 single page, Helvetica Base14, no embed | |
| PNG | binary | byte-identical | RGB raster, 5×7 ASCII bitmap font, zero deps |
PDF/PNG are produced from the same LaidOutDiagram as the SVG renderer — they are not external SVG-conversion stages. The PNG exporter ships a small ASCII bitmap font in-source; CJK glyphs fall back to a placeholder square. PDF labels go through a Unicode → WinAnsi remap so common punctuation (•, –, —, smart quotes, ellipsis) survives the round-trip.
| id | guideline | citation DOI |
|---|---|---|
prisma-2020 |
PRISMA 2020 (systematic reviews) | 10.1136/bmj.n71 |
consort-2010 |
CONSORT 2010 (parallel-group RCT) | 10.1136/bmj.c332 |
strobe |
STROBE (cohort participant flow, item 13) | 10.1016/S0140-6736(07)61602-X |
flowdoc presets show <id> prints the full preset including invariants and citation.
v0.1.0 — three presets (PRISMA 2020, CONSORT 2010, STROBE), three IO formats (YAML / JSON / CSV), five exporters (SVG, drawio, Mermaid, PDF, PNG), 80-test suite covering the full preset × format matrix. Roadmap: MOOSE, ARRIVE; Quarto extension; static web UI.