AAYMA
RU
Войти

AI Sana

Платформа, где бизнес описывает задачу (текстом, голосом или файлами), AI задаёт уточняющие вопросы, формирует карточку задания и оценивает её…

Рабочий MVP
Команда «Jective AI» 8💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: 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.md

AI 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 startFrontend и backend вместе
npm run dev:webТолько Vite, API запускается отдельно
npm run dev:apiТолько backend, с перезапуском при изменениях
npm run dev:fullFrontend + API, каталог загружается с сервера
npm run buildСборка frontend в apps/web/dist
npm run previewЛокальный просмотр готовой сборки на порту 3000
npm run checkESLint, тесты всех пакетов и сборка
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 выполните миграции в таком порядке:

  1. Регистрация и profiles — только если таблица профилей ещё не создана.
  2. Задачи и публичный каталог.
  3. Приватные вопросы и ответы AI.
  4. Отклики студентов.
  5. Принятие и отклонение откликов.

Каждый файл выполняется один раз целиком под 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, /scoreAI-анализ; 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-сборку.

Звёзды
⭐ 0
Форки
0
Язык
—
Последний push
в прошлом месяце
Коммиты
45
Авторы
3
Файлы
169
Ветки
7

Авторы коммитов

devalisher077 20Alibi 15Serv 10

История коммитов

  • 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
Ветки (7)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.