Skip to content
Framework: Vite + React + TypeScriptDifficulty: beginner

Todo, kanban and notes

A productivity app with a todo list, a drag-and-drop kanban board, and a notes editor sharing one local dataset.

Three views over persisted local state: a classic todo list with completion and filtering, a three-column board with HTML5 drag-and-drop plus keyboard-friendly move buttons, and a two-pane notes editor. Everything is typed and saved to localStorage through a tiny hook, which makes it a good base for learning state management before adding a database.

  • react
  • todo
  • kanban
  • notes
  • productivity
  • tailwind

This preview is the template's actual file tree and source code — exactly what is copied into a new project. Codexa does not publish screenshots or mock-ups of templates; run the project to see it rendered.

Files14 files

src/views/TodoList.tsx55 lines
import { useState, type FormEvent } from "react";
import { newId, type Task } from "../types";

type Props = { tasks: Task[]; setTasks: (next: Task[] | ((prev: Task[]) => Task[])) => void };

export function TodoList({ tasks, setTasks }: Props) {
  const [title, setTitle] = useState("");
  const [showDone, setShowDone] = useState(true);

  function add(e: FormEvent) {
    e.preventDefault();
    const t = title.trim();
    if (!t) return;
    setTasks((prev) => [{ id: newId(), title: t, column: "todo", createdAt: Date.now() }, ...prev]);
    setTitle("");
  }
  const toggle = (id: string) => setTasks((prev) => prev.map((t) => (t.id === id ? { ...t, column: t.column === "done" ? "todo" : "done" } : t)));
  const remove = (id: string) => setTasks((prev) => prev.filter((t) => t.id !== id));
  const visible = tasks.filter((t) => showDone || t.column !== "done");
  const remaining = tasks.filter((t) => t.column !== "done").length;

  return (
    <div className="mx-auto max-w-xl">
      <form onSubmit={add} className="flex gap-2">
        <label className="sr-only" htmlFor="new-task">
          New task
        </label>
        <input id="new-task" value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Add a task and press Enter" className="flex-1 rounded-md border border-slate-300 px-3 py-2 text-sm" />
        <button type="submit" className="rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white">
          Add
        </button>
      </form>
      <div className="mt-4 flex items-center justify-between text-sm text-slate-500">
        <span>
          {remaining} remaining
        </span>
        <label className="flex items-center gap-2">
          <input type="checkbox" checked={showDone} onChange={(e) => setShowDone(e.target.checked)} /> Show completed
        </label>
      </div>
      <ul className="mt-3 divide-y divide-slate-200 rounded-xl border border-slate-200 bg-white">
        {visible.map((t) => (
          <li key={t.id} className="flex items-center gap-3 p-3">
            <input type="checkbox" checked={t.column === "done"} onChange={() => toggle(t.id)} aria-label={"Mark " + t.title + (t.column === "done" ? " as not done" : " as done")} />
            <span className={"flex-1 text-sm " + (t.column === "done" ? "text-slate-400 line-through" : "")}>{t.title}</span>
            <button type="button" onClick={() => remove(t.id)} className="text-xs text-slate-400 hover:text-red-600" aria-label={"Delete " + t.title}>
              Delete
            </button>
          </li>
        ))}
        {visible.length === 0 ? <li className="p-6 text-center text-sm text-slate-500">Nothing here yet.</li> : null}
      </ul>
    </div>
  );
}

Dependencies

Documented from the template's package.json. The runtime has a prebuilt dependency set for Vite + React + TypeScript, so installs are fast.

PackageVersion
react^19.1.0
react-dom^19.1.0
vite^6.3.0
@vitejs/plugin-react^4.4.0
tailwindcss^4.1.0
@tailwindcss/vite^4.1.0
typescript^5.8.0

How it runs

Framework
Vite + React + TypeScript
Dev command
npm run dev
Build command
npm run build
Output directory
dist
Port
5173
Opens at
/
Difficulty
beginner

Projects run in an isolated sandbox with a live preview. Read the projects documentation for details on settings, snapshots and deployment.

View all
  • Framework: Vite + React + TypeScriptDifficulty: beginner
    Featured

    React starter

    A clean React + TypeScript + Tailwind single-page app. The default target for AI generation.

    • react
    • typescript
    • tailwind
    • vite
    • spa

    9 files

  • Framework: Node.js + ExpressDifficulty: intermediate

    Express REST API

    A TypeScript Express API with routing, validation, and an in-memory store you can swap for PostgreSQL.

    • node
    • express
    • api
    • typescript
    • backend

    5 files

  • Framework: Node.js + ExpressDifficulty: intermediate

    Structured Express API

    A notes REST API split into router, middleware, and store modules, with logging, error handling, and search.

    • node
    • express
    • api
    • rest
    • typescript

    8 files

Need the raw data? GET /api/v1/templates/vite-react-tasks returns this template with its files.

Build on Todo, kanban and notes

Create a free account, start from this template, and ask the AI agent to turn it into your app.