Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@

Chartifact is a low-code document format for creating interactive, data-driven pages such as reports, dashboards, and presentations. It travels like a document and works like an app. Easily editable and remixable, it’s a file type for an AI-native world.

## Features
## Ecosystem

* A **library of components** — charts, inputs, tables, images, text, and layout elements — defined declaratively and wired together with reactive variables:
The Chartifact GitHub repo has source code for these interoperating modules:

* A **document schema** that defines plugins and components that communicate together with reactive variables:

* **Text** – Markdown with dynamic placeholders
* **Inputs** – Textboxes, checkboxes, sliders, dropdowns
* **Tables** – Sortable, selectable, and editable data grids
* **Charts** – Vega and Vega-Lite visualizations
* **Tables** – Sortable, filterable, and selectable data grids
* **Images** – Dynamic image URLs based on variables
* **Text** – Markdown with dynamic placeholders
* **Presets** – Named sets of variable values for quick scenario switching

* A **VS Code extension** for editing, previewing, and exporting documents, with optional AI assistance.
Expand All @@ -21,8 +23,6 @@ Chartifact is a low-code document format for creating interactive, data-driven p

* Tools to **export standalone HTML** documents you can share or embed anywhere.

---

## Authoring Formats

Chartifact documents can be written in two formats:
Expand Down Expand Up @@ -56,21 +56,13 @@ Chartifact documents behave like small reactive systems — without custom JavaS

## Styling

Styling is done using scoped CSS blocks embedded in the document. This allows flexible layout and visual design without global side effects:

* Style documents as articles, dashboards, or slides
* Use CSS to control layout and theming
* No raw HTML injection or global styles

The predictable, declarative nature of the styling model makes it easy for both humans and LLMs to work with.
Styling is done using standard CSS. Examples provided to style documents as articles, dashboards, or slides.

## Security

Chartifact is designed to be safe by default:

* Rendered in sandboxed iframes to isolate execution
* No custom JavaScript execution
* CSP-compliant via Vega expression language
* No raw HTML in Markdown
* Rendered in sandboxed iframes to isolate execution

These constraints help ensure portability and safe embedding in various environments.
* XSS-Defensive CSS parsing
11 changes: 11 additions & 0 deletions docs/assets/data/abc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{"category":"A", "group": "x", "value":0.1},
{"category":"A", "group": "y", "value":0.6},
{"category":"A", "group": "z", "value":0.9},
{"category":"B", "group": "x", "value":0.7},
{"category":"B", "group": "y", "value":0.2},
{"category":"B", "group": "z", "value":1.1},
{"category":"C", "group": "x", "value":0.6},
{"category":"C", "group": "y", "value":0.1},
{"category":"C", "group": "z", "value":0.2}
]
11 changes: 11 additions & 0 deletions docs/assets/data/def.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{"category":"D", "group": "x", "value":1.2},
{"category":"D", "group": "y", "value":2.3},
{"category":"D", "group": "z", "value":3.4},
{"category":"E", "group": "x", "value":4.5},
{"category":"E", "group": "y", "value":5.6},
{"category":"E", "group": "z", "value":6.7},
{"category":"F", "group": "x", "value":7.8},
{"category":"F", "group": "y", "value":8.9},
{"category":"F", "group": "z", "value":9.0}
]
58 changes: 58 additions & 0 deletions docs/assets/examples/features/chart.idoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "../../../schema/idoc_v1.json",
"title": "Feature: Chart",
"dataLoaders": [
{
"dataSourceName": "chartData",
"type": "json",
"content": [
{"category": "A", "value": 20},
{"category": "B", "value": 34},
{"category": "C", "value": 55},
{"category": "D", "value": 40},
{"category": "E", "value": 67}
]
}
],
"groups": [
{
"groupId": "main",
"elements": [
"## Chart\nUse charts for data visualizations with Vega-Lite specifications.",
{
"type": "chart",
"chart": {
"chartIntent": "Simple bar chart showing values by category",
"chartTemplateKey": "bar",
"dataSourceBase": {
"dataSourceName": "chartData"
},
"spec": {
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
"data": {
"name": "chartData"
},
"mark": "bar",
"encoding": {
"x": {
"field": "category",
"type": "nominal",
"title": "Category"
},
"y": {
"field": "value",
"type": "quantitative",
"title": "Value"
},
"color": {
"field": "category",
"type": "nominal"
}
}
}
}
}
]
}
]
}
29 changes: 29 additions & 0 deletions docs/assets/examples/features/css.idoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "../../../schema/idoc_v1.json",
"title": "Feature: CSS",
"layout": {
"css": ".group { padding: 20px; background-color: #f8f9fa; border: 2px solid #3498db; border-radius: 8px; margin-bottom: 20px; } .group h2 { color: #3498db; } .group h3 { color: #2c3e50; } #demo { background-color: #e8f5e8; border-color: #28a745; } #demo h2 { color: #28a745; }"
},
"groups": [
{
"groupId": "main",
"elements": [
"## CSS Styling\nUse CSS to style documents with custom layouts and appearance.",
"### How CSS Works",
"- Each group gets a `.group` className automatically",
"- Each group gets an `#id` based on the groupId",
"- Add custom CSS in the `layout.css` property",
"- Style headers, backgrounds, borders, and spacing",
"- CSS applies to all groups in the document"
]
},
{
"groupId": "demo",
"elements": [
"## Demo Section",
"This section has `groupId=\"demo\"` so it gets `id=\"demo\"` and can be styled with `#demo`.",
"Notice this section has a green theme instead of blue, applied via the `#demo` CSS selector."
]
}
]
}
60 changes: 60 additions & 0 deletions docs/assets/examples/features/data-sources.idoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"$schema": "../../../schema/idoc_v1.json",
"title": "Feature: Data Sources",
"dataLoaders": [
{
"dataSourceName": "jsonData",
"type": "json",
"content": [
{"item": "Stapler", "category": "Office Tools", "price": 12.99, "inStock": true, "quantity": 25},
{"item": "Printer Paper", "category": "Paper", "price": 8.50, "inStock": true, "quantity": 150},
{"item": "Blue Pens", "category": "Writing", "price": 3.25, "inStock": false, "quantity": 0},
{"item": "Notebooks", "category": "Paper", "price": 5.75, "inStock": true, "quantity": 40},
{"item": "Desk Lamp", "category": "Furniture", "price": 29.99, "inStock": true, "quantity": 8},
{"item": "Paper Clips", "category": "Office Tools", "price": 2.10, "inStock": true, "quantity": 200},
{"item": "Whiteboard Markers", "category": "Writing", "price": 7.80, "inStock": false, "quantity": 0},
{"item": "File Folders", "category": "Storage", "price": 4.45, "inStock": true, "quantity": 75},
{"item": "Ergonomic Chair", "category": "Furniture", "price": 189.99, "inStock": true, "quantity": 3},
{"item": "Post-it Notes", "category": "Paper", "price": 6.25, "inStock": true, "quantity": 120},
{"item": "Hole Punch", "category": "Office Tools", "price": 15.50, "inStock": false, "quantity": 0},
{"item": "Scissors", "category": "Office Tools", "price": 9.75, "inStock": true, "quantity": 18}
]
},
{
"dataSourceName": "csvData",
"type": "url",
"format": "csv",
"url": "https://vega.github.io/editor/data/stocks.csv"
}
],
"groups": [
{
"groupId": "main",
"elements": [
"## Data Sources\nLoad data from JSON, CSV, TSV, or URLs with optional transformations.",
"### JSON Data",
{
"type": "table",
"dataSourceName": "jsonData",
"variableId": "jsonTable",
"tabulatorOptions": {
"autoColumns": true,
"layout": "fitColumns",
"maxHeight": "100px"
}
},
"### CSV from URL",
{
"type": "table",
"dataSourceName": "csvData",
"variableId": "csvTable",
"tabulatorOptions": {
"autoColumns": true,
"layout": "fitColumns",
"maxHeight": "200px"
}
}
]
}
]
}
86 changes: 86 additions & 0 deletions docs/assets/examples/features/data-transformations.idoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"$schema": "../../../schema/idoc_v1.json",
"title": "Feature: Data Transformations",
"dataLoaders": [
{
"dataSourceName": "rawData",
"type": "json",
"content": [
{"name": "Product A", "category": "Electronics", "price": 299, "inStock": true},
{"name": "Product B", "category": "Electronics", "price": 199, "inStock": false},
{"name": "Product C", "category": "Clothing", "price": 49, "inStock": true},
{"name": "Product D", "category": "Clothing", "price": 79, "inStock": true},
{"name": "Product E", "category": "Books", "price": 15, "inStock": true}
],
"dataFrameTransformations": [
{
"type": "filter",
"expr": "datum.inStock && datum.price <= maxPrice"
}
]
}
],
"variables": [
{
"variableId": "maxPrice",
"type": "number",
"initialValue": 100
},
{
"variableId": "categoryStats",
"type": "object",
"isArray": true,
"initialValue": [],
"calculation": {
"dependsOn": ["rawData"],
"dataFrameTransformations": [
{
"type": "aggregate",
"groupby": ["category"],
"ops": ["count", "mean"],
"fields": ["name", "price"],
"as": ["count", "avgPrice"]
}
]
}
}
],
"groups": [
{
"groupId": "main",
"elements": [
"## Data Transformations\nUse data transformations to filter, aggregate, and manipulate data.",
{
"type": "slider",
"variableId": "maxPrice",
"label": "Maximum price filter:",
"min": 0,
"max": 500,
"step": 10
},
"### Filtered Products (in stock, price ≤ ${{maxPrice}})",
{
"type": "table",
"dataSourceName": "rawData",
"variableId": "filteredTable",
"tabulatorOptions": {
"autoColumns": true,
"layout": "fitColumns",
"maxHeight": "200px"
}
},
"### Category Statistics",
{
"type": "table",
"dataSourceName": "categoryStats",
"variableId": "categoryStatsTable",
"tabulatorOptions": {
"autoColumns": true,
"layout": "fitColumns",
"maxHeight": "150px"
}
}
]
}
]
}
77 changes: 77 additions & 0 deletions docs/assets/examples/features/data-url.idoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"$schema": "../../../schema/idoc_v1.json",
"title": "Feature: Data Url",
"variables": [
{
"variableId": "anything",
"type": "string",
"initialValue": "abc"
}
],
"dataLoaders": [
{
"dataSourceName": "jsonData",
"type": "url",
"url": "http://127.0.0.1:8000/{{anything}}.json"
}
],
"groups": [
{
"groupId": "main",
"elements": [
"## Data Sources\nLoad data from JSON, CSV, TSV, or URLs with optional transformations.",
"### JSON Data",
{
"type": "dropdown",
"variableId": "anything",
"options": [
"abc",
"def"
]
},
{
"type": "chart",
"chart": {
"chartIntent": "show a grouped bar chart",
"chartTemplateKey": "grouped-bar",
"dataSourceBase": {
"dataSourceName": "jsonData"
},
"spec": {
"$schema": "https://vega.github.io/schema/vega-lite/v6.json",
"data": {
"name": "jsonData"
},
"mark": "bar",
"encoding": {
"x": {
"field": "category"
},
"y": {
"field": "value",
"type": "quantitative"
},
"xOffset": {
"field": "group"
},
"color": {
"field": "group"
}
}
}
}
},
{
"type": "table",
"dataSourceName": "jsonData",
"variableId": "jsonTable",
"tabulatorOptions": {
"autoColumns": true,
"layout": "fitColumns",
"maxHeight": "100px"
}
}
]
}
]
}
Loading