Roadmap
Configure a Kanban-like roadmap board with JSON and render it with reusable components
Roadmap
Kanban‑style roadmap driven by JSON under content/roadmap/ and rendered with typed React components. Each locale can have an independent configuration file.
Use config.en.json / config.zh.json to define columns and items. The schema is validated by Content Collections and Zod.
Files live in
content/roadmap/; schema is defined incontent-collections.tsunder theroadmapcollection.
JSON Example
{
"columns": [
{
"title": "Planned",
"icon": "Calendar", // Lucide Icon
"color": "#60A5FA",
"items": [
{ "title": "Landing video intro" }
]
},
{
"title": "In Progress",
"icon": "Loader", // Lucide Icon
"color": "#F59E0B",
"items": []
},
{
"title": "Shipped",
"icon": "Rocket", // Lucide Icon
"color": "#34D399",
"items": []
}
]
}Constraints (validated by Zod):
icon: alphabetic Lucide icon name, e.g.Rocketcolor: hex like#C084FCitems[]:{ title: string }
Create and Maintain
1) Create files
In content/roadmap/, create config.en.json (English) and config.zh.json (Chinese). Keep both files in version control.
content/roadmap/
├─ config.en.json
└─ config.zh.json2) Define columns
For each locale file, add a columns array. Each column includes title, Lucide icon (letters only), and HEX color.
{
"columns": [
{ "title": "Planned", "icon": "Calendar", "color": "#60A5FA", "items": [] },
{ "title": "In Progress", "icon": "Loader", "color": "#F59E0B", "items": [] },
{ "title": "Shipped", "icon": "Rocket", "color": "#34D399", "items": [] }
]
}3) Add items
Inside each column, add items like { "title": "Your task" }. One item equals one roadmap task.
{
"title": "Planned",
"items": [
{ "title": "Landing video intro" },
{ "title": "AI onboarding" }
]
}4) Localize
Maintain both locale files. The app automatically picks the file matching the current language; orders can differ per locale.
# English only example
content/roadmap/config.en.json
# Chinese only example
content/roadmap/config.zh.json5) Reorder / remove
Reorder items by changing the array order. Remove by deleting from the array. Column order = array order (left → right).
{
"columns": [
{ "title": "Shipped", ... },
{ "title": "In Progress", ... },
{ "title": "Planned", ... }
]
}6) Preview & publish
Run bun run dev to preview locally. Commit changes to publish; no code edits are required.
bun run dev
# push to your repo → CI/CD will publishRendering
import { Board, type RoadmapColumn } from '@/components/roadmap'
const columns: RoadmapColumn[] = [
{ title: 'Planned', key: 'planned', icon: 'Calendar', color: '#60A5FA', items: [{ title: '...' }] },
{ title: 'In Progress', key: 'inprogress', icon: 'Loader', color: '#F59E0B', items: [] },
{ title: 'Shipped', key: 'shipped', icon: 'Rocket', color: '#34D399', items: [] },
]
<Board
columns={columns}
/> Best Practices
- Keep item titles short; item
typecan carry extra context. - Pick high-contrast colors for column badges; use accessible color pairs.
- Keep column counts small (3–4) for readability.
- Use locales to show region-specific plans when needed.
FAQ
Q: Icon names don’t render.
A: icon must be a Lucide component name (letters only), e.g., Rocket, Calendar. Check spelling and case to match the exported names.
Q: Color doesn’t apply.
A: color must be a hex like #RRGGBB or #RGB. Invalid values are rejected by schema validation.
Q: How to present different roadmaps per language?
A: Maintain config.en.json and config.zh.json. The system loads the config that matches the current locale.