Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
Translation pending
Еженедельные подборки проверенных кандидатов для работодателей Центральной Азии.
Translation pending
BusinessTypeScript · CSSGitHub @kaay-itOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗= TalentStreams :toc: left :toc-title: Содержание :toclevels: 2
Платформа персонализированных подборок проверенных кандидатов для работодателей Центральной Азии.
Работодатели получают email-рассылку с анонимными карточками кандидатов. Ссылка в письме персонализирована — каждый работодатель видит только тех кандидатов, кто не исключил его компанию или отрасль из своих предпочтений.
== Технический стек
== Переменные окружения
Создайте файл .env.local в корне проекта:
GOOGLE_SHEET_ID=... GOOGLE_SERVICE_ACCOUNT_JSON={"type":"service_account","project_id":"...","private_key":"...","client_email":"..."}
DATABASE_URL=...
BLOB_READ_WRITE_TOKEN=...
SENDPULSE_CLIENT_ID=... SENDPULSE_CLIENT_SECRET=... SENDPULSE_MASTER_BOOK_NAME=Default SENDPULSE_FROM_EMAIL=[email protected] SENDPULSE_FROM_NAME=TalentStreams
EDITOR_SECRET защищает /editor и /api/publish — без него страница возвращает 404, а API-роут отвечает 401.
APP_URL используется для формирования proxy-ссылок на резюме (APP_URL/api/resume?url=...) — эти ссылки сохраняются в базе, поэтому значение должно совпадать для всех, кто их открывает (даже при локальной разработке против общей базы, см. ниже).
== Запуск локально
Приложение доступно на http://localhost:3000.
CAUTION: Локальный npm run dev обычно указывает на ту же базу (Neon) и ту же таблицу Google Sheets, что и продакшн — отдельного стенда нет. Ссылки на резюме, сохранённые в базе, абсолютные (APP_URL/api/resume?...) и всегда ведут на APP_URL из .env.local, даже если открыты со страницы, отрендеренной локально.
== Структура проекта
app/ page.tsx # Главная: лендинг, формы регистрации list/[listId]/page.tsx # Страница подборки (требует ?e= или ?secret=) profile/[id]/page.tsx # Полный профиль кандидата editor/ layout.tsx # Боковое меню редактора page.tsx # Выпуски (Releases) employers/page.tsx # Управление работодателями candidates/page.tsx # Управление кандидатами requests/page.tsx # Запросы на контакт streams/page.tsx # CRUD стримов settings/page.tsx # Задел на будущее (пока пусто) api/ publish/[listId]/route.ts # API-роут для curl-запуска рассылки upload/route.ts # POST: загрузка резюме → Vercel Blob resume/route.ts # GET: прокси приватных blob-файлов actions.ts # Все Server Actions
lib/ sheets.ts # Google Sheets: чтение, запись, типы (кандидаты, подборки) sendpulse.ts # SendPulse: OAuth, книги, кампании blob.ts # Хелперы для ссылок на Vercel Blob (в т.ч. имя скачиваемого файла) db/ index.ts # Drizzle-клиент (neon-http) schema.ts # Схемы: contactRequests, streams, employers, candidateResumes contact-requests.ts # CRUD запросов на контакт streams.ts # CRUD стримов employers.ts # CRUD работодателей resumes.ts # История версий резюме кандидата migrations/ # SQL-миграции (drizzle-kit)
components/ employer-registration-modal.tsx # Форма работодателя (публичная) employer-edit-modal.tsx # Редактирование работодателя в редакторе employer-create-modal.tsx # Быстрое добавление работодателя из редактора employer-section.tsx # UI подтверждения/отклонения/редактирования заявок candidate-registration-modal.tsx # Форма кандидата (публичная) candidate-edit-modal.tsx # Редактирование кандидата в редакторе candidate-create-modal.tsx # Быстрое добавление кандидата из редактора candidate-section.tsx # Таблица кандидатов: фильтры, модерация, резюме contact-requests-section.tsx # UI управления запросами на контакт streams-table.tsx # Inline-редактор стримов contact-button.tsx # Кнопка «Хочу связаться» general-inquiry-button.tsx # Кнопка «Связаться с нами» (общий запрос) publish-button.tsx # Кнопка запуска рассылки editor-nav.tsx # Боковая навигация редактора
== Где что хранится
Данные разделены между Google Sheets и Neon — не по историческим причинам, а по тому, кто их пишет:
[cols="2,1,3", options="header"] |=== | Данные | Хранилище | Почему
| Кандидаты (профили, регистрации)
| Google Sheets
| Часть полей всё ещё правится только напрямую в таблице (bio, industry, func и т. д.) — полный редактор в UI пока не построен
| Стримы
| Neon
| Полный CRUD через /editor/streams, таблицу больше не открывают
| Работодатели | Neon | Полный жизненный цикл (регистрация → подтверждение → редактирование → отключение → удаление) через UI
| Запросы на контакт | Neon | Приложение единственный писатель — редактор никогда не правит эти строки напрямую
| История версий резюме кандидата
| Neon
| Отдельная таблица (candidateResumes) — Sheets хранит только URL последней версии
| Файлы резюме
| Vercel Blob (приватное)
| Доступ только через прокси /api/resume
|===
Подробности и статус миграции оставшихся таблиц — docs/backlog.adoc, раздел «Приложение: переход на реляционную СУБД».
== Доступ к подборке /list/[listId]
|=== | Параметр | Результат
| ?e=[employer_token]
| Персонализированная подборка: кандидаты фильтруются по предпочтениям работодателя (исключённые компании/отрасли, гео)
| ?secret=[EDITOR_SECRET]
| Все кандидаты без фильтрации (просмотр редактора)
| (без параметров) | 404 |===
== Добавление новой функциональности
=== Новое поле в профиле кандидата (Google Sheets)
. Добавьте ключ в массив KNOWN_KEYS (lib/sheets.ts).
. Добавьте поле в тип Profile или Candidate (lib/sheets.ts).
. Добавьте алиасы в HEADER_ALIASES (английское и русское название заголовка) — используются функцией mapHeader() везде при чтении/записи.
. Заполните поле в buildProfile() / rowToRecord().
=== Новая таблица или поле в Neon
. Добавьте/измените схему в lib/db/schema.ts (Drizzle).
. npm run db:generate — сгенерировать миграцию (drizzle-kit), затем npm run db:migrate — применить.
. CRUD-функции — в соответствующем файле lib/db/*.ts (import "server-only", плоские async-функции, без классов).
=== Новый Server Action
Добавьте async-функцию с директивой "use server" в app/actions.ts.
Для мутаций, которые должны обновить UI редактора, вызывайте revalidatePath(...).
Для ожидаемых пользовательских ошибок (валидация, дубликаты) — возвращайте { ok: false, error } вместо throw: Next.js в production-сборке заменяет сообщение любого throw new Error(...) из Server Action на общий текст, чтобы не утекали детали непредвиденных ошибок — это ломает вывод ожидаемых сообщений пользователю (пример — registerEmployer()).
=== Новый раздел редактора
. Создайте app/editor/<раздел>/page.tsx с проверкой EDITOR_SECRET.
. Добавьте пункт в массив разделов в components/editor-nav.tsx.
=== Новая SendPulse-переменная контакта
Добавьте ключ в объект variables внутри syncEmployerToSendPulse (app/actions.ts).
В шаблоне письма используйте {{имя_переменной}}.
== Документация
docs/backlog.adoc — главный источник правды по архитектуре: список задач с приоритетами, статус миграции каждой таблицы, детали реализации каждой завершённой задачиdocs/spec.adoc — техническое задание (бизнес-логика, правила распределения по стримам, тексты писем)docs/manager-playbook.adoc — инструкция для нетехнического менеджераdocs/workspace.dsl — C4-модель (открывается в https://structurizr.com/dsl[Structurizr DSL])docs/editor-stream-flow.puml — PlantUML sequence-диаграмма жизненного цикла стрима== Запуск рассылки через API