docs: rewrite README, add CONTRIBUTING.md, developer and translation guides

Rewrite README to remove AI writing patterns (em dashes, promotional
language, vague claims). Make Quick Start section explicit about default
credentials and forced password change. Add Contributing section linking
to CONTRIBUTING.md, developer guide, and translation guide.

Create CONTRIBUTING.md with issue guidelines, PR workflow, commit
conventions, and development setup. Add developer guide (dev setup,
project structure, how to add a tool) and translation guide (how the
i18n system works, step-by-step for adding a language) to VitePress
docs. Register both new pages in the docs sidebar.
This commit is contained in:
Siddharth Kumar Sah
2026-03-28 12:14:24 +08:00
parent a0f68465ac
commit 9f68960eda
5 changed files with 436 additions and 21 deletions
+2
View File
@@ -32,6 +32,8 @@ export default defineConfig({
{ text: "Configuration", link: "/guide/configuration" },
{ text: "Database", link: "/guide/database" },
{ text: "Deployment", link: "/guide/deployment" },
{ text: "Developer guide", link: "/guide/developer" },
{ text: "Translation guide", link: "/guide/translations" },
],
},
{
+204
View File
@@ -0,0 +1,204 @@
# Developer guide
How to set up a local development environment and contribute code to Stirling Image.
## Prerequisites
- [Node.js](https://nodejs.org/) 22+
- [pnpm](https://pnpm.io/) 9+ (`corepack enable && corepack prepare pnpm@latest --activate`)
- [Docker](https://www.docker.com/) (for container builds and AI features)
- Git
Python 3.10+ is only needed if you are working on the AI/ML sidecar (background removal, upscaling, OCR).
## Setup
```bash
git clone https://github.com/siddharthksah/Stirling-Image.git
cd Stirling-Image
pnpm install
pnpm dev
```
This starts two dev servers:
| Service | URL | Notes |
|----------|--------------------------|------------------------------------|
| Frontend | http://localhost:1349 | Vite dev server, proxies /api |
| Backend | http://localhost:13490 | Fastify API (accessed via proxy) |
Open http://localhost:1349 in your browser. Login with `admin` / `admin`. You will be prompted to change the password on first login.
## Project structure
```
apps/
api/ Fastify backend
web/ Vite + React frontend
docs/ VitePress documentation (this site)
packages/
shared/ Constants, types, i18n strings
image-engine/ Sharp-based image operations
ai/ Python sidecar bridge for ML models
tests/
unit/ Vitest unit tests
integration/ Vitest integration tests (full API)
e2e/ Playwright end-to-end specs
fixtures/ Small test images
```
## Commands
```bash
pnpm dev # start frontend + backend
pnpm build # build all workspaces
pnpm typecheck # TypeScript check across monorepo
pnpm lint # Biome lint + format check
pnpm lint:fix # auto-fix lint + format
pnpm test # unit + integration tests
pnpm test:unit # unit tests only
pnpm test:integration # integration tests only
pnpm test:e2e # Playwright e2e tests
pnpm test:coverage # tests with coverage report
```
## Code conventions
- Double quotes, semicolons, 2-space indentation (enforced by Biome)
- ES modules in all workspaces
- [Conventional commits](https://www.conventionalcommits.org/) for semantic-release
- Zod for all API input validation
- No modifications to Biome, TypeScript, or editor config files. Fix the code, not the linter.
## Database
SQLite via Drizzle ORM. The database file lives at `./data/stirling.db` by default.
```bash
cd apps/api
npx drizzle-kit generate # generate a migration from schema changes
npx drizzle-kit migrate # apply pending migrations
```
Schema is defined in `apps/api/src/db/schema.ts`. Tables: users, sessions, settings, jobs, apiKeys, pipelines, teams, userFiles.
## Adding a new tool
Every tool follows the same pattern. Here is a minimal example.
### 1. Backend route
Create `apps/api/src/routes/tools/my-tool.ts`:
```ts
import { z } from "zod";
import type { FastifyInstance } from "fastify";
import { createToolRoute } from "../tool-factory.js";
const settingsSchema = z.object({
intensity: z.number().min(0).max(100).default(50),
});
export function registerMyTool(app: FastifyInstance) {
createToolRoute(app, {
toolId: "my-tool",
settingsSchema,
async process(inputBuffer, settings, filename) {
// Use sharp or other libraries to process the image
const sharp = (await import("sharp")).default;
const result = await sharp(inputBuffer)
// ... your processing logic
.toBuffer();
return {
buffer: result,
filename: filename.replace(/\.[^.]+$/, ".png"),
contentType: "image/png",
};
},
});
}
```
Then register it in `apps/api/src/routes/tools/index.ts`.
### 2. Frontend settings component
Create `apps/web/src/components/tools/my-tool-settings.tsx`:
```tsx
import { useState } from "react";
import { useToolProcessor } from "@/hooks/use-tool-processor";
import { useFileStore } from "@/stores/file-store";
export function MyToolSettings() {
const { files } = useFileStore();
const { processFiles, processing, error, downloadUrl } =
useToolProcessor("my-tool");
const [intensity, setIntensity] = useState(50);
const handleProcess = () => {
processFiles(files, { intensity });
};
return (
<div className="space-y-4">
{/* your controls here */}
<button
type="button"
onClick={handleProcess}
disabled={files.length === 0 || processing}
data-testid="my-tool-submit"
className="w-full py-2.5 rounded-lg bg-primary text-primary-foreground font-medium disabled:opacity-50"
>
Process
</button>
</div>
);
}
```
Then add the route and component to the tool registry in the frontend.
### 3. i18n entry
Add to `packages/shared/src/i18n/en.ts`:
```ts
"my-tool": {
name: "My Tool",
description: "Short description of what this tool does",
},
```
### 4. Tests
Add a `data-testid` attribute to your action button (as shown above) so e2e tests can target it reliably.
## Docker builds
Build the full production image locally:
```bash
docker build -f docker/Dockerfile -t stirling-image:latest .
```
Use BuildKit cache mounts for faster rebuilds:
```bash
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile -t stirling-image:latest .
```
## Environment variables
See the [Configuration guide](/guide/configuration) for the full list. Key ones for development:
| Variable | Default | Description |
|-----------------------------|-----------|------------------------------------------------|
| `AUTH_ENABLED` | `true` | Enable/disable authentication |
| `DEFAULT_USERNAME` | `admin` | Default admin username |
| `DEFAULT_PASSWORD` | `admin` | Default admin password |
| `SKIP_MUST_CHANGE_PASSWORD` | `false` | Skip forced password change (CI/dev only) |
| `RATE_LIMIT_PER_MIN` | `100` | API rate limit per minute |
| `MAX_UPLOAD_SIZE_MB` | `100` | Maximum upload size in MB |
+103
View File
@@ -0,0 +1,103 @@
# Translation guide
Stirling Image ships with English by default. The i18n system is designed so adding a new language is straightforward. This page walks you through the process.
## How translations work
All UI strings live in `packages/shared/src/i18n/`. The reference file is `en.ts`, which exports a typed object with every string the app uses. Other languages are separate files (e.g., `de.ts`, `fr.ts`) that export the same shape.
The `TranslationKeys` type is derived from the English file, so TypeScript will catch any missing keys in your translation.
## Adding a new language
### 1. Fork and branch
Fork the repository and create a new branch from `main`:
```bash
git checkout -b feat/add-german-translations
```
### 2. Copy the reference file
```bash
cp packages/shared/src/i18n/en.ts packages/shared/src/i18n/de.ts
```
### 3. Translate the strings
Open `de.ts` and translate every string value. Keep the object structure and keys exactly the same. Only change the values.
```ts
// packages/shared/src/i18n/de.ts
export const de = {
common: {
upload: "Vom Computer hochladen",
process: "Verarbeiten",
download: "Herunterladen",
cancel: "Abbrechen",
// ... translate all entries
},
tools: {
resize: {
name: "Größe ändern",
description: "Größe nach Pixeln, Prozent oder Social-Media-Vorgaben ändern",
},
// ... translate all tool entries
},
// ... translate all sections: settings, auth, pipeline, nav
} as const;
```
Things to keep in mind:
- Preserve any interpolation placeholders if they exist in the future (e.g., `{count}`, `{filename}`).
- Do not translate object keys, only values.
- Keep the `as const` assertion at the end.
### 4. Export the new language
Edit `packages/shared/src/i18n/index.ts` to include your language:
```ts
export type { TranslationKeys } from "./en.js";
export { en } from "./en.js";
export { de } from "./de.js";
```
### 5. Register in the frontend
The frontend needs to know about the new locale. Add it to the locale selector so users can switch languages. The exact location depends on how the locale switcher is implemented at the time of your contribution. Search for where `en` is referenced in the frontend and add your language alongside it.
### 6. Test it
```bash
pnpm typecheck # will catch missing or mistyped keys
pnpm dev # manually verify strings appear correctly
```
TypeScript is your safety net here. If your translation file is missing a key or has the wrong structure, `pnpm typecheck` will fail with a clear error.
### 7. Submit a PR
Push your branch and open a pull request. In the PR description, list which sections you translated and any strings you intentionally left in English (technical terms, proper nouns, etc.).
## Strings that don't need translation
Some strings are the same across languages: tool names that are English loanwords, technical terms, abbreviations. If a string is identical in your language, just leave it as the English value. No special configuration is needed.
## Adding new translation keys
If you are adding a new feature that needs new UI strings:
1. Add the new keys to `packages/shared/src/i18n/en.ts` first. This is the reference file.
2. Add translations to any other language files you can. If you can't translate them, leave the English value as a placeholder and note it in your PR.
3. Run `pnpm typecheck` to make sure all language files still satisfy the `TranslationKeys` type.
## File reference
| File | Purpose |
|------|---------|
| `packages/shared/src/i18n/en.ts` | English strings (reference locale) |
| `packages/shared/src/i18n/index.ts` | Exports all locales and the `TranslationKeys` type |
| `packages/shared/src/constants.ts` | Tool registry (names/descriptions also live here) |