AI Sana
Платформа, где бизнес описывает задачу (текстом, голосом или файлами), AI задаёт уточняющие вопросы, формирует карточку задания и оценивает её…
О проекте
Команда: Jective AI
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP
Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд
Суть
Платформа, где бизнес описывает задачу (текстом, голосом или файлами), AI задаёт уточняющие вопросы, формирует карточку задания и оценивает её, после чего задача публикуется в каталоге для студенческих команд, а бизнес принимает или отклоняет отклики.
Как устроено
Фронт на Vite и Tailwind, отдельный Node.js API, данные в Supabase (профили, задачи, рабочие сессии AI, отклики, решения) с RLS и миграциями SQL. Модуль task-analysis через OpenAI (gpt-4.1-mini) генерирует вопросы, собирает карточку задачи и выставляет оценку. Есть транскрипция голосового ввода и извлечение текста из вложений. Рабочая сессия AI автосохраняется, при сохранении задачи вопросы и ответы архивируются в analysis_snapshot.
Ключевые решения
- генерация уточняющих вопросов
- генерация карточки задачи
- скоринг задачи
- голосовой ввод (транскрипция)
- извлечение текста из вложений
- Supabase RLS
Особенности
Весь цикл закрыт: постановка задачи голосом или файлом, диалог с AI, публикация, отклики студентов и решение бизнеса. Приватные данные (исходное описание, ответы AI, контакт) разделены с публичными полями карточки через RLS.
Стек
JavaScript · Vite · Tailwind CSS · Node.js · Supabase · PostgreSQL · npm workspaces · ESLint · Prettier
Модели
gpt-4.1-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-d299ce4e-jective-ai.
README
README.mdAI Sana
Локальный проект на JavaScript: Vite + Tailwind CSS на frontend и отдельный Node.js API.
Нужен Node.js 24 (либо совместимые версии из engines в package.json).
Быстрый запуск
Из корня репозитория:
npm install
npm run dev
Интерфейс: http://localhost:3000, backend: http://127.0.0.1:3001.
npm run dev запускает оба процесса; остановка — Ctrl+C в терминале.
Регистрация, вход, задачи, отклики и промежуточная работа с AI используют Supabase.
Каталог показывает только реальные опубликованные задачи; новая база будет пустой.
Перед работой настройте окружение ниже и примените миграции задач.
Альтернативное имя той же команды:
npm run dev:full
Каталог всегда загружается через API, переключателя на демонстрационные данные нет.
Только frontend можно запустить через npm run dev:web, но для профиля, задач и AI ему нужен API.
Не запускайте dev и dev:full одновременно: они используют один порт.
Структура
apps/
web/
src/
app/ запуск, маршрутизация, состояние и события
pages/ страницы, возвращающие HTML
components/ общие элементы интерфейса и layout
features/
auth/ Supabase Auth, сессия и проверенный профиль
tasks/ каталог, публикация, приватное автосохранение и AI-контроллеры
proposals/ приватные отклики и решения бизнеса через API
shared/ API-клиент, экранирование, уведомления, анимации
styles/ Tailwind и существующие стили
test/ тесты frontend
api/
src/
modules/auth/ проверка токена и загрузка профиля
modules/tasks/ маршруты, сервис и repository задач
modules/proposals/ сохранение откликов и разграничение доступа
modules/task-analysis/ OpenAI: вопросы, формирование карточки и оценка
shared/ HTTP-ответы и ошибки
app.js сборка HTTP-приложения
server.js запуск и остановка сервера
packages/
contracts/ общий формат данных и проверки; фикстуры только для тестов
supabase/
migrations/ SQL: профили, задачи, рабочие сессии и отклики
scripts/
dev.js совместный запуск frontend и API
docs/
architecture.md правила расширения проекта
Проект использует npm workspaces: зависимости всех приложений устанавливаются одной командой
из корня. Общий package-lock.json фиксирует версии.
Команды
| Команда | Назначение |
|---|---|
npm run dev / npm start | Frontend и backend вместе |
npm run dev:web | Только Vite, API запускается отдельно |
npm run dev:api | Только backend, с перезапуском при изменениях |
npm run dev:full | Frontend + API, каталог загружается с сервера |
npm run build | Сборка frontend в apps/web/dist |
npm run preview | Локальный просмотр готовой сборки на порту 3000 |
npm run check | ESLint, тесты всех пакетов и сборка |
npm run format | Форматирование кода с Prettier |
npm run format:check | Проверка форматирования |
Другой порт frontend: npm run dev -- --port 3002.
Настройки API находятся в apps/api/.env.example; пример можно скопировать в apps/api/.env.
Подключение backend
Для приложения заполните apps/web/.env.local:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=your-publishable-key
VITE_API_BASE_URL=/api
API_TARGET=http://127.0.0.1:3001
И apps/api/.env для того же Supabase-проекта:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_PUBLISHABLE_KEY=your-publishable-key
OPENAI_API_KEY=your-openai-api-key
OPENAI_MODEL=gpt-4.1-mini
Оба файла исключены из Git. Для Supabase достаточно publishable key
(для старых проектов поддерживается anon key); secret/service_role ключи не нужны и конфигурация их отклоняет.
OpenAI-ключ нужен для анализа и остаётся только в apps/api/.env, не во frontend.
В Supabase → Authentication → URL Configuration добавьте адреса локального приложения
http://localhost:3000 и http://127.0.0.1:3000 в разрешённые Redirect URLs.
Подтверждение email остаётся включённым: после регистрации перейдите по ссылке из письма.
В apps/web/.env.example перечислены настройки клиента. Для отдельного запуска приложений
запустите npm run dev:api и npm run dev:web в двух терминалах. Vite перенаправляет /api
на backend. Если меняете порт API, измените и API_TARGET.
VITE_* попадает в браузерный bundle, поэтому эти переменные не подходят для секретов.
После изменения .env перезапустите Vite; для production создайте новую сборку.
База данных
В Supabase SQL Editor выполните миграции в таком порядке:
- Регистрация и profiles — только если таблица профилей ещё не создана.
- Задачи и публичный каталог.
- Приватные вопросы и ответы AI.
- Отклики студентов.
- Принятие и отклонение откликов.
Каждый файл выполняется один раз целиком под postgres. Миграции не удаляют старые данные
и не добавляют фиктивные задачи. Если profiles уже существует, начинайте со второго файла.
Ранее выполненные миграции повторять не нужно. Подробности и проверка доступа — в
инструкции сохранения задач и инструкции откликов.
Исходное описание, вопросы и ответы AI, контакт заказчика доступны только владельцу.
Остальные поля опубликованной карточки становятся публичными: не вставляйте в них секреты.
«Мои задачи» показывает сохранённые черновики и публикации текущего пользователя.
Текущая рабочая сессия AI автоматически сохраняется отдельно и восстанавливается после обновления страницы;
перед закрытием дождитесь завершения синхронизации с Supabase.
При сохранении задачи её вопросы и ответы также архивируются в приватном analysis_snapshot:
начало новой задачи не стирает анкеты ранее сохранённых, их можно открыть через «Мои задачи».
API
| Маршрут | Назначение / доступ |
|---|---|
GET /api/health | Проверка процесса API |
GET /api/tasks | Публичный каталог, { "data": Task[] } |
GET /api/tasks/:id | Публичная опубликованная карточка, { "data": Task } |
GET /api/tasks/mine | Собственные задачи; Bearer-токен бизнес-пользователя |
POST /api/tasks | Сохранение черновика или публикация; Bearer-токен бизнес-пользователя |
GET /api/task-workspace | Текущие приватные вопросы, ответы и карточка, либо data: null |
PUT /api/task-workspace | Автосохранение приватного рабочего состояния; бизнес-пользователь |
GET /api/proposals | Студенту — собственные отклики; бизнесу — отклики только на свои задачи |
POST /api/proposals | Отправка всех полей отклика на опубликованную задачу; только студент |
PATCH /api/proposals/:id/decision | Принять/отклонить отклик; только бизнес-владелец задачи |
GET /api/auth/me | Проверенные user и profile; Bearer-токен |
POST /api/ai/task-analysis/questions, /generate, /score | AI-анализ; Bearer-токен бизнес-пользователя |
Все успешные ответы обёрнуты в { "data": ... }. Приватное рабочее состояние требует
Bearer-токена и при чтении, и при записи. Читающие маршруты поддерживают HEAD. Ошибки имеют вид
{ "error": { "code": "NOT_FOUND", "message": "..." } } с соответствующим HTTP-статусом.
Если API недоступен, каталог показывает ошибку и кнопку повтора, а не подменяет ответ демоданными.
Сервер читает каталог из представления published_tasks, собственные задачи — из tasks,
текущую сессию — из task_workspaces. Приватные запросы используют пользовательский токен и RLS.
Если таблицы ещё не созданы, API сообщает об ошибке; перехода на фикстуры нет.
Подробности — в описании архитектуры и инструкции AI.
Текущие границы
Регистрация, вход, подтверждение email, восстановление сессии и выход подключены к Supabase.
Профиль и роль backend читает из profiles после проверки токена через Supabase Auth.
Кабинет недоступен до успешной проверки; при ошибке сети проверку можно повторить.
Задачи, черновики, вопросы, ответы и результаты AI сохраняются в Supabase после применения миграций.
Отклики сохраняют команду, идею, план, срок и ссылку; студент видит их в «Мои отклики»,
а владелец задачи — в «Отклики». Обновление страницы или кнопка «Обновить» загружает данные из базы.
На одну задачу студент может отправить один отклик; повтор запроса не создаёт дубликат.
Бизнес может принять или отклонить отклик и изменить решение позднее; студент видит
сохранённый статус и дату решения в «Мои отклики». Решение не закрывает задачу и не меняет
остальные отклики. Редактирование текста отправленного отклика пока не реализовано.
OpenAI выполняет настоящий анализ через backend. Избранное ещё не подключено к постоянному
хранению и остаётся локальным. Раздел «Моя команда» удалён; название команды указывается в отклике.
Восстановление пароля через письмо пока не реализовано.
Страницы остаются на обычном JavaScript, без React. Tailwind доступен в HTML-шаблонах;
Preflight отключён для сохранения существующего оформления. Старые стили находятся в слое components,
поэтому utility-классы Tailwind могут их переопределять. Шрифт Manrope загружается из Google Fonts;
без интернета используется системный шрифт.
vite preview предназначен для локальной проверки. При публикации раздавайте apps/web/dist
и настройте перенаправление /api к серверу на уровне хостинга или reverse proxy.
Vite-конфигурация не переносится в статическую production-сборку.
Авторы коммитов
История коммитов
- 2026-09-23 18:02Enhance README with project details and setup guide777devalisher077
- 2026-09-23 17:59Create README.mddevalisher077
- 2026-09-23 17:55777devalisher077
- 2026-09-23 17:54777devalisher077
- 2026-09-23 17:52ddddAlibi
- 2026-09-23 17:50Update README.mdAlibi
- 2026-09-23 17:45sssServ
- 2026-09-23 17:417878Serv
Все коммиты (45)
- 2026-09-23 17:37Merge pull request #22 from BAITC-Hacks/alisherdevalisher077
- 2026-09-23 17:37Merge branch 'production' into alisherdevalisher077
- 2026-09-23 17:36555Serv
- 2026-09-23 17:36777devalisher077
- 2026-09-23 17:30Merge pull request #21 from BAITC-Hacks/alibiAlibi
- 2026-09-23 17:30Merge branch 'production' into alibiAlibi
- 2026-09-23 17:27New changes 2Alibi
- 2026-09-23 17:22222Serv
- 2026-09-23 17:21New changesAlibi
- 2026-09-23 17:18222Serv
- 2026-09-23 17:16Merge pull request #20 from BAITC-Hacks/alisherdevalisher077
- 2026-09-23 17:15777devalisher077
- 2026-09-23 17:11serServ
- 2026-09-23 16:53Changed visualsAlibi
- 2026-09-23 16:48Added Voice to Text & Files and PhotosAlibi
- 2026-09-23 16:09333Serv
- 2026-09-23 15:59Merge pull request #15 from BAITC-Hacks/preproductionAlibi
- 2026-09-23 15:57Merge pull request #14 from BAITC-Hacks/alisherdevalisher077
- 2026-09-23 15:57777devalisher077
- 2026-09-23 15:37Merge pull request #13 from BAITC-Hacks/preproductiondevalisher077
- 2026-09-23 15:36Merge pull request #12 from BAITC-Hacks/alibiAlibi
- 2026-09-23 15:36Merge branch 'preproduction' into alibiAlibi
- 2026-09-23 15:34Added AI-AnalyzeAlibi
- 2026-09-23 15:33Merge pull request #11 from BAITC-Hacks/alisherdevalisher077
- 2026-09-23 15:33777devalisher077
- 2026-09-23 15:12Merge pull request #10 from BAITC-Hacks/serikkServ
- 2026-09-23 15:11444Serv
- 2026-09-23 15:04Merge pull request #9 from BAITC-Hacks/preproductiondevalisher077
- 2026-09-23 14:59Merge pull request #8 from BAITC-Hacks/preproductionServ
- 2026-09-23 14:54Merge pull request #6 from BAITC-Hacks/preproductionAlibi
- 2026-09-23 14:54Merge pull request #5 from BAITC-Hacks/alisherdevalisher077
- 2026-09-23 14:53777devalisher077
- 2026-09-23 14:07Merge pull request #4 from BAITC-Hacks/alisherAlibi
- 2026-09-23 14:06777devalisher077
- 2026-09-23 13:567777devalisher077
- 2026-09-23 13:55Merge pull request #2 from BAITC-Hacks/alibidevalisher077
- 2026-09-23 13:44Main PAGE for BusinessAlibi
Структура репозитория (169 файлов)
.gitignore .prettierignore .prettierrc.json .vite/deps/_metadata.json .vite/deps/package.json README.md README.txt apps/api/.env.example apps/api/package.json apps/api/src/app.js apps/api/src/config.js apps/api/src/modules/attachments/extraction.js apps/api/src/modules/attachments/router.js apps/api/src/modules/attachments/service.js apps/api/src/modules/auth/repository.js apps/api/src/modules/auth/router.js apps/api/src/modules/auth/service.js apps/api/src/modules/proposals/repository.js apps/api/src/modules/proposals/router.js apps/api/src/modules/proposals/service.js apps/api/src/modules/task-analysis/router.js apps/api/src/modules/task-analysis/scoring.js apps/api/src/modules/task-analysis/service.js apps/api/src/modules/task-analysis/transcription.js apps/api/src/modules/tasks/repository.js apps/api/src/modules/tasks/router.js apps/api/src/modules/tasks/service.js apps/api/src/server.js apps/api/src/shared/http-error.js apps/api/src/shared/json-body.js apps/api/test/app.test.js apps/api/test/attachments.test.js apps/api/test/auth.test.js apps/api/test/proposals.test.js apps/api/test/task-analysis.test.js apps/api/test/tasks.test.js apps/api/test/transcription.test.js apps/api/test/wiring.test.js apps/web/.env.example apps/web/.vite/deps/_metadata.json apps/web/.vite/deps/package.json apps/web/index.html apps/web/package.json apps/web/src/app/config.js apps/web/src/app/events.js apps/web/src/app/initial-state.js apps/web/src/app/router.js apps/web/src/app/store.js apps/web/src/components/attachments.js apps/web/src/components/layout.js apps/web/src/components/proposal-card.js apps/web/src/components/proposal-list.js apps/web/src/components/task-row.js apps/web/src/components/ui.js apps/web/src/components/voice-input.js apps/web/src/features/attachments/controller.js apps/web/src/features/attachments/service.js apps/web/src/features/auth/actions.js apps/web/src/features/auth/controller.js apps/web/src/features/auth/errors.js apps/web/src/features/auth/service.js apps/web/src/features/profiles/controller.js apps/web/src/features/profiles/service.js apps/web/src/features/proposals/actions.js apps/web/src/features/proposals/controller.js apps/web/src/features/proposals/form.js apps/web/src/features/proposals/permissions.js apps/web/src/features/proposals/repository.js apps/web/src/features/proposals/service.js apps/web/src/features/tasks/actions.js apps/web/src/features/tasks/analysis-controller.js apps/web/src/features/tasks/catalog-controller.js apps/web/src/features/tasks/model.js apps/web/src/features/tasks/publication-controller.js apps/web/src/features/tasks/repository.js apps/web/src/features/tasks/scoring-controller.js apps/web/src/features/tasks/voice-controller.js apps/web/src/features/tasks/workspace-controller.js apps/web/src/main.js apps/web/src/pages/account.js apps/web/src/pages/auth.js apps/web/src/pages/business.js apps/web/src/pages/catalog.js apps/web/src/pages/index.js apps/web/src/pages/landing.js apps/web/src/pages/profile.js apps/web/src/pages/proposals.js apps/web/src/pages/student.js apps/web/src/pages/task-editor.js apps/web/src/services/ai/taskAnalysis.js apps/web/src/services/ai/transcription.js apps/web/src/services/ai/types.js apps/web/src/shared/api/client.js apps/web/src/shared/data-error.js apps/web/src/shared/feedback.js apps/web/src/shared/html.js apps/web/src/shared/motion.js apps/web/src/shared/supabase.js apps/web/src/styles/attachments.css apps/web/src/styles/auth.css apps/web/src/styles/design.css apps/web/src/styles/legacy.css apps/web/src/styles/main.css apps/web/src/styles/palette.css apps/web/src/styles/profile.css apps/web/src/styles/task-editor.css apps/web/src/styles/workspace.css apps/web/test/api-client.test.js apps/web/test/attachments.test.js apps/web/test/auth-controller.test.js apps/web/test/auth-errors.test.js apps/web/test/auth-pages.test.js apps/web/test/auth-service.test.js apps/web/test/catalog-controller.test.js apps/web/test/data-error.test.js apps/web/test/event-wiring.test.js apps/web/test/landing-cleanup.test.js apps/web/test/model.test.js apps/web/test/motion.test.js apps/web/test/navigation-cleanup.test.js apps/web/test/pages.test.js apps/web/test/profiles.test.js apps/web/test/proposal-access.test.js apps/web/test/proposal-decision-events.test.js apps/web/test/proposal-decision-pages.test.js apps/web/test/proposal-decisions.test.js apps/web/test/proposal-pages.test.js apps/web/test/proposal-persistence.test.js apps/web/test/proposal-profiles.test.js apps/web/test/publication-controller.test.js apps/web/test/repository.test.js apps/web/test/router.test.js apps/web/test/scoring.test.js apps/web/test/task-analysis.test.js apps/web/test/task-persistence-flow.test.js apps/web/test/task-persistence-pages.test.js apps/web/test/voice.test.js apps/web/test/workspace-controller.test.js apps/web/vite.config.js docs/architecture.md docs/profiles.md docs/proposals.md docs/supabase-registration.md docs/task-analysis.md docs/task-attachments.md docs/task-persistence.md docs/task-proposals.md docs/voice-input.md eslint.config.js package-lock.json package.json packages/contracts/package.json packages/contracts/src/attachments.js packages/contracts/src/fixtures.js packages/contracts/src/index.js packages/contracts/src/proposals.js packages/contracts/test/auth-contracts.test.js packages/contracts/test/contracts.test.js packages/contracts/test/proposals.test.js packages/contracts/test/tasks-write.test.js scripts/dev.js supabase/migrations/20260923000100_registration_profiles.sql supabase/migrations/20260923000200_task_attachments.sql supabase/migrations/20260923000200_tasks.sql supabase/migrations/20260923000300_profile_settings.sql supabase/migrations/20260923000300_task_workspaces.sql supabase/migrations/20260923000400_proposals.sql supabase/migrations/20260923000400_task_proposals.sql supabase/migrations/20260923000500_proposal_decisions.sql
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.