| Service | Package | Port | Type |
|---|---|---|---|
| Frontend | @workspace/printfx | $PORT (21685) | Vite dev server |
| API Server | @workspace/api-server | $PORT (8080) | Express 5 |
| Mockup Sandbox | @workspace/mockup-sandbox | $PORT | Vite dev server |
| Service | Status | Notes |
|---|---|---|
| Redis | Not running | Queue is in-memory for V1 |
| ImageMagick | Not installed | Not used in V1 |
| PostgreSQL | Provisioned (lib/db) | Not used for jobs/uploads in V1 |
G'MIC 3.5.4 is installed and used for real image processing.
The service is implemented in artifacts/api-server/src/services/gmicService.ts:
- Detects alpha channel from PNG header byte offset 25 (color type 4 or 6)
- For
preserve/modifytransparency modes with RGBA input: uses+channels[0] 3to save alpha → process RGB[0]→ reattach alpha with-append[0,1] c - For
flattentransparency mode: strips alpha with-channels 0,2, converts to RGB before processing - All effect args use
[0]image selectors to target only the first image in the G'MIC stack
Timing per job:
- Validation: ~400ms
- G'MIC processing: 500ms–3s depending on image size and preset
- Total round-trip to
preview_ready: ~2–4 seconds
| Preset | G'MIC Commands | Output Channels |
|---|---|---|
| halftone_print | to_gray → normalize → blur → threshold | gray+alpha (x2) |
| distressed_grunge | noise → unsharp → normalize | RGBA (x4) |
| vintage_poster | normalize → quantize → normalize | RGB (x3, no alpha) |
| ink_bleed | blur → unsharp → normalize | RGBA (x4) |
| mono_stencil | to_gray → blur → normalize → threshold | gray+alpha (x2) |
- Uploads:
storage/tmp/uploads/— files saved as{uuid}.{ext} - Previews:
storage/tmp/previews/— files saved as{jobId}_preview.{ext} - Finals:
storage/tmp/finals/— files saved as{jobId}_final.{ext}
All paths are relative to workspace root. The API server resolves them using process.cwd() which points to artifacts/api-server/ directory.
Important: process.cwd() inside the API server resolves to artifacts/api-server/. Use ../../ prefix to reach workspace root files.
Jobs are stored in a Map<string, Job> in jobService.ts. This resets on every server restart. This is intentional for V1 — no database needed.
Express's built-in body parser does not handle multipart/form-data. The upload route manually parses multipart boundaries without multer dependency to keep the server lightweight.
The Replit proxy routes traffic by path:
/api/*→ API server (port 8080)/*→ Frontend (port 21685)
When migrating to real processing:
- Install G'MIC CLI in the container
- Replace
simulateProcessing()injobs.tswith real worker dispatch - Add Redis for job queue (
rqorbull) - Add cleanup cron job for temp files
- Consider R2 or S3 for final output storage