Briefkit

Design notes

Briefkit Design Notes

Briefkit is a lightweight static report-site toolkit for agents that need to turn research into clear, attractive, decision-oriented throwaway websites.

These notes capture approved design decisions and open questions during early design.

Product thesis

Briefkit is a report forge, not an agent framework, CMS, dashboard product, or backend service.

Agents should be able to create polished, decision-oriented static sites quickly from local files while reusing one shared Briefkit core.

Core priorities:

  • static output;
  • local and portable;
  • MDX-first authoring;
  • dense, scannable, informational reports;
  • good defaults with escape hatches;
  • reusable modules without forcing a rigid schema;
  • one shared installed core usable by many simultaneous report folders.

Architecture model

Briefkit core is installed once and reused by many local report folders.

~/Code/briefkit/                 # shared core toolkit
  bin/briefkit
  src/layouts/
  src/components/
  src/styles/
  astro.base.config.mjs

/tmp/skyrim-brief/               # local report source only
  index.mdx
  components/
  data/
  public/

/tmp/wagos-brief/                # another local report source only
  index.mdx
  components/
  data/
  public/

The CLI should support concurrent dev servers using the same core:

briefkit dev /tmp/skyrim-brief --port 4311
briefkit dev /tmp/wagos-brief --port 4312

Each report gets isolated generated / cache / build directories so Astro / Vite state does not collide.

Briefkit should hide Astro ceremony. Users and agents should not need to copy a full Astro app for every report.

Authoring model

Reports are MDX-first.

A report can use:

  • freeform Markdown / MDX prose;
  • raw HTML / JSX-like markup where needed;
  • reusable Briefkit core components;
  • local report-specific components;
  • local data files.

Example:

---
title: Vendor Decision Brief
---

import { Callout, BriefTable, Tooltip } from "briefkit";
import WeirdMatrix from "@report/components/WeirdMatrix.astro";
import risks from "@report/data/risks.yaml";

# Vendor Decision Brief

<Callout type="info" title="Verdict">
Pick Vendor B unless support risk dominates.
</Callout>

<WeirdMatrix />

<BriefTable
  caption="Risk register"
  columns={[
    { key: "risk", label: "Risk" },
    { key: "warning", label: "Warning sign" },
    { key: "mitigation", label: "Mitigation" }
  ]}
  rows={risks}
  stickyHeader
  stickyFirstColumn
/>

Structured data should be used where useful, but Briefkit should not become a schema prison.

Good structured candidates:

  • facts;
  • risks;
  • scores;
  • sources;
  • glossary;
  • decision rules.

Freeform content should remain first-class for analysis, caveats, recommendations, and narrative reasoning.

Report folder contract

The minimum valid report is:

my-report/
  index.mdx

Supported optional structure:

my-report/
  index.mdx
  pages/**/*.mdx
  components/**/*.{astro,tsx,jsx}
  data/**/*.{json,yaml,yml,csv}
  public/**/*
  briefkit.config.{ts,js,mjs}

Rules:

  • index.mdx or pages/index.mdx is required.
  • components/ is for local one-off modules.
  • data/ is for local report data.
  • public/ is copied / served as simple static files.
  • briefkit.config is optional.

Local imports

Reports should be able to import local files through a stable alias:

import CustomThing from "@report/components/CustomThing.astro";
import risks from "@report/data/risks.yaml";

This avoids fragile relative paths for nested pages.

Assets

Briefkit defaults to simple static assets.

my-report/
  public/
    chart.png
    source-screenshot.jpg
    appendix.pdf

MDX references:

![Chart](/chart.png)

<a href="/appendix.pdf">Download appendix</a>

Advanced bundled assets may be considered later, but are not required for the initial design.

Layout behavior

Pages are automatically wrapped in the standard Briefkit report layout by default.

Default frontmatter behavior:

---
title: Skyrim Decision
---

is equivalent to:

---
title: Skyrim Decision
layout: report
---

Escape hatches:

---
title: Raw Appendix
layout: none
---
---
title: Custom Page
layout: custom
customLayout: "@report/components/MyLayout.astro"
---

Future built-in layouts may include wide or article.

Default layout includes a sidebar navigation / table of contents.

Sidebar behavior:

  • generated page navigation from discovered MDX files;
  • generated in-page table of contents from headings;
  • on mobile, sidebar should collapse above content or into a details block;
  • in print, sidebar should be hidden.

For a single-page report, sidebar shows heading TOC.

For a multi-page report, sidebar shows:

Pages
- Main matrix
- HOH fit analysis

On this page
- Verdict
- Hard facts
- Risk register

Page ordering:

  1. explicit order from briefkit.config if declared;
  2. otherwise alphabetical;
  3. index.mdx should be first when no explicit order exists.

Page label:

navTitle || title || filename

Heading anchors are generated so agents can link to page#section, and the sidebar exposes those links.

Config / frontmatter escape hatches may later include:

---
toc: false
---

or:

export default {
  toc: true,
};

Route model

Each MDX page renders as:

/mdx-filename-without-ext/

Examples:

index.mdx              -> /
hoh-fit.mdx            -> /hoh-fit/
pages/sources.mdx      -> /sources/
pages/vendor-risk.mdx  -> /vendor-risk/

Routes are based on file basename, not nested source path.

Collision rule:

pages/a/sources.mdx
pages/b/sources.mdx

would both map to:

/sources/

Briefkit should error and require explicit route configuration.

Explicit route override:

export default {
  pages: [
    { file: "index.mdx", route: "/" },
    { file: "pages/hoh-fit.mdx", route: "/hoh-fit/" },
    { file: "pages/source-notes.mdx", route: "/sources/" },
  ],
};

Component / module API

Briefkit should support both children-first and data-driven components. The right API depends on the module.

General rule:

  • prose-heavy blocks should be children-first;
  • repeatable tables and matrices should be data-driven;
  • plain MDX and Markdown tables should remain valid when clearer than a component.

Examples:

<Callout type="warning" title="Main caveat">
Do not add plugins casually. This list only has 11 standard plugin slots free.
</Callout>

Supported callout types for v0:

  • note
  • tip
  • info
  • warning
  • danger

Callouts should be compact, visually distinct, readable in light and dark modes, and appropriate for decision reports. They should not become giant marketing cards.

import risks from "@report/data/risks.yaml";

<BriefTable
  caption="Risk register"
  columns={[
    { key: "risk", label: "Risk" },
    { key: "warning", label: "Warning sign" },
    { key: "mitigation", label: "Mitigation" }
  ]}
  rows={risks}
  stickyHeader
  stickyFirstColumn
/>

BriefTable should support both inline children and data-driven rows.

Inline mode is fastest for one-off reports:

<BriefTable caption="Risk register" stickyHeader stickyFirstColumn>
| Risk | Warning sign | Mitigation |
|---|---|---|
| Maintenance fatigue | You skip travel prep | Use inns and jobs |
</BriefTable>

Data mode is useful when data already exists in data/ or is reused across pages:

import risks from "@report/data/risks.yaml";

<BriefTable
  caption="Risk register"
  columns={[
    { key: "risk", label: "Risk" },
    { key: "warning", label: "Warning sign" },
    { key: "mitigation", label: "Mitigation" }
  ]}
  rows={risks}
  stickyHeader
  stickyFirstColumn
/>

BriefTable options for v0:

  • caption: table title;
  • columns: data-mode column mapping;
  • rows: data-mode row objects;
  • stickyHeader: sticky top header row;
  • stickyFirstColumn: sticky first column, styled as row headers;
  • class: escape hatch.

Rules:

  • normal Markdown tables should still be styled decently;
  • BriefTable is the preferred wrapper for important report tables;
  • if rows/columns are provided, render from data;
  • if no rows/columns are provided, render children;
  • if both data and children are provided, error rather than silently choosing one.

Tooltips should be inline by default. Reports are throwaway artifacts, so the fastest and clearest authoring path is to define the explanation where the term appears.

Example:

<Tooltip term="Frostfall">Cold/exposure survival mod.</Tooltip>

A data-driven glossary may be considered later if repeated-term management becomes painful, but it is not a v0 requirement.

Components should not require large prop objects when plain MDX is clearer.

v0 core modules

Briefkit v0 should keep the primitive component set intentionally small:

  • ReportLayout
  • Callout
  • Tooltip
  • BriefTable

Other report structures are documented patterns built from those primitives:

  • verdict: Callout
  • source notes: Callout or BriefTable
  • risk register: BriefTable
  • facts table: BriefTable
  • score matrix: BriefTable
  • decision rules: Callout or BriefTable

Modules should be useful primitives, not a rigid report schema.

Standard report header shows the page title only. No v0 standard subtitle, date, status, author, updated, or confidence metadata in the header. Reports that need that information can put it in the body with a Callout or BriefTable.

Standard report footer should credit the generator and show build time.

Config example:

export default {
  author: "Claude",
};

Footer with author:

Made by Claude with Briefkit | {Build Time}

Footer without author:

Made with Briefkit | {Build Time}

The author field belongs in config, not page frontmatter.

Theme and color mode

Default visual theme is light paper-first: dense, polished, readable, and print-friendly.

The standard layout should support a soft dark mode for late-night reading. Dark mode should be gentle, not pure black / high-contrast neon.

Theme implementation should use CSS tokens and a document attribute, not separate component sets.

Color mode behavior:

  • default is auto;
  • header includes a light / dark / auto toggle;
  • user choice should apply client-side for browsing;
  • build-time option can force one mode for generated output;
  • color mode is not controlled in page frontmatter.

Color mode is controlled by runtime UI and CLI / build options, not by report config or page frontmatter.

CLI examples:

briefkit dev ./report --color-mode auto
briefkit build ./report --color-mode dark

Suggested token posture:

TokenLightDark
Backgroundwarm off-whitecharcoal / ink gray
Paperwhiteslightly lighter charcoal
Textnear-blackwarm light gray
Mutedgraysoft gray
Lineswarm graylow-contrast slate
Accentmuted brown / blue / greendesaturated teal / blue
Tableswhite with subtle header filldark panels with slightly raised headers
Tooltippale yellowmuted navy / slate panel

CLI command surface

Briefkit v0 should have only two primary commands:

briefkit dev ./report
briefkit build ./report

dev is the main workflow. Most reports are expected to be created, read with live reload, and then discarded without a final build.

dev behavior:

  • starts a live-reload local server;
  • chooses an available port unless --port is provided;
  • watches MDX, local components, data, and public assets;
  • uses the shared Briefkit core without copying it into the report folder;
  • isolates generated / cache files per running report so concurrent dev servers can run safely;
  • opens the browser automatically by default;
  • prints that the browser was opened.

Example output:

Briefkit dev server running
Report: /tmp/skyrim-brief
URL: http://localhost:4311
Opened browser window.

Agents should not separately open the browser after running briefkit dev; Briefkit owns browser-opening to avoid duplicate tabs / windows.

Optional flag:

briefkit dev ./report --no-open

Example concurrent usage:

briefkit dev /tmp/skyrim-brief --port 4311
briefkit dev /tmp/wagos-brief --port 4312

build behavior:

  • generates a static site from a report folder;
  • supports build-time options such as forced color mode;
  • is for the minority case where the throwaway site needs to be saved, shared, or deployed.

No preview command for v0. No export command for v0.

Config file

Optional config file:

briefkit.config.{ts,js,mjs}

v0 shape:

export default {
  title: "Skyrim Modlist Decision",
  author: "Claude",
  pages: [
    "index.mdx",
    { file: "pages/hoh-fit.mdx", title: "HOH fit", route: "/hoh-fit/" },
  ],
};

Fields:

  • title: optional whole-report title / name;
  • author: footer credit;
  • pages: explicit page order and optional title / route overrides.

Color mode is not a config field. It is controlled by runtime UI and CLI / build options.

Page ordering / inclusion rules:

  • if pages exists, listed pages appear first in that order;
  • unlisted discovered pages are still included afterward, sorted alphabetically;
  • if no pages, all discovered pages are sorted alphabetically, with index.mdx first;
  • page title defaults to frontmatter title, then config title, then filename unless a config page entry overrides it;
  • route defaults to /filename-without-ext/, with index.mdx as /.

Hidden pages use frontmatter:

---
title: Scratch Notes
hidden: true
---

Hidden pages are not rendered as routes and do not appear in navigation.

Generated Astro workspaces

Briefkit should hide Astro ceremony by generating disposable Astro wrapper workspaces under the OS temp directory.

Report folders stay simple and do not contain copied Briefkit core or generated Astro project files.

Example report folder:

/tmp/skyrim-brief/
  index.mdx
  pages/hoh-fit.mdx
  data/
  components/

Generated workspace:

/tmp/briefkit/skyrim-brief-a8f31/
  astro.config.mjs
  package.json
  src/pages/index.astro
  src/pages/hoh-fit.astro

The workspace is disposable. If /tmp/briefkit/* disappears, Briefkit recreates it on the next dev or build.

For concurrent dev servers, each report path should get an isolated workspace identity. If the same report runs twice, include port or run id to avoid collisions.

Aliases in the generated Astro config should include:

briefkit -> shared Briefkit core
@report -> current report folder

Build output

Default build output is:

{report-folder}/brief/

Example:

briefkit build /tmp/skyrim-brief

writes to:

/tmp/skyrim-brief/brief/

Override:

briefkit build /tmp/skyrim-brief --out /tmp/brief/skyrim-modlist-decision

The whole-report title comes from:

config.title -> index page frontmatter title -> report folder name

Package / install model

Briefkit should be developed as a normal npm package in this repo with a global CLI bin.

v0 local development:

npm install
npm link
briefkit dev /tmp/my-report

Future published usage:

npm install -g briefkit
briefkit dev /tmp/my-report

Package shape:

{
  "name": "briefkit",
  "bin": {
    "briefkit": "./bin/briefkit.js"
  }
}

The package should expose the CLI plus reusable Astro / MDX components imported as briefkit.

Automatic wrapping and rendering

The CLI should discover pages, read frontmatter, and generate one Astro wrapper route per visible MDX page in the temp workspace.

Each generated wrapper imports the report MDX page and renders it inside ReportLayout unless the page opts out with layout: none or supplies a custom layout.

The wrapper passes layout data including:

  • current page info;
  • visible pages for sidebar navigation;
  • current page headings for sidebar TOC;
  • report config;
  • build time;
  • color mode.

Open questions

  • Whether route output should support .html mode later for direct file browsing.