Add browserless service to prod compose and document clean-pdf
This commit is contained in:
@@ -48,4 +48,6 @@ TOOLBOX_VISIBLE=""
|
|||||||
|
|
||||||
# Чистый PDF (browserless на staging/prod; локально — SSH-туннель на staging)
|
# Чистый PDF (browserless на staging/prod; локально — SSH-туннель на staging)
|
||||||
BROWSER_WS_URL="ws://localhost:3333"
|
BROWSER_WS_URL="ws://localhost:3333"
|
||||||
|
# Секрет browserless (TOKEN в его env) — на прод/staging генерировать: openssl rand -hex 24
|
||||||
|
BROWSERLESS_TOKEN=""
|
||||||
PDF_MONTHLY_LIMIT="100"
|
PDF_MONTHLY_LIMIT="100"
|
||||||
|
|||||||
@@ -171,6 +171,37 @@ CSS-классы: `.card-aubade`, `.btn-aubade`, `.btn-aubade-accent`, `.tag-aub
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `POST` | `/api/auth/[...all]` | Better Auth handler | Все |
|
| `POST` | `/api/auth/[...all]` | Better Auth handler | Все |
|
||||||
| `POST` | `/api/admin/upload` | Загрузка файла в S3, возвращает `{ url, key }` | admin |
|
| `POST` | `/api/admin/upload` | Загрузка файла в S3, возвращает `{ url, key }` | admin |
|
||||||
|
| `GET` | `/api/pdf` | Чистый PDF из URL (Bearer-ключ или сессия) — см. раздел ниже | платный студент, admin, curator |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Чистый PDF (`/tools/clean-pdf`, `/api/pdf`)
|
||||||
|
|
||||||
|
Инструмент Obsidian Toolbox: превращает произвольный URL в чистый PDF (без рекламы и меню, с типографикой, оглавлением, A4/Letter, light/dark). Полный дизайн-документ: [`docs/specs/20260706-clean-pdf-design.md`](docs/specs/20260706-clean-pdf-design.md).
|
||||||
|
|
||||||
|
**Пайплайн генерации:**
|
||||||
|
|
||||||
|
```
|
||||||
|
URL студента
|
||||||
|
→ browserless (Chromium по WebSocket, playwright-core) загружает страницу
|
||||||
|
→ Next.js забирает итоговый HTML
|
||||||
|
→ Defuddle (JSDOM) выделяет основной контент
|
||||||
|
→ HTML-шаблон (типографика, A4/Letter, light/dark, оглавление)
|
||||||
|
→ Playwright page.pdf() в том же browserless
|
||||||
|
→ application/pdf в ответе
|
||||||
|
```
|
||||||
|
|
||||||
|
Доступ: любой платный студент (есть `CourseEnrollment` вне `FREE_COURSE_SLUG`), admin/curator — без ограничений. Видимость страницы гейтится флагом `TOOLBOX_VISIBLE`, но сам `/api/pdf` работает независимо от него (доступ проверяется отдельно). Ключ для внешнего API — модель `PdfApiKey` (`sbpdf_<random>`, ленивая генерация, регенерация инвалидирует старый).
|
||||||
|
|
||||||
|
**Env-переменные:**
|
||||||
|
|
||||||
|
| Переменная | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `BROWSER_WS_URL` | WebSocket-адрес browserless (`ws://browserless:3000` в compose, `ws://localhost:3333` при туннеле локально) |
|
||||||
|
| `BROWSERLESS_TOKEN` | Секрет browserless (`TOKEN` в его env) — общий и для сервиса, и для клиента в LMS |
|
||||||
|
| `PDF_MONTHLY_LIMIT` | Лимит генераций в месяц на студента (по умолчанию `100`), без пересборки |
|
||||||
|
|
||||||
|
Контейнер `browserless` (`ghcr.io/browserless/chromium`) — внутренний, порт наружу не публикуется ни на staging, ни на проде.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ services:
|
|||||||
NEXT_PUBLIC_APP_URL: "https://school.second-brain.ru"
|
NEXT_PUBLIC_APP_URL: "https://school.second-brain.ru"
|
||||||
RESEND_API_KEY: "${RESEND_API_KEY}"
|
RESEND_API_KEY: "${RESEND_API_KEY}"
|
||||||
EMAIL_FROM: "${EMAIL_FROM}"
|
EMAIL_FROM: "${EMAIL_FROM}"
|
||||||
|
BROWSER_WS_URL: "ws://browserless:3000"
|
||||||
|
BROWSERLESS_TOKEN: "${BROWSERLESS_TOKEN}"
|
||||||
|
PDF_MONTHLY_LIMIT: "${PDF_MONTHLY_LIMIT:-100}"
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
browserless:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
@@ -32,5 +37,15 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|
||||||
|
browserless:
|
||||||
|
image: ghcr.io/browserless/chromium
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TOKEN: "${BROWSERLESS_TOKEN}"
|
||||||
|
CONCURRENT: "2"
|
||||||
|
QUEUED: "10"
|
||||||
|
TIMEOUT: "120000"
|
||||||
|
mem_limit: 1g
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|||||||
Reference in New Issue
Block a user