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: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
*/node_modules
dist
*/dist
.git
*.md
.env*
logs.txt
*.session.sql
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
inject-workspace-packages=true
51 changes: 51 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# --- Stage 1: base (install deps) ---
FROM node:24-alpine AS base
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json .npmrc ./
COPY packages/common/package.json packages/common/
COPY apps/backend/package.json apps/backend/
COPY apps/webpage/package.json apps/webpage/
RUN pnpm install --frozen-lockfile

# --- Stage 2: build-common ---
FROM base AS build-common
COPY packages/common/ packages/common/
RUN pnpm --filter @cuttlekit/common build

# --- Stage 3: build-backend ---
FROM build-common AS build-backend
COPY apps/backend/ apps/backend/
RUN pnpm --filter @cuttlekit/backend build
RUN pnpm deploy --filter @cuttlekit/backend --prod /app/deployed

# --- Stage 4: build-webpage ---
FROM build-common AS build-webpage
ARG VITE_API_BASE="http://localhost:34512"
ENV VITE_API_BASE=${VITE_API_BASE}
COPY apps/webpage/ apps/webpage/
RUN pnpm --filter @cuttlekit/webpage build

# --- Stage 5: backend runtime ---
FROM node:24-alpine AS backend
RUN apk add --no-cache tini
WORKDIR /app
COPY --from=build-backend /app/deployed/node_modules/ ./node_modules/
COPY --from=build-backend /app/apps/backend/dist/ ./dist/
COPY config.toml ./
COPY drizzle/ ./drizzle/
RUN mkdir -p /app/data && chown node:node /app/data
ENV DATABASE_URL=file:/app/data/memory.db
USER node
EXPOSE 34512
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/index.mjs"]

# --- Stage 6: webpage runtime ---
FROM node:24-alpine AS webpage
RUN npm i -g serve
WORKDIR /app
COPY --from=build-webpage /app/apps/webpage/dist/ ./dist/
USER node
EXPOSE 34513
CMD ["serve", "-s", "dist", "-l", "34513"]
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ pnpm run dev:backend:no-env

Then open http://localhost:5173 🚀

### Docker

Make sure you have a `config.toml` (see step 3) and your env vars ready, then:

```bash
# With .env file
docker compose up --build

# With 1Password CLI (or similar secret injectors)
op run --env-file=.env -- docker compose up --build
```

Open http://localhost:34513

## Current Constraints

We're actively working on these:
Expand Down
10 changes: 10 additions & 0 deletions apps/backend/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from "tsdown";

export default defineConfig({
entry: ["src/index.ts"],
format: "esm",
// By default tsdown externalizes all node_modules deps.
// Force-bundle workspace packages and their transitive pure-JS deps
// so the output is self-contained for Docker deployment.
noExternal: [/@cuttlekit\//, "effect", /^@effect\//, "drizzle-orm"],
});
2 changes: 1 addition & 1 deletion apps/webpage/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { loadFontsFromHTML } from "./fonts";
import { loadIconsFromHTML } from "./icons";
import type { Action, Patch, StreamEventWithOffset } from "@cuttlekit/common/client";

const API_BASE = "http://localhost:34512";
const API_BASE = import.meta.env.VITE_API_BASE ?? "http://localhost:34512";
const STORAGE_KEY = "generative-ui-stream";
const MODEL_STORAGE_KEY = "generative-ui-model";

Expand Down
25 changes: 25 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
services:
backend:
build:
context: .
target: backend
ports:
- "34512:34512"
environment:
- GOOGLE_API_KEY=${GOOGLE_API_KEY:-}
- GROQ_API_KEY=${GROQ_API_KEY:-}
- INCEPTION_API_KEY=${INCEPTION_API_KEY:-}
- DENO_API_KEY=${DENO_API_KEY:-}
- LINEAR_API_KEY=${LINEAR_API_KEY:-}
- NOTION_API_KEY=${NOTION_API_KEY:-}
restart: unless-stopped

webpage:
build:
context: .
target: webpage
ports:
- "34513:34513"
depends_on:
- backend
restart: unless-stopped
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.