Веб-приложение для зуботехнической лаборатории: наряды, переписка с врачом, учёт конструкций и титановых оснований, хранение 3D-файлов.
Разработано по итогам разговора с первым клиентом 30 сентября 2026.
Лицензия: проприетарная, все права защищены. См. LICENSE. Репозиторий открыт для чтения, но не для использования и развёртывания третьими лицами.
Врач и техник работают в разных программах и переписываются в мессенджерах. Из переписки потом вручную пересоздаётся наряд: конструкции теряются, сроки и цены договариваются устно. Приложение собирает это в одном месте:
- наряд из переписки — врач пишет «отсутствуют 28, 17, 16, 45, 32», техник отвечает предложением, после согласования кнопка «Сформировать наряд» ставит договорённые конструкции первыми;
- переписка внутри наряда — обсуждение этапов, цен и сроков в личном кабинете;
- справочник конструкций — каталог с ценами и разбором прайс-листа;
- учёт титановых оснований с выдачей и возвратом;
- 3D-файлы — приём, выдача, статусы «выпилено / запечено».
| Область | Что реализовано |
|---|---|
| Лаборатории | полноценная сущность, регистрация, раздельные данные по clinic_id |
| Роли | врач, техник, администрация; специализации внутри ролей |
| Наряды | этапы, конструкции, цены, печать, выгрузка в Excel |
| Переписка | чат врач ↔ техник, уведомления, Telegram |
| Доступы | пароли (scrypt), коды входа, приглашения, восстановление пароля |
| Хранилище | локальный диск или S3; квоты лаборатории, учёт свободного места |
| Пробный период | триал, блокировка по его истечении |
| Интерфейс | адаптивная вёрстка, PWA, работа с телефона |
| Защита | rate-limit по сотруднику и адресу, разделение по клинике, HSTS |
Node.js 22, Express 5, SQLite через better-sqlite3, EJS, multer, ExcelJS,
nodemailer, qrcode, AWS SDK (S3). Сборка в исполняемый файл — pkg.
- Node.js 22.x — версия закреплена в
.nvmrc,package.json → enginesи целяхpkg. Уbetter-sqlite3под Node 26 нет готовой сборки, а исходники не компилируются: в Node 26 движок V8 убралinfo.This(). - Linux-система с systemd для развёртывания (для локального запуска достаточно Node).
Проверка: cat .nvmrc && node -v
git clone https://github.com/lAlbertvh/ztbase.git
cd ztbase
npm ci
# обязательная переменная — без неё приложение в production не стартует
export SESSION_SECRET=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
cp .env.example .env # см. deploy/ztlab.env.example — он полнее
node server.jsПриложение слушает 127.0.0.1:3000 по умолчанию. Наружу его отдавать не
нужно — перед ним должен стоять nginx с TLS. Проверка живости:
curl -sf http://127.0.0.1:3000/healthНастройки берутся из окружения, полный список с пояснениями —
deploy/ztlab.env.example.
Полная инструкция — deploy/README.md: целевая схема, установка на VPS, nginx, сертификат, бэкапы, письма, откат.
Кратко:
sudo deploy/install-vps.sh # Node 22, пользователь, каталоги, таймеры
sudo systemctl start ztlab
curl -sf http://127.0.0.1:3000/health
sudo deploy/check.sh ztbase.ru # полная проверка: сервис, nginx, TLS, входСхема боевого развёртывания:
интернет ──443──▶ VPS (nginx + TLS ─▶ 127.0.0.1:3000 Node ─▶ SQLite, 3D-файлы)
Наружу открыты ровно три порта: 22 (SSH), 80 (только выпуск сертификата), 443 (сайт).
npm test # 497 проверок, десять наборов
npm run test:unit # только быстрые юнит-тестыНаборы: manipulations, inbox, quota, landing — юнит; orders,
storage, setup, chat, clinics, password — живые, поднимают
приложение. Тесты гоняются в CI при каждом пуше.
Контакты для сайта и приложения берутся из одного content/site.json:
в разметке лендинга и правовых документов стоят метки {{phone}},
{{email}}, которые подставляет src/services/landing-render.js.
git pull
sudo deploy/deploy.shСкрипт проверяет версию Node и наличие секрета, снимает копию базы,
обновляет код, выполняет npm ci, перезапускает сервис и проверяет
/health. Откат: git log, затем git checkout <коммит> и повторный
sudo deploy/deploy.sh.
| Документ | О чём |
|---|---|
| docs/architecture.md | слои приложения, кто за что отвечает, куда класть новый код |
| docs/development.md | как вести разработку локально: запуск, тесты, коммиты, выкладка |
| docs/prompts.md | готовые промты для работы над проектом |
| docs/work-plan.md | план работ, что сделано, что дальше |
| docs/product-plan.md | что просит клиент, тарифы, роли, модель данных |
| deploy/README.md | развёртывание и эксплуатация на VPS |
Начать с docs/architecture.md и docs/development.md — они отвечают на
вопрос «где что лежит» и «как не испортить».
server.js точка входа: собирает приложение, 375 строк
src/config.js пути, порт, лимиты — единственное место, где живут пути
src/middleware/auth.js проверка сессии, роль, пробный период, лимиты входа
src/routes/ HTTP-маршруты по разделам (13 модулей)
src/services/ предметная область: наряды, квоты, письма, триал (21 модуль)
src/db/ схема таблиц и миграции, все идемпотентны
src/lib/password.js хэширование паролей (scrypt)
views/ шаблоны EJS; views/orders — нарядные формы и печать
public/ CSS, JS, иконки, манифест и service worker
test/ девять наборов тестов
deploy/ установка, деплой, бэкапы, проверки, nginx, таймеры
docs/ архитектура, разработка, промты, план работ
content/site.json тексты лендинга и правовых страниц
Правило: server.js только собирает приложение и ничего не решает.
Логика — в src/services/, HTTP — в src/routes/, пути — в src/config.js.
Бэкап ежедневно в 3:17, проверка живости — чаще. Оба описаны в
deploy/README.md; копии живут в /var/backups/ztlab/, вывозятся на другую
машину скриптом deploy/backup-offsite.sh.
Работающий продукт с первым клиентом. Открытые вопросы перечислены в
docs/product-plan.md (раздел 9) и deploy/README.md (раздел «Нерешённое»).