Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .taskfiles/backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ tasks:
dev:
desc: "Start backend dev server"
ignore_error: true
vars:
PORT: '{{.PORT | default "8080"}}'
AIENGINE_URL: '{{.AIENGINE_URL | default ""}}'
env:
SERVER_PORT: '{{.PORT}}'
cmds:
- cmd: cmd /c gradlew.bat :stirling-pdf:bootRun
- cmd: '{{if .AIENGINE_URL}}set "AIENGINE_URL={{.AIENGINE_URL}}" && set "AIENGINE_ENABLED=true" && {{end}}cmd /c gradlew.bat :stirling-pdf:bootRun'
platforms: [windows]
- cmd: ./gradlew :stirling-pdf:bootRun
- cmd: '{{if .AIENGINE_URL}}AIENGINE_URL={{.AIENGINE_URL}} AIENGINE_ENABLED=true {{end}}./gradlew :stirling-pdf:bootRun'
platforms: [linux, darwin]

build:
Expand Down
6 changes: 5 additions & 1 deletion .taskfiles/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ vars:
tasks:
prepare:
desc: "Prepare desktop build dependencies"
deps: [jlink, ":frontend:prepare:desktop", provisioner]
deps:
- jlink
- task: ":frontend:prepare"
vars: { MODE: desktop }
- provisioner

provisioner:
desc: "Build installer provisioner"
Expand Down
8 changes: 6 additions & 2 deletions .taskfiles/engine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,24 @@ tasks:
deps: [prepare]
ignore_error: true
dir: src
vars:
PORT: '{{.PORT | default "5001"}}'
env:
PYTHONUNBUFFERED: "1"
cmds:
- uv run uvicorn stirling.api.app:app --host 0.0.0.0 --port 5001
- uv run uvicorn stirling.api.app:app --host 0.0.0.0 --port {{.PORT}}

dev:
desc: "Start engine dev server with hot reload"
deps: [prepare]
ignore_error: true
dir: src
vars:
PORT: '{{.PORT | default "5001"}}'
env:
PYTHONUNBUFFERED: "1"
cmds:
- uv run uvicorn stirling.api.app:app --host 0.0.0.0 --port 5001 --reload
- uv run uvicorn stirling.api.app:app --host 0.0.0.0 --port {{.PORT}} --reload

lint:
desc: "Run linting"
Expand Down
116 changes: 57 additions & 59 deletions .taskfiles/frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,107 +15,97 @@ tasks:
CI: '{{ .CI | default "false" }}'

prepare:env:
desc: "Generate .env from example if missing"
run: once
deps: [install]
cmds:
- npx tsx scripts/setup-env.ts
sources:
- scripts/setup-env.ts
generates:
- .env.local

prepare:env:saas:
desc: "Generate .env and .env.saas from examples if missing"
run: once
deps: [install]
cmds:
- npx tsx scripts/setup-env.ts --saas
sources:
- scripts/setup-env.ts
generates:
- .env.local
- .env.saas.local

prepare:env:desktop:
desc: "Generate .env and .env.desktop from examples if missing"
run: once
internal: true
run: when_changed
deps: [install]
vars:
MODE: '{{.MODE | default ""}}'
cmds:
- npx tsx scripts/setup-env.ts --desktop
- npx tsx scripts/setup-env.ts{{if .MODE}} --{{.MODE}}{{end}}
sources:
- scripts/setup-env.ts
generates:
- .env.local
- .env.desktop.local
- .env{{if .MODE}}.{{.MODE}}{{end}}.local

prepare:icons:
desc: "Generate icon bundle from source references"
internal: true
run: once
deps: [install]
cmds:
- node scripts/generate-icons.js

prepare:
desc: "Set up dev environment"
run: once
deps: [prepare:env, prepare:icons]

prepare:saas:
desc: "Prepare for SaaS mode"
run: once
deps: [prepare:env:saas, prepare:icons]

prepare:desktop:
desc: "Prepare for desktop mode"
run: once
deps: [prepare:env:desktop, prepare:icons]
run: when_changed
vars:
MODE: '{{.MODE | default ""}}'
deps:
- task: prepare:env
vars: { MODE: '{{.MODE}}' }
- prepare:icons

# ============================================================
# Development
# ============================================================

dev:_run:
internal: true
ignore_error: true
vars:
MODE: '{{.MODE}}'
PORT: '{{.PORT | default "5173"}}'
BACKEND_URL: '{{.BACKEND_URL | default "http://localhost:8080"}}'
OPEN: '{{.OPEN | default ""}}'
env:
BACKEND_URL: '{{.BACKEND_URL}}'
cmds:
- npx vite --mode {{.MODE}} --port {{.PORT}}{{if .OPEN}} --open{{end}}

dev:
desc: "Start frontend dev server"
deps: [prepare]
ignore_error: true
cmds:
- npx vite
- task: dev:proprietary
vars: { PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

dev:core:
desc: "Start frontend dev server in core mode"
deps: [prepare]
ignore_error: true
cmds:
- npx vite --mode core
- task: dev:_run
vars: { MODE: core, PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

dev:proprietary:
desc: "Start frontend dev server in proprietary mode"
deps: [prepare]
ignore_error: true
cmds:
- npx vite --mode proprietary
- task: dev:_run
vars: { MODE: proprietary, PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

dev:saas:
desc: "Start frontend dev server in SaaS mode"
deps: [prepare:saas]
ignore_error: true
deps:
- task: prepare
vars: { MODE: saas }
cmds:
- npx vite --mode saas
- task: dev:_run
vars: { MODE: saas, PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

dev:desktop:
desc: "Start frontend dev server in desktop mode"
deps: [prepare:desktop]
ignore_error: true
deps:
- task: prepare
vars: { MODE: desktop }
cmds:
- npx vite --mode desktop
- task: dev:_run
vars: { MODE: desktop, PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

dev:prototypes:
desc: "Start frontend dev server in prototypes mode"
deps: [prepare]
ignore_error: true
cmds:
- npx vite --mode prototypes
- task: dev:_run
vars: { MODE: prototypes, PORT: '{{.PORT}}', BACKEND_URL: '{{.BACKEND_URL}}', OPEN: '{{.OPEN}}' }

# ============================================================
# Build
Expand All @@ -141,13 +131,17 @@ tasks:

build:saas:
desc: "Build for SaaS mode"
deps: [prepare:saas]
deps:
- task: prepare
vars: { MODE: saas }
cmds:
- npx vite build --mode saas

build:desktop:
desc: "Build for desktop mode"
deps: [prepare:desktop]
deps:
- task: prepare
vars: { MODE: desktop }
cmds:
- npx vite build --mode desktop

Expand Down Expand Up @@ -211,13 +205,17 @@ tasks:

typecheck:saas:
desc: "Typecheck SaaS build variant"
deps: [prepare:saas]
deps:
- task: prepare
vars: { MODE: saas }
cmds:
- npx tsc --noEmit --project src/saas/tsconfig.json

typecheck:desktop:
desc: "Typecheck desktop build variant"
deps: [prepare:desktop]
deps:
- task: prepare
vars: { MODE: desktop }
cmds:
- npx tsc --noEmit --project src/desktop/tsconfig.json

Expand Down
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This file provides guidance to AI Agents when working with code in this reposito

This project uses [Task](https://taskfile.dev/) as a unified command runner. All build, dev, test, lint, and docker commands can be run from the repo root via `task <command>`. Run `task --list` to see all available commands.

Task `desc:` fields should describe **what** the task does, not **how** it does it. Keep them generic and stable: don't reference implementation details like aliases, internal helpers, mode flags, or which other task delegates to which. The description is for users picking a command from `task --list`, not a changelog of refactors.

### Quick Reference
- `task install` — install all dependencies
- `task dev` — start backend + frontend concurrently
Expand Down Expand Up @@ -143,7 +145,7 @@ The project structure is defined in `engine/pyproject.toml`. Any new dependencie
- These files are committed to Git and must not contain private keys
- Local overrides (API keys, machine-specific settings) go in uncommitted sibling `.env.local` / `.env.saas.local` / `.env.desktop.local` files — Vite automatically layers them on top
- Never use `|| 'hardcoded-fallback'` inline — put defaults in the committed env files
- `task frontend:prepare` / `prepare:saas` / `prepare:desktop` create empty `.local` override files on first run
- `task frontend:prepare` creates empty `.local` override files on first run; pass `MODE=saas` or `MODE=desktop` to also create the mode-specific `.local` file
- Prepare runs automatically as a dependency of all `dev*`, `build*`, and `desktop*` tasks
- See `frontend/README.md#environment-variables` for full documentation

Expand Down
44 changes: 37 additions & 7 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ version: '3'

output: prefixed

vars:
FIND_FREE_PORT_PS: powershell -NoProfile -File scripts\find-free-port.ps1 -Preferred
FIND_FREE_PORT_SH: bash scripts/find-free-port.sh

includes:
backend:
taskfile: .taskfiles/backend.yml
Expand Down Expand Up @@ -35,17 +39,43 @@ tasks:
# ============================================================

dev:
desc: "Start backend + frontend concurrently"
desc: "Start backend + frontend concurrently on free ports"
vars:
PORTS:
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8080,5173{{else}}{{.FIND_FREE_PORT_SH}} 8080 5173{{end}}'
BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 1}}'
deps:
- backend:dev
- frontend:dev
- task: backend:dev
vars:
PORT: '{{.BACKEND_PORT}}'
- task: frontend:dev
vars:
PORT: '{{.FRONTEND_PORT}}'
BACKEND_URL: 'http://localhost:{{.BACKEND_PORT}}'
OPEN: "true"

dev:all:
desc: "Start backend + frontend + engine concurrently"
desc: "Start backend + frontend + engine concurrently on free ports"
vars:
PORTS:
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8080,5173,5001{{else}}{{.FIND_FREE_PORT_SH}} 8080 5173 5001{{end}}'
BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 1}}'
ENGINE_PORT: '{{index (splitList "\n" .PORTS) 2}}'
deps:
- backend:dev
- frontend:dev:prototypes
- engine:dev
- task: engine:dev
vars:
PORT: '{{.ENGINE_PORT}}'
- task: backend:dev
vars:
PORT: '{{.BACKEND_PORT}}'
AIENGINE_URL: 'http://localhost:{{.ENGINE_PORT}}'
- task: frontend:dev:prototypes
vars:
PORT: '{{.FRONTEND_PORT}}'
BACKEND_URL: 'http://localhost:{{.BACKEND_PORT}}'
OPEN: "true"

# ============================================================
# Build
Expand Down
Loading
Loading