SSR Build and Deploy Guide
This guide explains the public SSR build and deploy workflow in Zova within the Cabloy monorepo.
Why this page exists
The other SSR pages explain architecture, behavior, and troubleshooting.
This page answers a more operational question:
- how do you build and package SSR output correctly for Cabloy?
That matters because Cabloy SSR is a fullstack workflow, not only a frontend build command.
A complete SSR deployment path usually needs all of these pieces to stay aligned:
- the correct frontend SSR flavor build
- any related REST/type generation steps used by the target workflow
- the backend runtime that consumes the built frontend output
- environment/config choices that differ between dev and prod
Start from the shared root scripts
In Cabloy Basic, the root package.json is the first workflow surface.
Representative current root scripts include:
npm run dev:zova:admin
npm run dev:zova:web
npm run build:zova
npm run build:zova:admin
npm run build:zova:web
npm run buildA practical rule is:
- start from the root wrapper when the normal repo workflow already covers your need
- drop into deeper Zova flavor-specific scripts only when you need tighter control or debugging detail
Read together with:
Detect the edition first
Before documenting or automating SSR build commands, detect the active edition.
In the current public repo:
__CABLOY_BASIC__means Cabloy Basic- current public root wrappers target Basic-specific flavors such as
cabloyBasicAdminandcabloyBasicWeb
For Cabloy Start:
- the same high-level SSR workflow still applies
- but flavor names, site baselines, assets, and project paths can differ
- do not reuse Basic flavor examples blindly in Start-specific documentation or automation
Two common workflow levels
Level 1: root-wrapper workflow
Use this when you want the standard Cabloy Basic monorepo workflow.
Representative commands:
npm run dev:zova:admin
npm run dev:zova:web
npm run build:zova
npm run buildPractical interpretation:
dev:zova:*is for normal frontend SSR development entrybuild:zovabuilds frontend SSR output in batch modebuild:zova:adminandbuild:zova:webare explicit root-wrapper paths for flavor-specific SSR output plus related REST generationbuildis the fullstack alignment path when frontend and backend output should move together
Level 2: flavor-specific Zova workflow
Use this when you need appMode/flavor detail explicitly.
Representative current Basic examples include:
cd zova && npm run dev:ssr:cabloyBasicAdmin
cd zova && npm run dev:ssr:cabloyBasicWeb
cd zova && npm run build:ssr:cabloyBasicAdmin
cd zova && npm run build:ssr:cabloyBasicWeb
cd zova && npm run build:rest:cabloyBasicAdmin
cd zova && npm run build:rest:cabloyBasicWebThis level is useful when you need to separate:
- admin vs web
- SSR output vs REST/type output
- root-wrapper behavior vs lower-level flavor behavior
Development workflow
A normal SSR development workflow in Cabloy Basic is:
npm run dev:zova:adminor:
npm run dev:zova:webUse this when the task is:
- page development
- route debugging
- SSR UI iteration
- hydration behavior review
If you need deeper script control or need to verify the exact Zova flavor path, inspect the flavor-specific scripts described in Frontend Scripts.
Build workflow
Build frontend SSR output only
Use this when you need the frontend SSR artifacts refreshed but do not yet need the full backend build flow.
Representative current Basic command:
npm run build:zovaThis is the first useful step when:
- frontend SSR code changed
- static assets or SSR bundle output need regeneration
- you want to distinguish frontend build problems from backend runtime problems
Build the fullstack output together
Use this when frontend SSR output and backend runtime should be aligned in one workflow.
Representative current root command:
npm run buildIn the current repo, this means:
- build Zova SSR output first
- then build Vona
This is the safer default when a change crosses the frontend/backend SSR boundary.
Where REST/type generation fits
Some workflows need more than SSR HTML output alone.
In current Basic examples, there are separate REST/type generation commands such as:
cd zova && npm run build:rest:cabloyBasicAdmin
cd zova && npm run build:rest:cabloyBasicWebTreat these deliberately.
Use them when the workflow depends on generated contract-aligned frontend surfaces in addition to SSR bundle output.
Do not assume every SSR-only change needs manual extra regeneration, but do verify whether your target workflow depends on these generated artifacts.
Dev vs prod mindset
A frequent SSR mistake is assuming that “works in dev” means “ready for deploy.”
Dev and prod can differ in important ways:
- dev may proxy through a frontend dev server
- prod depends on built SSR output and built client assets
- asset path assumptions can differ after build
- runtime env/config choices can differ between dev and prod
That is why SSR deployment work should always include both:
- the build step
- a targeted verification pass against built behavior
Read together with:
Practical deployment checklist
Use this checklist before treating an SSR build as deploy-ready.
1. confirm the target edition and flavor
Ask:
- am I in Cabloy Basic or Cabloy Start?
- is this admin or web?
- am I using the correct SSR flavor for that target?
2. confirm the intended workflow level
Ask:
- is the root wrapper enough?
- do I need the lower-level Zova flavor script for this task?
- does the workflow also depend on REST/type generation?
3. rebuild the relevant frontend SSR output
Use the narrowest meaningful build first.
Typical options:
npm run build:zova- targeted
build:ssr:*commands insidezova
4. align backend and frontend when the change crosses the boundary
If the change affects the integrated SSR runtime path, prefer:
npm run buildThat reduces the chance of testing stale frontend output against newer backend code or the reverse.
5. verify built behavior, not only dev behavior
At minimum, re-check:
- the expected page loads through SSR
- client assets load correctly
- hydration behaves as expected
- no edition-specific UI/theme assumption breaks the real target flavor
Common deployment mistakes
Mistake 1: only testing dev mode
Dev success does not prove that the built SSR bundle and built client assets are correct.
Mistake 2: building the wrong flavor
A command can succeed while still producing output for the wrong target.
Always confirm whether the target is:
- Basic vs Start
- admin vs web
- root-wrapper path vs direct flavor script
Mistake 3: forgetting the fullstack boundary
If the issue appears only after frontend/backend integration, a frontend-only build check may be insufficient.
Use the fullstack build path when the change crosses the SSR boundary.
Mistake 4: assuming deploy problems are page-logic problems
Some SSR deploy failures come from stale output, missing assets, wrong flavor selection, or env/config mismatch before they come from page logic itself.
How this guide relates to other SSR docs
Use these pages together:
- SSR Overview for the baseline SSR feature model
- SSR Architecture Overview for the fullstack mental model
- SSR Troubleshooting Guide for symptom-based diagnosis
- Frontend Scripts for script lookup
- Environment and Config Guide for runtime/config selection
- Fullstack Vona + Zova Integration for the monorepo integration model
Recommended reading order
If you are deploying or packaging SSR behavior, use this path:
- this page for build/deploy workflow
- Frontend Scripts
- Environment and Config Guide
- SSR Architecture Overview
- SSR Troubleshooting Guide
- Fullstack Vona + Zova Integration
Implementation checks for SSR build/deploy changes
Before finalizing an SSR build/deploy change, ask:
- did I detect the correct edition and target flavor first?
- did I choose the right workflow level: root wrapper or lower-level flavor script?
- did I rebuild the relevant frontend SSR output?
- if the change crosses the frontend/backend SSR boundary, did I verify the aligned fullstack build path?
- did I verify built behavior rather than relying only on dev behavior?
That keeps SSR deployment guidance aligned with the real Cabloy monorepo workflow rather than with generic frontend-only assumptions.