Documentation

    Hosted installer: at launch

    Report folders, local data and output

    All reference topics

    Report folders, local data and output

    Each rendered report requires its own named folder with exactly one .rmd directly inside it. Missing sources/roots, multiple .rmd files (including nested ones), unreadable inventories, escaped paths and external symlinks are hard failures. CLI commands exit nonzero; editor/service/browser hosts expose actionable structured diagnostics. Parsing, formatting and static suggestions stay available to repair invalid source. No host infers a report from its process working directory.

    Report folder
    quarterly-sales/
      report.rmd
      report.rstyle.yaml       # optional; referenced explicitly
      data/sales.csv          # optional larger input
      media/logo.svg          # optional local media
      Rendered/               # generated; exact capital R
        report.html
        data/sales.csv        # copied when used, including local links
        media/logo.svg        # copied when used; media is also embedded
        report.rstyle.yaml    # copied when referenced
    

    Small authored charts/tables default to expanded row mappings inside the consuming block:

    YAML
    type: bar
    title: Revenue increased from January to February
    encoding: {x: month, y: revenue}
    data:
      inline:
        - month: Jan
          revenue: 100
        - month: Feb
          revenue: 140
    # For larger inputs choose exactly one block-local file reference instead:
    # data: {csv: data/sales.csv}
    # data: {json: data/sales.json}
    

    Header data and block data.id are retired and fail with replacement guidance. For portable report bundles, each block chooses exactly one of inline, csv or json; file references are relative, bounded paths inside the same report root. Native hosts check canonical paths including symlinks; browser/source-only hosts must supply a matching explicit report_folder: {root, source, files} inventory before resolving or rendering. Static browser bundles use a sibling report-folder.json, generated by the builder. In-memory playground drafts have one explicit isolated virtual folder and support inline/embedded resources only.

    Configured native hosts also resolve data.sql, data.metricflow and data.cache through named connectors declared in report.connectors.yaml beside the report. The host must supply the connector’s runtime and configuration; a missing connector declaration is a resource-resolution failure. See examples/sql-report for a local DuckDB report. Credentials stay in trusted host configuration.

    The accepted data.url field is not implemented by current native or browser loaders. Save remote input as a report-local CSV or JSON file for validation, rendering and portable exports.

    Pure core performs no I/O. Hosts provide resolved CSV/JSON bytes in RenderOptions.data keyed by the exact local reference, with style sources/media supplied by their adapters. The source key decides the parser, never the content: csv: content is CSV and json: content is JSON, and content that does not parse as the declared format is data.csv or data.json (error) at the block’s line.

    Data typing is one contract for inline, CSV and JSON rows in every block:

    • CSV is UTF-8 with a dropped BOM, RFC 4180 quoting and a comma delimiter only; there is no delimiter option, and a semicolon file fails as ragged rows. A CSV or JSON file in another encoding, such as an Excel export in Windows-1250, is a data.csv or data.json error at its first byte that is not UTF-8, and only the blocks that read it fail. Every header and value is trimmed. The header is the first row; names must be non-empty and unique, else data.csv.header. A row with a different number of fields is data.csv and names the file line. An empty cell is null; true and false are booleans; a number whose decimal value survives binary64 is a number (10.50 becomes 10.5); a token with a leading zero (00123; not 0 or 0.5) is a string identifier that sorts as text and is never totalled; an integer beyond 2^53 or a decimal that does not round-trip is numeric text that keeps its digits; anything else is a string.
    • JSON is an array of flat row objects whose values are strings, finite numbers, booleans or null. Any other top-level shape, including the former {"inline": [...]} wrapper, or a nested object or array value is data.json (error) naming the row and key.
    • Inline rows follow the JSON value rule: a row that is not a mapping, or a nested value, is one data.inline error at that row (table.data.inline[1]), naming the row and key.
    • Missing values are null, an empty CSV cell, or ., NA, N/A, NaN, null and none in any case after trimming. Charts draw a gap and count the rows in a chart.missing-observations info check. Tables print the cell as written, sort it after every value in both directions and leave it out of totals. Any other text in a numeric chart channel, including comma-grouped numbers such as 1,234, is chart.non-numeric (error) naming the row and value; in a table it stays text.
    • Dates and times are strings only (a quoted year is temporal, an unquoted year a number). YYYY is year precision, YYYY-MM month, YYYY-MM-DD day; a date followed by T, t or a space and HH:MM is minute precision, with :SS second precision and a fraction of 1 to 9 digits after . or , millisecond precision (digits beyond three are dropped). A date-time may end in Z or z, ±HH, ±HHMM or ±HH:MM; without an offset it is UTC. Surrounding spaces are ignored. Out-of-range fields (month 13, 30 February, 25:00, an offset of 24 hours) make the value a non-date. An axis is calendar only when every x value qualifies.
    • Limits, enforced in core for every host: a .rmd source over 16 MiB is source.limit; one resolved dataset over 16 MiB is data.limit; generated HTML over 64 MiB is render.output-limit.

    CSV numeric cells become JSON numbers only when their decimal value survives binary64 parsing and JSON number serialization. Longer decimals and integers that would lose digits, such as 1.234567890123456789 or 9007199254740993, remain source text; chart coordinates still use binary64 while readouts and source downloads retain those digits. Ordinary numeric typing and insignificant trailing-zero normalization are unchanged. JSON input cannot recover digits already rounded by its producer.

    Native generate and VS Code RichView: Export to Rendered create Rendered/<source-basename>.html. -o name.html selects another basename there; an explicit output path must be directly inside that same Rendered directory. Source/style/data are preserved. Output directories/files cannot escape or be symlinks, and inputs cannot collide with output. CSS, licensed fonts, data/media and the Rust chart runtime are embedded in HTML; referenced local files are also copied under Rendered with matching relative paths. Missing interactive runtime refuses chart export with a build/package instruction. Browser downloads cannot select a filesystem directory: save their self-contained HTML inside your report’s Rendered; reports with local document links must use native/editor export for the copied bundle (browser download refuses them). Explicit external web links/embeds still depend on their remote destinations.

    PDF output

    richview generate report.rmd --to pdf writes Rendered/report.pdf atomically. A .pdf output filename also selects this mode. --page a4|letter defaults to A4; --browser PATH or RICHVIEW_BROWSER selects a local Chromium-family browser, otherwise discovery checks PATH and macOS application bundles. Linux and macOS are supported; Windows and hosted rendering are not. Chrome 131 or later provides running titles and page counters. --settle-timeout defaults to 30 seconds. MCP richview_render accepts output: report|pdf and page: a4|letter. Core/JavaScript RenderOptions.output returns print-ready HTML; filesystem export and browser execution belong to the native host.

    PDF HTML carries data-rv-output="pdf" and chart payloads with output: "pdf" and motion.enabled: false. The driver emulates print/reduced motion at the page text width, awaits the runtime’s window.__richview.settled() hook (or fonts, chart mounts and final frames with older runtimes), then requests a tagged PDF with an outline. All browser requests except the staged report, data: resources and GET requests for the images of credited https://images.unsplash.com/ photo figures (image blocks and title_image) that the report shows are blocked (export.network-blocked). Data, styles and media retain the bounded report-folder contract; PDF mode allows no other remote resources.

    The print stylesheet is present in every report. Sleek prints as Air, the light builtin its print-as token names; other styles keep their treatment. PDF page margins are 20 mm top, 18 mm sides and 22 mm bottom, with a running title and page / pages footer after the first page. Content keeps its source order; figures and their following source note, callouts, metrics and table rows avoid breaks. Tables print all rows, repeat headers and print totals once. Video becomes a poster plus caption/filename, or a diagnosed text card without a poster; audio and embeds become link cards; PDF HTML emits no players or iframe. Local links print as text. Images load eagerly, chart controls are hidden, and the existing RichView colophon follows the content. No outputs.* frontmatter, carousel or story output is implemented by this contract.

    Whole HTTP(S) URL table cells link with the hostname as their screen text and the full address in href and title; print uses the full address. ISO dates and identifier-like cells keep their tokens on one line. Table payloads, sorting and CSV values retain the original source strings.

    The former --allow-network flag is removed. Keep data inside the report folder or use a configured native connector.

    Was this page useful? Suggest an edit