@smbcloud / cli / commits / cc6389f

Deploy SvelteKit apps with kind = "sveltekit"

The vite-spa deploy path is now process_deploy_static_site.rs, and its record/rsync/mark-done flow is shared by both kinds. A sveltekit project builds with SvelteKitBuild and ships adapter-static's output, which defaults to build/ instead of dist/. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

keypair34 committed Sep 30, 2026 at 14:12 UTC cc6389f03311de02acdbf8da8f26f8ccc54ae739
4 files changed +55 -15
crates/cli/src/cloud-deploy/mod.rs
+1 -1
@@ -4,8 +4,8 @@ pub mod process_deploy;
4 pub mod process_deploy_nextjs_ssr;
5 pub mod process_deploy_rails;
6 pub mod process_deploy_rust;
7 +pub mod process_deploy_static_site;
8 pub mod process_deploy_swift;
8 -pub mod process_deploy_vite_spa;
9 pub mod process_migrate;
10 mod remote_messages;
11 pub(crate) mod setup_create_new_project;
crates/cli/src/cloud-deploy/process_deploy.rs
+6 -1
@@ -9,8 +9,8 @@ use {
9 process_deploy_nextjs_ssr::process_deploy_nextjs_ssr,
10 process_deploy_rails::process_deploy_rails,
11 process_deploy_rust::process_deploy_rust,
12 + process_deploy_static_site::{process_deploy_sveltekit, process_deploy_vite_spa},
13 process_deploy_swift::process_deploy_swift,
13 - process_deploy_vite_spa::process_deploy_vite_spa,
14 remote_messages::{build_next_app, start_server},
15 },
16 token::{get_smb_token::get_smb_token, is_logged_in::is_logged_in},
@@ -144,6 +144,11 @@ pub async fn process_deploy(
144 return process_deploy_vite_spa(env, config).await;
145 }
146
147 + // Route SvelteKit projects built with adapter-static: install + build, rsync the output.
148 + if config.project.kind.as_deref() == Some("sveltekit") {
149 + return process_deploy_sveltekit(env, config).await;
150 + }
151 +
152 // Route Next.js SSR projects: pnpm install + build, rsync 8 items, SSH pm2 restart.
153 if config.project.kind.as_deref() == Some("nextjs-ssr") {
154 return process_deploy_nextjs_ssr(env, config).await;
crates/cli/src/cloud-deploy/process_deploy_static_site.rs renamed
+46 -11
@@ -18,13 +18,53 @@ use {
18 };
19
20 pub async fn process_deploy_vite_spa(env: Environment, config: Config) -> Result<CommandResult> {
21 - // Resolve required SPA fields from the project config.
21 // `source` is the local directory containing the vite project (e.g. "frontend/connected-devices/").
22 // `path` is the remote destination on the server, consumed by rsync_deploy.
24 - let project_path = config.project.source.as_deref().unwrap_or(".");
25 - let output_dir = config.project.output.as_deref().unwrap_or("dist");
26 - let package_manager = config.project.package_manager.as_deref().unwrap_or("pnpm");
23 + let strategy = smbcloud_deploy::ViteSpaBuild {
24 + project_path: config.project.source.as_deref().unwrap_or(".").to_string(),
25 + output_dir: config
26 + .project
27 + .output
28 + .as_deref()
29 + .unwrap_or("dist")
30 + .to_string(),
31 + package_manager: config
32 + .project
33 + .package_manager
34 + .as_deref()
35 + .unwrap_or("pnpm")
36 + .to_string(),
37 + };
38 + deploy_static_build(env, config, &strategy).await
39 +}
40 +
41 +pub async fn process_deploy_sveltekit(env: Environment, config: Config) -> Result<CommandResult> {
42 + // adapter-static writes to `build/` unless svelte.config.js sets `pages`.
43 + let strategy = smbcloud_deploy::SvelteKitBuild {
44 + project_path: config.project.source.as_deref().unwrap_or(".").to_string(),
45 + output_dir: config
46 + .project
47 + .output
48 + .as_deref()
49 + .unwrap_or("build")
50 + .to_string(),
51 + package_manager: config
52 + .project
53 + .package_manager
54 + .as_deref()
55 + .unwrap_or("pnpm")
56 + .to_string(),
57 + };
58 + deploy_static_build(env, config, &strategy).await
59 +}
60
61 +/// Builds locally with `strategy`, then rsyncs the output to the project's
62 +/// remote `path` for nginx to serve as static files.
63 +async fn deploy_static_build(
64 + env: Environment,
65 + config: Config,
66 + strategy: &dyn BuildStrategy,
67 +) -> Result<CommandResult> {
68 // Fetch user for SSH key and deployment record.
69 let access_token = crate::token::get_smb_token::get_smb_token(env)?;
70 let user = me(env, client(), &access_token).await?;
@@ -32,16 +72,11 @@ pub async fn process_deploy_vite_spa(env: Environment, config: Config) -> Result
72 // ── Step 1: build locally (engine BuildStrategy) ─────────────────────────
73
74 let reporter = crate::ui::reporter::SpinnerReporter::new();
35 - let artifact = smbcloud_deploy::ViteSpaBuild {
36 - project_path: project_path.to_string(),
37 - output_dir: output_dir.to_string(),
38 - package_manager: package_manager.to_string(),
39 - }
40 - .build(&reporter)?;
75 + let artifact = strategy.build(&reporter)?;
76
77 // ── Step 2: record deployment as Started ─────────────────────────────────
78 //
44 - // A pure rsync SPA deploy has no git commit hash; use a UTC timestamp as a
79 + // A pure rsync static deploy has no git commit hash; use a UTC timestamp as a
80 // lightweight, non-empty identifier for the API record.
81
82 let deploy_ref = Utc::now().format("%Y%m%dT%H%M%SZ").to_string();
crates/smbcloud-model/src/project.rs
+2 -2
@@ -85,11 +85,11 @@ pub struct Project {
85 pub created_at: DateTime<Utc>,
86 #[serde(default = "default_datetime")]
87 pub updated_at: DateTime<Utc>,
88 - /// Deployment kind, e.g. "vite-spa", "nextjs-ssr", or "rust".
88 + /// Deployment kind, e.g. "vite-spa", "sveltekit", "nextjs-ssr", or "rust".
89 pub kind: Option<String>,
90 /// Local source directory to build from, e.g. "frontend/connected-devices"
91 /// or a Rust crate root like ".".
92 - /// Used by local-build deploys such as vite-spa, nextjs-ssr, and rust.
92 + /// Used by local-build deploys such as vite-spa, sveltekit, nextjs-ssr, and rust.
93 /// Distinct from `path`, which is the remote destination on the server.
94 pub source: Option<String>,
95 /// Build output directory relative to `source`, e.g. "dist".