Clean up.

This commit is contained in:
2026-06-13 12:24:41 -07:00
parent 9fe95f6d1e
commit 74a902ee62
11 changed files with 217 additions and 91 deletions

View File

@@ -24,10 +24,10 @@ How to build CLI tools following Unix philosophy.
## Project layout
Each tool is an independent project under `components/` with its own `pyproject.toml`:
Each tool is an independent project under `~/.castle/code/` with its own `pyproject.toml`:
```
components/my-tool/
~/.castle/code/my-tool/
├── src/my_tool/
│ ├── __init__.py
│ └── main.py # Entry point
@@ -37,13 +37,13 @@ components/my-tool/
└── CLAUDE.md
```
Examples: `components/pdf2md/`, `components/gpt/`, `components/protonmail/`
Examples: `code/pdf2md/`, `code/gpt/`, `code/protonmail/`
## Creating a new tool
```bash
castle create my-tool --stack python-cli --description "Does something"
cd components/my-tool && uv sync
cd ~/.castle/code/my-tool && uv sync
```
This scaffolds the project and registers it in `castle.yaml`.
@@ -317,7 +317,7 @@ uv run ruff format . # Format
programs:
my-tool:
description: Does something useful
source: components/my-tool
source: code/my-tool
stack: python-cli
behavior: tool
```
@@ -328,7 +328,7 @@ Tools with system dependencies declare them directly on the program:
programs:
pdf2md:
description: Convert PDF files to Markdown
source: components/pdf2md
source: code/pdf2md
stack: python-cli
behavior: tool
system_dependencies: [pandoc, poppler-utils]

View File

@@ -102,7 +102,7 @@ Castle passes config via env vars in castle.yaml:
programs:
my-service:
description: Does something useful
source: components/my-service
source: code/my-service
stack: python-fastapi
behavior: daemon
@@ -292,12 +292,15 @@ Mapping convention:
Castle services use filesystem storage with JSON metadata sidecars:
```
/data/castle/my-service/
$CASTLE_DATA_DIR/my-service/ # default /data/castle/my-service/
└── bucket/
├── item-name
└── item-name.meta.json
```
The service receives this path via the generated `<PREFIX>_DATA_DIR` env var —
it never hardcodes it. Use the `data_dir` setting from your config.
```python
# storage.py
import hashlib

View File

@@ -20,7 +20,7 @@ How to build, serve, and manage web frontends as castle components.
```bash
# Create the project
mkdir components/my-frontend && cd components/my-frontend
mkdir ~/.castle/code/my-frontend && cd ~/.castle/code/my-frontend
pnpm create vite . --template react-ts
# Core dependencies
@@ -116,7 +116,7 @@ handles serving directly from the build output.
programs:
my-frontend:
description: Web dashboard
source: components/my-frontend
source: code/my-frontend
build:
commands:
- ["pnpm", "build"]
@@ -124,7 +124,8 @@ programs:
- dist/
```
For production, Caddy serves the static `dist/` output directly — no
For production, `castle deploy` copies the build output to
`~/.castle/artifacts/content/<name>/` and Caddy serves it from there — no
Node process needed. See [Serving with Caddy](#serving-with-caddy) below.
For development with Vite's dev server, add a service entry:
@@ -148,12 +149,23 @@ See @docs/component-registry.md for the full registry reference.
## Serving with Caddy
For production, serve the static `dist/` output directly from Caddy rather than
running a Node process. The gateway Caddyfile can serve the files:
For production, the static build output is served by Caddy rather than a Node
process. You do **not** write this block by hand — `castle deploy` generates it.
The flow:
1. `castle deploy` runs the program's `build.commands`, then copies each
`build.outputs` directory from `~/.castle/code/<name>/` into
`~/.castle/artifacts/content/<name>/` (`core/src/castle_core/deploy.py`,
`_copy_app_static`).
2. The Caddyfile generator scans `~/.castle/artifacts/content/`; any directory
containing an `index.html` is served as a SPA at a path prefix matching its
name. `castle-app` is special-cased to serve at the root `/`.
The generated block looks like this (written to `~/.castle/artifacts/specs/Caddyfile`):
```caddyfile
handle_path /app/* {
root * /data/repos/castle/my-frontend/dist
handle_path /my-frontend/* {
root * /home/payne/.castle/artifacts/content/my-frontend
try_files {path} /index.html
file_server
}
@@ -161,7 +173,8 @@ handle_path /app/* {
The `try_files {path} /index.html` directive is essential for SPA routing —
it falls back to `index.html` for any path that doesn't match a static file,
letting React Router handle client-side routes.
letting React Router handle client-side routes. The serving prefix is derived
from the program name, not hand-configured.
## API integration