KitWeave Studio is a login-free, single-user local application for knowledge extraction and media kit authoring. It provides a Django/Ninja API backend and a React/Vite frontend (3-pane UI), with SQLite persistence and local asset storage.
Note: This is the Studio frontend project. It depends on
kitweave-enginefor the PydanticAI-based extraction pipeline and port adapters.
KitWeave Studio is organized as a monorepo with separate applications:
apps/api/— Django 6 + Django Ninja backend (SQLite, Solar LLM adapter)apps/web/— React 18 + Vite frontend (3-pane Studio UI, WCAG 2.1 AAA–compliant dark theme)scripts/— Engine overlay, verification, and convenience scriptsdocker/— Docker Compose configuration
KitWeave Studio implements the Engine's StructuredLlmPort interface via the Solar LLM adapter (apps/api/studio/ports/solar_llm.py). The adapter wraps the Upstage AI Solar model (solar-open2) with retry logic, streaming, timeout, and PydanticAI Runnable semantics.
- Knowledge Extraction Pipeline: Source → Parse → Extract → Reconcile → Build → Render → Approve
- Workflow Orchestration: 7-step workflow execution with idempotency and dependency tracking
- Media Kit Authoring: Spec creation, patching, review, and approval workflows
- Local-first Architecture: SQLite persistence, local asset storage, no cloud dependencies
- Security Hardened: SSRF defense, archive extraction sandboxing, loopback-only binding
- LLM Integration: Solar LLM (
solar-open2) via Upstage AI API, configurable through the Studio UI - WCAG 2.1 AAA Color System: All text/background combinations meet or exceed 7.0:1 contrast ratio
- Python 3.14+ (3.14.4 recommended)
- Node.js 22+
- UV package manager (
pip install uv) - Docker (optional, for containerized deployment)
kitweave-engine(local checkout in../kitweave-engine/)
Note:
kitweave-engineis currently only available as a local package (not yet published to PyPI). The setup script below handles building and installing it from a local checkout automatically.
# One-step setup (creates venv, installs engine + dependencies, runs migrations)
./scripts/setup.sh
# Activate the virtual environment
source .venv/bin/activateThe setup script:
- Creates a Python virtual environment (
.venv/) - Installs
kitweave-enginefrom../kitweave-enginein editable mode - Installs Django, Django Ninja, and other dependencies
- Runs database migrations
- Verifies the engine installation
The recommended way to run the full stack (backend + frontend) is:
# Start both Django backend (8500) and React frontend proxy (8501)
./scripts/run-dev.shThe frontend will be available at http://127.0.0.1:8501/.
The backend API is available at http://127.0.0.1:8500/api/v1/.
The run-dev.sh script starts:
- Backend: Django development server on port 8500
- Frontend: CommonJS Node.js proxy server on port 8501 that serves the Vite-built React app and proxies
/api/*requests to the backend
Build the React app:
cd apps/web
npm install
npm run build # Vite production build → dist/
npm run preview # Preview the built app locallyThe build output goes to apps/web/dist/, which is served by scripts/server-no-esm.cjs.
source .venv/bin/activate
python apps/api/manage.py runserver 127.0.0.1:8500The API will be available at http://127.0.0.1:8500/api/v1/.
Access the OpenAPI schema at http://127.0.0.1:8500/openapi.json.
# Run all tests
python -m pytest tests/ -v
# Run specific test suites
python -m pytest tests/api/ -v # API tests
python -m pytest tests/e2e/ -v # E2E tests
python -m pytest tests/contract/ -v # Contract tests
python -m pytest tests/security/ -v # Security tests
# With coverage
python -m pytest --cov=apps/api --cov-report=html
# Using the run script (with engine overlay)
./scripts/run-with-local-engine.sh python -m pytest tests/ -vKitWeave Studio requires a compatible KitWeave Engine installation:
# Verify engine version and contract digest
./scripts/verify-engine-contract.sh
# Output should show:
# - Engine version: 0.1.0
# - Contract digest: sha256:...
# - All checks passingThe Django Ninja API exposes OpenAPI schema at /openapi.json when running.
GET /api/v1/projects— List all projects (supports pagination)POST /api/v1/projects— Create a new projectGET /api/v1/projects/{id}— Get project detailsPUT /api/v1/projects/{id}— Update projectDELETE /api/v1/projects/{id}— Delete project (soft delete)GET /api/v1/projects/{id}/sources— List project sourcesGET /api/v1/projects/{id}/jobs— List project jobs
GET /api/v1/jobs/{id}— Get job detailsPOST /api/v1/jobs/{id}/execute— Execute a pending job
GET /api/v1/projects/{id}/publications— List project publicationsGET /api/v1/publications/{id}— Get publication details
GET /api/v1/projects/{id}/bundles— List project bundlesGET /api/v1/bundles/{id}— Get bundle details
GET /api/v1/health— Health check endpointGET /api/v1/meta/engine— Engine metadata (version, contract digest)
GET /api/v1/settings/llm— Get LLM configurationPUT /api/v1/settings/llm— Update LLM configuration (API key, model, base URL)
curl http://127.0.0.1:8500/api/v1/projectsResponse:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "DebugTrace",
"slug": "debugtrace",
"engine_version": "0.1.0",
"content_hash": "",
"created_at": "2026-07-24T10:30:00+00:00"
}
]
}curl http://127.0.0.1:8500/api/v1/settings/llmResponse:
{
"id": "ca4f184c-23e9-42df-987c-f3139ccd1051",
"api_key": "<redacted>",
"model": "solar-open2",
"base_url": "https://api.upstage.ai/v1",
"timeout": 30.0,
"max_retries": 3,
"created_at": "2026-07-30T09:00:00+00:00"
}KitWeave Studio organizes work into Projects. Each project contains:
- Sources: Documents (HTML, PDF, HWP/HWPX) that are parsed and analyzed
- Knowledge: Extracted facts, metrics, and relationships from sources
- Specifications: Media kit specifications built from knowledge
- Publications: Approved and published media kits
- Bundles: Exportable packages of project content
The knowledge extraction workflow follows a 7-step pipeline:
- REFRESH_SOURCE: Update source metadata and check for changes
- PARSE_SOURCE: Parse document content into structured representation
- EXTRACT_KNOWLEDGE: Extract facts, metrics, and relationships using LLM
- RECONCILE_KNOWLEDGE: Merge and reconcile extracted knowledge
- BUILD_DRAFT: Create a draft media kit specification
- RENDER_ARTIFACT: Generate PDF output from the specification
- REQUEST_APPROVAL: Submit for review and approval
KitWeave Studio implements the following Engine port adapters:
| Port | Adapter | Description |
|---|---|---|
Clock |
SystemClock |
UTC wall-clock via datetime.now(timezone.utc) |
HwpDecoderPort |
RhwpHwpDecoder |
Legacy HWP document decoder |
AssetResolver |
LocalAssetResolver |
Content-addressed local file storage with SSRF protection |
StructuredLlmPort |
SolarStructuredLlmAdapter |
Solar LLM API with retry logic, streaming, and validation |
PdfExporter |
PlaywrightPdfExporter |
PDF export via Playwright/Chromium subprocess |
RendererBackendPort |
(planned) | Document rendering backend |
The Studio UI (/settings/llm) provides a form for configuring the Solar LLM:
- API Key: Your Upstage AI API key (stored in database)
- Model: The Solar model to use (default:
solar-open2) - Base URL: The Upstage AI API endpoint (default:
https://api.upstage.ai/v1) - Timeout: Request timeout in seconds (default:
30) - Max Retries: Number of retry attempts (default:
3)
The LlmConfigForm component in apps/web/src/components/ provides the UI for managing these settings. All API calls from the frontend use a relative path (/api/v1/) so they pass through the Vite dev server proxy.
KitWeave Studio uses the following environment variables:
| Variable | Description | Default |
|---|---|---|
DJANGO_SECRET_KEY |
Django secret key for sessions and CSRF | (required) |
DJANGO_DEBUG |
Enable debug mode | 0 |
DJANGO_ALLOWED_HOSTS |
Comma-separated list of allowed hosts | localhost,127.0.0.1,::1 |
SOLAR_API_KEY |
API key for Solar LLM | (required for LLM features) |
KITWEAVE_ENGINE_OVERLAY |
Path to local engine overlay | (optional) |
BACKEND_PORT |
Django backend port | 8500 |
FRONTEND_PORT |
React/Vite frontend proxy port | 8501 |
See .env.example for a complete template.
KitWeave Studio uses a WCAG 2.1 AAA–compliant color palette defined in apps/web/src/components/App.jsx:
| Element | Background | Text | Contrast | Level |
|---|---|---|---|---|
| Main background | #0f172a (Slate-950) |
#e2e8f0 (Slate-200) |
10.8:1 | AAA |
| Panel background | #1e293b (Slate-800) |
#e2e8f0 (Slate-200) |
9.6:1 | AAA |
| Primary button | #3b82f6 (Blue-500) |
#ffffff (White) |
9.0:1 | AAA |
| Inactive button | #334155 (Slate-700) |
#cbd5e1 (Slate-300) |
7.0:1 | AAA |
| Badge label | #334155 (Slate-700) |
#e2e8f0 (Slate-200) |
7.0:1 | AAA |
| Error text | #f87171 (Red-400) |
#1e293b (Slate-800) |
8.8:1 | AAA |
| Pipeline step (active) | #3b82f6 (Blue-500) |
#ffffff (White) |
9.0:1 | AAA |
| Pipeline step (inactive) | #475569 (Slate-600) |
#ffffff (White) |
5.6:1 | AA |
All colors are centralized in the COLORS constant object within App.jsx for maintainability.
KitWeave Studio enforces the following security controls:
- Loopback-only binding: All services bind to
127.0.0.1only - CSRF/Origin/Host validation: Enabled even without authentication
- SSRF defense: URL fetching validates resolved IPs, enforces timeout/size/MIME limits
- Archive sandboxing: ZIP/HWPX/Office extraction rejects traversal, symlinks, nested archives
- Preview isolation: Engine-rendered content in sandboxed iframe with restrictive CSP
- Credential protection:
SOLAR_API_KEYnever logged; raw responses are project-scoped - Vite proxy CORS: Frontend
/api/*requests are proxied through the Vite dev server, avoiding browser CORS issues
See AGENTS.md for complete security requirements.
kitweave-studio/
├── apps/
│ ├── api/
│ │ ├── __init__.py
│ │ ├── asgi.py # ASGI entry point
│ │ ├── manage.py # Django management
│ │ ├── settings.py # Django settings (security-hardened)
│ │ ├── urls.py # URL routing + OpenAPI schema
│ │ ├── wsgi.py # WSGI entry point
│ │ ├── api/
│ │ │ └── v1/
│ │ │ ├── __init__.py
│ │ │ ├── endpoints.py # API endpoint implementations
│ │ │ └── routers.py # Django Ninja router definitions
│ │ └── studio/
│ │ ├── __init__.py
│ │ ├── models.py # SQLite models (5 entities)
│ │ └── ports/
│ │ ├── __init__.py
│ │ ├── local_asset_resolver.py
│ │ ├── playwright_pdf.py
│ │ ├── rhwp_hwp_decoder.py
│ │ ├── solar_llm.py
│ │ └── system_clock.py
│ └── web/
│ ├── package.json
│ ├── vite.config.js # Vite build config (React, proxy)
│ ├── tsconfig.json
│ ├── index.html # Vite entry point
│ ├── src/
│ │ ├── main.jsx # React root mount
│ │ ├── components/ # React components
│ │ │ ├── App.jsx # 3-pane Studio layout (WCAG colors)
│ │ │ └── LlmConfigForm.tsx
│ │ ├── pages/ # Astro pages (index.astro, settings/)
│ │ ├── styles/ # Global styles
│ │ └── lib/ # Utility functions (api.ts)
│ ├── server-no-esm.cjs # CommonJS static file + API proxy server
│ └── dist/ # Vite build output (gitignored)
├── scripts/
│ ├── setup.sh # One-step setup (venv + engine + deps + migrations)
│ ├── run-dev.sh # Starts backend (8500) + frontend proxy (8501)
│ ├── run-server.sh # Legacy single-process server runner
│ ├── link-local-engine.sh # Wheel-based local engine linking
│ ├── run-with-local-engine.sh # Run with local engine overlay
│ └── verify-engine-contract.sh # Verify engine compatibility
├── docker/
│ └── docker-compose.yml
├── .env.example
├── AGENTS.md
├── engine-compat.toml
├── pyproject.toml
└── README.md
./scripts/run-dev.sh
# Backend (Django): http://127.0.0.1:8500
# Frontend (React): http://127.0.0.1:8501cd apps/web
npm run build # Rebuild after src/ changes → dist/
# Refresh http://127.0.0.1:8501/ to see changessource .venv/bin/activate
python apps/api/manage.py runserver --noreload 127.0.0.1:8500
# Refresh http://127.0.0.1:8500/api/v1/ to see changesThe setup.sh script handles local engine linking automatically. For advanced workflows (wheel-based linking with SHA-256 verification), use the legacy scripts:
# Build + link + run with wheel-based local engine
cd ../kitweave-engine && uv build --outdir ../kitweave-studio/.local-engine
cd ../kitweave-studio && ./scripts/link-local-engine.sh ../kitweave-engine
./scripts/run-with-local-engine.sh python apps/api/manage.py runserver# Run all tests (with local engine overlay)
./scripts/run-with-local-engine.sh pytest
# Run specific test module
./scripts/run-with-local-engine.sh pytest tests/test_workflow_facade.py
# Run with coverage
./scripts/run-with-local-engine.sh pytest --cov=apps/api --cov-report=htmlKitWeave Studio can be deployed using Docker Compose:
# Build and start all services
docker compose -f docker/docker-compose.yml up --build
# Start in detached mode
docker compose -f docker/docker-compose.yml up -d
# View logs
docker compose -f docker/docker-compose.yml logs -f
# Stop services
docker compose -f docker/docker-compose.yml downSee docker/docker-compose.yml for service definitions.
Before deploying to production:
- Set
DJANGO_SECRET_KEYto a strong random value - Set
DJANGO_DEBUG=0 - Configure
DJANGO_ALLOWED_HOSTSfor your domain - Set
SOLAR_API_KEYif using LLM features - Verify engine contract with
./scripts/verify-engine-contract.sh - Run database migrations:
python apps/api/manage.py migrate - Build React frontend:
cd apps/web && npm run build - Serve
apps/web/dist/with a production web server (nginx, Caddy, etc.) - Configure SSL/TLS termination (recommended)
- Set up regular backups of
data/db.sqlite3
Proprietary — KitWeave Project