# ordo-desk — полный пакет (ТЗ, контекст, дизайн-система) Собрано 2026-08-14 на meteor-prod-01. Прототип интерфейса — отдельным файлом `prototype/index.html` рядом с этим документом (открывается в браузере как есть). Содержание: - 0. Навигация по пакету - 1. Памятка для сессии Claude Code - 2. Контекст и принятые решения - 3. Техническое задание - 4. Дизайн-система --- # 0. Навигация по пакету ## ordo-desk — пакет для переноса на новый сервер Всё, что нужно, чтобы продолжить работу в новом чате на другой машине: контекст решений, техническое задание, дизайн-система и кликабельный прототип интерфейса. ### Порядок чтения 1. `docs/01-context-and-decisions.md` — как пришли к этой системе, какие пути отвергнуты и почему. 2. `docs/02-spec.md` — **техническое задание**: модель данных, виды баз, документы, права, поиск, шорткаты, API + MCP для агента Hermes, производительность, PWA и десктоп, фазы работ. 3. `docs/03-design-system.md` — токены, типографика, компоненты, иконки, планка качества. 4. `prototype/index.html` — открыть в браузере. Это спецификация в картинках: все экраны и состояния. 5. `CLAUDE.md` — короткая памятка для новой сессии Claude Code, кладётся в корень проекта. ### Что это за система (одним абзацем) Мультитенантная система ведения проектов: аккаунт (Nurion, Inside Realty, Личное) → проекты → задачи, документы, базы-справочники, финансы. Задачи в логике Todoist (метки, «Сегодня», быстрый ввод строкой), базы и документы в логике Notion (настраиваемые виды, блочный редактор, база внутри страницы), проект — сквозная сущность, к которой цепляется всё остальное. Заметки зеркалятся markdown-файлами. Домен: ordo.ins.is. **Это не MVP.** Планка — законченный продукт с первого экрана, см. §1.1 в ТЗ. ### Прототип Открывается как обычный файл, без сборки и сервера: `prototype/index.html`. Онлайн-копия (пока жива): https://ordo-proto.sites.meteor.group Что посмотреть: переключатель аккаунта в левом верхнем углу, разделы в рейле, фильтры на «Проектах», вкладки внутри проекта, метки и композер на «Задачах», блок «База» внутри документа, виды базы «Цели» (доска по сферам, таблица, календарь, галерея) и панель настройки вида. ### Первое сообщение в новом чате > Прочитай `README.md`, `CLAUDE.md` и всё в `docs/`, открой `prototype/index.html`. > Это ТЗ на систему, которую делаем. Дальше обсуждаем технические нюансы и начинаем фазу 0. ### Что осталось решить Список открытых вопросов — в конце `docs/02-spec.md` (§13): валюты, повторяющиеся задачи, календарь встреч, гостевые ссылки, двусторонний markdown. --- # 1. Памятка для сессии Claude Code ## ordo-desk — своя система ведения проектов > Этот файл подгружается автоматически, когда сессия работает с файлами в `/home/meteor/apps/ordo-desk/`. > Он — точка входа: что это за проект, где спека, где прототип, какие решения уже приняты. ### Что это Собственная мультитенантная система ведения проектов: аккаунт (тенант) → проекты → задачи, документы, базы, финансы. Заменяет связку Notion + Todoist + Apple Notes. Планируется на домене **ordo.ins.is**. Кода пока нет — есть спецификация и кликабельный прототип интерфейса. ### Где что лежит | Файл | Что внутри | |---|---| | `docs/01-context-and-decisions.md` | Путь решений: почему не Huly, почему не форк, почему не AppFlowy, почему своё | | `docs/02-spec.md` | **ТЗ**: модель данных, виды баз, документы, права, API + MCP, поиск, шорткаты, PWA, десктоп, фазы работ | | `docs/03-design-system.md` | Дизайн-система: токены, типографика, компоненты, иконки, паттерны | | `/home/meteor/sites/ordo-proto/public/index.html` | **Исходник прототипа** (source of truth, один файл) | | `/home/meteor/apps/ordo/specs/2026-08-14-project-over-spaces-design.md` | Спека форка Huly — **отвергнутый путь**, оставлен для истории | Живой прототип: **https://ordo-proto.sites.meteor.group** (noindex, публичный URL без авторизации). ### Как обновить прототип ```bash ## правим один файл $EDITOR /home/meteor/sites/ordo-proto/public/index.html ## выкладываем docker exec meteor-api-1 node dist/scripts/site-sync.js ordo-proto ``` Папка `/home/meteor/sites/ordo-proto/` — источник истины, синк затирает всё остальное. Подробности механики статических сайтов — `/home/meteor/sites/CLAUDE.md`. ### Принятые решения, которые не надо переоткрывать 1. **Пишем своё приложение**, не форкаем Huly и не берём AppFlowy как движок. Обоснование — в `docs/01-context-and-decisions.md`, там цифры по замедлению апстрима и по лицензиям. 2. **Проект — главная сущность**, всё цепляется к нему. Метка — про состояние, а не про тему. 3. **Заметки хранятся markdown-файлами** (зеркало в git), база — индекс для поиска и связей. 4. **API-first**: интерфейс и агент Hermes ходят через один и тот же JSON API, MCP — обёртка над ним. 5. **Редактор не пишем**: BlockNote/TipTap. Своё — только блок «База» внутри документа. 6. **Ordo (Huly) остаётся работать параллельно** как запасной аэродром, пока не переедет первый проект. ### Стиль работы - Прототип — это спецификация в картинках. Любое изменение интерфейса сначала в прототипе, потом в `docs/02-spec.md`. - Русский язык в интерфейсе и документах, кроме имён полей в схеме БД. - Не заводить справочник людей и контактов — сознательное решение владельца. --- # 2. Контекст и принятые решения ## Контекст и решения Хронология исследования 2026-08-14 (одна сессия Claude Code). Здесь — почему система выглядит именно так и какие пути отвергнуты. Нужно, чтобы в новом чате не переоткрывать закрытые вопросы. ### С чего началось Вопрос был про Huly (self-hosted инсталляция `ordo` на ordo.ins.is, версия v0.7.426): почему раздел «Карточки» не похож на Notion. Дальше разговор развернулся в «а можно ли из этого сделать мою систему» и закончился решением писать своё. ### Что выяснили про Huly **Карточки — не Notion.** В модели карточек v0.7.426 (`models/card/src/index.ts`) зарегистрированы представления Table, List, Grid, Feed — канбана нет вообще. Группировка в списке жёстко ограничена четырьмя полями (`_class`, `createdBy`, `modifiedBy`, `parent`). Notion-аналог в Huly — модуль Documents (тимспейсы), а Cards — типизированные объекты с атрибутами. **Проекта как сквозной сущности нет.** Пространство принадлежит модулю: `tracker.class.Project`, `document.class.Teamspace`, `card.class.CardSpace`, канал чата — четыре независимых пространства, каждое со своим составом участников и своим архивом. **Кастомные поля почти недоступны.** В Settings → Классы кастомизируются только Contact и Task; у пространств кастомные атрибуты добавлять нельзя. Полноценные пользовательские поля есть только у карточек (MasterTag). **Заметки не в файлах.** Документы — collaborative-объекты; наружу экспорт JSON/CSV, Print to PDF, бэкап воркспейса. Импорт из markdown+YAML есть (unified import format), обратной живой выгрузки нет. **Мобильного нет, десктоп ходит на huly.app** (подключение к self-hosted — открытый issue). ### Что выяснили про форк Huly - Масштаб: 192 плагина, 94 модели, 63 серверных плагина, 22 сервиса, 15 базовых пакетов; 313 МБ репо. - Безопасность привязана к пространствам: транзактор держит карты пространств и участников в памяти и подставляет `space: {$in: [...]}` в каждый запрос (`foundations/server/packages/middleware/src/spaceSecurity.ts`). Значит «проект над пространствами» дёшев и безопасен, а «проект вместо пространств» — переписывание слоя безопасности. - Апстрим замедлился: **87 коммитов за 13 недель против 247 за предыдущие 13**, последние недели 4/3/1 коммит; хостед-сервис Huly закрывают («hosting is no longer being funded»). - Вывод: форк — это усыновление чужой кодовой базы без активного мейнтейнера. Спека форка написана и лежит в `/home/meteor/apps/ordo/specs/2026-08-14-project-over-spaces-design.md`. **Путь отвергнут**, документ оставлен на случай возврата к теме. ### Что выяснили про AppFlowy - Основное приложение — Dart/Flutter, AGPL-3.0; редактор `appflowy-editor` — тоже Dart. В веб-систему не переносится. - `AppFlowy-Web` — React + Slate + Yjs, AGPL-3.0, активно развивается. Код технически взять можно, но: AGPL с сетевой оговоркой делает всю систему AGPL, и это не библиотека, а приложение (свой формат документов, своя модель баз, свой redux и API-клиент). - Решение: **заимствуем поведение и UX-решения** (виды баз, строка-как-страница, поповеры полей), код не берём. Редактор — BlockNote поверх TipTap. ### Почему в итоге своё Список требований делится надвое. Дорого писать: совместное редактирование в реальном времени, чат, движок живых запросов, мультиарендность на тысячи воркспейсов. Дёшево писать: проекты с атрибутами и фильтрами, задачи, метки, канбан, заметки, справочники, права по проекту. Из дорогого не нужно ничего: команда — три человека, переговоры в телеграме, документы пишет один. Зато в чужом движке сопротивление ровно там, где важно: сквозной проект, markdown-файлы, мобильное. В своём коде это не фичи, а следствие схемы (`project_id` в каждой таблице, файл как способ хранения). Плюс отправная точка: `apps/nurion-projects` уже даёт половину каркаса — Express + SQLite, админка, кабинет с авторизацией, i18n, деплой, MCP-сервер. ### Требования, добавленные владельцем по ходу 1. Вертикальный рейл разделов (Проекты, Задачи, Документы, Базы, Финансы). 2. Мультитенантность: аккаунт (Nurion, Inside Realty, Личное) → проекты внутри. 3. Финансы заложить сразу, включить позже. 4. Справочник людей и контактов — **не делать**. 5. Метки задач как в Todoist, с закреплением в меню. 6. Композер задачи как в Todoist: одна строка с разбором даты/метки/приоритета, выбор проекта, режим «разобрать текст». 7. Базы с настраиваемыми видами как в Notion: доска/таблица/список/галерея/календарь, группировки, фильтры, обложки. 8. Агент Hermes через телеграм — спрашивать статусы, двигать задачи. 9. Очень быстрый веб, PWA, готовность к десктопу под Apple Silicon. 10. Горячие клавиши и сильный полнотекстовый поиск. ### Прототип Кликабельный прототип интерфейса: **https://ordo-proto.sites.meteor.group** Исходник: `/home/meteor/sites/ordo-proto/public/index.html` (один файл, без сборки). Он и есть спецификация в картинках: все экраны, состояния и подсказки-пояснения внутри интерфейса. --- # 3. Техническое задание ## ТЗ: ordo-desk — мультитенантная система ведения проектов Версия документа: 2026-08-14. Статус: черновик к реализации, дополняется по ходу. Прототип интерфейса (обязателен к просмотру перед чтением): https://ordo-proto.sites.meteor.group ### 1. Что строим Личная и командная система, где **проект — главная сущность**, а всё остальное цепляется к нему: задачи, документы, записи справочников, финансы, доступы. Заменяет Notion + Todoist + Apple Notes. Домен: **ordo.ins.is**. Ключевые свойства: мультитенантность (несколько аккаунтов-контуров), настраиваемые поля и виды баз, markdown-хранение заметок, очень быстрый интерфейс, работа через API (включая агента в телеграме), готовность к PWA и десктопу. ### 1.1 Планка качества **Это не MVP.** Система делается сразу как законченный продукт: выверенный дизайн (см. `03-design-system.md`), обе темы равного качества, мгновенный отклик, рабочая мобильная раскладка, горячие клавиши, поиск. «Потом допилим» не закладывается ни в один экран: если фича не готова — её нет в интерфейсе, а не сделана наполовину. Раздел «Финансы» в прототипе помечен черновиком именно поэтому: он выключен, а не выглядит недоделанным. Практические следствия: - Ни одного экрана без пустого состояния, состояния загрузки и состояния ошибки. - Ни одной формы без валидации и понятного текста ошибки. - Мобильная и десктопная сборки не откладываются «на потом»: архитектура выбирается так, чтобы они получались из того же кода (см. §9). ### 2. Продуктовые принципы 1. **Проект отвечает «про что»**, метка — «в каком состоянии / с кем связано». Метки общие на аккаунт. 2. **Одна запись живёт в одном месте.** Связь — это поле-ссылка, двусторонняя. Копий нет. 3. **Заметка — файл.** Markdown с фронтматтером, зеркало в git; БД хранит индекс и связи. 4. **Никакой линеровщины**: нет вех, спринтов, оценок в часах, story points. 5. **Ничего в обход API.** Интерфейс, агент и скрипты используют один контракт. 6. **Разделы включаются по аккаунту.** Финансы могут быть выключены в одном контуре и включены в другом. 7. **Нет справочника людей и контактов.** Люди — только участники; контрагенты — записи в базе «Юрлица». ### 3. Модель данных Postgres. Именование полей — английское, интерфейс — русский. #### 3.1 Тенанты и люди ``` accounts id, slug, name, icon, color, settings jsonb, created_at users id, email, name, avatar, tz, created_at memberships user_id, account_id, role: owner|member|guest, can_finance bool, created_at -- финансы отдельным флагом sessions id, user_id, expires_at, agent bool -- agent=true для токенов Hermes ``` Все прикладные таблицы несут `account_id`. Ни один запрос не выполняется без него — это дисциплина уровня репозитория, а не «фильтр на всякий случай». #### 3.2 Проекты ``` projects id, account_id, key (короткий код: NARYN), title, description, cover_file_id, color, stage_id, archived bool, owner_id, created_at, updated_at project_fields id, account_id, name, kind: select|multiselect|text|number|date|checkbox|relation|money, options jsonb, position, system bool -- набор полей задаётся на аккаунт project_values project_id, field_id, value jsonb -- страна, индустрия, доля, бюджет… project_members project_id, user_id, role: owner|member|guest ``` Стадия проекта (`stage_id`) — системное поле-выбор со своим набором значений на аккаунт (Подготовка / В работе / Выход / Архив). #### 3.3 Задачи и метки ``` tasks id, account_id, project_id NULL, parent_id NULL, title, description, status_id, due_at, due_all_day bool, remind_at, priority 1..4, assignee_id, position, done_at, created_by, created_at, updated_at task_statuses id, account_id, name, kind: todo|doing|done, position, color labels id, account_id, name, color, pinned bool, position task_labels task_id, label_id task_links task_id, target_type: document|record|project, target_id ``` `project_id NULL` = «Входящие». Подзадачи — `parent_id`, без отдельной сущности «группа задач». Метки закрепляются флагом `pinned` — закреплённые попадают в левое меню и в строку над списком. #### 3.4 Базы (конструктор справочников) Универсальная механика: цели, домены, юрлица, объекты, договоры, платежи — одна и та же схема. ``` databases id, account_id, name, icon, description, system_kind NULL fields id, database_id, name, kind, options jsonb, position, required bool records id, database_id, account_id, project_id NULL, title, created_at, updated_at values record_id, field_id, value jsonb relations id, account_id, from_field_id, to_database_id, symmetric_name record_links from_record_id, to_record_id, relation_id ``` Типы полей: `text | number | money | date | datetime | select | multiselect | checkbox | url | email | phone | file | image | progress | relation | formula(позже)`. Поле `project_id` на записи — системная связь с проектом; именно она наполняет вкладку «Связанные записи» карточки проекта. #### 3.5 Виды (то, что делает базы «как в Notion») ``` views id, database_id, name, kind: table|board|list|gallery|calendar, group_by field_id NULL, -- колонки доски = значения поля filters jsonb, -- [{field, op, value}] sort jsonb, -- [{field, dir}] fields jsonb, -- какие поля показывать в строке/карточке cover field_id NULL, -- поле-картинка под обложку scope: private|account, owner_id NULL, position ``` Требования к поведению: - Переключение вида не меняет данные — только представление. - Доска: колонки по значениям `group_by`, перетаскивание меняет значение поля. - Календарь: раскладка по выбранному полю даты. - Галерея: обложка из поля-картинки, подпись из title + выбранных полей. - Запись открывается **страницей** (свойства сверху, содержимое-документ снизу, связи внизу). - Тот же самый механизм используется блоком «База» внутри документа. #### 3.6 Документы ``` documents id, account_id, project_id NULL, parent_id NULL, title, icon, cover_file_id, path (для файла), kind: page|meeting|spec, created_by, created_at, updated_at doc_blocks id, document_id, position, type, content jsonb -- канон для редактора doc_links document_id, target_type, target_id -- обратные ссылки ``` - Редактор — **BlockNote поверх TipTap** (не пишем свой). - Блоки: заголовки, списки, чек-лист, выноска, код, таблица, картинка, подстраница, **блок «База»** (хранит запрос: database_id + filters + view kind), ссылка на запись. - Чек-лист умеет превращать пункт в задачу проекта (создаётся `tasks` со ссылкой на документ). - **Markdown-зеркало**: `brain///-.md`, фронтматтер с полями, блок «База» сериализуется директивой ```` ```db {json} ```` . Направление одно: система → файлы. #### 3.7 Финансы (заложить сразу, включить позже) Системная база `payments`: `date, direction: in|out, amount, currency, rate_at_date, project_id, category_id, counterparty_record_id, document_id NULL, planned bool`. Плюс `budgets`: `project_id, amount, currency, approved_at`. Ничего специального: та же механика записей, свои виды. Доступ — по флагу `can_finance`. ### 4. Права Два уровня, оба проверяются на сервере: 1. **Аккаунт**: `owner` видит всё, `member` — проекты, где состоит, `guest` — только выданные проекты. 2. **Проект**: `project_members`. Приглашение в проект открывает задачи, документы и связанные записи. Финансы — отдельный флаг `can_finance`, чтобы партнёр видел стройку, но не движение денег. Записи баз наследуют доступ проекта, к которому привязаны; записи без проекта видны всем участникам аккаунта. ### 5. Поиск Требование: «сильный поиск по содержимому». - **Этап 1 — Postgres FTS.** `tsvector` по задачам, документам (плоский текст блоков), записям баз и названиям проектов; словари `russian` + `simple`, расширения `unaccent` и `pg_trgm` для опечаток и подстрок. Одна вью `search_index(account_id, kind, id, title, body, tsv)`, обновляется триггером. - **Этап 2 — Meilisearch** (не Elasticsearch), если FTS перестанет хватать: он на порядок легче, умеет опечатки и мгновенную выдачу из коробки, ставится одним контейнером. Elasticsearch уже крутится на этом сервере ради Huly и жрёт 1,2 ГБ — второй такой не нужен. - UI: `⌘K` — поиск по всему аккаунту с группировкой по типу, стрелки + Enter, недавнее сверху. - Поиск обязан уважать права: индекс несёт `account_id` и `project_id`, фильтрация до выдачи. ### 6. Горячие клавиши | Клавиши | Действие | |---|---| | `⌘K` / `Ctrl+K` | Глобальный поиск и переход | | `Q` | Быстрая задача из любого места (композер) | | `A` | Добавить задачу в текущий список | | `G` затем `P` / `T` / `D` / `B` / `F` | Переход: Проекты / Задачи / Документы / Базы / Финансы | | `X` | Отметить задачу выполненной | | `E` | Редактировать выделенную задачу | | `1…4` | Приоритет выделенной задачи | | `⌘Enter` | Сохранить и закрыть | | `Esc` | Закрыть модалку / снять выделение | | `⌘\` | Свернуть боковую панель | | `/` | Меню блоков в редакторе | | `?` | Шпаргалка по клавишам | Реализация: один менеджер горячих клавиш со стеком контекстов (глобальный → экран → модалка), чтобы модалка перехватывала `Esc` и `⌘Enter`, не ломая остальное. ### 7. API и агент Hermes **API-first.** Интерфейс не ходит в базу напрямую. Контракт: JSON, `/api/v1/...`, авторизация сессией (веб) или токеном (агент). Токен несёт scope: `read`, `tasks:write`, `docs:write`, `finance:read`. Минимальный набор ресурсов: `accounts`, `projects`, `tasks`, `labels`, `documents`, `databases`, `records`, `views`, `search`. **MCP-сервер** — тонкая обёртка над тем же API, инструменты: ``` projects.list(account, filters) project.status(project) tasks.search(query|filters) task.create(title, project, due, labels) task.move(task, status|project) task.complete(task) note.append(document, text) search.everything(query) record.create/update(database, values) finance.summary(project) # если scope позволяет ``` Тогда Hermes в телеграме работает без отдельного бэкенда: «что по Нарыну» → `project.status`, «перекинь смету на бурение в работу» → `task.move`. Опыт есть — MCP-сервер Nurion уже в проде (`apps/nurion-projects`), включая OAuth; ловушка оттуда: **сообщения об ошибках только ASCII**. ### 8. Разбор строки задачи Один парсер обслуживает три входа: композер в интерфейсе, режим «разобрать текст», команды агента. Понимает: `завтра`, `в пн`, `15 авг 11:00`, `через 3 дня`, `каждый вторник` (позже), `@метка`, `!1..!4` или `!важно`, `#проект`, `+исполнитель`. Разобранное подсвечивается прямо в строке и показывается чипами под ней — как в прототипе. ### 9. Производительность: что берём у Huly Huly ощущается быстрым не случайно — я разобрал её архитектуру на нашей же инсталляции `ordo` (v0.7.426). Четыре приёма стоит скопировать, три — сознательно не копировать. **Берём:** 1. **Отсечение прав одним индексным условием.** В `foundations/server/packages/middleware/src/spaceSecurity.ts` транзактор держит карты пространств и участников в памяти и подставляет в каждый запрос `space: {$in: [...]}` — проверка доступа стоит один `IN` по индексу, а не построчный предикат. Наш аналог: любой запрос сужается по `(account_id, project_id)` с составным индексом, права считаются один раз при входе и живут в памяти процесса. 2. **Живые запросы вместо перезапросов.** Клиент Huly держит результат выборки в памяти и применяет к нему приходящие транзакции — список не перезагружается никогда. Наш аналог: WebSocket-канал с дельтами (`entity, op, payload`), клиент патчит нормализованный кэш. Именно отсюда ощущение мгновенности, а не из «быстрого бэкенда». 3. **Журнал изменений как основа синхронизации.** У Huly всё построено на append-only журнале транзакций. Нам не нужен event sourcing целиком, но нужна таблица `changes(seq, account_id, entity, id, op, ts)`: клиент хранит `last_seq` в IndexedDB и при открытии тянет только дельту. Это же бесплатно даёт оффлайн и холодный старт «из кэша за 100 мс». 4. **Справочная модель грузится один раз.** Поля, статусы, метки, базы, виды — небольшой словарь, который клиент получает при подключении и кэширует. Huly так грузит модель; их же грабли: модель раздувается — держим словарь в десятках сущностей, не в сотнях. 5. **Адресная рассылка.** События уходят только участникам проекта, получатели вычисляются по членству в памяти — без широковещания на весь аккаунт. **Не берём:** CRDT-совместное редактирование (Y.js + отдельный сервис), Kafka/Redpanda для асинхронной индексации, отдельный fulltext-сервис на Elasticsearch. Для трёх человек это пятнадцать контейнеров ради задачи, которую решают Postgres и один процесс. ### 9.1 PWA, мобильное и десктоп - **Клиентское приложение** на JSON API (не серверный рендер страниц). Это отличается от `apps/nurion-projects` и выбрано сознательно. - **Кэш в IndexedDB** + оптимистичные обновления: отметка задачи и перетаскивание карточки применяются мгновенно, синхронизация фоном, откат при ошибке. - Пагинация и виртуализация длинных списков; запрос отдаёт только поля вида. - HTTP-кэш с ETag, `stale-while-revalidate`; ассеты с версией в имени. - **PWA**: service worker, оффлайн-оболочка, установка на iPhone — мобильное приложение без отдельной разработки. - **Десктоп — Tauri**: тот же фронт, бинарник под `aarch64-apple-darwin` собирается на маке владельца, вес около 10 МБ против сотни у Electron. Electron — запасной вариант, если понадобятся ноутбучные API. - Бюджет отклика: открытие экрана из кэша < 100 мс, любое действие пользователя < 50 мс до отклика UI. **Что закладывается в код сразу, чтобы мобильное и десктопное приложения получились без переписывания:** | Решение | Зачем | |---|---| | Весь доступ к данным — через слой API-клиента, ни одного прямого запроса из компонента | Тот же клиент используют PWA, Tauri и агент | | Адрес сервера — параметр конфигурации, не константа | Десктоп-сборка подключается к своему серверу | | Авторизация токеном в защищённом хранилище, а не только cookie | В Tauri и в мобильном контексте cookie ведут себя иначе | | Роутинг на History API без серверных зависимостей | Оффлайн-навигация в оболочке | | Все размеры в относительных единицах, безопасные зоны (`env(safe-area-inset-*)`) | Айфон с чёлкой, полноэкранный десктоп | | Никаких `hover`-only взаимодействий | На тач-экране их не существует; ручка блока и меню доступны по нажатию | | Service worker с версионированным кэшем оболочки | Установка на домашний экран, запуск без сети | | Файлы и картинки — через абстракцию хранилища | На десктопе появится локальный кэш вложений | | Иконки приложения и splash в двух темах | Требование магазинов и macOS | ### 10. Стек TypeScript везде. Сервер: Node + Fastify, Postgres, drizzle или kysely. Клиент: React (BlockNote — React-компонент) + Vite, состояние — TanStack Query поверх собственного кэша. Редактор: BlockNote/TipTap. Поиск: Postgres FTS → Meilisearch. Десктоп: Tauri. MCP: официальный SDK. Деплой: Docker + Traefik на этом сервере, домен ordo.ins.is. ### 11. Экраны Все есть в прототипе, каждый со встроенными пояснениями: 1. **Проекты** — галерея / таблица / доска, фильтры по полям аккаунта, сохранённые виды. 2. **Проект** — шапка с полями, вкладки: Обзор · Задачи · Документы · Связанные записи · Финансы · Доступ. 3. **Задачи** — «Сегодня» со всеми проектами аккаунта, закреплённые метки, панель меток, композер. 4. **Документы** — дерево страниц, блочный редактор, slash-меню, блок «База», обратные ссылки. 5. **Базы** — список баз, таблица записей с группировкой, схема полей и связей. 6. **База с видами (Цели)** — доска по сферам, таблица, календарь дедлайнов, галерея, панель настройки вида. 7. **Финансы** — сводка аккаунта, бюджеты и освоение, движение денег в проекте. 8. **Настройки аккаунта** — поля проектов, участники, экспорт в markdown, включение разделов. ### 12. Порядок работ | Фаза | Содержание | Оценка | |---|---|---| | 0 | Каркас: репозиторий, Postgres, аутентификация, аккаунты и участники, деплой на ordo.ins.is | 3–4 дня | | 1 | Проекты: поля аккаунта, CRUD, галерея/таблица/доска, фильтры, сохранённые виды | 1 неделя | | 2 | Задачи: статусы, метки с закрепом, «Сегодня», доска проекта, композер + парсер строки, шорткаты | 1,5 недели | | 3 | Документы: BlockNote, дерево, markdown-зеркало в git, обратные ссылки | 1,5 недели | | 4 | Базы: поля, записи, связи, виды (таблица/доска/галерея/календарь), блок «База» в документе | 2 недели | | 5 | Поиск ⌘K, PWA, кэш и оптимистичные обновления | 1 неделя | | 6 | API-токены + MCP-сервер, подключение Hermes | 4–5 дней | | 7 | Финансы: бюджеты, платежи, сводка, флаг доступа | 1 неделя | | 8 | Tauri-сборка под Apple Silicon | 2–3 дня | Порядок фаз 0–2 даёт работающую замену Todoist примерно за три недели; после фазы 3 можно переносить заметки; после 4 — закрывать Notion. ### 13. Открытые вопросы 1. Валюты в финансах: хранить исходную + курс на дату или приводить всё к $? 2. Повторяющиеся задачи — нужны ли и в каком виде (`каждый вторник`)? 3. Нужен ли календарь встреч отдельным разделом или хватит вида «календарь» у баз? 4. Гостевые ссылки на отдельный документ наружу — нужны ли? 5. Двусторонняя синхронизация markdown (файл → система) — оставляем выключенной? --- # 4. Дизайн-система ## Дизайн-система ordo-desk Источник истины — прототип: `/home/meteor/sites/ordo-proto/public/index.html` (живой: https://ordo-proto.sites.meteor.group). Здесь — словами то, что там кодом. Планка: **это не MVP**. Интерфейс должен выглядеть и ощущаться законченным продуктом с первого экрана: выверенная типографика, одинаковые отступы, ни одного «временного» состояния, светлая и тёмная темы равного качества, отклик на действие быстрее, чем пользователь успевает заметить. ### 1. Токены Все цвета — CSS-переменные на `:root`, тёмная тема переопределяет только значения. Три состояния темы: системная (`prefers-color-scheme`), явная светлая, явная тёмная (`[data-theme]` на корне). Ни один цвет не объявляется только внутри медиазапроса. **Светлая** ``` --bg #FAF9F7 --surface #FFFFFF --surface-2 #F4F2EF --surface-sunk #F0EEEA --rail #EDEAE5 --ink #1C1A18 --ink-2 #46413C --muted #7A736C --faint #9A938B --line #E7E3DD --line-strong #D6D0C8 --accent #C9452C --accent-ink #FFFFFF --accent-soft rgba(201,69,44,.10) ``` **Тёмная** ``` --bg #141312 --surface #1C1B19 --surface-2 #232120 --surface-sunk #1A1918 --rail #100F0E --ink #EDE9E4 --ink-2 #C9C3BB --muted #99928A --faint #7C756D --line #302D2A --line-strong #3E3A36 --accent #E4674B --accent-ink #1A1412 --accent-soft rgba(228,103,75,.14) ``` **Семантика статусов** (пара «текст / подложка» в каждой теме): зелёный `#2F6B52`, янтарный `#9A6A11`, фиолетовый `#5B49A0`, синий `#26608F`, серый `#6B655E`. Акцент — только для действий, просрочки и активного состояния. Статусы никогда не красятся акцентом. **Скругления** `--r-sm 6px` (чипы, кнопки), `--r-md 10px` (карточки, поповеры), `--r-lg 14px` (панели). **Тени** три уровня: карточка, поднятая карточка, поповер/модалка. ### 2. Типографика Системный стек (`-apple-system, Segoe UI, Roboto…`) — он же у Notion и Todoist, даёт нативное ощущение и нулевой вес. Веб-шрифт не подключаем; если однажды понадобится — только self-hosted woff2. | Роль | Размер / вес | |---|---| | Заголовок экрана | 26 px / 700, tracking −0.02em | | Заголовок документа | 32 px / 700, tracking −0.025em | | Заголовок панели | 15 px / 600 | | Основной текст | 14 px / 400, интерлиньяж 1.45 | | Вторичный | 13 px, цвет `--muted` | | Подпись, счётчик | 12 px, цвет `--faint` | | Ярлык-заголовок группы | 11 px / 600, uppercase, tracking .07em | Цифры в колонках, датах и суммах — `font-variant-numeric: tabular-nums`. Технические строки (пути файлов, домены, телефоны, суммы) — моноширинный стек. ### 3. Каркас Три колонки: **рейл 58 px** (иконки разделов) → **боковая панель 268 px** (контекст раздела) → **контент**. Рейл и панель липкие на всю высоту. Сверху контента — липкая полоса с хлебными крошками, которые всегда начинаются с аккаунта. Брейкпоинты: `≤1040px` — боковая панель скрывается, рейл остаётся; `≤720px` — рейл прячется, появляется горизонтальная навигация. Мобильная раскладка обязана быть рабочей, а не «оно как-то открывается»: списки в одну колонку, доски скроллятся горизонтально, модалки во всю ширину. ### 4. Компоненты - **Рейл** — иконка + подсказка при наведении; активный пункт на светлой подложке с акцентным цветом; точка-маркер для разделов в разработке. - **Переключатель аккаунта** — квадратная плитка вверху рейла, по клику поповер со списком контуров, ролями и кнопкой «Новый аккаунт». - **Чип** (`.chip`) — статус, свойство, ссылка на сущность. Пять семантических цветов + пунктирный вариант для пустого значения. - **Метка** (`.tag`) — скруглённая пилюля с иконкой-биркой; нажатая работает как фильтр. - **Строка задачи** — круглый чекбокс (акцентный контур = приоритет), заголовок, метаданные: срок (красный при просрочке), проект точкой, метки, ссылки на сущности. - **Карточка доски** — обложка **в край карточки** (гасим внутренние отступы, скругляем только верхние углы, соотношение 16:9), заголовок, метаданные, при необходимости полоса прогресса. - **Плитка галереи** — обложка 16:9, заголовок, чипы, подвал со счётчиками. - **Таблица** — липкая шапка с иконкой типа поля, зебры нет, ховер строки, группировочные строки с подложкой; горизонтальный скролл внутри своего контейнера. - **Полоса видов** — вкладки сохранённых видов + «+ Вид», справа настройка вида и фильтр. - **Панель настройки вида** — отображение, группировка, фильтры, сортировка, обложка, видимые поля, область (личный / общий). - **Композер задачи** — модалка: строка с подсветкой разобранных дата/метка/приоритет, описание, ряд чипов-свойств, выбор проекта с группировкой по аккаунтам, режим «Разобрать текст». - **Редактор** — блоки с ручкой перетаскивания при наведении, slash-меню, выноски, чек-листы, блок «База», обратные ссылки внизу страницы. - **Календарь** — сетка месяца, сегодня выделен акцентной подложкой, события цветными пилюлями. - **KPI-плитка** — подпись, крупное табличное число, дельта; зелёный для поступлений, акцент для обязательств. - **Подсказка** (`.hint`) — блок на акцентной подложке, объясняет механику. В прототипе несёт роль спецификации; в продукте остаётся только там, где реально помогает. ### 5. Иконки Инлайновый SVG-спрайт, 24×24, обводка `currentColor` 1.7 px, скруглённые концы, без заливок кроме точек-акцентов. Размеры: 20 px в рейле, 16 px в списках, 14 px в чипах. Псевдографика (▦ ◫ ☗) запрещена — на разных ОС ломается. Набор: projects, tasks, doc, base, finance, search, theme, settings, grid, clock, star, stage, archive, calendar, board, home, building, globe, phone, tool, users, check, circle, x, inbox, layers, percent, down, up, sync, flag, link, image, tag, pin, filter. ### 6. Движение и отклик - Переходы 120–140 мс, только `background`, `color`, `box-shadow`, `transform`. - Наведение на карточку — подъём на 1 px и усиление тени. - `prefers-reduced-motion` выключает всё. - Любое действие пользователя отражается в интерфейсе мгновенно (оптимистично), сеть догоняет фоном. ### 7. Доступность и мелочи Видимый фокус на всех интерактивных элементах, минимальная цель нажатия 32 px, контраст текста не ниже 4.5:1 в обеих темах, у иконок-кнопок обязательный `title`/`aria-label`, модалки закрываются по `Esc` и клику по фону. ---