
Integrate Todo List
Drop a React TodoProvider, context store, and status-aware row UI into your app so agent-driven builds share one todo list pattern.
Overview
integrate-todo-list is an agent skill for the Build phase that wires a React TodoProvider, context store, and status-aware todo rows into your frontend.
Install
npx skills add https://github.com/cognitedata/builder-skills --skill integrate-todo-listWhat is this skill?
- TodoContext + TodoProvider with memoized store value for React children
- TodoItemRow maps pending, in_progress, and completed states to Tabler icons
- In-progress rows use activeForm label text and subtle primary background highlight
- Typed TodoList and TodoItem contracts for agent-safe refactors
- Composable pattern: wrap app routes once with TodoProvider
- Three todo statuses: pending, in_progress, completed
- TodoItemRow uses 13px Tabler status icons
Adoption & trust: 1k installs on skills.sh; 4 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
Your agent keeps reinventing ad-hoc todo state and list markup instead of a consistent React pattern with clear in-progress semantics.
Who is it for?
Solo builders on React + Tabler icon stacks who need a fast, consistent task list UI inside a SaaS or internal builder surface.
Skip if: Non-React stacks, full project-management products needing assignees and due dates, or backends that require server-synced todos out of the box.
When should I use this skill?
You are building a React frontend and need a shared todo store plus status-aware list rows integrated under TodoProvider.
What do I get? / Deliverables
You integrate TodoProvider at the app root and render TodoItemRow lists with pending, in_progress, and completed visuals aligned to typed todo models.
- TodoContext and TodoProvider module
- TodoItemRow component with status styling
Recommended Skills
Journey fit
Todo list UI and state wiring are front-end Build work when you are assembling the product shell, not a separate launch or ops concern. Frontend subphase is where React context, list rendering, and in-progress visual states belong in the solo-builder journey shelf.
How it compares
Use as a focused UI integration snippet instead of importing a heavy PM library for a simple agent task panel.
Common Questions / FAQ
Who is integrate-todo-list for?
Indie developers and agent users building React frontends who want a standard todo context and row components without scaffolding list UX manually.
When should I use integrate-todo-list?
Use it during Build frontend work when adding a task sidebar, agent progress panel, or onboarding checklist to an existing React app.
Is integrate-todo-list safe to install?
It is front-end component code; review the Security Audits panel on this page and audit any data you later connect to the todo store.
SKILL.md
READMESKILL.md - Integrate Todo List
import { createContext, useState, useMemo } from 'react'; import type { ReactNode } from 'react'; import type { TodoList } from './types'; export interface TodoStoreValue { todos: TodoList; setTodos: (todos: TodoList) => void; } export const TodoContext = createContext<TodoStoreValue>({ todos: [], setTodos: () => undefined, }); export function TodoProvider({ children }: { children: ReactNode }) { const [todos, setTodos] = useState<TodoList>([]); const value = useMemo(() => ({ todos, setTodos }), [todos]); return <TodoContext.Provider value={value}>{children}</TodoContext.Provider>; } import { IconCircle, IconCircleFilled, IconCircleCheckFilled } from '@tabler/icons-react'; import type { TodoItem } from './types'; interface TodoItemRowProps { item: TodoItem; } const STATUS_ICONS = { pending: <IconCircle size={13} className="shrink-0 text-muted-foreground/50" />, in_progress: <IconCircleFilled size={13} className="shrink-0 text-primary animate-pulse" />, completed: <IconCircleCheckFilled size={13} className="shrink-0 text-success" />, }; export function TodoItemRow({ item }: TodoItemRowProps) { const label = item.status === 'in_progress' ? item.activeForm : item.content; const isInProgress = item.status === 'in_progress'; const isCompleted = item.status === 'completed'; return ( <div className={[ 'flex items-start gap-2.5 rounded-sm px-2 py-1 -mx-2', isInProgress ? 'bg-primary/5' : '', ].join(' ')} > <span className="mt-0.5">{STATUS_ICONS[item.status]}</span> <span className={[ 'text-sm leading-snug', isCompleted ? 'text-muted-foreground/60 line-through' : '', isInProgress ? 'text-foreground font-medium' : 'text-muted-foreground', ].join(' ')} > {label} </span> </div> ); } import { Badge, Card, CardContent, CardHeader, CardHeaderRight, CardTitle } from '@cognite/aura/components'; import { TodoItemRow } from './TodoItemRow'; import type { TodoList } from './types'; interface TodoPanelProps { todos: TodoList; } export function TodoPanel({ todos }: TodoPanelProps) { if (todos.length === 0) return null; const completedCount = todos.filter((t) => t.status === 'completed').length; const progressPct = Math.round((completedCount / todos.length) * 100); return ( <div className="mb-3"> <Card> <CardHeader className="pb-2"> <CardTitle as="h3" className="text-xs font-semibold uppercase tracking-widest text-muted-foreground"> Tasks </CardTitle> <CardHeaderRight> <Badge variant="secondary" size="default"> {completedCount}/{todos.length} </Badge> </CardHeaderRight> </CardHeader> <div className="mx-4 h-px bg-border"> <div className="h-full bg-success transition-all duration-500 ease-out" style={{ width: `${progressPct}%` }} /> </div> <CardContent className="max-h-40 overflow-y-auto pt-3"> {todos.map((item, i) => ( // Index is safe here: the agent only appends to the end and updates in place — it never reorders or inserts in the middle. // Using content as a key would cause remounts (and animation resets) whenever the agent updates a task title with discovered node names. <TodoItemRow key={i} item={item} /> ))} </CardContent> </Card> </div> ); } import { Tool, ToolContent, ToolHeader } from '@cognite/aura/components'; interface ToolCall { name: string; input?: unknown; output?: string; details?: unknown; } interface TodoToolResultCardProps { toolCall: ToolCall; } interface TodoDetails { completed: number; inProgress: number; pending: number; newTodos: { content: string; status: string }[]; } function isTodoDetails(value: unknown): value is TodoDetails { return ( typeof value === 'object' &&