feat(docs): auto-generate llms.txt via vitepress-plugin-llms

Replace static llms.txt and llms-full.txt with auto-generated versions
that stay in sync with docs on every build. The plugin also generates
per-page .md files for individual page fetching by LLMs.
This commit is contained in:
Siddharth Kumar Sah 2026-04-08 00:53:26 +08:00
parent e8c6a26cb9
commit 6a362d6443
5 changed files with 613 additions and 514 deletions

View file

@ -1,4 +1,5 @@
import { defineConfig } from "vitepress";
import llmstxt from "vitepress-plugin-llms";
export default defineConfig({
title: "Stirling Image",
@ -14,6 +15,45 @@ export default defineConfig({
["link", { rel: "llms-txt", href: "/stirling-image/llms.txt" }],
],
vite: {
plugins: [
llmstxt({
domain: "https://stirling-image.github.io",
customLLMsTxtTemplate: `# {title}
{description}
{details}
## Docs
{toc}
## API Quick Reference
- Base URL: \`http://localhost:1349\`
- Auth: Session token via \`POST /api/auth/login\` or API key (\`Authorization: Bearer si_...\`)
- Tools: \`POST /api/v1/tools/{toolId}\` (multipart: file + settings JSON)
- Batch: \`POST /api/v1/tools/{toolId}/batch\` (multiple files, returns ZIP)
- Pipelines: \`POST /api/v1/pipeline/execute\` (chain tools sequentially)
- Interactive API docs on running instance: \`/api/docs\`
- OpenAPI spec on running instance: \`/api/v1/openapi.yaml\`
## Source
- [GitHub](https://github.com/stirling-image/stirling-image)
- License: AGPLv3 (commercial license also available)
`,
customTemplateVariables: {
description:
"Self-hosted, open-source image processing platform with 30+ tools. Runs in a single Docker container. Available as :latest (full, ~11 GB with AI/ML) or :lite (~1.5 GB, image processing only).",
details:
"Resize, compress, convert, remove backgrounds, upscale, run OCR, and more - without sending images to external services.",
},
}),
],
},
themeConfig: {
logo: "/logo.svg",

View file

@ -9,7 +9,8 @@
},
"devDependencies": {
"tsx": "^4.19.0",
"vitepress": "^1.1.4"
"vitepress": "^1.1.4",
"vitepress-plugin-llms": "^1.12.0"
},
"license": "AGPL-3.0"
}

View file

@ -1,476 +0,0 @@
# Stirling Image — Complete Documentation
Self-hosted, open-source image processing platform with 30+ tools. Runs in a single Docker container. Resize, compress, convert, remove backgrounds, upscale, run OCR, and more - without sending images to external services. Available as :latest (full, ~11 GB with AI/ML) or :lite (~1.5 GB, image processing only).
- GitHub: https://github.com/stirling-image/stirling-image
- Docs: https://stirling-image.github.io/stirling-image/
- License: AGPLv3 (commercial license also available)
---
# Getting Started
## Run with Docker
The fastest way to get Stirling Image running:
```bash
docker run -d \
--name stirling-image \
-p 1349:1349 \
-v stirling-data:/data \
stirlingimage/stirling-image:latest
```
Open `http://localhost:1349` in your browser. Log in with `admin` / `admin`.
## Run with Docker Compose
Create a `docker-compose.yml`:
```yaml
services:
stirling-image:
image: stirlingimage/stirling-image:latest
container_name: stirling-image
ports:
- "1349:1349"
volumes:
- stirling-data:/data
- stirling-workspace:/tmp/workspace
environment:
- AUTH_ENABLED=true
- DEFAULT_USERNAME=admin
- DEFAULT_PASSWORD=admin
restart: unless-stopped
volumes:
stirling-data:
stirling-workspace:
```
```bash
docker compose up -d
```
## Build from source
Requirements: Node.js 22+, pnpm 9+, Python 3.10+
```bash
git clone https://github.com/stirling-image/stirling-image.git
cd stirling-image
pnpm install
pnpm dev
```
This starts both the API server and the React frontend at `http://localhost:1349`.
---
# Architecture
Stirling Image is a monorepo managed with pnpm workspaces and Turborepo. Everything ships as a single Docker container.
## Project structure
```
Stirling-Image/
├── apps/
│ ├── api/ # Fastify backend
│ ├── web/ # React + Vite frontend
│ └── docs/ # VitePress documentation site
├── packages/
│ ├── image-engine/ # Sharp-based image operations
│ ├── ai/ # Python AI model bridge
│ └── shared/ # Types, constants, i18n
└── docker/ # Dockerfile and Compose config
```
## Packages
### @stirling-image/image-engine
Core image processing library built on Sharp. Handles all non-AI operations: resize, crop, rotate, flip, convert, compress, strip metadata, and color adjustments. No network dependencies, runs entirely in-process.
### @stirling-image/ai
Bridge layer that calls Python scripts via child processes. Each AI capability has a TypeScript wrapper that spawns a Python subprocess, passes image data through the filesystem, and returns the result.
Supported operations:
- Background removal — BiRefNet-Lite model via rembg
- Upscaling — RealESRGAN
- OCR — PaddleOCR
- Face detection/blurring — MediaPipe
- Object erasing (inpainting) — LaMa Cleaner
Python scripts live in `packages/ai/python/`. The Docker image pre-downloads all model weights during the build so the container works offline.
### @stirling-image/shared
Shared TypeScript types, constants (like APP_VERSION and tool definitions), and i18n translation strings used by both frontend and backend.
## How a request flows
1. The user picks a tool in the web UI and uploads an image.
2. The frontend sends a multipart POST to `/api/v1/tools/:toolId` with the file and settings.
3. The API route validates the input with Zod, auto-orients the image based on EXIF metadata, then calls the appropriate package function.
4. For AI tools, the TypeScript bridge spawns a Python subprocess, waits for it to finish, and reads the output file.
5. The API returns a `jobId` and `downloadUrl`. The frontend can poll `/api/v1/jobs/:jobId/progress` via SSE for real time status.
6. The user downloads the processed image from `/api/v1/download/:jobId/:filename`.
---
# Configuration
All configuration is done through environment variables. Every variable has a sensible default.
## Server
| Variable | Default | Description |
|---|---|---|
| PORT | 1349 | Port the server listens on |
| RATE_LIMIT_PER_MIN | 100 | Maximum requests per minute per IP |
## Authentication
| Variable | Default | Description |
|---|---|---|
| AUTH_ENABLED | false | Set to true to require login. Docker image defaults to true. |
| DEFAULT_USERNAME | admin | Username for the initial admin account. Only used on first run. |
| DEFAULT_PASSWORD | admin | Password for the initial admin account. Change after first login. |
## Storage
| Variable | Default | Description |
|---|---|---|
| STORAGE_MODE | local | local or s3. Only local is currently implemented. |
| DB_PATH | ./data/stirling.db | Path to the SQLite database file |
| WORKSPACE_PATH | ./tmp/workspace | Directory for temporary files during processing |
| FILES_STORAGE_PATH | ./data/files | Directory for persistent user files |
## Processing limits
| Variable | Default | Description |
|---|---|---|
| MAX_UPLOAD_SIZE_MB | 100 | Maximum file size per upload in megabytes |
| MAX_BATCH_SIZE | 200 | Maximum number of files in a single batch request |
| CONCURRENT_JOBS | 3 | Number of batch jobs that run in parallel |
| MAX_MEGAPIXELS | 100 | Maximum image resolution allowed |
## Cleanup
| Variable | Default | Description |
|---|---|---|
| FILE_MAX_AGE_HOURS | 24 | How long temporary files are kept before deletion |
| CLEANUP_INTERVAL_MINUTES | 30 | How often the cleanup job runs |
## Appearance
| Variable | Default | Description |
|---|---|---|
| APP_NAME | Stirling Image | Display name shown in the UI |
| DEFAULT_THEME | light | Default theme (light or dark) |
| DEFAULT_LOCALE | en | Default interface language |
## Volumes
- `/data` — Persistent storage for SQLite database and user files. Mount to keep data across restarts.
- `/tmp/workspace` — Temporary storage for images being processed. Optional but prevents container layer growth.
---
# Database
SQLite with Drizzle ORM. Database file at DB_PATH (default: ./data/stirling.db).
## Tables
### users
| Column | Type | Notes |
|---|---|---|
| id | integer | Primary key, auto-increment |
| username | text | Unique, required |
| passwordHash | text | bcrypt hash |
| role | text | admin or user |
| mustChangePassword | integer | Boolean flag for forced password reset |
| createdAt | text | ISO timestamp |
### sessions
| Column | Type | Notes |
|---|---|---|
| id | text | Primary key (session token) |
| userId | integer | Foreign key to users.id |
| expiresAt | text | ISO timestamp |
### api_keys
| Column | Type | Notes |
|---|---|---|
| id | integer | Primary key |
| userId | integer | Foreign key to users.id |
| keyHash | text | SHA-256 hash of the key |
| name | text | User-provided label |
| createdAt | text | ISO timestamp |
| lastUsedAt | text | Updated on each request |
Keys are prefixed with `si_` followed by 96 hex characters.
### pipelines
| Column | Type | Notes |
|---|---|---|
| id | integer | Primary key |
| name | text | Pipeline name |
| description | text | Optional |
| steps | text | JSON array of { toolId, settings } |
| createdAt | text | ISO timestamp |
### settings
| Column | Type | Notes |
|---|---|---|
| key | text | Primary key |
| value | text | Setting value |
---
# Deployment
## Docker Compose (recommended)
```yaml
services:
stirling-image:
image: stirlingimage/stirling-image:latest
container_name: stirling-image
ports:
- "1349:1349"
volumes:
- stirling-data:/data
- stirling-workspace:/tmp/workspace
environment:
- AUTH_ENABLED=true
- DEFAULT_USERNAME=admin
- DEFAULT_PASSWORD=admin
restart: unless-stopped
volumes:
stirling-data:
stirling-workspace:
```
## What's inside the container
Multi-stage Docker build:
1. Build stage — installs Node.js dependencies, builds React frontend with Vite
2. Production stage — Node 22 image with Python 3, ImageMagick, Tesseract, potrace, ML packages, pre-downloaded model weights
Python packages: rembg (BiRefNet-Lite), RealESRGAN, PaddleOCR, MediaPipe, LaMa Cleaner, onnxruntime, opencv-python, Pillow, numpy.
## Health check
```
GET /api/v1/health
```
Returns 200 OK if the server is running. Used by Docker HEALTHCHECK.
## Reverse proxy (nginx example)
```nginx
server {
listen 80;
server_name images.example.com;
client_max_body_size 200M;
location / {
proxy_pass http://localhost:1349;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
```
---
# REST API
Base URL: `http://localhost:1349`
Interactive API docs on running instance: `/api/docs`
OpenAPI 3.1 spec: `/api/v1/openapi.yaml`
## Authentication
1. Session token — POST /api/auth/login with {username, password}. Returns {token}. Pass as `Authorization: Bearer <token>`.
2. API key — Generate via POST /api/v1/api-keys. Prefixed with `si_`. Pass as `Authorization: Bearer si_...`.
## Tools
### Execute a tool
```
POST /api/v1/tools/:toolId
Content-Type: multipart/form-data
```
Fields: `file` (image), `settings` (JSON string with tool-specific options).
Response: `{ jobId, downloadUrl, originalSize, processedSize }`
### Available tool IDs
Image operations: resize, crop, rotate, convert, compress, strip-metadata, border
Color: brightness-contrast, saturation, color-channels, color-effects, replace-color
Text/codes: watermark-text, watermark-image, text-overlay, qr-generate, barcode-read, ocr
Composition: compose, collage, split, image-to-pdf
Analysis: info, compare, find-duplicates, color-palette
Conversion: svg-to-raster, vectorize, favicon, gif-tools
AI-powered: remove-background, upscale, blur-faces, erase-object, smart-crop
Utility: bulk-rename
### Batch processing
```
POST /api/v1/tools/:toolId/batch
Content-Type: multipart/form-data
```
Multiple files with same settings. Returns ZIP file. X-Job-Id header for progress tracking.
## Pipelines
- Execute: POST /api/v1/pipeline/execute (multipart: file + steps JSON array)
- Save: POST /api/v1/pipeline/save (JSON: {name, description, steps})
- List: GET /api/v1/pipeline/list
- Delete: DELETE /api/v1/pipeline/:id
## Files
- Upload: POST /api/v1/upload
- Download: GET /api/v1/download/:jobId/:filename (public, no auth)
- List saved: GET /api/v1/files
- Save to library: POST /api/v1/files/upload
- Save result: POST /api/v1/files/save-result (JSON: {jobId, filename})
- Get metadata: GET /api/v1/files/:id
- Download saved: GET /api/v1/files/:id/download
- Thumbnail: GET /api/v1/files/:id/thumbnail
- Delete: DELETE /api/v1/files (JSON: {ids: [...]})
## API Keys
- Create: POST /api/v1/api-keys (JSON: {name}) — returns full key once
- List: GET /api/v1/api-keys — metadata only
- Delete: DELETE /api/v1/api-keys/:id
## Settings
- Get all: GET /api/v1/settings
- Get one: GET /api/v1/settings/:key
- Update: PUT /api/v1/settings (admin only, JSON key-value object)
## Teams
- List: GET /api/v1/teams
- Create: POST /api/v1/teams (JSON: {name})
- Rename: PUT /api/v1/teams/:id (JSON: {name})
- Delete: DELETE /api/v1/teams/:id
## Auth endpoints
- Login: POST /api/auth/login
- Logout: POST /api/auth/logout
- Session: GET /api/auth/session
- Change password: POST /api/auth/change-password
- List users (admin): GET /api/auth/users
- Create user (admin): POST /api/auth/register
- Update user (admin): PUT /api/auth/users/:id
- Delete user (admin): DELETE /api/auth/users/:id
- Reset password (admin): POST /api/auth/users/:id/reset-password
## Branding
- Get logo: GET /api/v1/settings/logo (public)
- Upload logo (admin): POST /api/v1/settings/logo
- Delete logo (admin): DELETE /api/v1/settings/logo
## Progress tracking (SSE)
```
GET /api/v1/jobs/:jobId/progress
```
Server-Sent Events stream: {status, progress (0-100), completedFiles, failedFiles}
## Error responses
```json
{ "statusCode": 400, "error": "Bad Request", "message": "Invalid image format" }
```
Status codes: 400 (invalid input), 401 (not authenticated), 403 (not authorized), 413 (file too large), 429 (rate limited), 500 (server error)
---
# Image Engine
The @stirling-image/image-engine package handles all non-AI image operations via Sharp.
## Operations
### resize
width (number), height (number), fit (cover/contain/fill/inside/outside), withoutEnlargement (boolean), percentage (number)
### crop
left (number), top (number), width (number), height (number)
### rotate
angle (number, degrees)
### flip
direction: horizontal or vertical
### convert
format (jpeg/png/webp/avif/tiff/gif/heic), quality (1-100)
### compress
quality (1-100), format (optional override)
### strip-metadata
Removes EXIF, IPTC, XMP metadata. No parameters.
### Color adjustments
brightness (-100 to 100), contrast (-100 to 100), saturation (-100 to 100)
### Color filters
grayscale, sepia, invert — no parameters
### Color channels
red (-100 to 100), green (-100 to 100), blue (-100 to 100)
Supported input formats: JPEG, PNG, WebP, AVIF, TIFF, GIF, HEIC/HEIF, SVG, RAW (via libraw)
---
# AI Engine
The @stirling-image/ai package wraps Python ML models. Each operation spawns a Python subprocess. All model weights are bundled in the Docker image.
## Background removal
Model: BiRefNet-Lite via rembg. Parameters: model (string), alphaMatting (boolean), alphaMattingForegroundThreshold (0-255), alphaMattingBackgroundThreshold (0-255).
## Upscaling
Model: RealESRGAN. Parameters: scale (2 or 4).
## OCR
Model: PaddleOCR. Parameters: language (en/ch/fr/de/etc). Returns text with bounding boxes and confidence scores.
## Face detection and blurring
Model: MediaPipe. Parameters: blurStrength (number). Returns blurred image with face region metadata.
## Object erasing (inpainting)
Model: LaMa. Input: image + mask (white = erase, black = keep). Returns inpainted image.
## Bridge mechanism
TypeScript bridge spawns Python subprocess, writes input to temp file, parses JSON progress from stderr for SSE streaming, reads output image, cleans up. Timeout: 5 minutes.

View file

@ -1,31 +0,0 @@
# Stirling Image
> Self-hosted, open-source image processing platform with 30+ tools. Runs in a single Docker container. Available as `:latest` (full, ~11 GB with AI/ML) or `:lite` (~1.5 GB, image processing only).
## Docs
- [Getting Started](https://stirling-image.github.io/stirling-image/guide/getting-started): Docker setup, build from source
- [Architecture](https://stirling-image.github.io/stirling-image/guide/architecture): Monorepo structure, request flow, packages
- [Configuration](https://stirling-image.github.io/stirling-image/guide/configuration): Environment variables, Docker volumes
- [Database](https://stirling-image.github.io/stirling-image/guide/database): SQLite schema, tables, migrations
- [Deployment](https://stirling-image.github.io/stirling-image/guide/deployment): Docker Compose, reverse proxy, CI/CD
- [Docker Tags](https://stirling-image.github.io/stirling-image/guide/docker-tags): Full vs Lite image variants, version pinning
- [REST API](https://stirling-image.github.io/stirling-image/api/rest): All API endpoints, auth, tools, pipelines, batch
- [Image Engine](https://stirling-image.github.io/stirling-image/api/image-engine): Sharp-based operations (resize, crop, rotate, convert, compress, color)
- [AI Engine](https://stirling-image.github.io/stirling-image/api/ai): Python ML models (rembg, RealESRGAN, PaddleOCR, MediaPipe, LaMa)
- [Full Documentation (LLM-friendly)](https://stirling-image.github.io/stirling-image/llms-full.txt): All docs in a single plain-text file
## API Quick Reference
- Base URL: `http://localhost:1349`
- Auth: Session token via `POST /api/auth/login` or API key (`Authorization: Bearer si_...`)
- Tools: `POST /api/v1/tools/{toolId}` (multipart: file + settings JSON)
- Batch: `POST /api/v1/tools/{toolId}/batch` (multiple files, returns ZIP)
- Pipelines: `POST /api/v1/pipeline/execute` (chain tools sequentially)
- Interactive API docs on running instance: `/api/docs`
- OpenAPI spec on running instance: `/api/v1/openapi.yaml`
## Source
- [GitHub](https://github.com/stirling-image/stirling-image)
- License: AGPLv3 (commercial license also available)

File diff suppressed because it is too large Load diff