@smbcloud / cli / commits / 64ec8a6

Document the sveltekit deploy kind

Adds sveltekit to the kind list in AGENTS.md and to the monorepo skill: an example [[projects]] entry, the field defaults, the build steps, and the adapter-static and nginx fallback settings a client-rendered app needs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

keypair34 committed Sep 30, 2026 at 14:13 UTC 64ec8a647dd23b774ba42868648e0136819cf8ed
2 files changed +43 -10
.agents/AGENTS.md
+1 -1
@@ -130,7 +130,7 @@ Two cross-cutting globals are resolved once in `main` before any handler runs:
130
131 ## Deploy subsystem (`crates/cli/src/deploy/`)
132
133 -The most involved area. `process_deploy.rs` loads `.smb/config.toml` (running interactive `setup_project` if missing), overlays server-side config, validates project access, then **dispatches by `config.project.kind`** to a per-stack path: `vite-spa`, `nextjs-ssr`, `rails`, `rust`, `swift` each have their own `process_deploy_*.rs`. If `kind` is unset it falls back to `deployment_method`: `Rsync` (build locally, upload over rsync, restart over SSH) or `Git` (push to a remote git hook), with `detect_runner.rs` sniffing the framework from `package.json`/`Gemfile`/`Package.swift`/`Cargo.toml`.
133 +The most involved area. `process_deploy.rs` loads `.smb/config.toml` (running interactive `setup_project` if missing), overlays server-side config, validates project access, then **dispatches by `config.project.kind`** to a per-stack path: `vite-spa` and `sveltekit` (SvelteKit with `adapter-static`) share `process_deploy_static_site.rs`; `nextjs-ssr`, `rails`, `rust`, `swift` each have their own `process_deploy_*.rs`. If `kind` is unset it falls back to `deployment_method`: `Rsync` (build locally, upload over rsync, restart over SSH) or `Git` (push to a remote git hook), with `detect_runner.rs` sniffing the framework from `package.json`/`Gemfile`/`Package.swift`/`Cargo.toml`.
134
135 **Monorepo**: `runner = Monorepo` with a `[[projects]]` array in config; `smb deploy --project <name>` (or an interactive picker) swaps `config.project` to the named sub-project before the dispatch above. `migrate.rs`/`smb migrate` pushes local deploy fields up to the server.
136
.agents/skills/smbcloud-deploy-monorepo/SKILL.md
+42 -9
@@ -1,6 +1,6 @@
1 ---
2 name: smbcloud-deploy-monorepo
3 -description: Use when deploying from a monorepo with smbCloud CLI, especially repositories that contain multiple deployable sub-projects with different strategies (Next.js SSR, Vite SPA, Rails, static) behind a single `.smb/config.toml` with `runner = 255` and `[[projects]]` entries.
3 +description: Use when deploying from a monorepo with smbCloud CLI, especially repositories that contain multiple deployable sub-projects with different strategies (Next.js SSR, Vite SPA, SvelteKit, Rails, static) behind a single `.smb/config.toml` with `runner = 255` and `[[projects]]` entries.
4 ---
5
6 # smbCloud Deploy Monorepo
@@ -12,7 +12,7 @@ Applies to:
12 - repositories with `runner = 255` in `[project]`
13 - `.smb/config.toml` files with `[[projects]]` arrays
14 - `process_deploy.rs` monorepo resolution logic
15 -- sub-project routing to `nextjs-ssr`, `vite-spa`, `rails`, rsync, or git deploy paths
15 +- sub-project routing to `nextjs-ssr`, `vite-spa`, `sveltekit`, `rails`, rsync, or git deploy paths
16 - multi-tenant PM2 and Nginx server configuration
17 - CI workflows that deploy individual sub-projects from a monorepo
18
@@ -121,6 +121,20 @@ output = "dist"
121 package_manager = "pnpm"
122 created_at = "2025-09-20T16:33:05.154Z"
123 updated_at = "2025-09-20T16:33:05.154Z"
124 +
125 +[[projects]]
126 +id = <n>
127 +name = "<app>"
128 +repository = "<app>"
129 +description = "SvelteKit app built with adapter-static."
130 +source = "apps/<app>"
131 +path = "apps/web/<app>"
132 +runner = 0
133 +kind = "sveltekit"
134 +output = "build"
135 +package_manager = "pnpm"
136 +created_at = "2025-09-20T16:33:05.154Z"
137 +updated_at = "2025-09-20T16:33:05.154Z"
138 ```
139
140 ## Sub-project field reference
@@ -134,13 +148,13 @@ updated_at = "2025-09-20T16:33:05.154Z"
148 | `repository` | yes | remote repository name on the smbCloud server (used for git deploy and SSH paths) |
149 | `description` | no | human-readable description |
150 | `source` | yes | local path to the sub-project directory, relative to the monorepo root |
137 -| `path` | depends | remote directory on the server, relative to `~/` — required for `nextjs-ssr` and `vite-spa` |
151 +| `path` | depends | remote directory on the server, relative to `~/`, required for `nextjs-ssr`, `vite-spa`, and `sveltekit` |
152 | `runner` | yes | server tier: `0` (NodeJs), `1` (Static), `2` (Ruby), `3` (Swift) |
139 -| `kind` | depends | deploy strategy: `"nextjs-ssr"`, `"vite-spa"`, `"rails"`, or omitted for generic deploy |
140 -| `package_manager` | depends | `"pnpm"` or `"npm"` — required for `nextjs-ssr` and `vite-spa` |
153 +| `kind` | depends | deploy strategy: `"nextjs-ssr"`, `"vite-spa"`, `"sveltekit"`, `"rails"`, or omitted for generic deploy |
154 +| `package_manager` | depends | `"pnpm"` or `"npm"`, used by `nextjs-ssr`, `vite-spa`, and `sveltekit`; defaults to `"pnpm"` |
155 | `pm2_app` | depends | PM2 process name — required for `nextjs-ssr` |
156 | `port` | depends | runtime port — required for `nextjs-ssr`, defaults to `3000` if omitted |
143 -| `output` | depends | build output directory — required for `vite-spa`, typically `"dist"` |
157 +| `output` | depends | build output directory: `vite-spa` defaults to `"dist"`, `sveltekit` to `"build"` |
158 | `shared_lib` | no | path to shared library directory to rsync before deploy — used by `rails` |
159 | `compile_cmd` | no | SSH command to run on the server after syncing shared libs — used by `rails` |
160 | `deployment_method` | no | `0` (Git) or `1` (Rsync) — only matters when `kind` is not set |
@@ -163,6 +177,7 @@ smb deploy --project <name>
177 ┌────┼──────────┬──────────────┐
178 ▼ ▼ ▼ ▼
179 vite-spa nextjs-ssr rails (none)
180 + sveltekit
181 │ │ │ │
182 ▼ ▼ ▼ ▼
183 pnpm pnpm rsync deployment_method?
@@ -190,6 +205,23 @@ Local build, rsync the output directory. No PM2 — Nginx serves static files di
205
206 Required fields: `kind`, `source`, `path`, `output`, `package_manager`
207
208 +A plain Svelte + Vite app (no SvelteKit) is a `vite-spa`.
209 +
210 +### Strategy: `sveltekit`
211 +
212 +SvelteKit built with `@sveltejs/adapter-static`. Shares the `vite-spa` ship path (`process_deploy_static_site.rs`); only the build differs:
213 +
214 +1. Read the adapter from `package.json`. Anything other than `adapter-static` (`adapter-auto`, `adapter-node`, …) fails before building, naming the adapter. Server-rendered SvelteKit needs a Node process, which this path doesn't manage.
215 +2. `<package_manager> install`, then `<package_manager> run build`, inside `source/`, with the terminal attached.
216 +3. Check `output` (default `build`) has a top-level `.html` file: a prerendered `index.html` or an SPA fallback such as `200.html`.
217 +4. Rsync `output/` to `path`.
218 +
219 +Required fields: `kind`, `source`, `path`
220 +
221 +Optional: `output` (default `"build"`, match `pages` in `adapter-static`), `package_manager` (default `"pnpm"`)
222 +
223 +For a client-rendered app, set `fallback` in `adapter-static` and keep `paths.relative: false` in `svelte.config.js`, so deep links load assets from `/_app/` instead of a relative path. Nginx needs a matching `try_files $uri $uri/ /<fallback>;`. Use `200.html` rather than `index.html` as the fallback when `/` is prerendered, so deep links don't boot from the landing page's markup.
224 +
225 ### Strategy: `rails`
226
227 Rsync shared libraries, SSH compile native extensions, git force-push the sub-project directory to the server's bare repo (triggers post-receive hook).
@@ -206,7 +238,7 @@ When `kind` is omitted, the `deployment_method` field controls the path. Git pus
238
239 The `source` field is the most important monorepo-specific field. It tells the CLI where the sub-project lives relative to the monorepo root.
240
209 -For `nextjs-ssr` and `vite-spa`, the CLI changes into the `source` directory before running build commands:
241 +For `nextjs-ssr`, `vite-spa`, and `sveltekit`, the CLI changes into the `source` directory before running build commands:
242
243 - `pnpm install` runs inside `source/`
244 - `pnpm build` runs inside `source/`
@@ -486,14 +518,14 @@ Current tracking model in the CLI:
518 - requests still route through the umbrella workspace `id`
519 - when `frontend_app_id` is present in the deploy target config, the payload also carries it so the API can attribute the deploy to the correct app inside the repo or monorepo
520
489 -For non-git deploys (rsync, nextjs-ssr, vite-spa), the `commit_hash` field is a UTC timestamp (`20250920T163305Z`) since there is no git commit on the deploy path.
521 +For non-git deploys (rsync, nextjs-ssr, vite-spa, sveltekit), the `commit_hash` field is a UTC timestamp (`20250920T163305Z`) since there is no git commit on the deploy path.
522
523 ## Adding a new sub-project to a monorepo
524
525 1. Create the project in smbCloud (via `smb init` in a temporary directory, or the web console) to get an `id`
526 2. Add a `[[projects]]` entry to the monorepo's `.smb/config.toml` with the correct `kind`, `source`, `path`, `runner`, and strategy-specific fields
527 3. If `kind = "nextjs-ssr"`: allocate a unique port, configure PM2 ecosystem file on the server, add Nginx reverse proxy config
496 -4. If `kind = "vite-spa"`: add Nginx static file config
528 +4. If `kind = "vite-spa"` or `kind = "sveltekit"`: add Nginx static file config (with an SPA fallback `try_files` for client-rendered SvelteKit)
529 5. If `kind = "rails"`: set up a bare git repo on the server with a post-receive hook
530 6. Test with `smb deploy -p <name>`
531
@@ -609,6 +641,7 @@ If you are changing env manually outside the deploy flow, `pm2 restart <app> --u
641 - forgetting to set `runner = 255` on the root `[project]` of a monorepo — the CLI treats it as a standalone project and tries to deploy the root
642 - duplicating `port` values across sub-projects on the same server
643 - using `kind = "nextjs-ssr"` on a project without `output: "standalone"` in its Next.js config
644 +- using `kind = "sveltekit"` with `adapter-auto` or `adapter-node`; switch `svelte.config.js` to `adapter-static` instead
645 - running `smb deploy` from a subdirectory instead of the monorepo root — `source` paths will not resolve
646 - forgetting `--mkpath` on rsync in CI workflows — first deploys fail because the remote directory does not exist
647 - forgetting `--copy-links` on `.next/standalone/` uploads — the server receives broken `pnpm` symlinks and PM2 crashes with `Cannot find module 'next'`