ВНИМАНИЕ

Просьба дочитать данный файл от начала и до КОНЦА, чтобы не упустить важную информацию касающуюся демонстрации проекта

Трамплин

Трамплин — интерактивная карьерная платформа, которая объединяет талантливых студентов, выпускников, работодателей и кураторов вузов.
Соискатели находят стажировки, вакансии, менторские программы и карьерные мероприятия. Работодатели публикуют возможности и получают отклики. Кураторы модерируют контент, верифицируют компании и управляют пользователями.

Платформа включает:

  • интерактивную карту с вакансиями и мероприятиями,
  • карточки возможностей с тегами навыков,
  • личные кабинеты трёх ролей,
  • систему откликов и статусов,
  • нетворкинг между соискателями,
  • верификацию работодателей,
  • модерацию контента.

Наша команда Numerum

Дувакин Андрей — фуллстак + DevOps
Лучевников Лев — фронтенд-разработчик
Филимонов Михаил — бэкенд-разработчик

Технологический стек

  • Backend: FastAPI (Python), SQLAlchemy 2.0, PostgreSQL, JWT-аутентификация
  • Frontend: React + Vite + JavaScript + Ant Design + RTK Query
  • Инфраструктура: Docker, Kubernetes (microk8s), Helm-чарт, cert-manager + Lets Encrypt

Развернутый дистрибутив

WEB: https://springboard.numerum.team
API: https://api.springboard.numerum.team (с автоматической Swagger-документацией)
Хранение файлов: PersistentVolume с hostPath

Структура проекта

API

Бэкенд построен на FastAPI с луковой архитектурой.

api/
├── app/
│   ├── application/         — репозитории 
│   ├── controllers/         — FastAPI-роутеры 
│   ├── infrastructure/      — бизнес-сервисы
│   ├── domain/
│   │   ├── models/          — SQLAlchemy-модели (ORM)
│   │   └── entities/        — Pydantic-схемы (DTO)
│   ├── database/            — сессии, Alembic-миграции
│   ├── core/                — константы, настройки
│   └── main.py, settings.py
├── k8s/helm/springboard-api — Helm-чарт для продакшена
└── req.txt

API спроектирован так, что добавление новых сущностей требует минимум изменений — достаточно добавить модель, репозиторий, сервис и роутер.

WEB

Фронтенд реализован на React + Vite + JavaScript с использованием UI-библиотеки Ant Design и state-менеджмента через RTK Query.

web/
├── src/
│   ├── Api/                 — RTK Query слайсы (vacanciesApi, applicantProfilesApi и др.)
│   ├── App/                 — роутинг, PrivateRoute, AdminRoute
│   ├── Components/
│   │   ├── Pages/           — HomePage (карта + лента), CabinetPage (три роли), OpportunityPage и др.
│   │   └── Widgets/
│   ├── Redux/               — store + слайсы
│   ├── Core/                — константы, конфиги
│   └── Hooks/
├── k8s/helm/springboard-web — Helm-чарт
└── Dockerfile

Система ролей

Права проверяются как на бэкенде (Depends), так и на фронтенде (PrivateRoute / AdminRoute).

Куратор с привелегией администратора

  • Полный доступ к модерации
  • Верификация компаний
  • Управление пользователями и ролями
  • Просмотр всех возможностей и откликов

Работодатель

  • Создание и управление вакансиями, стажировками, менторскими программами и карьерными мероприятиями
  • Просмотр откликов и изменение их статусов
  • Редактирование профиля компании

Соискатель

  • Просмотр карты и ленты возможностей
  • Отклики и добавление в «Избранное»
  • Личный кабинет с резюме, навыками, образованием, опытом и контактами
  • Нетворкинг (профессиональные контакты)
  • Настройка приватности профиля

Развертывание проекта

API

Бэкенд можно запустить тремя способами — от самого простого до полноценного production-деплоймента.

1. Локальный запуск (без Docker)

# Клонируем репозиторий
git clone https://git.numerum.team/andrei/it-planet-springboard.git
cd it-planet-springboard/api

# Создаём виртуальное окружение и устанавливаем зависимости
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -r req.txt

# Создаём файл .env в корне api/
cp .env.example .env
# Редактируем .env — обязательно заполняем:
DB_DRIVER=postgresql+asyncpg
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=springboard
DB_SCHEMA=public
SECRET_KEY=your_very_strong_secret_key_here

# Применяем миграции
alembic upgrade head

# Запускаем сервер
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

API: http://localhost:8000

2. Запуск через Docker

Обратите внимание, что для хранения файлов необходимо создавать хранилище.
Вариант A — просто тянуть готовый образ

docker run -d \
  --name springboard-api \
  -p 8000:8000 \
  -e DB_DRIVER=postgresql+asyncpg \
  -e DB_HOST=host.docker.internal \
  -e DB_PORT=5432 \
  -e DB_USER=postgres \
  -e DB_PASSWORD=your_password \
  -e DB_NAME=springboard \
  -e DB_SCHEMA=public \
  -e SECRET_KEY=supersecretkey123 \
  -v ./uploads:/app/uploads \
  andreiduvakin/springboard-api:latest

Вариант B — собрать локально
Запускается из папки api:

docker build -t springboard-api . -а app/Dockerfile
docker run -d --name springboard-api -p 8000:8000 springboard-api

3. Production-развёртывание в Kubernetes

Используется Helm-чарт k8s/helm/springboard-api.

# Устанавливаем чарт (пример для нашего microk8s)
helm upgrade --install springboard-api k8s/helm/springboard-api --namespace springboard-api --create-namespace

Что нужно настроить в values.yaml:

env:
  DB_DRIVER: postgresql+asyncpg
  DB_HOST: db.numerum.team
  DB_PORT: 30000
  DB_USER: springboard
  DB_NAME: springboard
  DB_SCHEMA: public

Secret с чувствительными данными:

# k8s/helm/springboard-api/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: springboard-api-secret
type: Opaque
data:
  SECRET_KEY: base64_encoded_very_long_key==
  DB_PASSWORD: base64_encoded_password==

ОБРАТИТЕ ВНИМАНИЕ
В настоящем решении не предоставлен действительный файл k8s/helm/springboard-api/templates/secrets.yaml - для предотвращения несанкционированного доступа к нашей базе данных. Для ВАШЕЙ конфигурации нужно создавать свой файл.

PersistentVolume автоматически создаётся через pvc.yaml и монтирует папку /mnt/k8s_storage/springboard-api/uploads на хосте — все загруженные студентами файлы сохраняются между перезапусками. После деплоя:

API: https://api.springboard.numerum.team/
Swagger/ReDoc: https://api.springboard.numerum.team/docs

Именно так система работает в продакшене прямо сейчас — с HTTPS, Lets Encrypt, персистентным хранилищем и автоматическим масштабированием.

WEB

Фронтенд можно запустить тремя способами — от локальной разработки до production-развёртывания в Kubernetes.

1. Локальный запуск

git clone https://git.numerum.team/andrei/it-planet-springboard.git
cd it-planet-springboard/web

# Устанавливаем зависимости
npm install

# Создаём .env файл (в корне web/)
echo "VITE_BASE_URL=http://localhost:8000/api/v1" > .env

# Запускаем dev-сервер
npm run dev

Приложение будет доступно по адресу: http://localhost:5173

2. Запуск через Docker

Запускается из папки web: Вариант A — готовый образ
Готовый образ уже собран с продакшен-настройками! VITE_BASE_URL жёстко зашиты в образ на этапе сборки:

ENV VITE_BASE_URL=https://api.springboard.numerum.team/api/v1

Поэтому запуск предельно прост:

docker run -d \
  --name springboard-web \
  -p 3000:3000 \
  andreiduvakin/springboard-web:latest

Вариант B — сборка локально

docker run -d \
  --name springboard-web \
  -p 3000:3000 \
  --build-arg VITE_BASE_URL=http://localhost:8000/api/v1 \
  andreiduvakin/springboard-web:latest

Приложение доступно по адресу: http://localhost:3000

3. Production-развёртывание в Kubernetes

Используется Helm-чарт k8s/helm/springboard-web.

helm upgrade --install springboard-web k8s/helm/springboard-web --namespace springboard-web --create-namespace

Поскольку переменные окружения уже зашиты в образ на этапе npm run build, в values.yaml ничего передавать не нужно.

После деплоя приложение доступно по адресу: https://springboard.numerum.team
Именно так работает продакшен прямо сейчас.

Демонстрация

Видео ДЕМОНСТРАЦИИ проекта достпуно по ссылке: https://rutube.ru/video/b735056d4624028858cc18f4b8cba38b/

А также по этой ссылке: https://disk.yandex.ru/i/jfSKMd9uadv2rg

Пожалуйста, досмотрите видео целиком.

Регистрация

В системе можно зарегистрироваться перейдя на страницу регистрации из страницы входа.

Description
No description provided
Readme
Languages
Python 51.3%
JavaScript 48.4%
Mako 0.1%