docs: correct technical notes (no /api/health, unused env vars, dead server.js, preview caveats)
This commit is contained in:
+35
-16
@@ -13,24 +13,33 @@ PNGer uses a multi-layered architecture designed for responsiveness and efficien
|
|||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
A[User Browser] --> B[Svelte Frontend]
|
A[User Browser] --> B[Svelte Frontend]
|
||||||
B --> C[Canvas API (Live Preview)]
|
B --> C["Canvas API (live preview, client-side)"]
|
||||||
B --> D[Express API (Backend)]
|
B --> D["Express API (POST /api/transform)"]
|
||||||
D --> E[Sharp Image Library]
|
D --> E[Sharp Image Library]
|
||||||
D --> F[Runtime Environment (Docker)]
|
E --> F[Response buffer streamed back as a download]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Nothing is persisted at any point: the upload lives in memory for the duration of the request and the result is streamed straight back.
|
||||||
|
|
||||||
### Backend (Express + Sharp)
|
### Backend (Express + Sharp)
|
||||||
|
|
||||||
The backend is built with Node.js and TypeScript, using Express for the API and Sharp for high-performance image processing.
|
The backend is built with Node.js and TypeScript, using Express for the API and Sharp for high-performance image processing.
|
||||||
|
|
||||||
**Key Endpoints:**
|
**Endpoints** — there is exactly one:
|
||||||
- `POST /api/transform` - Transform image (resize, crop, compress, convert)
|
- `POST /api/transform` — `multipart/form-data`, field `file`, plus optional `width`, `height`, `quality` (default 80), `format` (`png` | `webp` | `jpeg`, default `png`), `fit` (default `inside`) and `position` (default `center`). Returns the image bytes with `Content-Disposition: attachment`; `400` if no file, `500` if Sharp throws.
|
||||||
- `GET /api/health` - Health check
|
|
||||||
|
> **There is no `GET /api/health`.** Earlier revisions of this document claimed one. The router defines only `POST /transform`, so a GET to `/api/health` falls through to the SPA catch-all and returns `index.html` with a 200 — which means a monitor pointed at it will always report healthy. The container's own `HEALTHCHECK` correctly probes `/` instead.
|
||||||
|
|
||||||
**Key Dependencies:**
|
**Key Dependencies:**
|
||||||
- `sharp`: High-performance image processing (handles resizing, cropping, and format conversion).
|
- `sharp`: High-performance image processing (handles resizing, cropping, and format conversion). Resizes use `withoutEnlargement: true`, so output never exceeds the source dimensions.
|
||||||
- `multer`: Middleware for handling `multipart/form-data`, used for file uploads.
|
- `multer`: Middleware for handling `multipart/form-data`, used for file uploads. Configured with `memoryStorage()` and **no `limits`** — see the dead-code note below.
|
||||||
- `express`: Web framework for the API.
|
- `express`: Web framework for the API; also serves the built frontend from `dist/public` with an `app.get("*")` SPA fallback.
|
||||||
|
- `cors`: Applied wide open (`app.use(cors())`) so the Vite dev server on `:5173` can reach the API on `:3000`. In production both are the same origin.
|
||||||
|
|
||||||
|
### Dead code you will trip over
|
||||||
|
|
||||||
|
- **`backend/src/server.js`** is not the server. The entrypoint is `src/index.ts` → `dist/index.js`. `server.js` is an older standalone CommonJS implementation with `/api/health`, `/api/process` and `/api/metadata`, `helmet`, a PNG-only file filter and a real `MAX_FILE_SIZE` limit. `tsconfig.json` has no `allowJs`, so `tsc` never compiles it and it never reaches `dist/`; it also `require`s `helmet` and `dotenv`, which are not in `package.json`. It is the source of most of the features these docs used to describe. Either port the good parts (size limit, MIME filter, real health endpoint) into `routes/image.ts` or delete it.
|
||||||
|
- **`frontend/src/main.js` and `frontend/src/main.ts`** both exist. `index.html` loads `main.js`, and only `main.js` imports `./app.css` — "fixing" the script tag to point at `main.ts` would silently drop every style in the app.
|
||||||
|
|
||||||
### Frontend (Svelte + Vite)
|
### Frontend (Svelte + Vite)
|
||||||
|
|
||||||
@@ -63,6 +72,11 @@ Live preview is implemented using a client-side Canvas-based approach to provide
|
|||||||
4. The canvas content is displayed side-by-side with the original for comparison.
|
4. The canvas content is displayed side-by-side with the original for comparison.
|
||||||
5. File sizes are estimated from the Canvas data URL to provide immediate feedback on optimization savings.
|
5. File sizes are estimated from the Canvas data URL to provide immediate feedback on optimization savings.
|
||||||
|
|
||||||
|
**Fidelity caveats — the preview is an approximation, not the output:**
|
||||||
|
- The preview is encoded by the browser's Canvas encoder; the download is encoded by Sharp. Byte counts will differ.
|
||||||
|
- Canvas ignores the quality argument for PNG (it is always lossless), so dragging quality changes nothing in a PNG preview while it does change the real output.
|
||||||
|
- The preview's `calculateDimensions()` will happily scale an image **up**; the server sets `withoutEnlargement: true` and will not. The "Retina @2x" preset is exactly this case — the preview grows, the downloaded file does not.
|
||||||
|
|
||||||
### Docker Strategy & Fixes
|
### Docker Strategy & Fixes
|
||||||
|
|
||||||
PNGer uses a multi-stage Docker build to minimize image size and maximize security.
|
PNGer uses a multi-stage Docker build to minimize image size and maximize security.
|
||||||
@@ -99,13 +113,16 @@ npm run dev
|
|||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
**Backend (.env):**
|
Only `PORT` is actually read by the application. The full table, including which variables are declared-but-unused, is in [INSTALL.md](INSTALL.md#environment-variables).
|
||||||
- `PORT`: 3000 (internal)
|
|
||||||
- `MAX_FILE_SIZE`: 10485760 (10MB default)
|
|
||||||
- `CORS_ORIGIN`: http://localhost:5173
|
|
||||||
|
|
||||||
**Frontend (.env):**
|
**Backend:**
|
||||||
- `VITE_API_URL`: http://localhost:3000/api
|
- `PORT`: 3000 — read by `src/index.ts`.
|
||||||
|
- `MAX_FILE_SIZE`: declared in the `Dockerfile` and compose file, **not enforced** — the live `multer` config sets no `limits`.
|
||||||
|
- `CORS_ORIGIN`: in `backend/.env.example`, **not read** — `app.use(cors())` takes no options.
|
||||||
|
- `TEMP_DIR` / `/app/temp`: created by the `Dockerfile`, **never written to** — processing is entirely in memory.
|
||||||
|
|
||||||
|
**Frontend:**
|
||||||
|
- `VITE_API_URL`: **not read.** `lib/api.ts` picks its base URL from `import.meta.env.DEV` (`http://localhost:3000/api` in dev, `/api` in a build).
|
||||||
|
|
||||||
## Development Workflow & Standards
|
## Development Workflow & Standards
|
||||||
|
|
||||||
@@ -124,6 +141,8 @@ npm run dev
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
More symptoms, including container-level ones, in [INSTALL.md](INSTALL.md#troubleshooting).
|
||||||
|
|
||||||
- **Port in use**: `lsof -ti:3000 | xargs kill -9`
|
- **Port in use**: `lsof -ti:3000 | xargs kill -9`
|
||||||
- **Sharp issues**: `npm rebuild sharp`
|
- **Sharp issues**: `npm rebuild sharp`
|
||||||
- **Docker Cache**: `docker builder prune` if builds fail unexpectedly.
|
- **Docker Cache**: `docker builder prune` if builds fail unexpectedly.
|
||||||
@@ -131,4 +150,4 @@ npm run dev
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Last Updated**: March 12, 2026
|
**Last Updated**: July 2026 — reconciled against the code during the docs standardization pass. Deployment and configuration detail now lives in [INSTALL.md](INSTALL.md) and [UNRAID.md](UNRAID.md).
|
||||||
Reference in New Issue
Block a user