From dacfd8167b6aa487b95311b43192c4fb53ade4f6 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 12:19:49 +0000 Subject: [PATCH 01/18] Add fork kit and euro marketing app Co-authored-by: thanisch --- .github/workflows/auto-sync.yml | 48 ++++++++ apps/marketing/app/globals.css | 42 +++++++ apps/marketing/app/layout.tsx | 34 +++++ apps/marketing/app/page.tsx | 198 ++++++++++++++++++++++++++++++ apps/marketing/next.config.ts | 8 ++ apps/marketing/package.json | 32 +++++ apps/marketing/postcss.config.mjs | 5 + apps/marketing/tsconfig.json | 11 ++ bun.lock | 29 +++++ fork-kit/README.md | 9 ++ fork-kit/bootstrap-fork.sh | 115 +++++++++++++++++ 11 files changed, 531 insertions(+) create mode 100644 .github/workflows/auto-sync.yml create mode 100644 apps/marketing/app/globals.css create mode 100644 apps/marketing/app/layout.tsx create mode 100644 apps/marketing/app/page.tsx create mode 100644 apps/marketing/next.config.ts create mode 100644 apps/marketing/package.json create mode 100644 apps/marketing/postcss.config.mjs create mode 100644 apps/marketing/tsconfig.json create mode 100644 fork-kit/README.md create mode 100755 fork-kit/bootstrap-fork.sh diff --git a/.github/workflows/auto-sync.yml b/.github/workflows/auto-sync.yml new file mode 100644 index 00000000000..279eca7c97e --- /dev/null +++ b/.github/workflows/auto-sync.yml @@ -0,0 +1,48 @@ +name: Auto Sync Upstream + +on: + schedule: + - cron: '17 3 * * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +concurrency: + group: auto-sync-upstream + cancel-in-progress: true + +jobs: + sync: + name: Sync upstream main + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + + - name: Fetch upstream + run: | + git remote add upstream https://github.com/simstudioai/sim.git || git remote set-url upstream https://github.com/simstudioai/sim.git + git fetch upstream main + + - name: Prepare sync branch + run: | + git checkout -B auto-sync/upstream-main origin/main + git merge --no-edit upstream/main + git push --force-with-lease origin auto-sync/upstream-main + + - name: Open or update pull request + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr view auto-sync/upstream-main --base main >/dev/null 2>&1 || gh pr create --base main --head auto-sync/upstream-main --title 'chore(sync): update fork from upstream main' --body 'Automated upstream sync from simstudioai/sim main.' + diff --git a/apps/marketing/app/globals.css b/apps/marketing/app/globals.css new file mode 100644 index 00000000000..a58da3fbfd4 --- /dev/null +++ b/apps/marketing/app/globals.css @@ -0,0 +1,42 @@ +@import "tailwindcss"; + +:root { + --marketing-bg: #08090a; + --marketing-panel: rgba(255, 255, 255, 0.08); + --marketing-panel-strong: rgba(255, 255, 255, 0.14); + --marketing-border: rgba(255, 255, 255, 0.14); + --marketing-text: #f7f3ea; + --marketing-muted: rgba(247, 243, 234, 0.68); + --marketing-soft: rgba(247, 243, 234, 0.46); + --marketing-euro: #d8ff7a; + --marketing-cyan: #86f7ff; + --marketing-pink: #ff80d5; +} + +* { + box-sizing: border-box; +} + +html { + background: var(--marketing-bg); + color: var(--marketing-text); +} + +body { + margin: 0; + min-height: 100vh; + background: radial-gradient(circle at 18% 10%, rgba(216, 255, 122, 0.22), transparent 28rem), + radial-gradient(circle at 84% 18%, rgba(134, 247, 255, 0.18), transparent 24rem), + radial-gradient(circle at 78% 78%, rgba(255, 128, 213, 0.16), transparent 28rem), + linear-gradient(135deg, #08090a 0%, #111315 48%, #070808 100%); + color: var(--marketing-text); + font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +@source './**/*.{js,ts,jsx,tsx,mdx}'; diff --git a/apps/marketing/app/layout.tsx b/apps/marketing/app/layout.tsx new file mode 100644 index 00000000000..a8e6140dd37 --- /dev/null +++ b/apps/marketing/app/layout.tsx @@ -0,0 +1,34 @@ +import type { ReactNode } from 'react' +import type { Metadata, Viewport } from 'next' +import '@/app/globals.css' + +export const viewport: Viewport = { + width: 'device-width', + initialScale: 1, + themeColor: '#08090a', +} + +export const metadata: Metadata = { + title: 'Sim Marketing Overlay — Euro Pricing', + description: + 'A focused Sim marketing overlay for European pricing, plan positioning, and buyer conversion.', + applicationName: 'Sim Marketing', + openGraph: { + title: 'Sim Marketing Overlay — Euro Pricing', + description: + 'A focused Sim marketing overlay for European pricing, plan positioning, and buyer conversion.', + type: 'website', + }, +} + +interface RootLayoutProps { + children: ReactNode +} + +export default function RootLayout({ children }: RootLayoutProps) { + return ( + + {children} + + ) +} diff --git a/apps/marketing/app/page.tsx b/apps/marketing/app/page.tsx new file mode 100644 index 00000000000..64979a539cc --- /dev/null +++ b/apps/marketing/app/page.tsx @@ -0,0 +1,198 @@ +import { ArrowRight, BadgeEuro, Check, Gem, Globe2, ShieldCheck, Sparkles, Zap } from 'lucide-react' + +const currencyMode = + process.env.BILLING_CURRENCY?.toLowerCase() === 'eur' + ? 'BILLING_CURRENCY=eur' + : 'Euro overlay preview' + +const PLANS = [ + { + name: 'Community', + price: '€0', + period: 'forever', + description: 'Prototype agents, tables, and knowledge workflows without a card.', + accent: 'from-cyan-200 to-lime-200', + features: ['1,000 starter credits', '5 GB file storage', '1 personal workspace'], + }, + { + name: 'Pro', + price: '€25', + period: 'per month', + description: 'Launch production automations with predictable monthly credits.', + accent: 'from-lime-200 to-emerald-200', + features: ['6,000 credits/month', '50 GB file storage', '3 personal workspaces'], + featured: true, + }, + { + name: 'Max', + price: '€100', + period: 'per month', + description: 'Scale multi-step agents with deeper usage pools and team-ready limits.', + accent: 'from-pink-200 to-amber-100', + features: ['25,000 credits/month', '500 GB file storage', '10 personal workspaces'], + }, +] as const + +const PROOF_POINTS = [ + { + label: 'Built for EU buyers', + value: '€', + description: 'Every primary price and structured plan callout uses euro display.', + }, + { + label: 'Open-source core', + value: 'OSS', + description: 'Keep the builder self-hostable while presenting a polished commercial overlay.', + }, + { + label: 'Agent workflow ready', + value: '1k+', + description: 'Position integrations, models, and workflow execution in one sales narrative.', + }, +] as const + +const STEPS = [ + 'Connect the systems your team already uses.', + 'Build the first agent visually in the workflow builder.', + 'Run, inspect, and iterate before scaling to paid usage.', +] as const + +export default function MarketingPage() { + return ( +
+
+
+ + + +
+
+
+
+

+ Ship AI workflows with pricing that already speaks in euros. +

+

+ A focused marketing overlay for EU-facing launches: clear plan cards, explicit euro + display, and a buyer story that connects the visual builder to measurable automation. +

+ +
+ + +
+ +
+ {PLANS.map((plan) => ( +
+
+ ))} +
+ +
+ {PROOF_POINTS.map((point) => ( +
+
+

{point.label}

+ {point.value === '€' ? ( +
+

{point.value}

+

{point.description}

+
+ ))} +
+
+
+ ) +} diff --git a/apps/marketing/next.config.ts b/apps/marketing/next.config.ts new file mode 100644 index 00000000000..847ac72a400 --- /dev/null +++ b/apps/marketing/next.config.ts @@ -0,0 +1,8 @@ +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + poweredByHeader: false, + reactStrictMode: true, +} + +export default nextConfig diff --git a/apps/marketing/package.json b/apps/marketing/package.json new file mode 100644 index 00000000000..c67490bab6a --- /dev/null +++ b/apps/marketing/package.json @@ -0,0 +1,32 @@ +{ + "name": "marketing", + "version": "0.1.0", + "private": true, + "license": "Apache-2.0", + "scripts": { + "dev": "next dev --port 3003", + "build": "next build", + "start": "next start --port 3003", + "type-check": "tsc --noEmit", + "lint": "biome check --write --unsafe .", + "lint:check": "biome check .", + "format": "biome format --write .", + "format:check": "biome format ." + }, + "dependencies": { + "lucide-react": "^0.479.0", + "next": "16.2.6", + "react": "19.2.4", + "react-dom": "19.2.4" + }, + "devDependencies": { + "@sim/tsconfig": "workspace:*", + "@tailwindcss/postcss": "^4.0.12", + "@types/node": "24.2.1", + "@types/react": "^19", + "@types/react-dom": "^19", + "postcss": "^8", + "tailwindcss": "^4.0.12", + "typescript": "^5.7.3" + } +} diff --git a/apps/marketing/postcss.config.mjs b/apps/marketing/postcss.config.mjs new file mode 100644 index 00000000000..a7f73a2d1d7 --- /dev/null +++ b/apps/marketing/postcss.config.mjs @@ -0,0 +1,5 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + }, +} diff --git a/apps/marketing/tsconfig.json b/apps/marketing/tsconfig.json new file mode 100644 index 00000000000..9cf5d91b218 --- /dev/null +++ b/apps/marketing/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@sim/tsconfig/nextjs.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules", ".next"] +} diff --git a/bun.lock b/bun.lock index 5848be606fe..6ebbf34de90 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "simstudio", @@ -55,6 +56,26 @@ "typescript": "^5.8.2", }, }, + "apps/marketing": { + "name": "marketing", + "version": "0.1.0", + "dependencies": { + "lucide-react": "^0.479.0", + "next": "16.2.6", + "react": "19.2.4", + "react-dom": "19.2.4", + }, + "devDependencies": { + "@sim/tsconfig": "workspace:*", + "@tailwindcss/postcss": "^4.0.12", + "@types/node": "24.2.1", + "@types/react": "^19", + "@types/react-dom": "^19", + "postcss": "^8", + "tailwindcss": "^4.0.12", + "typescript": "^5.7.3", + }, + }, "apps/realtime": { "name": "@sim/realtime", "version": "0.1.0", @@ -2814,6 +2835,8 @@ "marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="], + "marketing": ["marketing@workspace:apps/marketing"], + "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], @@ -4236,6 +4259,10 @@ "mammoth/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "marketing/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], + + "marketing/lucide-react": ["lucide-react@0.479.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-aBhNnveRhorBOK7uA4gDjgaf+YlHMdMhQ/3cupk6exM10hWlEU+2QtWYOfhXhjAsmdb6LeKR+NZnow4UxRRiTQ=="], + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], @@ -4686,6 +4713,8 @@ "log-update/wrap-ansi/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + "marketing/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + "next/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], "next/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], diff --git a/fork-kit/README.md b/fork-kit/README.md new file mode 100644 index 00000000000..2b1d80ab799 --- /dev/null +++ b/fork-kit/README.md @@ -0,0 +1,9 @@ +# Fork Kit + +Run the bootstrap once after creating a fork: + +```bash +bash fork-kit/bootstrap-fork.sh +``` + +The script creates ignored local `.env` files with fresh development secrets, keeps existing env files intact, and installs an active scheduled upstream sync workflow at `.github/workflows/auto-sync.yml`. diff --git a/fork-kit/bootstrap-fork.sh b/fork-kit/bootstrap-fork.sh new file mode 100755 index 00000000000..1137343598e --- /dev/null +++ b/fork-kit/bootstrap-fork.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +require_command() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Missing required command: $1" >&2 + exit 1 + fi +} + +secret() { + openssl rand -hex 32 +} + +write_file_if_missing() { + local target="$1" + local content="$2" + + if [ -f "$target" ]; then + echo "Keeping existing $target" + return + fi + + mkdir -p "$(dirname "$target")" + printf "%s\n" "$content" >"$target" + echo "Wrote $target" +} + +require_command openssl + +BETTER_AUTH_SECRET_VALUE="$(secret)" +ENCRYPTION_KEY_VALUE="$(secret)" +API_ENCRYPTION_KEY_VALUE="$(secret)" +INTERNAL_API_SECRET_VALUE="$(secret)" +POSTGRES_PASSWORD_VALUE="${POSTGRES_PASSWORD:-postgres}" + +COMMON_ENV="POSTGRES_USER=postgres +POSTGRES_PASSWORD=${POSTGRES_PASSWORD_VALUE} +POSTGRES_DB=simstudio +POSTGRES_PORT=5432 +DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD_VALUE}@localhost:5432/simstudio +BETTER_AUTH_URL=http://localhost:3000 +NEXT_PUBLIC_APP_URL=http://localhost:3000 +BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET_VALUE} +ENCRYPTION_KEY=${ENCRYPTION_KEY_VALUE} +API_ENCRYPTION_KEY=${API_ENCRYPTION_KEY_VALUE} +INTERNAL_API_SECRET=${INTERNAL_API_SECRET_VALUE} +SOCKET_SERVER_URL=http://localhost:3002 +NEXT_PUBLIC_SOCKET_URL=http://localhost:3002 +BILLING_CURRENCY=eur" + +write_file_if_missing ".env" "$COMMON_ENV" +write_file_if_missing "apps/sim/.env" "$COMMON_ENV" +write_file_if_missing "apps/realtime/.env" "NODE_ENV=development +PORT=3002 +DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD_VALUE}@localhost:5432/simstudio +BETTER_AUTH_URL=http://localhost:3000 +BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET_VALUE} +INTERNAL_API_SECRET=${INTERNAL_API_SECRET_VALUE} +NEXT_PUBLIC_APP_URL=http://localhost:3000" +write_file_if_missing "packages/db/.env" "DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD_VALUE}@localhost:5432/simstudio" + +write_file_if_missing ".github/workflows/auto-sync.yml" "name: Auto Sync Upstream + +on: + schedule: + - cron: '17 3 * * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +concurrency: + group: auto-sync-upstream + cancel-in-progress: true + +jobs: + sync: + name: Sync upstream main + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: \${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + + - name: Fetch upstream + run: | + git remote add upstream https://github.com/simstudioai/sim.git || git remote set-url upstream https://github.com/simstudioai/sim.git + git fetch upstream main + + - name: Prepare sync branch + run: | + git checkout -B auto-sync/upstream-main origin/main + git merge --no-edit upstream/main + git push --force-with-lease origin auto-sync/upstream-main + + - name: Open or update pull request + env: + GH_TOKEN: \${{ secrets.GITHUB_TOKEN }} + run: | + gh pr view auto-sync/upstream-main --base main >/dev/null 2>&1 || gh pr create --base main --head auto-sync/upstream-main --title 'chore(sync): update fork from upstream main' --body 'Automated upstream sync from simstudioai/sim main.' +" + +echo "Fork bootstrap complete." From a2a7af4d0d010e34f96e4e0e6a83a05236c54b4b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 12:20:28 +0000 Subject: [PATCH 02/18] Fix marketing plan typing Co-authored-by: thanisch --- apps/marketing/app/page.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/marketing/app/page.tsx b/apps/marketing/app/page.tsx index 64979a539cc..90c3988c462 100644 --- a/apps/marketing/app/page.tsx +++ b/apps/marketing/app/page.tsx @@ -13,6 +13,7 @@ const PLANS = [ description: 'Prototype agents, tables, and knowledge workflows without a card.', accent: 'from-cyan-200 to-lime-200', features: ['1,000 starter credits', '5 GB file storage', '1 personal workspace'], + featured: false, }, { name: 'Pro', @@ -30,6 +31,7 @@ const PLANS = [ description: 'Scale multi-step agents with deeper usage pools and team-ready limits.', accent: 'from-pink-200 to-amber-100', features: ['25,000 credits/month', '500 GB file storage', '10 personal workspaces'], + featured: false, }, ] as const From 99d365ee7724529bde0317cb016d6f440be5e494 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 12:29:27 +0000 Subject: [PATCH 03/18] Configure Cursor Cloud dev environment Co-authored-by: thanisch --- .cursor/Dockerfile | 34 +++++++++++++++ .cursor/environment.json | 11 +++++ AGENTS.md | 14 ++++++ CLAUDE.md | 14 ++++++ scripts/cursor-cloud-install.sh | 37 ++++++++++++++++ scripts/cursor-cloud-start.sh | 77 +++++++++++++++++++++++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 .cursor/Dockerfile create mode 100644 .cursor/environment.json create mode 100755 scripts/cursor-cloud-install.sh create mode 100755 scripts/cursor-cloud-start.sh diff --git a/.cursor/Dockerfile b/.cursor/Dockerfile new file mode 100644 index 00000000000..f64fefbacaf --- /dev/null +++ b/.cursor/Dockerfile @@ -0,0 +1,34 @@ +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV BUN_INSTALL=/home/ubuntu/.bun +ENV PATH=/home/ubuntu/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + ca-certificates \ + curl \ + docker-compose-v2 \ + docker.io \ + git \ + iptables \ + jq \ + openssh-client \ + openssl \ + postgresql-client \ + ripgrep \ + sudo \ + tmux \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -m -s /bin/bash ubuntu \ + && usermod -aG docker ubuntu \ + && echo "ubuntu ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/ubuntu \ + && chmod 0440 /etc/sudoers.d/ubuntu + +USER ubuntu +WORKDIR /workspace + +RUN curl -fsSL https://bun.sh/install | bash diff --git a/.cursor/environment.json b/.cursor/environment.json new file mode 100644 index 00000000000..012b30a25c7 --- /dev/null +++ b/.cursor/environment.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://www.cursor.com/schemas/environment.schema.json", + "build": { + "dockerfile": "Dockerfile", + "context": ".." + }, + "install": "bash scripts/cursor-cloud-install.sh", + "start": "bash scripts/cursor-cloud-start.sh", + "ports": [3000, 3001, 3002, 3003, 5432], + "user": "ubuntu" +} diff --git a/AGENTS.md b/AGENTS.md index 78feaedb30a..4c0f605969b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -468,3 +468,17 @@ Two hard rules that the skills assume: For the full authoring instructions — SubBlock property tables, `condition`/`dependsOn`/`required`/`mode`/`canonicalParamId` syntax, required block metadata (`integrationType`, `tags`, `authMode`, `docsLink`, `{Service}BlockMeta`), file-input/`normalizeFileInput` patterns, and checklists — use the skills: `/add-integration` (end-to-end), `/add-tools`, `/add-block`, `/add-trigger`. +## Cursor Cloud specific instructions + +Cursor Cloud uses `.cursor/environment.json` for repo-scoped environment setup. The install command is `bash scripts/cursor-cloud-install.sh`; it ensures Bun, Docker/Compose, fork env files, and workspace dependencies are present. The start command is `bash scripts/cursor-cloud-start.sh`; it starts Docker when needed and brings up the Postgres 17 + pgvector `db` service from `docker-compose.local.yml`. + +Expected ports: + +- `3000` — Sim app +- `3001` — docs +- `3002` — realtime Socket.IO +- `3003` — marketing overlay +- `5432` — local Postgres + +If Docker cannot use the system service inside a Cloud container, the start script falls back to a local `dockerd` process using `vfs` storage with iptables disabled, which is compatible with the Cursor Cloud constraints observed for this repo. + diff --git a/CLAUDE.md b/CLAUDE.md index 78feaedb30a..4c0f605969b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -468,3 +468,17 @@ Two hard rules that the skills assume: For the full authoring instructions — SubBlock property tables, `condition`/`dependsOn`/`required`/`mode`/`canonicalParamId` syntax, required block metadata (`integrationType`, `tags`, `authMode`, `docsLink`, `{Service}BlockMeta`), file-input/`normalizeFileInput` patterns, and checklists — use the skills: `/add-integration` (end-to-end), `/add-tools`, `/add-block`, `/add-trigger`. +## Cursor Cloud specific instructions + +Cursor Cloud uses `.cursor/environment.json` for repo-scoped environment setup. The install command is `bash scripts/cursor-cloud-install.sh`; it ensures Bun, Docker/Compose, fork env files, and workspace dependencies are present. The start command is `bash scripts/cursor-cloud-start.sh`; it starts Docker when needed and brings up the Postgres 17 + pgvector `db` service from `docker-compose.local.yml`. + +Expected ports: + +- `3000` — Sim app +- `3001` — docs +- `3002` — realtime Socket.IO +- `3003` — marketing overlay +- `5432` — local Postgres + +If Docker cannot use the system service inside a Cloud container, the start script falls back to a local `dockerd` process using `vfs` storage with iptables disabled, which is compatible with the Cursor Cloud constraints observed for this repo. + diff --git a/scripts/cursor-cloud-install.sh b/scripts/cursor-cloud-install.sh new file mode 100755 index 00000000000..a98fd3be33d --- /dev/null +++ b/scripts/cursor-cloud-install.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}" +export PATH="$BUN_INSTALL/bin:$PATH" + +install_bun() { + if command -v bun >/dev/null 2>&1; then + return + fi + + curl -fsSL https://bun.sh/install | bash + export PATH="$BUN_INSTALL/bin:$PATH" +} + +install_docker() { + if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then + return + fi + + if ! command -v sudo >/dev/null 2>&1 || ! sudo -n true >/dev/null 2>&1; then + echo "Docker/Compose is missing and passwordless sudo is unavailable." >&2 + exit 1 + fi + + sudo apt-get update + sudo apt-get install -y docker.io docker-compose-v2 +} + +install_bun +install_docker + +bash fork-kit/bootstrap-fork.sh +bun install diff --git a/scripts/cursor-cloud-start.sh b/scripts/cursor-cloud-start.sh new file mode 100755 index 00000000000..3d3f1a74475 --- /dev/null +++ b/scripts/cursor-cloud-start.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}" +export PATH="$BUN_INSTALL/bin:$PATH" + +docker_ready() { + docker info >/dev/null 2>&1 || sudo docker info >/dev/null 2>&1 +} + +compose_up_db() { + if docker info >/dev/null 2>&1; then + docker compose -f docker-compose.local.yml up -d db + return + fi + + sudo docker compose -f docker-compose.local.yml up -d db +} + +start_system_docker() { + if ! command -v sudo >/dev/null 2>&1 || ! sudo -n true >/dev/null 2>&1; then + return 1 + fi + + if command -v systemctl >/dev/null 2>&1 && sudo systemctl start docker >/dev/null 2>&1; then + return 0 + fi + + if command -v service >/dev/null 2>&1 && sudo service docker start >/dev/null 2>&1; then + return 0 + fi + + return 1 +} + +start_fallback_dockerd() { + if ! command -v sudo >/dev/null 2>&1 || ! sudo -n true >/dev/null 2>&1; then + echo "Docker daemon is not running and passwordless sudo is unavailable." >&2 + exit 1 + fi + + mkdir -p /tmp/cursor-dockerd + sudo pkill dockerd >/dev/null 2>&1 || true + sudo pkill containerd >/dev/null 2>&1 || true + sudo dockerd \ + --host=unix:///var/run/docker.sock \ + --iptables=false \ + --bridge=none \ + --ip-forward=false \ + --storage-driver=vfs \ + >/tmp/cursor-dockerd/dockerd.log 2>&1 & +} + +wait_for_docker() { + for _ in $(seq 1 30); do + if docker_ready; then + return 0 + fi + sleep 1 + done + + echo "Docker did not become ready. Recent daemon logs:" >&2 + if [ -f /tmp/cursor-dockerd/dockerd.log ]; then + tail -n 80 /tmp/cursor-dockerd/dockerd.log >&2 + fi + exit 1 +} + +if ! docker_ready; then + start_system_docker || start_fallback_dockerd + wait_for_docker +fi + +compose_up_db From 2292d6410d370798807b2e73c0d46894ec6114a7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 12:45:48 +0000 Subject: [PATCH 04/18] Fix Cursor devcontainer server install Co-authored-by: thanisch --- .devcontainer/Dockerfile | 28 ++++++++++++++-------------- .devcontainer/devcontainer.json | 2 +- .devcontainer/docker-compose.yml | 12 +++++++++--- .devcontainer/post-create.sh | 6 ++++++ 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 201719f0f00..b83629883d7 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,35 +1,34 @@ -FROM oven/bun:1.3.13-alpine +FROM oven/bun:1.3.13 -# Install necessary packages for development -RUN apk add --no-cache \ +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + bash-completion \ + ca-certificates \ git \ curl \ wget \ jq \ sudo \ - postgresql-client \ vim \ nano \ - bash \ - bash-completion \ zsh \ - zsh-vcs \ - ca-certificates \ - shadow + postgresql-client \ + && rm -rf /var/lib/apt/lists/* # Create a non-root user with matching UID/GID ARG USERNAME=bun ARG USER_UID=1000 ARG USER_GID=$USER_UID -# Create user group if it doesn't exist RUN if ! getent group $USER_GID >/dev/null; then \ - addgroup -g $USER_GID $USERNAME; \ + groupadd --gid $USER_GID $USERNAME; \ fi -# Create user if it doesn't exist RUN if ! getent passwd $USER_UID >/dev/null; then \ - adduser -D -u $USER_UID -G $(getent group $USER_GID | cut -d: -f1) $USERNAME; \ + useradd --uid $USER_UID --gid $USER_GID --create-home --shell /bin/bash $USERNAME; \ fi # Add sudo support @@ -44,4 +43,5 @@ WORKDIR /workspace # Expose the ports we're interested in EXPOSE 3000 EXPOSE 3001 -EXPOSE 3002 \ No newline at end of file +EXPOSE 3002 +EXPOSE 3003 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 99bd1b3a4fb..92e4e488d51 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -29,7 +29,7 @@ } }, - "forwardPorts": [3000, 3002, 5432], + "forwardPorts": [3000, 3001, 3002, 3003, 5432], "postCreateCommand": "bash -c 'bash .devcontainer/post-create.sh || true'", diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index f3482d665d4..7ca9ddd3202 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -16,11 +16,14 @@ services: - DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio - BETTER_AUTH_URL=http://localhost:3000 - NEXT_PUBLIC_APP_URL=http://localhost:3000 - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-your_auth_secret_here} - - ENCRYPTION_KEY=${ENCRYPTION_KEY:-your_encryption_key_here} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev-secret-at-least-32-characters-long} + - ENCRYPTION_KEY=${ENCRYPTION_KEY:-dev-encryption-key-at-least-32-chars} + - API_ENCRYPTION_KEY=${API_ENCRYPTION_KEY:-} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-dev-internal-api-secret-min-32-chars} - COPILOT_API_KEY=${COPILOT_API_KEY} - SIM_AGENT_API_URL=${SIM_AGENT_API_URL} - OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434} + - SOCKET_SERVER_URL=${SOCKET_SERVER_URL:-http://realtime:3002} - NEXT_PUBLIC_SOCKET_URL=${NEXT_PUBLIC_SOCKET_URL:-} - BUN_INSTALL_CACHE_DIR=/home/bun/.bun/cache depends_on: @@ -31,6 +34,7 @@ services: ports: - "3000:3000" - "3001:3001" + - "3003:3003" working_dir: /workspace realtime: @@ -50,7 +54,9 @@ services: - DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio - BETTER_AUTH_URL=http://localhost:3000 - NEXT_PUBLIC_APP_URL=http://localhost:3000 - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-your_auth_secret_here} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev-secret-at-least-32-characters-long} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-dev-internal-api-secret-min-32-chars} + - REDIS_URL=${REDIS_URL:-} depends_on: db: condition: service_healthy diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index c7ceff427e6..368f43bfbda 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -8,6 +8,12 @@ echo "🔧 Setting up Sim development environment..." # Change to the workspace root directory cd /workspace +# Create local development env files with valid secrets before tools read env. +if [ -f "fork-kit/bootstrap-fork.sh" ]; then + echo "📄 Bootstrapping local fork env files..." + bash fork-kit/bootstrap-fork.sh +fi + # Install global packages for development (done at runtime, not build time) echo "📦 Installing global development tools..." bun install -g turbo drizzle-kit typescript @types/node 2>/dev/null || { From d333431b2c8ca7fbd21fc9cfb41e439a8381fc30 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 12:51:02 +0000 Subject: [PATCH 05/18] Pin Bun and add native build tools Co-authored-by: thanisch --- .cursor/Dockerfile | 8 ++++++-- .devcontainer/Dockerfile | 4 ++++ scripts/cursor-cloud-install.sh | 7 ++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.cursor/Dockerfile b/.cursor/Dockerfile index f64fefbacaf..467ca189fd5 100644 --- a/.cursor/Dockerfile +++ b/.cursor/Dockerfile @@ -11,19 +11,23 @@ RUN apt-get update \ curl \ docker-compose-v2 \ docker.io \ + g++ \ git \ iptables \ jq \ + make \ openssh-client \ openssl \ postgresql-client \ + pkg-config \ + python3 \ ripgrep \ sudo \ tmux \ unzip \ && rm -rf /var/lib/apt/lists/* -RUN useradd -m -s /bin/bash ubuntu \ +RUN if ! getent passwd ubuntu >/dev/null; then useradd -m -s /bin/bash ubuntu; fi \ && usermod -aG docker ubuntu \ && echo "ubuntu ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/ubuntu \ && chmod 0440 /etc/sudoers.d/ubuntu @@ -31,4 +35,4 @@ RUN useradd -m -s /bin/bash ubuntu \ USER ubuntu WORKDIR /workspace -RUN curl -fsSL https://bun.sh/install | bash +RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.13" diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b83629883d7..55b75ff2809 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -8,13 +8,17 @@ RUN apt-get update \ bash-completion \ ca-certificates \ git \ + g++ \ curl \ wget \ + make \ jq \ sudo \ vim \ nano \ zsh \ + pkg-config \ + python3 \ postgresql-client \ && rm -rf /var/lib/apt/lists/* diff --git a/scripts/cursor-cloud-install.sh b/scripts/cursor-cloud-install.sh index a98fd3be33d..570e3fee6f9 100755 --- a/scripts/cursor-cloud-install.sh +++ b/scripts/cursor-cloud-install.sh @@ -6,13 +6,14 @@ cd "$ROOT_DIR" export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}" export PATH="$BUN_INSTALL/bin:$PATH" +REQUIRED_BUN_VERSION="1.3.13" install_bun() { - if command -v bun >/dev/null 2>&1; then + if command -v bun >/dev/null 2>&1 && [ "$(bun --version)" = "$REQUIRED_BUN_VERSION" ]; then return fi - curl -fsSL https://bun.sh/install | bash + curl -fsSL https://bun.sh/install | bash -s "bun-v${REQUIRED_BUN_VERSION}" export PATH="$BUN_INSTALL/bin:$PATH" } @@ -27,7 +28,7 @@ install_docker() { fi sudo apt-get update - sudo apt-get install -y docker.io docker-compose-v2 + sudo apt-get install -y docker.io docker-compose-v2 python3 make g++ pkg-config } install_bun From 9ff50fd9a7e10afd6223be2b971473b456fbb9a0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:08:28 +0000 Subject: [PATCH 06/18] Install devcontainer command wrappers Co-authored-by: thanisch --- .devcontainer/post-create.sh | 39 +++++++++++++++++++++++++++++++ .devcontainer/sim-commands.sh | 44 +++++++++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 368f43bfbda..e0ff00d7aaa 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -52,6 +52,45 @@ if [ ! -f ~/.bashrc ] && [ ! -f ~/.zshrc ]; then echo "fi" >> ~/.bashrc fi +echo "🔧 Installing project command wrappers..." +sudo tee /usr/local/bin/sim-start > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace && exec bun run dev:full +EOF +sudo tee /usr/local/bin/sim-app > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace && exec bun run dev +EOF +sudo tee /usr/local/bin/sim-sockets > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace && exec bun run dev:sockets +EOF +sudo tee /usr/local/bin/sim-migrate > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace/packages/db && exec bun run db:migrate +EOF +sudo tee /usr/local/bin/sim-generate > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace/packages/db && exec bunx drizzle-kit generate --config=./drizzle.config.ts +EOF +sudo tee /usr/local/bin/sim-rebuild > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace && bun run build && exec bun run start +EOF +sudo tee /usr/local/bin/docs-dev > /dev/null <<'EOF' +#!/usr/bin/env bash +cd /workspace/apps/docs && exec bun run dev +EOF +sudo tee /usr/local/bin/pgc > /dev/null <<'EOF' +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -d simstudio "$@" +EOF +sudo tee /usr/local/bin/check-db > /dev/null <<'EOF' +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -c '\l' +EOF +sudo chmod +x /usr/local/bin/sim-start /usr/local/bin/sim-app /usr/local/bin/sim-sockets /usr/local/bin/sim-migrate /usr/local/bin/sim-generate /usr/local/bin/sim-rebuild /usr/local/bin/docs-dev /usr/local/bin/pgc /usr/local/bin/check-db + # Clean and reinstall dependencies to ensure platform compatibility echo "📦 Cleaning and reinstalling dependencies..." if [ -d "node_modules" ]; then diff --git a/.devcontainer/sim-commands.sh b/.devcontainer/sim-commands.sh index 640feb2f95a..8d0c6c572b1 100755 --- a/.devcontainer/sim-commands.sh +++ b/.devcontainer/sim-commands.sh @@ -3,18 +3,42 @@ # Source this file to add project-specific commands to your shell # Add to your ~/.bashrc or ~/.zshrc: source /workspace/.devcontainer/sim-commands.sh -# Project-specific aliases for Sim development -alias sim-start="cd /workspace && bun run dev:full" -alias sim-app="cd /workspace && bun run dev" -alias sim-sockets="cd /workspace && bun run dev:sockets" -alias sim-migrate="cd /workspace/apps/sim && bunx drizzle-kit push" -alias sim-generate="cd /workspace/apps/sim && bunx drizzle-kit generate" -alias sim-rebuild="cd /workspace && bun run build && bun run start" -alias docs-dev="cd /workspace/apps/docs && bun run dev" +sim-start() { + cd /workspace && bun run dev:full +} + +sim-app() { + cd /workspace && bun run dev +} + +sim-sockets() { + cd /workspace && bun run dev:sockets +} + +sim-migrate() { + cd /workspace/packages/db && bun run db:migrate +} + +sim-generate() { + cd /workspace/packages/db && bunx drizzle-kit generate --config=./drizzle.config.ts +} + +sim-rebuild() { + cd /workspace && bun run build && bun run start +} + +docs-dev() { + cd /workspace/apps/docs && bun run dev +} # Database connection helpers -alias pgc="PGPASSWORD=postgres psql -h db -U postgres -d simstudio" -alias check-db="PGPASSWORD=postgres psql -h db -U postgres -c '\l'" +pgc() { + PGPASSWORD=postgres psql -h db -U postgres -d simstudio +} + +check-db() { + PGPASSWORD=postgres psql -h db -U postgres -c '\l' +} # Default to workspace directory cd /workspace 2>/dev/null || true From 624e5fa32cdfc66cdb44f70d310c410c726928ce Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:20:09 +0000 Subject: [PATCH 07/18] Set writable Bun tempdir in devcontainer Co-authored-by: thanisch --- .devcontainer/docker-compose.yml | 2 ++ .devcontainer/post-create.sh | 22 ++++++++++++++++++---- .devcontainer/sim-commands.sh | 12 ++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 7ca9ddd3202..7d6f92acfae 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -26,6 +26,7 @@ services: - SOCKET_SERVER_URL=${SOCKET_SERVER_URL:-http://realtime:3002} - NEXT_PUBLIC_SOCKET_URL=${NEXT_PUBLIC_SOCKET_URL:-} - BUN_INSTALL_CACHE_DIR=/home/bun/.bun/cache + - TMPDIR=/home/bun/.cache/tmp depends_on: db: condition: service_healthy @@ -57,6 +58,7 @@ services: - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev-secret-at-least-32-characters-long} - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-dev-internal-api-secret-min-32-chars} - REDIS_URL=${REDIS_URL:-} + - TMPDIR=/home/bun/.cache/tmp depends_on: db: condition: service_healthy diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index e0ff00d7aaa..9064c147ff2 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -8,6 +8,10 @@ echo "🔧 Setting up Sim development environment..." # Change to the workspace root directory cd /workspace +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" ~/.bun/cache +chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache + # Create local development env files with valid secrets before tools read env. if [ -f "fork-kit/bootstrap-fork.sh" ]; then echo "📄 Bootstrapping local fork env files..." @@ -55,30 +59,44 @@ fi echo "🔧 Installing project command wrappers..." sudo tee /usr/local/bin/sim-start > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace && exec bun run dev:full EOF sudo tee /usr/local/bin/sim-app > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace && exec bun run dev EOF sudo tee /usr/local/bin/sim-sockets > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace && exec bun run dev:sockets EOF sudo tee /usr/local/bin/sim-migrate > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace/packages/db && exec bun run db:migrate EOF sudo tee /usr/local/bin/sim-generate > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace/packages/db && exec bunx drizzle-kit generate --config=./drizzle.config.ts EOF sudo tee /usr/local/bin/sim-rebuild > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace && bun run build && exec bun run start EOF sudo tee /usr/local/bin/docs-dev > /dev/null <<'EOF' #!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" cd /workspace/apps/docs && exec bun run dev EOF sudo tee /usr/local/bin/pgc > /dev/null <<'EOF' @@ -100,10 +118,6 @@ if [ -d "node_modules" ]; then rm -rf apps/docs/node_modules fi -# Ensure Bun cache directory exists and has correct permissions -mkdir -p ~/.bun/cache -chmod 700 ~/.bun ~/.bun/cache - # Install dependencies with platform-specific binaries echo "Installing dependencies with Bun..." bun install diff --git a/.devcontainer/sim-commands.sh b/.devcontainer/sim-commands.sh index 8d0c6c572b1..71a7fa292ee 100755 --- a/.devcontainer/sim-commands.sh +++ b/.devcontainer/sim-commands.sh @@ -3,31 +3,43 @@ # Source this file to add project-specific commands to your shell # Add to your ~/.bashrc or ~/.zshrc: source /workspace/.devcontainer/sim-commands.sh +ensure-sim-tempdir() { + export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" + mkdir -p "$TMPDIR" +} + sim-start() { + ensure-sim-tempdir cd /workspace && bun run dev:full } sim-app() { + ensure-sim-tempdir cd /workspace && bun run dev } sim-sockets() { + ensure-sim-tempdir cd /workspace && bun run dev:sockets } sim-migrate() { + ensure-sim-tempdir cd /workspace/packages/db && bun run db:migrate } sim-generate() { + ensure-sim-tempdir cd /workspace/packages/db && bunx drizzle-kit generate --config=./drizzle.config.ts } sim-rebuild() { + ensure-sim-tempdir cd /workspace && bun run build && bun run start } docs-dev() { + ensure-sim-tempdir cd /workspace/apps/docs && bun run dev } From 77969e2f5d9409f01f0066aa6382203fd0704d2f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:34:18 +0000 Subject: [PATCH 08/18] Defer heavy devcontainer setup Co-authored-by: thanisch --- .devcontainer/post-create.sh | 96 ++++++----------------------------- .devcontainer/sim-commands.sh | 6 +++ 2 files changed, 22 insertions(+), 80 deletions(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 9064c147ff2..ed4f517ee2e 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -18,12 +18,6 @@ if [ -f "fork-kit/bootstrap-fork.sh" ]; then bash fork-kit/bootstrap-fork.sh fi -# Install global packages for development (done at runtime, not build time) -echo "📦 Installing global development tools..." -bun install -g turbo drizzle-kit typescript @types/node 2>/dev/null || { - echo "⚠️ Some global packages may already be installed, continuing..." -} - # Set up bun completions (with proper shell detection) echo "🔧 Setting up shell completions..." if [ -n "$SHELL" ] && [ -f "$SHELL" ]; then @@ -57,6 +51,18 @@ if [ ! -f ~/.bashrc ] && [ ! -f ~/.zshrc ]; then fi echo "🔧 Installing project command wrappers..." +sudo tee /usr/local/bin/sim-setup > /dev/null <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" ~/.bun/cache +chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache +cd /workspace +bash fork-kit/bootstrap-fork.sh +bun install +cd packages/db +bun run db:migrate +EOF sudo tee /usr/local/bin/sim-start > /dev/null <<'EOF' #!/usr/bin/env bash export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" @@ -107,88 +113,18 @@ sudo tee /usr/local/bin/check-db > /dev/null <<'EOF' #!/usr/bin/env bash exec env PGPASSWORD=postgres psql -h db -U postgres -c '\l' EOF -sudo chmod +x /usr/local/bin/sim-start /usr/local/bin/sim-app /usr/local/bin/sim-sockets /usr/local/bin/sim-migrate /usr/local/bin/sim-generate /usr/local/bin/sim-rebuild /usr/local/bin/docs-dev /usr/local/bin/pgc /usr/local/bin/check-db - -# Clean and reinstall dependencies to ensure platform compatibility -echo "📦 Cleaning and reinstalling dependencies..." -if [ -d "node_modules" ]; then - echo "Removing existing node_modules to ensure platform compatibility..." - rm -rf node_modules - rm -rf apps/sim/node_modules - rm -rf apps/docs/node_modules -fi - -# Install dependencies with platform-specific binaries -echo "Installing dependencies with Bun..." -bun install - -# Check for native dependencies -echo "Checking for native dependencies compatibility..." -if grep -q '"trustedDependencies"' apps/sim/package.json 2>/dev/null; then - echo "⚠️ Native dependencies detected. Bun will handle compatibility during install." -fi - -# Set up environment variables if .env doesn't exist for the sim app -if [ ! -f "apps/sim/.env" ]; then - echo "📄 Creating apps/sim/.env from template..." - if [ -f "apps/sim/.env.example" ]; then - cp apps/sim/.env.example apps/sim/.env - else - echo "DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio" > apps/sim/.env - fi -fi - -# Set up env for the realtime server (must match the shared values in apps/sim/.env) -if [ ! -f "apps/realtime/.env" ] && [ -f "apps/realtime/.env.example" ]; then - echo "📄 Creating apps/realtime/.env from template..." - cp apps/realtime/.env.example apps/realtime/.env -fi - -# Set up packages/db/.env for drizzle-kit and migration scripts -if [ ! -f "packages/db/.env" ] && [ -f "packages/db/.env.example" ]; then - echo "📄 Creating packages/db/.env from template..." - cp packages/db/.env.example packages/db/.env -fi - -# Generate schema and run database migrations -echo "🗃️ Running database schema generation and migrations..." -echo "Generating schema..." -cd apps/sim -bunx drizzle-kit generate -cd ../.. - -echo "Waiting for database to be ready..." -# Try to connect to the database, but don't fail the script if it doesn't work -( - timeout=60 - while [ $timeout -gt 0 ]; do - if PGPASSWORD=postgres psql -h db -U postgres -c '\q' 2>/dev/null; then - echo "Database is ready!" - cd apps/sim - DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio bunx drizzle-kit push - cd ../.. - break - fi - echo "Database is unavailable - sleeping (${timeout}s remaining)" - sleep 5 - timeout=$((timeout - 5)) - done - - if [ $timeout -le 0 ]; then - echo "⚠️ Database connection timed out, skipping migrations" - fi -) || echo "⚠️ Database setup had issues but continuing..." +sudo chmod +x /usr/local/bin/sim-setup /usr/local/bin/sim-start /usr/local/bin/sim-app /usr/local/bin/sim-sockets /usr/local/bin/sim-migrate /usr/local/bin/sim-generate /usr/local/bin/sim-rebuild /usr/local/bin/docs-dev /usr/local/bin/pgc /usr/local/bin/check-db # Clear the welcome message flag to ensure it shows after setup unset SIM_WELCOME_SHOWN echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "✅ Sim development environment setup complete!" +echo "✅ Sim development container bootstrap complete!" echo "" -echo "Your environment is now ready. A new terminal session will show" -echo "available commands. You can start the development server with:" +echo "Open a terminal and run the heavier setup when you are ready:" echo "" +echo " sim-setup" echo " sim-start" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" diff --git a/.devcontainer/sim-commands.sh b/.devcontainer/sim-commands.sh index 71a7fa292ee..fee7e20b323 100755 --- a/.devcontainer/sim-commands.sh +++ b/.devcontainer/sim-commands.sh @@ -8,6 +8,11 @@ ensure-sim-tempdir() { mkdir -p "$TMPDIR" } +sim-setup() { + ensure-sim-tempdir + cd /workspace && bash fork-kit/bootstrap-fork.sh && bun install && cd packages/db && bun run db:migrate +} + sim-start() { ensure-sim-tempdir cd /workspace && bun run dev:full @@ -64,6 +69,7 @@ if [ -z "$SIM_WELCOME_SHOWN" ]; then echo "🚀 Sim Development Environment" echo "" echo "Project commands:" + echo " sim-setup - Install deps and run DB migrations" echo " sim-start - Start app + socket server" echo " sim-app - Start only main app" echo " sim-sockets - Start only socket server" From 1eba5b074bc6316d897bfa9b992279439dab1111 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:39:23 +0000 Subject: [PATCH 09/18] Start only app and db for devcontainer attach Co-authored-by: thanisch --- .devcontainer/devcontainer.json | 1 + .devcontainer/docker-compose.yml | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 92e4e488d51..165603a80ec 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,7 @@ { "name": "Sim Dev Environment", "dockerComposeFile": "docker-compose.yml", + "runServices": ["app", "db"], "service": "app", "workspaceFolder": "/workspace", "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 7d6f92acfae..dbcc02a4fb9 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -30,8 +30,6 @@ services: depends_on: db: condition: service_healthy - migrations: - condition: service_completed_successfully ports: - "3000:3000" - "3001:3001" From 0224df682e3c6773faaf091fc5a7d46f60f16cd1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:43:17 +0000 Subject: [PATCH 10/18] Run devcontainer app as bun user Co-authored-by: thanisch --- .devcontainer/devcontainer.json | 1 + .devcontainer/docker-compose.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 165603a80ec..a875ca57b29 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,6 +5,7 @@ "service": "app", "workspaceFolder": "/workspace", "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", + "containerUser": "bun", "customizations": { "vscode": { diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index dbcc02a4fb9..f9e76685051 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -7,12 +7,14 @@ services: - ..:/workspace:cached - bun-cache:/home/bun/.bun/cache:delegated command: sleep infinity + user: bun deploy: resources: limits: memory: 8G environment: - NODE_ENV=development + - HOME=/home/bun - DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio - BETTER_AUTH_URL=http://localhost:3000 - NEXT_PUBLIC_APP_URL=http://localhost:3000 From 55f66be3a338a44f7cc00d26635e47c4e2ff1d64 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:48:32 +0000 Subject: [PATCH 11/18] Remove devcontainer post-create attach blocker Co-authored-by: thanisch --- .devcontainer/Dockerfile | 64 +++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 55b75ff2809..5563d793db9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -42,6 +42,70 @@ RUN echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ # Set up shell environment RUN echo "export PATH=\$PATH:/home/$USERNAME/.bun/bin" >> /etc/profile +RUN cat > /usr/local/bin/sim-setup <<'EOF' \ + && cat > /usr/local/bin/sim-start <<'EOF2' \ + && cat > /usr/local/bin/sim-app <<'EOF3' \ + && cat > /usr/local/bin/sim-sockets <<'EOF4' \ + && cat > /usr/local/bin/sim-migrate <<'EOF5' \ + && cat > /usr/local/bin/sim-generate <<'EOF6' \ + && cat > /usr/local/bin/sim-rebuild <<'EOF7' \ + && cat > /usr/local/bin/docs-dev <<'EOF8' \ + && cat > /usr/local/bin/pgc <<'EOF9' \ + && cat > /usr/local/bin/check-db <<'EOF10' \ + && chmod +x /usr/local/bin/sim-setup /usr/local/bin/sim-start /usr/local/bin/sim-app /usr/local/bin/sim-sockets /usr/local/bin/sim-migrate /usr/local/bin/sim-generate /usr/local/bin/sim-rebuild /usr/local/bin/docs-dev /usr/local/bin/pgc /usr/local/bin/check-db +#!/usr/bin/env bash +set -euo pipefail +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" ~/.bun/cache +chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache +cd /workspace +bash fork-kit/bootstrap-fork.sh +bun install +cd packages/db +bun run db:migrate +EOF +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev:full +EOF2 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev +EOF3 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev:sockets +EOF4 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/packages/db && exec bun run db:migrate +EOF5 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/packages/db && exec bunx drizzle-kit generate --config=./drizzle.config.ts +EOF6 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && bun run build && exec bun run start +EOF7 +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/apps/docs && exec bun run dev +EOF8 +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -d simstudio "$@" +EOF9 +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -c '\l' +EOF10 + WORKDIR /workspace # Expose the ports we're interested in diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a875ca57b29..9d00a8eedd0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -33,7 +33,7 @@ "forwardPorts": [3000, 3001, 3002, 3003, 5432], - "postCreateCommand": "bash -c 'bash .devcontainer/post-create.sh || true'", + "postCreateCommand": "bash -c 'true'", "remoteUser": "bun" } From 3527d36e2aba5f312be17f2169536d14be9a5a9d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 13:54:23 +0000 Subject: [PATCH 12/18] Avoid heredocs in devcontainer Dockerfile Co-authored-by: thanisch --- .devcontainer/Dockerfile | 66 +----------------------- .devcontainer/install-commands.sh | 85 +++++++++++++++++++++++++++++++ .dockerignore | 1 + 3 files changed, 88 insertions(+), 64 deletions(-) create mode 100644 .devcontainer/install-commands.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5563d793db9..b79e972d436 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -39,72 +39,10 @@ RUN if ! getent passwd $USER_UID >/dev/null; then \ RUN echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ && chmod 0440 /etc/sudoers.d/$USERNAME -# Set up shell environment RUN echo "export PATH=\$PATH:/home/$USERNAME/.bun/bin" >> /etc/profile -RUN cat > /usr/local/bin/sim-setup <<'EOF' \ - && cat > /usr/local/bin/sim-start <<'EOF2' \ - && cat > /usr/local/bin/sim-app <<'EOF3' \ - && cat > /usr/local/bin/sim-sockets <<'EOF4' \ - && cat > /usr/local/bin/sim-migrate <<'EOF5' \ - && cat > /usr/local/bin/sim-generate <<'EOF6' \ - && cat > /usr/local/bin/sim-rebuild <<'EOF7' \ - && cat > /usr/local/bin/docs-dev <<'EOF8' \ - && cat > /usr/local/bin/pgc <<'EOF9' \ - && cat > /usr/local/bin/check-db <<'EOF10' \ - && chmod +x /usr/local/bin/sim-setup /usr/local/bin/sim-start /usr/local/bin/sim-app /usr/local/bin/sim-sockets /usr/local/bin/sim-migrate /usr/local/bin/sim-generate /usr/local/bin/sim-rebuild /usr/local/bin/docs-dev /usr/local/bin/pgc /usr/local/bin/check-db -#!/usr/bin/env bash -set -euo pipefail -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" ~/.bun/cache -chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache -cd /workspace -bash fork-kit/bootstrap-fork.sh -bun install -cd packages/db -bun run db:migrate -EOF -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace && exec bun run dev:full -EOF2 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace && exec bun run dev -EOF3 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace && exec bun run dev:sockets -EOF4 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace/packages/db && exec bun run db:migrate -EOF5 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace/packages/db && exec bunx drizzle-kit generate --config=./drizzle.config.ts -EOF6 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace && bun run build && exec bun run start -EOF7 -#!/usr/bin/env bash -export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" -mkdir -p "$TMPDIR" -cd /workspace/apps/docs && exec bun run dev -EOF8 -#!/usr/bin/env bash -exec env PGPASSWORD=postgres psql -h db -U postgres -d simstudio "$@" -EOF9 -#!/usr/bin/env bash -exec env PGPASSWORD=postgres psql -h db -U postgres -c '\l' -EOF10 +COPY .devcontainer/install-commands.sh /tmp/install-commands.sh +RUN bash /tmp/install-commands.sh && rm /tmp/install-commands.sh WORKDIR /workspace diff --git a/.devcontainer/install-commands.sh b/.devcontainer/install-commands.sh new file mode 100644 index 00000000000..d9a64bcb802 --- /dev/null +++ b/.devcontainer/install-commands.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +set -euo pipefail + +cat > /usr/local/bin/sim-setup <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" ~/.bun/cache +chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache +cd /workspace +bash fork-kit/bootstrap-fork.sh +bun install +cd packages/db +bun run db:migrate +EOF + +cat > /usr/local/bin/sim-start <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev:full +EOF + +cat > /usr/local/bin/sim-app <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev +EOF + +cat > /usr/local/bin/sim-sockets <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && exec bun run dev:sockets +EOF + +cat > /usr/local/bin/sim-migrate <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/packages/db && exec bun run db:migrate +EOF + +cat > /usr/local/bin/sim-generate <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/packages/db && exec bunx drizzle-kit generate --config=./drizzle.config.ts +EOF + +cat > /usr/local/bin/sim-rebuild <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace && bun run build && exec bun run start +EOF + +cat > /usr/local/bin/docs-dev <<'EOF' +#!/usr/bin/env bash +export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" +mkdir -p "$TMPDIR" +cd /workspace/apps/docs && exec bun run dev +EOF + +cat > /usr/local/bin/pgc <<'EOF' +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -d simstudio "$@" +EOF + +cat > /usr/local/bin/check-db <<'EOF' +#!/usr/bin/env bash +exec env PGPASSWORD=postgres psql -h db -U postgres -c '\l' +EOF + +chmod +x /usr/local/bin/sim-setup \ + /usr/local/bin/sim-start \ + /usr/local/bin/sim-app \ + /usr/local/bin/sim-sockets \ + /usr/local/bin/sim-migrate \ + /usr/local/bin/sim-generate \ + /usr/local/bin/sim-rebuild \ + /usr/local/bin/docs-dev \ + /usr/local/bin/pgc \ + /usr/local/bin/check-db diff --git a/.dockerignore b/.dockerignore index 98af3e0c6e5..6fa2fffb9b6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -26,6 +26,7 @@ docs/ # CI/CD and DevOps .github .devcontainer +!.devcontainer/install-commands.sh .husky docker-compose*.yml Dockerfile* From 0a9f320b749898fd4e3a4f0174f4c5c415e675f2 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 14:02:01 +0000 Subject: [PATCH 13/18] Use official devcontainer base image Co-authored-by: thanisch --- .devcontainer/Dockerfile | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b79e972d436..21a103fe72a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,8 @@ -FROM oven/bun:1.3.13 +FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 ENV DEBIAN_FRONTEND=noninteractive +ENV BUN_INSTALL=/home/bun/.bun +ENV PATH=/home/bun/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin RUN apt-get update \ && apt-get install -y --no-install-recommends \ @@ -20,27 +22,25 @@ RUN apt-get update \ pkg-config \ python3 \ postgresql-client \ + unzip \ && rm -rf /var/lib/apt/lists/* -# Create a non-root user with matching UID/GID ARG USERNAME=bun ARG USER_UID=1000 ARG USER_GID=$USER_UID -RUN if ! getent group $USER_GID >/dev/null; then \ - groupadd --gid $USER_GID $USERNAME; \ - fi - -RUN if ! getent passwd $USER_UID >/dev/null; then \ - useradd --uid $USER_UID --gid $USER_GID --create-home --shell /bin/bash $USERNAME; \ - fi - -# Add sudo support -RUN echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME +RUN if getent passwd vscode >/dev/null; then userdel -r vscode; fi \ + && if getent group $USER_GID >/dev/null; then groupmod -n $USERNAME "$(getent group $USER_GID | cut -d: -f1)"; else groupadd --gid $USER_GID $USERNAME; fi \ + && useradd --uid $USER_UID --gid $USER_GID --create-home --shell /bin/bash $USERNAME \ + && echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME RUN echo "export PATH=\$PATH:/home/$USERNAME/.bun/bin" >> /etc/profile +USER bun +RUN curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.13" +USER root + COPY .devcontainer/install-commands.sh /tmp/install-commands.sh RUN bash /tmp/install-commands.sh && rm /tmp/install-commands.sh From f4d727ef528931e58216f68144851dd49fe8da60 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 14:20:22 +0000 Subject: [PATCH 14/18] Create devcontainer tempdir for Cursor server Co-authored-by: thanisch --- .devcontainer/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 21a103fe72a..baa56a00f7f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,6 +2,7 @@ FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 ENV DEBIAN_FRONTEND=noninteractive ENV BUN_INSTALL=/home/bun/.bun +ENV TMPDIR=/home/bun/.cache/tmp ENV PATH=/home/bun/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin RUN apt-get update \ @@ -33,7 +34,9 @@ RUN if getent passwd vscode >/dev/null; then userdel -r vscode; fi \ && if getent group $USER_GID >/dev/null; then groupmod -n $USERNAME "$(getent group $USER_GID | cut -d: -f1)"; else groupadd --gid $USER_GID $USERNAME; fi \ && useradd --uid $USER_UID --gid $USER_GID --create-home --shell /bin/bash $USERNAME \ && echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ - && chmod 0440 /etc/sudoers.d/$USERNAME + && chmod 0440 /etc/sudoers.d/$USERNAME \ + && mkdir -p /home/$USERNAME/.cache/tmp /home/$USERNAME/.cursor-server \ + && chown -R $USERNAME:$USERNAME /home/$USERNAME/.cache /home/$USERNAME/.cursor-server RUN echo "export PATH=\$PATH:/home/$USERNAME/.bun/bin" >> /etc/profile From ab0fc4a3cc967586c26ef25eeedac9188a85c5b0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 14:25:48 +0000 Subject: [PATCH 15/18] Make sim setup tolerant of cache volume permissions Co-authored-by: thanisch --- .devcontainer/install-commands.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.devcontainer/install-commands.sh b/.devcontainer/install-commands.sh index d9a64bcb802..cdc5d795356 100644 --- a/.devcontainer/install-commands.sh +++ b/.devcontainer/install-commands.sh @@ -6,7 +6,8 @@ cat > /usr/local/bin/sim-setup <<'EOF' set -euo pipefail export TMPDIR="${TMPDIR:-$HOME/.cache/tmp}" mkdir -p "$TMPDIR" ~/.bun/cache -chmod 700 "$TMPDIR" ~/.bun ~/.bun/cache +sudo chown -R "$(id -u):$(id -g)" "$TMPDIR" ~/.bun >/dev/null 2>&1 || true +chmod 700 "$TMPDIR" >/dev/null 2>&1 || true cd /workspace bash fork-kit/bootstrap-fork.sh bun install From 4a926fc51004cb83e8580b7411335ce4a2ff779d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 15:45:28 +0000 Subject: [PATCH 16/18] Bind Next dev servers to all interfaces Co-authored-by: thanisch --- apps/docs/package.json | 2 +- apps/marketing/package.json | 2 +- apps/sim/package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 5dafcf46383..42e8640dcc4 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -4,7 +4,7 @@ "private": true, "license": "Apache-2.0", "scripts": { - "dev": "next dev --port 3001", + "dev": "next dev --hostname 0.0.0.0 --port 3001", "build": "fumadocs-mdx && NODE_OPTIONS='--max-old-space-size=8192' next build", "start": "next start", "postinstall": "fumadocs-mdx", diff --git a/apps/marketing/package.json b/apps/marketing/package.json index c67490bab6a..db9b4f9b5d3 100644 --- a/apps/marketing/package.json +++ b/apps/marketing/package.json @@ -4,7 +4,7 @@ "private": true, "license": "Apache-2.0", "scripts": { - "dev": "next dev --port 3003", + "dev": "next dev --hostname 0.0.0.0 --port 3003", "build": "next build", "start": "next start --port 3003", "type-check": "tsc --noEmit", diff --git a/apps/sim/package.json b/apps/sim/package.json index 31d799eac3c..cc610e23fe1 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -8,9 +8,9 @@ "node": ">=20.0.0" }, "scripts": { - "dev": "next dev --port 3000", + "dev": "next dev --hostname 0.0.0.0 --port 3000", "dev:clean": "rm -rf .next/dev/cache", - "dev:webpack": "next dev --webpack", + "dev:webpack": "next dev --hostname 0.0.0.0 --port 3000 --webpack", "load:workflow": "bun run load:workflow:baseline", "load:workflow:baseline": "BASE_URL=${BASE_URL:-http://localhost:3000} WARMUP_DURATION=${WARMUP_DURATION:-10} WARMUP_RATE=${WARMUP_RATE:-2} PEAK_RATE=${PEAK_RATE:-8} HOLD_DURATION=${HOLD_DURATION:-20} bunx artillery run scripts/load/workflow-concurrency.yml", "load:workflow:waves": "BASE_URL=${BASE_URL:-http://localhost:3000} WAVE_ONE_DURATION=${WAVE_ONE_DURATION:-10} WAVE_ONE_RATE=${WAVE_ONE_RATE:-6} QUIET_DURATION=${QUIET_DURATION:-5} WAVE_TWO_DURATION=${WAVE_TWO_DURATION:-15} WAVE_TWO_RATE=${WAVE_TWO_RATE:-8} WAVE_THREE_DURATION=${WAVE_THREE_DURATION:-20} WAVE_THREE_RATE=${WAVE_THREE_RATE:-10} bunx artillery run scripts/load/workflow-waves.yml", From 3b69a7ba1d7f8600ad80e901dd21278bdd8310fd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 15:47:24 +0000 Subject: [PATCH 17/18] Revert "Bind Next dev servers to all interfaces" This reverts commit 4a926fc51004cb83e8580b7411335ce4a2ff779d. --- apps/docs/package.json | 2 +- apps/marketing/package.json | 2 +- apps/sim/package.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 42e8640dcc4..5dafcf46383 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -4,7 +4,7 @@ "private": true, "license": "Apache-2.0", "scripts": { - "dev": "next dev --hostname 0.0.0.0 --port 3001", + "dev": "next dev --port 3001", "build": "fumadocs-mdx && NODE_OPTIONS='--max-old-space-size=8192' next build", "start": "next start", "postinstall": "fumadocs-mdx", diff --git a/apps/marketing/package.json b/apps/marketing/package.json index db9b4f9b5d3..c67490bab6a 100644 --- a/apps/marketing/package.json +++ b/apps/marketing/package.json @@ -4,7 +4,7 @@ "private": true, "license": "Apache-2.0", "scripts": { - "dev": "next dev --hostname 0.0.0.0 --port 3003", + "dev": "next dev --port 3003", "build": "next build", "start": "next start --port 3003", "type-check": "tsc --noEmit", diff --git a/apps/sim/package.json b/apps/sim/package.json index cc610e23fe1..31d799eac3c 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -8,9 +8,9 @@ "node": ">=20.0.0" }, "scripts": { - "dev": "next dev --hostname 0.0.0.0 --port 3000", + "dev": "next dev --port 3000", "dev:clean": "rm -rf .next/dev/cache", - "dev:webpack": "next dev --hostname 0.0.0.0 --port 3000 --webpack", + "dev:webpack": "next dev --webpack", "load:workflow": "bun run load:workflow:baseline", "load:workflow:baseline": "BASE_URL=${BASE_URL:-http://localhost:3000} WARMUP_DURATION=${WARMUP_DURATION:-10} WARMUP_RATE=${WARMUP_RATE:-2} PEAK_RATE=${PEAK_RATE:-8} HOLD_DURATION=${HOLD_DURATION:-20} bunx artillery run scripts/load/workflow-concurrency.yml", "load:workflow:waves": "BASE_URL=${BASE_URL:-http://localhost:3000} WAVE_ONE_DURATION=${WAVE_ONE_DURATION:-10} WAVE_ONE_RATE=${WAVE_ONE_RATE:-6} QUIET_DURATION=${QUIET_DURATION:-5} WAVE_TWO_DURATION=${WAVE_TWO_DURATION:-15} WAVE_TWO_RATE=${WAVE_TWO_RATE:-8} WAVE_THREE_DURATION=${WAVE_THREE_DURATION:-20} WAVE_THREE_RATE=${WAVE_THREE_RATE:-10} bunx artillery run scripts/load/workflow-waves.yml", From 440e916b9156853e3517ff0af92dcdba8ce04adf Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 11 Jun 2026 17:22:55 +0000 Subject: [PATCH 18/18] Add critters for Next CSS optimization Co-authored-by: thanisch --- apps/sim/package.json | 1 + bun.lock | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/apps/sim/package.json b/apps/sim/package.json index 31d799eac3c..eafe55da2f9 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -121,6 +121,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.0.0", + "critters": "0.0.25", "croner": "^9.0.0", "cronstrue": "3.3.0", "csv-parse": "6.1.0", diff --git a/bun.lock b/bun.lock index 6ebbf34de90..b9bdf8faeed 100644 --- a/bun.lock +++ b/bun.lock @@ -200,6 +200,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.0.0", + "critters": "0.0.25", "croner": "^9.0.0", "cronstrue": "3.3.0", "csv-parse": "6.1.0", @@ -2075,6 +2076,8 @@ "cpu-features": ["cpu-features@0.0.10", "", { "dependencies": { "buildcheck": "~0.0.6", "nan": "^2.19.0" } }, "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA=="], + "critters": ["critters@0.0.25", "", { "dependencies": { "chalk": "^4.1.0", "css-select": "^5.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.2", "htmlparser2": "^8.0.2", "postcss": "^8.4.23", "postcss-media-query-parser": "^0.2.3" } }, "sha512-ROF/tjJyyRdM8/6W0VqoN5Ql05xAGnkf5b7f3sTEl1bI5jTQQf8O918RD/V9tEb9pRY/TKcvJekDbJtniHyPtQ=="], + "croner": ["croner@9.1.0", "", {}, "sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g=="], "cronstrue": ["cronstrue@3.3.0", "", { "bin": { "cronstrue": "bin/cli.js" } }, "sha512-iwJytzJph1hosXC09zY8F5ACDJKerr0h3/2mOxg9+5uuFObYlgK0m35uUPk4GCvhHc2abK7NfnR9oMqY0qZFAg=="], @@ -3203,6 +3206,8 @@ "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], + "postcss-media-query-parser": ["postcss-media-query-parser@0.2.3", "", {}, "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig=="], + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], @@ -4143,6 +4148,10 @@ "concat-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "critters/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "critters/htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], + "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="], @@ -4571,6 +4580,8 @@ "concat-stream/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "critters/htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="], "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],