Как я построил канбан-доску для управления 19 проектами

У меня есть JSON-файл с 75 задачами. Часть выполнена, часть ждёт, часть заморожена. Раньше я смотрел на это как на список. Сегодня я превратил это в живую канбан-доску — с drag-and-drop, фильтрами и прогресс-баром. И всё это за одну сессию с AI-агентом.

Исходные данные

Файл evolution_backlog.json — это центральный нерв моей лаборатории. В нём:

  • 75 задач разного типа: архитектура, безопасность, документация, фичи, рефакторинг
  • 5 статусов: pending, in_progress, completed, frozen, on_hold
  • Поля: name, insight, type, priority, project

Это задачи, не проекты. Проектов у меня 19. Задач — 75+. Это разные сущности.

Задачи генерируются автоматически — агенты добавляют инсайты после каждого сканирования проектов. Проблема была в том, что JSON неудобно читать глазами, а в Excel таскать лень.

Что построил

FastAPI-сервер, который:

  • Читает evolution_backlog.json напрямую
  • Автоматически делает бэкапы перед каждой записью (до 10 штук)
  • Отдаёт задачи с фильтрацией по статусу, типу, приоритету и поиском

Реакт-фронт, который:

  • Показывает 5 колонок канбана (Ожидание → В работе → Готово → Заморожено → Пауза)
  • Поддерживает drag-and-drop между колонками (перетащил задачу — статус обновился на сервере)
  • Фильтры по типу задачи и приоритету
  • Прогресс-бар: сколько из 75 выполнено
  • Всё в тёмной теме, моноширинный шрифт, стиль терминала

Код сервера

Сервер — это один файл kanban_server.py. Ровно один эндпоинт для обновления:

@app.patch("/api/kanban/tasks/{task_id}")
def update_task(task_id: int, update: TaskUpdate):
    data = load_backlog()
    task = next((t for t in tasks if t.get("id") == task_id), None)
    old_status = task.get("status")
    task.update(update_dict)
    save_backlog(data)  # с автоматическим бэкапом
    return {"ok": True, "task": task, "old_status": old_status}

Drag-and-drop на фронте — нативный HTML5 Drag API, без библиотек:

<div
  draggable
  onDragStart={() => handleDragStart(task)}
>
  {task.name}
</div>
// ...
<div
  onDragOver={e => e.preventDefault()}
  onDrop={() => handleDrop('completed')}
>
  Готово ({completedCount})
</div>

Поиск — клиентский, без лишних запросов к серверу. Фильтры тоже.

Что получилось

Канбан-доска — отдельная вкладка в экосистеме. Прогресс: из 75 задач 27 выполнены. Это 36%. Видно сразу — красная полоска прогресса вверху страницы.

Что дальше

В бэклоге ещё 50 задач в статусе pending. Часть из них — документация, которую можно делать автоматически. Часть — архитектурные, которые требуют человеческого решения. Теперь это всё видно на одной странице.

Идея в том, что AI-агенты не только добавляют задачи в бэклог, но и выполняют их — и карточки сами ползут вправо. Канбан становится дашбордом не проектов, а самой лаборатории.

Технические детали

  • Фронт: React + Vite + TypeScript
  • Бэкенд: FastAPI + uvicorn
  • Данные: JSON-файл, без базы данных
  • Бэкапы: автоматические, ротирующиеся
  • Проксируется через nginx

Оригинал: https://articles.shtab-ai.ru/articles/myrmex-kanban.html