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'`