| name | write-docs |
| description | Style guide for writing OpenIVM documentation. Auto-loaded when writing, editing, or reviewing docs, README, user guides, or SQL reference pages. Blends Snowflake's structured clarity with DuckDB's concise, example-first approach. |
OpenIVM Documentation Style Guide
This guide defines how to write documentation for OpenIVM. The style blends
Snowflake's structured clarity (hierarchical sections, callout boxes,
thorough parameter docs) with DuckDB's concise, example-first approach
(lead with code, short sentences, practical tone).
1. Core Principles
- Lead with examples. Show what it does before explaining how it works.
DuckDB puts Examples before Syntax. Follow that: example first, reference second.
- One idea per sentence. Keep sentences to 15-25 words. Break longer thoughts
into two sentences. Never nest more than one subordinate clause.
- Address the reader as "you". Not "the user" or "one". Active voice, imperative
mood for instructions: "Create a view" not "A view can be created".
- No filler. Cut "In order to", "It should be noted that", "Please note that".
Just state the fact.
- Be precise about behavior. Don't say "may" when you mean "does". Don't say
"should" when you mean "must". Reserve "may" for genuine uncertainty.
- Document every feature and every known limitation. If a feature exists, it must
appear in the docs. If a limitation exists, it must appear in a Limitations section.
Undocumented features and silent limitations are bugs. When you add or change a
feature in code, update the corresponding docs page in the same commit.
2. Page Structure
2.1 Conceptual / User Guide Pages
Follow Snowflake's overview page pattern:
# Page Title ← H1: noun phrase, no verb
← 2-3 sentence intro: what this is + why it matters
## How It Works ← H2: explain the mechanism
### Sub-concept ← H3: one per distinct idea
## When to Use This ← H2: use cases, decision criteria
## Limitations ← H2: always present, even if short
## Examples ← H2: 2-4 progressively complex examples
## See Also ← H2: links to related pages
Intro paragraph: State what the feature is and what problem it solves.
Two to three sentences maximum. No history, no motivation essay.
Good: "Delta tables track changes to base tables. OpenIVM creates them
automatically when you define a materialized view."
Bad: "In the field of incremental view maintenance, it has long been
recognized that tracking changes is essential. To this end, OpenIVM
provides a mechanism called delta tables, which we will now describe."
2.2 SQL Reference Pages
Follow DuckDB's statement page pattern, with Snowflake's parameter rigor:
# STATEMENT NAME ← H1: the SQL command
← 1-2 sentence description
## Examples ← H2: FIRST, before syntax
## Syntax ← H2: formal syntax block
## Parameters ← H2: every parameter documented
### Required Parameters ← H3: if many params
### Optional Parameters ← H3: if many params
## Usage Notes ← H2: behavioral details, edge cases
## Limitations ← H2: what doesn't work
## See Also ← H2: related commands
2.3 Function / Pragma Reference Pages
Follow DuckDB's aggregate function pattern:
# Function Category ← H1
← Brief overview sentence
## Examples ← H2: common usage patterns
## Function List ← H2: table with Name | Description | Example
## Detailed Reference ← H2: per-function details if needed
### function_name(params) ← H4: one heading per function
3. Syntax Blocks
Use fenced SQL code blocks. Follow Snowflake's notation for formal syntax:
CREATE MATERIALIZED VIEW <view_name> AS
<select_statement>
Notation conventions:
<placeholder> — user-supplied value (angle brackets)
[ optional ] — optional clause (square brackets)
{ choice1 | choice2 } — choose one (braces + pipe)
... — repeatable element
- Keywords in UPPERCASE, identifiers in lowercase
For informal examples (the Examples section), use real values, not placeholders:
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT product, SUM(amount) AS total, COUNT(*) AS cnt
FROM orders
GROUP BY product;
4. Parameter Documentation
Use Snowflake's definition-list style. Each parameter gets:
- Name in backtick code font
- Description — what it does, in one sentence
- Type and Default — on their own line if applicable
- Constraints — what values are valid
Format:
`view_name`
The name of the materialized view to create.
`select_statement`
The SQL query that defines the view contents. Must be a SELECT statement.
Supported: projections, filters, GROUP BY, SUM, COUNT, inner joins.
Not supported: outer joins, window functions, DISTINCT, LIMIT.
`ivm_refresh_mode`
Controls how the view is refreshed.
- `'auto'` — Choose incremental or full based on cost model. **Default.**
- `'incremental'` — Always use incremental maintenance.
- `'full'` — Always recompute from scratch.
5. Examples
5.1 Structure
Every page with examples must follow this pattern:
- Start simple. First example: the most common, minimal use case.
- Build up. Each subsequent example adds one concept (filter, join, config option).
- Show setup AND result. Include the CREATE, INSERT, PRAGMA, and SELECT output.
- Use realistic data. Not
foo/bar/baz. Use orders, products, employees.
5.2 Format
CREATE MATERIALIZED VIEW product_totals AS
SELECT product, SUM(amount) AS total
FROM orders
GROUP BY product;
INSERT INTO orders VALUES ('Widget', 100), ('Gadget', 200), ('Widget', 50);
SELECT * FROM product_totals;
┌─────────┬───────┐
│ product │ total │
│ varchar │ int32 │
├─────────┼───────┤
│ Gadget │ 200 │
│ Widget │ 150 │
└─────────┴───────┘
INSERT INTO orders VALUES ('Widget', 75);
PRAGMA ivm('product_totals');
SELECT * FROM product_totals;
┌─────────┬───────┐
│ product │ total │
│ varchar │ int32 │
├─────────┼───────┤
│ Gadget │ 200 │
│ Widget │ 225 │
└─────────┴───────┘
5.3 SQL Comment Style
- Use
-- comments, not /* */
- Comment above the statement, not inline
- Describe what and why, not the SQL syntax itself
- Start with a verb: "Create...", "Insert...", "Refresh..."
PRAGMA ivm('product_totals');
PRAGMA ivm('product_totals');
6. Callout Boxes
Use Markdown blockquote callouts. Three types, used sparingly:
Note — Additional context that helps understanding
> **Note:** Delta tables are created automatically. You do not need to
> create them manually.
Use when: the reader might otherwise miss a helpful detail.
Important — Something that can cause incorrect results if ignored
> **Important:** The multiplicity column must be BOOLEAN. Using INTEGER
> multiplicities will produce incorrect aggregate results.
Use when: ignoring this causes silent data corruption or wrong results.
Tip — A non-obvious efficiency or convenience trick
> **Tip:** Set `ivm_adaptive_refresh = true` to let OpenIVM automatically choose
> between incremental refresh and full recompute based on delta size.
Use when: there's a better way that the reader might not discover on their own.
Rules:
- Maximum 2-3 callouts per page. More than that means the prose needs rewriting.
- Never put critical information only in a callout. The main text must stand alone.
- Never stack two callouts back-to-back.
7. Tables
Use tables for structured reference data. Follow DuckDB's function table pattern.
7.1 When to Use Tables
- Function/pragma lists: Name | Description | Example
- Parameter options: Value | Behavior
- Feature comparison: Feature | Supported? | Notes
- Configuration options: Setting | Type | Default | Description
7.2 When NOT to Use Tables
- Explanations of how something works (use prose)
- Step-by-step instructions (use numbered lists)
- Anything with more than 5 columns (too wide)
7.3 Format
| Setting | Type | Default | Description |
|---|---|---|---|
| `ivm_refresh_mode` | VARCHAR | `'auto'` | Refresh strategy |
| `ivm_adaptive_refresh` | BOOLEAN | `false` | Enable adaptive cost model |
- Left-align text columns, right-align numbers
- Use backticks for code values in cells
- Keep descriptions to one line
8. Cross-References
8.1 "See Also" Sections
Place at the bottom of every page. List 3-7 related pages:
## See Also
- [CREATE MATERIALIZED VIEW](create-materialized-view.md) — Define a new materialized view
- [PRAGMA ivm](pragma-ivm.md) — Refresh a materialized view incrementally
- [Delta Tables](delta-tables.md) — How change tracking works
Format: [Page Title](link) — one-line description.
8.2 Inline References
Use sparingly in prose. Link on first mention only:
OpenIVM tracks changes in [delta tables](delta-tables.md).
Subsequent mentions of delta tables are not linked.
9. Limitations Sections
Every feature page must have a Limitations section. Follow Snowflake's pattern:
## Limitations
- Only inner joins are supported. Outer, cross, and semi joins are not
incrementally maintained.
- MIN and MAX aggregates require group recomputation on delete.
SUM and COUNT are fully incremental.
- Maximum 16 tables in a single join (`ivm::MAX_JOIN_TABLES`).
- Views using window functions, DISTINCT, or LIMIT are classified as
`FULL_REFRESH` and always recomputed.
Rules:
- Use a bulleted list, one limitation per bullet
- State what is NOT supported, then (optionally) what happens instead
- Don't apologize or promise future fixes
- Order by importance (most impactful first)
10. Writing Checklist
Before publishing any documentation page, verify:
11. File Organization
The project has two documentation locations:
README.md (project root) — The landing page. Contains:
- One-paragraph project description
- Feature highlights (bulleted)
- Quick-start example (create view, insert, refresh, select)
- Build instructions
- Link to
docs/ for detailed documentation
docs/ — Detailed documentation, organized by topic:
docs/
├── getting-started.md ← Quick start guide (install, first MV, first refresh)
├── user-guide/
│ ├── materialized-views.md ← Conceptual: what MVs are, how they work
│ ├── delta-tables.md ← Conceptual: change tracking
│ ├── refresh-modes.md ← Conceptual: auto/incremental/full
│ └── cost-model.md ← Conceptual: adaptive decisions
├── sql-reference/
│ ├── create-materialized-view.md
│ ├── pragma-ivm.md
│ ├── pragma-ivm-cost.md
│ └── configuration.md
└── limitations.md ← Global limitations page
Rules:
- Each docs page must be self-contained: a reader landing from search should
understand it without reading other pages first.
- The README must stay concise (under 150 lines). Detailed content goes in
docs/.
- When you add a feature, add or update the corresponding page in
docs/.
- When you discover a limitation, add it to
docs/limitations.md AND to the
relevant feature page's Limitations section.