Files
obsidian/Projects/Pulse/Architecture.md
2026-02-06 14:12:11 +00:00

11 KiB
Raw Blame History

Pulse — Архитектура проекта

Обзор

Pulse — персональное productivity-приложение для управления задачами, привычками и напоминаниями с интеграцией Telegram-бота.

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

Backend (pulse-api)

  • Язык: Go 1.22
  • Web-фреймворк: chi/v5
  • База данных: PostgreSQL 16
  • ORM: sqlx (raw SQL + struct mapping)
  • Аутентификация: JWT (access 15 мин / refresh 365 дней)
  • Email: Resend API
  • Telegram: go-telegram-bot-api/v5
  • Scheduler: robfig/cron/v3
  • Контейнеризация: Docker + Docker Compose

Frontend (pulse-web)

  • Фреймворк: React 18
  • Сборщик: Vite 5
  • Стили: TailwindCSS
  • Состояние: Zustand (auth), TanStack Query (data fetching)
  • Анимации: Framer Motion
  • Иконки: Lucide React
  • Контейнеризация: nginx:alpine

Инфраструктура

  • Хостинг: VM Ubuntu (192.168.31.60)
  • Reverse proxy: Nginx Proxy Manager
  • SSL: Let's Encrypt (auto-renew)
  • Git: Gitea (git.digital-home.site)
  • Домены:
    • API: api.digital-home.site
    • Web: pulse.digital-home.site

Структура Backend

homelab-api/
├── cmd/api/
│   └── main.go              # Точка входа, инициализация
├── internal/
│   ├── bot/
│   │   ├── bot.go           # Telegram bot, long polling
│   │   └── handlers.go      # Обработчики команд и callback
│   ├── config/
│   │   └── config.go        # Загрузка переменных окружения
│   ├── handler/
│   │   ├── auth.go          # Регистрация, логин, JWT
│   │   ├── habits.go        # CRUD привычек
│   │   ├── health.go        # Health check
│   │   ├── profile.go       # Профиль пользователя
│   │   └── tasks.go         # CRUD задач
│   ├── middleware/
│   │   └── auth.go          # JWT middleware
│   ├── model/
│   │   ├── habit.go         # Модель привычки
│   │   ├── task.go          # Модель задачи
│   │   └── user.go          # Модель пользователя
│   ├── repository/
│   │   ├── db.go            # Подключение к PostgreSQL
│   │   ├── habit.go         # SQL-запросы для привычек
│   │   ├── task.go          # SQL-запросы для задач
│   │   └── user.go          # SQL-запросы для пользователей
│   ├── scheduler/
│   │   └── scheduler.go     # Cron jobs для уведомлений
│   └── service/
│       ├── auth.go          # Бизнес-логика авторизации
│       ├── email.go         # Отправка email через Resend
│       ├── habit.go         # Бизнес-логика привычек
│       └── task.go          # Бизнес-логика задач
├── Dockerfile
├── docker-compose.yml
├── go.mod
└── go.sum

Структура Frontend

pulse-web/
├── public/
│   └── favicon.svg          # Иконка молния ⚡
├── src/
│   ├── api/
│   │   ├── client.js        # Axios instance + interceptors
│   │   ├── habits.js        # API привычек
│   │   ├── profile.js       # API профиля
│   │   └── tasks.js         # API задач
│   ├── components/
│   │   ├── CreateHabitModal.jsx
│   │   ├── CreateTaskModal.jsx
│   │   ├── EditHabitModal.jsx
│   │   ├── EditTaskModal.jsx
│   │   └── Navigation.jsx   # Нижняя навигация
│   ├── pages/
│   │   ├── ForgotPassword.jsx
│   │   ├── Habits.jsx       # Управление привычками
│   │   ├── Home.jsx         # Главная (сегодня)
│   │   ├── Login.jsx
│   │   ├── Register.jsx
│   │   ├── ResetPassword.jsx
│   │   ├── Settings.jsx     # Настройки профиля
│   │   ├── Stats.jsx        # Статистика
│   │   ├── Tasks.jsx        # Управление задачами
│   │   └── VerifyEmail.jsx
│   ├── store/
│   │   └── auth.js          # Zustand store для авторизации
│   ├── App.jsx              # Роутинг
│   ├── index.css            # Глобальные стили
│   └── main.jsx             # Entry point
├── Dockerfile
├── docker-compose.yml
├── index.html
├── nginx.conf
├── package.json
├── tailwind.config.js
└── vite.config.js

База данных

Таблицы

-- Пользователи
users (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  username VARCHAR(100) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  email_verified BOOLEAN DEFAULT FALSE,
  telegram_chat_id BIGINT,
  notifications_enabled BOOLEAN DEFAULT TRUE,
  timezone VARCHAR(50) DEFAULT 'Europe/Moscow',
  morning_reminder_time TIME DEFAULT '09:00',
  evening_reminder_time TIME DEFAULT '21:00',
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
)

-- Задачи
tasks (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  title VARCHAR(255) NOT NULL,
  description TEXT,
  icon VARCHAR(10) DEFAULT '📋',
  color VARCHAR(7) DEFAULT '#6B7280',
  due_date DATE,
  priority INTEGER DEFAULT 0,  -- 0=none, 1=low, 2=medium, 3=high
  reminder_time TIME,
  completed_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
)

-- Привычки
habits (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  name VARCHAR(255) NOT NULL,
  description TEXT,
  icon VARCHAR(10) DEFAULT '✨',
  color VARCHAR(7) DEFAULT '#10B981',
  frequency VARCHAR(20) DEFAULT 'daily',  -- daily, weekly, custom
  target_days INTEGER[],  -- [1,3,5] для пн,ср,пт
  target_count INTEGER DEFAULT 1,
  reminder_time TIME,
  archived BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
)

-- Логи привычек
habit_logs (
  id SERIAL PRIMARY KEY,
  habit_id INTEGER REFERENCES habits(id),
  user_id INTEGER REFERENCES users(id),
  date DATE NOT NULL,
  count INTEGER DEFAULT 1,
  created_at TIMESTAMP DEFAULT NOW()
)

-- Email токены
email_tokens (
  id SERIAL PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  token VARCHAR(255) NOT NULL,
  type VARCHAR(50) NOT NULL,  -- verification, password_reset
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
)

API Endpoints

Авторизация

Method Endpoint Описание
POST /auth/register Регистрация
POST /auth/login Вход
POST /auth/refresh Обновить токены
POST /auth/verify-email Подтвердить email
POST /auth/forgot-password Запросить сброс пароля
POST /auth/reset-password Сбросить пароль

Профиль (требует JWT)

Method Endpoint Описание
GET /profile Получить профиль
PUT /profile Обновить профиль

Задачи (требует JWT)

Method Endpoint Описание
GET /tasks Список задач
GET /tasks/today Задачи на сегодня
POST /tasks Создать задачу
GET /tasks/{id} Получить задачу
PUT /tasks/{id} Обновить задачу
DELETE /tasks/{id} Удалить задачу
POST /tasks/{id}/complete Отметить выполненной
POST /tasks/{id}/uncomplete Снять отметку

Привычки (требует JWT)

Method Endpoint Описание
GET /habits Список привычек
POST /habits Создать привычку
GET /habits/{id} Получить привычку
PUT /habits/{id} Обновить привычку
DELETE /habits/{id} Удалить (архивировать)
POST /habits/{id}/log Отметить выполнение
GET /habits/{id}/logs История выполнений
DELETE /habits/{id}/logs/{logId} Удалить запись
GET /habits/stats Общая статистика
GET /habits/{id}/stats Статистика привычки

Telegram Bot

Команды

Команда Описание
/start Показать Chat ID
/tasks Задачи на сегодня
/habits Привычки на сегодня
/help Справка

Inline кнопки

  • Выполнено — отмечает задачу/привычку
  • 🗑 Удалить — удаляет задачу
  • +30 мин — откладывает напоминание

Уведомления

  1. Утреннее (настраивается): задачи и привычки на сегодня
  2. Вечернее (настраивается): итоги дня
  3. Индивидуальные: по reminder_time каждой задачи/привычки

Docker Compose

Backend (homelab-api)

services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: homelab
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: homelab
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - backend

  api:
    build: .
    environment:
      - DATABASE_URL=postgres://homelab:${DB_PASSWORD}@db:5432/homelab?sslmode=disable
      - JWT_SECRET=${JWT_SECRET}
      - RESEND_API_KEY=${RESEND_API_KEY}
      - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
    depends_on:
      - db
    networks:
      - backend
      - services_proxy

Frontend (pulse-web)

services:
  web:
    build: .
    networks:
      - services_proxy

Дизайн

Цвета

  • Primary (Deep Teal): #115E59
  • Accent (Burnished Amber): #F59E0B
  • Surface: #F8FAFC
  • Text: #1E293B

Шрифты

  • Body: Inter (Google Fonts)

UI-компоненты

  • Карточки с тенями и закруглениями (rounded-2xl)
  • Backdrop blur для header
  • Framer Motion анимации
  • Inline кнопки в Telegram

Репозитории


Создано: 2026-02-06