Build data-driven apps with markdown
Tinkerdown is a CLI tool for creating interactive, data-driven applications using markdown files. Connect to databases, APIs, and files with zero boilerplate. Built on LiveTemplate.
Tinkerdown replaces typical app scaffolding with a single markdown file — data sources in YAML, layout in markdown, interactions via HTML attributes.
- One file = one app. Data connections, layout, and interactions all live in one place. No build step, no node_modules, no boilerplate.
- AI gets it right. A single declarative file with no component tree or state management means less surface area for LLMs to misconfigure.
- 9 data sources out of the box. SQLite, PostgreSQL, REST APIs, JSON, CSV, shell commands, markdown, WASM, and computed/derived sources. Point at existing infrastructure and get a working UI.
- Progressive complexity. Write standard markdown — task lists become interactive, tables auto-bind to data sources. Need more control? Add HTML attributes. Need full custom layouts? Drop to Go templates. Each step builds on the last without rewriting. See the Progressive Complexity Guide.
- Git-native and self-hosted. Plain text in a repo. Version history, search, collaboration, offline access, no subscriptions.
- Made for disposable software. The admin panel for this sprint. The tracker for that hiring round. Software you'd never scaffold a React project for, but that's useful for days or weeks.
# Install
go install github.com/livetemplate/tinkerdown/cmd/tinkerdown@latest
# Create a new app
tinkerdown new myapp
cd myapp
# Run the app
tinkerdown serve
# Open http://localhost:8080Write a markdown file with a YAML source definition and a standard markdown table. Tinkerdown infers that the "Tasks" heading matches the "tasks" source and auto-generates an interactive table with add, edit, and delete:
---
title: Task Manager
sources:
tasks:
type: sqlite
db: ./tasks.db
table: tasks
readonly: false
---
# Task Manager
## Tasks
| Title | Status | Due Date |
|-------|--------|----------|Run tinkerdown serve and get a fully interactive app with database persistence — no HTML needed:
Need more control? Use HTML attributes for explicit binding:
<table lvt-source="tasks" lvt-columns="title,status" lvt-datatable lvt-actions="Complete,Delete">
</table>- Single-file apps: Everything in one markdown file with frontmatter
- 9 data sources: SQLite, JSON, CSV, REST APIs, PostgreSQL, exec scripts, markdown, WASM, computed
- Auto-rendering: Tables, selects, and lists generated from data
- Real-time updates: WebSocket-powered reactivity
- Zero config:
tinkerdown servejust works - Hot reload: Changes reflect immediately
Define sources in your page's frontmatter:
---
sources:
tasks:
type: sqlite
path: ./tasks.db
query: SELECT * FROM tasks
users:
type: rest
from: https://api.example.com/users
config:
type: json
path: ./_data/config.json
---| Type | Description | Example |
|---|---|---|
sqlite |
SQLite databases | lvt-source-sqlite-test |
json |
JSON files | lvt-source-file-test |
csv |
CSV files | lvt-source-file-test |
rest |
REST APIs | lvt-source-rest-test |
pg |
PostgreSQL | lvt-source-pg-test |
exec |
Shell commands | lvt-source-exec-test |
markdown |
Markdown files | markdown-data-todo |
wasm |
WASM modules | lvt-source-wasm-test |
computed |
Derived/aggregated data | computed-source |
Generate HTML automatically from data sources:
<!-- Table with actions -->
<table lvt-source="tasks" lvt-columns="title,status" lvt-actions="Edit,Delete">
</table>
<!-- Select dropdown -->
<select lvt-source="categories" lvt-value="id" lvt-label="name">
</select>
<!-- List -->
<ul lvt-source="items" lvt-field="name">
</ul>See Auto-Rendering Guide for full details.
| Attribute | Description |
|---|---|
lvt-source |
Connect element to a data source |
lvt-click |
Handle click events |
lvt-submit |
Handle form submissions |
lvt-change |
Handle input changes |
lvt-confirm |
Show confirmation dialog before action |
lvt-data-* |
Pass data with actions |
See lvt-* Attributes Reference for the complete list.
Recommended: Configure in frontmatter (single-file apps):
---
title: My App
sources:
tasks:
type: sqlite
path: ./tasks.db
query: SELECT * FROM tasks
styling:
theme: clean
---For complex apps: Use tinkerdown.yaml for shared configuration:
# tinkerdown.yaml - for multi-page apps with shared sources
server:
port: 3000
sources:
shared_data:
type: rest
from: ${API_URL}
cache:
ttl: 5mSee Configuration Reference for when to use each approach.
Tinkerdown works great with AI assistants. Describe what you want:
Create a task manager with SQLite storage,
a table showing tasks with title/status/due date,
a form to add tasks, and delete buttons on each row.
See AI Generation Guide for tips on using Claude Code and other AI tools.
Getting Started:
Guides:
Reference:
Planning:
git clone https://github.com/livetemplate/tinkerdown.git
cd tinkerdown
go mod download
go test ./...
go build -o tinkerdown ./cmd/tinkerdownMIT
Contributions welcome! See ROADMAP.md for planned features and current priorities.
