Skip to content

Commit 9e3da52

Browse files
committed
docs: update all documentation for Docker, security, update system
- GETTING-STARTED.md: Docker section, update instructions, project structure - DEPLOYMENT.md: Docker self-hosting, CI/CD pipeline, update system - ARCHITECTURE.md: withSecurity pattern, Docker infrastructure, perf optimizations - API-ROUTES.md: withSecurity wrapper, /api/version-check endpoint - CONTRIBUTING.md: Docker scripts, security requirement for new routes - STATE-MANAGEMENT.md: useVersionCheck hook - Fix: repo name 1337vibe -> Devonz in docker-compose + version-check - Fix: MCPSettings type in mcp.spec.ts
1 parent fa67291 commit 9e3da52

9 files changed

Lines changed: 199 additions & 8 deletions

File tree

app/lib/stores/mcp.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it, vi, beforeEach } from 'vitest';
2-
import { mcpStore, updateMCPSettings } from './mcp';
2+
import { mcpStore, updateMCPSettings, type MCPSettings } from './mcp';
33

44
// Mock fetch globally
55
const mockFetch = vi.fn();
@@ -57,11 +57,11 @@ describe('mcpStore', () => {
5757
});
5858

5959
it('should update settings', () => {
60-
const newSettings = {
60+
const newSettings: MCPSettings = {
6161
maxLLMSteps: 10,
6262
mcpConfig: {
6363
mcpServers: {
64-
testServer: { command: 'test', args: [], env: {} },
64+
testServer: { type: 'stdio', command: 'test', args: [], env: {} },
6565
},
6666
},
6767
};

app/routes/api.version-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { withSecurity } from '~/lib/security';
99
*/
1010
async function versionCheckLoader(_args: LoaderFunctionArgs) {
1111
const owner = 'zebbern';
12-
const repo = '1337vibe';
12+
const repo = 'Devonz';
1313
const branch = 'main';
1414

1515
// Get local commit hash (set at build time by pre-start.cjs)

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ services:
1313
# ── Production ────────────────────────────────────────────
1414
# Pulls from GHCR by default. Use --build to build locally.
1515
devonz:
16-
image: ghcr.io/zebbern/1337vibe:latest
16+
image: ghcr.io/zebbern/devonz:latest
1717
build:
1818
context: .
1919
dockerfile: Dockerfile

docs/API-ROUTES.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Devonz uses Remix file-based routing. All API endpoints are in `app/routes/api.*
1111
- `action()` — Handles POST/PUT/DELETE requests
1212
- `loader()` — Handles GET requests
1313

14+
All route handlers are wrapped with `withSecurity()` from `app/lib/security.ts`. This middleware enforces CORS origin validation, SameSite=Strict cookie policy, and input sanitization.
15+
1416
---
1517

1618
## Chat & AI
@@ -133,6 +135,7 @@ Validated with Zod. Returns a data stream with:
133135
| `/api/system/git-info` | GET | Git installation and version info |
134136
| `/api/update` | GET | Check for application updates |
135137
| `/api/bug-report` | POST | Submit bug reports |
138+
| `/api/version-check` | GET | Compares local commit hash against latest GitHub commit to detect available updates |
136139

137140
---
138141

@@ -166,14 +169,18 @@ const providerSettings = JSON.parse(cookies['providers'] || '{}');
166169

167170
There is no server-side session management — all auth state lives in browser cookies.
168171

172+
Additionally, all routes are protected by the `withSecurity()` wrapper which validates CORS origins, enforces `SameSite=Strict` on cookies, and applies a domain allowlist on the git proxy route (`/api/git-proxy/*`).
173+
169174
---
170175

171176
## Error Handling Pattern
172177

173178
API routes follow this pattern:
174179

175180
```typescript
176-
export async function action({ request }: ActionFunctionArgs) {
181+
import { withSecurity } from '~/lib/security';
182+
183+
async function myAction({ request }: ActionFunctionArgs) {
177184
// 1. Parse request body
178185
const rawBody = await request.json();
179186

@@ -193,4 +200,9 @@ export async function action({ request }: ActionFunctionArgs) {
193200
return new Response(JSON.stringify({ error: error.message }), { status: 500 });
194201
}
195202
}
203+
204+
export const action = withSecurity(myAction, {
205+
allowedMethods: ['POST'],
206+
rateLimit: false,
207+
});
196208
```

docs/ARCHITECTURE.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ Handles LLM response parsing and action execution:
100100

101101
### 7. Server Layer (`app/routes/api.*`)
102102

103-
~35 Remix API routes. See [API Routes](API-ROUTES.md).
103+
~36 Remix API routes. See [API Routes](API-ROUTES.md).
104104

105-
**Key pattern**: Routes use Remix conventions — `action()` for POST/PUT/DELETE, `loader()` for GET. Server-only code lives in `app/lib/.server/`.
105+
**Key pattern**: Routes use Remix conventions — `action()` for POST/PUT/DELETE, `loader()` for GET. Server-only code lives in `app/lib/.server/`. All route handlers are wrapped with `withSecurity()` from `app/lib/security.ts`, which enforces CORS origin validation, SameSite cookie attributes, and request sanitization.
106106

107107
---
108108

@@ -196,6 +196,12 @@ User enables Agent Mode + sends task
196196

197197
6. **CSS custom properties for theming**: All theme colors flow through `--bolt-elements-*` variables, enabling runtime theme switching without rebuilds.
198198

199+
7. **Security by default** — Every API route is wrapped with `withSecurity()`, enforcing CORS, SameSite cookies, and a URL allowlist on the git proxy.
200+
201+
8. **Docker-first deployment** — Multi-stage Dockerfile + docker-compose.yml with GHCR CI/CD and optional Watchtower auto-update enables one-command self-hosting.
202+
203+
9. **Startup performance** — Vite `optimizeDeps` pre-bundles critical dependencies and unconfigured LLM providers are skipped during initialization.
204+
199205
---
200206

201207
## File Naming Conventions

docs/CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ describe('MyComponent', () => {
138138
});
139139
```
140140

141+
The project currently has 282 tests across 21 test files.
142+
141143
### Test File Location
142144

143145
Colocate test files next to source files:
@@ -160,6 +162,8 @@ api.chat.ts → POST /api/chat
160162
api.models.$provider.ts → GET /api/models/:provider
161163
```
162164

165+
Every route handler must be wrapped with `withSecurity()` from `~/lib/security`. This is mandatory for all new routes.
166+
163167
### Request Validation
164168

165169
Use Zod for request body validation:
@@ -219,6 +223,7 @@ See [LLM-PROVIDERS.md](LLM-PROVIDERS.md) — step-by-step guide.
219223
3. Validate input with Zod
220224
4. Read credentials from cookies
221225
5. Return `json()` responses with proper status codes
226+
6. Wrap with `withSecurity()` — import from `~/lib/security` and wrap your handler function
222227

223228
---
224229

@@ -266,3 +271,10 @@ Use conventional commits:
266271
| `test` | `pnpm test` | Run tests (Vitest) |
267272
| `test:watch` | `pnpm test:watch` | Watch mode tests |
268273
| `clean` | `pnpm clean` | Clean build artifacts |
274+
| `update` | `pnpm run update` | Pull latest and reinstall (git users) |
275+
| `docker:build` | `pnpm docker:build` | Build Docker image |
276+
| `docker:run` | `pnpm docker:run` | Run Docker container |
277+
| `docker:up` | `pnpm docker:up` | Start via Docker Compose |
278+
| `docker:down` | `pnpm docker:down` | Stop Docker Compose |
279+
| `docker:dev` | `pnpm docker:dev` | Docker dev mode |
280+
| `docker:update` | `pnpm docker:update` | Update Docker deployment |

docs/DEPLOYMENT.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,101 @@ Devonz supports deploying generated projects to four platforms directly from the
1010

1111
---
1212

13+
## Docker Self-Hosting
14+
15+
### Quick Start
16+
17+
```bash
18+
# 1. Clone the repo
19+
git clone https://github.com/zebbern/Devonz.git
20+
cd Devonz/bolt.diy
21+
22+
# 2. Copy environment template
23+
cp .env.example .env.local
24+
# Edit .env.local with your API keys
25+
26+
# 3. Run with Docker Compose (pulls from GHCR)
27+
docker compose up -d
28+
```
29+
30+
### Building Locally
31+
32+
```bash
33+
pnpm docker:build # Build image locally
34+
pnpm docker:run # Run standalone container
35+
docker compose up -d --build # Build + run via Compose
36+
```
37+
38+
### Docker Image
39+
40+
The project publishes Docker images to GitHub Container Registry on every push to `main`:
41+
42+
- **Image**: `ghcr.io/zebbern/devonz:latest`
43+
- **Base**: `node:20-slim` with `git` and `curl`
44+
- **Size**: ~1.5 GB
45+
- **User**: Non-root (`appuser:1001`)
46+
47+
### Docker Compose Profiles
48+
49+
| Profile | Command | Description |
50+
| --- | --- | --- |
51+
| Default | `docker compose up -d` | Production mode |
52+
| Dev | `docker compose --profile dev up devonz-dev` | Dev mode with hot reload |
53+
| Auto-Update | `docker compose --profile auto-update up -d` | Adds Watchtower for automatic updates |
54+
55+
### Environment Variables
56+
57+
Set `RUNNING_IN_DOCKER=true` in your Docker environment (automatically set in docker-compose.yml). This adjusts Ollama and LMStudio base URLs to use `host.docker.internal` instead of `localhost`.
58+
59+
See `.env.example` for the complete list of 55+ environment variables.
60+
61+
---
62+
63+
## CI/CD Pipeline
64+
65+
### GitHub Actions
66+
67+
The workflow at `.github/workflows/docker-publish.yml` automatically builds and pushes Docker images to GHCR.
68+
69+
**Triggers:**
70+
- Push to `main` branch → tags image as `latest` and `sha-<hash>`
71+
- Push version tag (e.g., `v1.0.0`) → tags image as `1.0.0` and `1.0`
72+
73+
**Features:**
74+
- Docker Buildx with GitHub Actions cache for fast rebuilds
75+
- Multi-stage build (base → deps → build → prod-deps → runtime)
76+
- Automatic authentication via `GITHUB_TOKEN`
77+
78+
---
79+
80+
## Update System
81+
82+
### Version Check
83+
84+
The `/api/version-check` endpoint compares the local git commit hash against the latest commit on `main` via the GitHub API. The `UpdateBanner` component in the UI uses this to show a non-intrusive notification when updates are available.
85+
86+
### Updating
87+
88+
**Git Clone users:**
89+
```bash
90+
pnpm run update # Pulls latest, installs, rebuilds
91+
pnpm run update -- --skip-build # Skip rebuild
92+
```
93+
94+
**Docker users:**
95+
```bash
96+
pnpm docker:update # docker compose pull && docker compose up -d
97+
```
98+
99+
**Docker auto-update (Watchtower):**
100+
```bash
101+
docker compose --profile auto-update up -d
102+
```
103+
104+
Watchtower polls GHCR every 5 minutes and automatically restarts the container when a new image is available.
105+
106+
---
107+
13108
## Supported Platforms
14109

15110
| Platform | Push Code | Deploy | Custom Domains | Status Check |

docs/GETTING-STARTED.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ OPENAI_LIKE_API_MODELS=model-name-1,model-name-2
113113

114114
> **Note**: API keys can also be set through the UI settings panel at runtime. They are stored in browser cookies, not on the server.
115115
116+
> See `.env.example` for the full list of 55+ documented environment variables. Copy it as a starting point: `cp .env.example .env.local`
117+
116118
---
117119

118120
## Running the App
@@ -154,13 +156,76 @@ Runs build and start in sequence.
154156
| `pnpm lint:fix` | Auto-fix lint issues + format with Prettier |
155157
| `pnpm typecheck` | Run TypeScript type checking (`tsc --noEmit`) |
156158
| `pnpm clean` | Remove build artifacts |
159+
| `pnpm run update` | Pull latest code, install deps, rebuild (git clone users) |
160+
| `pnpm docker:build` | Build production Docker image |
161+
| `pnpm docker:run` | Run Docker container standalone |
162+
| `pnpm docker:up` | Start via Docker Compose |
163+
| `pnpm docker:down` | Stop Docker Compose services |
164+
| `pnpm docker:dev` | Dev mode with hot reload in Docker |
165+
| `pnpm docker:update` | Pull latest GHCR image and restart |
166+
167+
---
168+
169+
## Running with Docker
170+
171+
### Quick Start (Pull from GHCR)
172+
173+
```bash
174+
# Copy env template
175+
cp .env.example .env.local
176+
# Edit .env.local with your API keys
177+
178+
# Pull and run
179+
docker compose up -d
180+
```
181+
182+
### Build Locally
183+
184+
```bash
185+
pnpm docker:build # Build image
186+
pnpm docker:run # Run standalone
187+
# or
188+
docker compose up -d --build # Build + run via Compose
189+
```
190+
191+
### Auto-Update (Watchtower)
192+
193+
```bash
194+
# Automatically pulls new images every 5 minutes
195+
docker compose --profile auto-update up -d
196+
```
197+
198+
The `RUNNING_IN_DOCKER=true` environment variable is set automatically in the Docker Compose configuration, which adjusts Ollama and LMStudio base URLs to use `host.docker.internal`.
199+
200+
---
201+
202+
## Updating Devonz
203+
204+
### Git Clone Users
205+
206+
```bash
207+
pnpm run update # Pull, install, rebuild
208+
pnpm run update -- --skip-build # Pull + install only
209+
```
210+
211+
### Docker Users
212+
213+
```bash
214+
pnpm docker:update # Pull latest image + restart
215+
```
216+
217+
The app shows a blue banner at the top of the page when a new version is available, with instructions for both update methods.
157218

158219
---
159220

160221
## Project Structure Quick Reference
161222

162223
```text
163224
bolt.diy/
225+
├── .dockerignore # Docker ignore rules
226+
├── .github/workflows/ # CI/CD pipelines
227+
├── Dockerfile # Production Docker build
228+
├── docker-compose.yml # Docker Compose config
164229
├── app/ # Application source code
165230
│ ├── components/ # React components
166231
│ ├── lib/ # Core logic

docs/STATE-MANAGEMENT.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ All hooks live in `app/lib/hooks/`. They often wrap store access or provide data
192192
| `useShortcuts` | Keyboard shortcut registration |
193193
| `useSupabaseConnection` | Supabase connection state |
194194
| `useViewport` | Responsive breakpoint detection |
195+
| `useVersionCheck` | Polls `/api/version-check` to detect available updates, drives `UpdateBanner` |
195196

196197
---
197198

0 commit comments

Comments
 (0)