Dev Workflow Overview
This page answers one practical question: what order should you follow when developing apps for Lazycat microservice?
If you only remember one thing, remember this:
- Frontend development: run
project deploy, open the app, then start the local dev server. - Backend development: run
project deploy, open the app, then sync code into the real runtime and start the process manually. - Release: always build the release package from
lzc-build.ymland final artifacts.
Goal
After this page, you should be clear about:
- Which files belong to development and which belong to release.
- Why frontend traffic is redirected to the dev machine.
- Why backend code is expected to run inside the real microservice runtime.
- When to use
project deploy,project sync --watch, andproject release.
Workflow Map At A Glance
The core decision is simple:
- If you are changing frontend code, redirect traffic to the dev machine.
- If you are changing backend code, move the code into the real microservice runtime.
- If you are publishing, keep only release artifacts.
Prerequisites
Before starting, assume you have already done the following:
- Finished Environment Setup.
- Successfully completed Hello World in 5 Minutes at least once.
- Verified that local
lzc-clican reach the target microservice. - Know the basic files in your project root.
Build One Mental Model First
The recommended workflow is easiest to understand with these three layers:
lzc-build.ymlPurpose: the release build config.lzc-build.dev.ymlPurpose: the development override config that only stores dev-specific differences.lzc-manifest.ymlPurpose: the stable app runtime structure; dev-only logic is enabled or removed by#@buildpreprocessing.
A typical project usually keeps these four files:
lzc-manifest.ymlpackage.ymllzc-build.ymllzc-build.dev.yml
A minimal dev config often looks like this:
pkg_id: org.example.todo.dev
envs:
- DEV_MODE=1The important parts are:
pkg_id: org.example.todo.devPurpose: prevent dev deployment from overwriting the release app.DEV_MODE=1Purpose: make dev-only#@buildblocks inlzc-manifest.ymlactive only in development.
Which Build Config Do project Commands Use
If lzc-build.dev.yml exists, these commands prefer it by default:
lzc-cli project deploylzc-cli project infolzc-cli project startlzc-cli project execlzc-cli project cplzc-cli project synclzc-cli project log
Every command prints the active Build config line, which tells you which build config file is actually in use.
If you want the release config explicitly, add --release:
lzc-cli project deploy --release
lzc-cli project info --releaseproject release always uses lzc-build.yml.
Why Dev Logic Belongs to Request Inject
The core of this workflow is request inject.
The reason is straightforward:
- For frontend development, browser traffic must be redirected to the dev server running on the dev machine.
- For backend development, requests may need to return a guide page, proxy to a service in the container, or proxy to the dev machine depending on runtime state.
- All of these behaviors belong to request handling, so request inject is the natural place for them.
The recommended pattern is:
- Keep release routes stable.
- Put dev-only inject logic inside
#@build if env.DEV_MODE=1. - This ensures the release package does not physically contain development-only request splitting logic.
Minimal example:
application:
routes:
- /=file:///lzcapp/pkg/content/dist
#@build if env.DEV_MODE=1
injects:
- id: dev-entry
on: request
when:
- "/*"
do:
- src: |
// dev-only request inject
#@build endFrontend Development Path
Frontend Flow Diagram
When To Use It
Use this path when your frontend runs on the dev machine, for example with:
npm run devThe app entry traffic is redirected to that dev machine by request inject.
Recommended Order
lzc-cli project deploylzc-cli project info- Open the app first
- Then run
npm run dev - Refresh the page and continue development
Why Open the App Before Starting the Dev Server
This gives you three immediate benefits:
- You can confirm whether the instance is already linked to the dev machine.
- The page tells you which port the inject script is actually waiting for.
- If the dev machine is offline, or the instance has not synced its dev-machine link yet, the page gives explicit guidance instead of showing only a blank page or a generic proxy error.
Typical Request Flow
- The browser opens the app domain on the microservice.
- Request inject first checks whether this instance is already linked to a dev machine.
- If it is linked, the request is forwarded to that machine through the client tunnel.
- The frontend dev server returns the page and hot-reload results.
How To Verify Success
Any of the following means the frontend flow is working:
- The page stops showing the “waiting for development environment” guide and shows your real dev page.
- Changes in files like
src/App.vueappear after refresh. project log -fno longer reports that the dev machine is offline or unavailable.
Terminology Note
In implementation terms, this dev-machine link maps to ctx.dev.id in the inject context. At the getting-started level, you only need to understand it as: the app instance knows which dev machine should receive development traffic.
Backend Development Path
Backend Flow Diagram
When To Use It
Use this path when backend code must run inside the real microservice runtime, for example when it depends on:
- Real
/lzcapp/runor/lzcapp/varpaths. - Runtime sockets, mounts, permissions, or real container networking.
- A runtime environment that is hard to simulate fully on the dev machine.
Recommended Order
lzc-cli project deploylzc-cli project info- Open the app first
- If the page says the backend is not ready, then start sync and the backend process
- Refresh again after the backend is ready
A common loop looks like this:
lzc-cli project sync --watch
lzc-cli project exec /bin/sh
# inside container
/app/run.shWhy Backend Development Is Not Centered On Local Simulation
Because at this stage you are validating how the code behaves inside the real microservice runtime, not only whether the code is syntactically correct or logically valid.
That means the real questions are:
- Can the backend start correctly in the real container?
- Does it behave correctly with real
/lzcapp/*paths? - Can request inject switch traffic based on real backend readiness?
Current Template Guidance
The current template direction is roughly:
golang- Dev mode does not auto-start the backend.
- You build and start it manually for full control.
springboot- Dev mode does not auto-start the backend.
python/node- These are better suited for a dev service that runs directly, with request inject forwarding traffic to it.
How To Verify Success
Any combination of the following usually means the backend path is working:
project sync --watchkeeps syncing without errors.project exec /bin/shenters the container and lets you start the backend manually.- The app page switches from a backend guide page to the real business response.
- Requests are correctly forwarded by request inject after refresh.
Release Path
The goal of release is simple: produce a clean, stable LPK without development-side effects.
What A Release Package Should Look Like
- It uses
lzc-build.yml. - It does not carry the dev-only
pkg_idoverride. - It does not include dev-only
#@buildbranches. - The image contains only final artifacts, not dev toolchains.
- If release does not need static content,
contentdircan be omitted.
Release Command
lzc-cli project release -o app.lpkHow To Verify The Release Package Is Clean
At minimum, check these points:
- The package name does not contain
.devor a similar suffix. - The packaged manifest does not contain dev-only inject blocks.
- The release image is not built from
Dockerfile.devor another dev alias. - The release package works without the dev machine being online.
A Simple Decision Table
When you are unsure which path to use, decide from this table:
| Your Goal | Use This | Do Not Start With |
|---|---|---|
| Change UI and iterate with hot reload | project deploy + open app + npm run dev | Do not start from release packaging |
Change backend code that depends on real /lzcapp/* runtime | project deploy + project sync --watch + project exec | Do not prioritize full local runtime simulation |
| Build a package for others to install | project release | Do not treat a dev deployment result as the release package |
Common Errors
1. Dev changes overwrite the release app
This usually means:
- The project does not have
lzc-build.dev.yml. - Or it exists but does not contain a dedicated dev
pkg_id.
Fix:
- Check whether
lzc-build.dev.ymlexists. - Check the printed
Build configline in command output. - Check whether a dedicated dev
pkg_idsuch aspkg_id: org.example.todo.devis present.
2. The page keeps showing a waiting-for-development guide
This usually means:
- The frontend dev server is not started.
- The instance has not synced its dev-machine link yet.
- The dev machine is offline.
Fix:
- Run
lzc-cli project deployagain. - Start
npm run dev. - Refresh and compare the actual listening port with the port shown on the guide page.
3. Backend code is synced, but the app still does not work
This usually means:
- The backend process did not really start.
- The request inject target does not match the actual listening address.
- The service has started but is not ready yet.
Fix:
- Use
lzc-cli project exec /bin/shto verify inside the container. - Use
lzc-cli project log -ffor runtime logs. - Compare the actual backend address with the request inject target and ready condition.
Next Step
Continue in this order:
- If you have not run the workflow once yet, go back to Hello World in 5 Minutes.
- If you want to write request inject rules, continue with Request Inject Dev Cookbook.
- If you want to connect a backend over HTTP, continue with HTTP Routing with Backend.
- If you want the exact build field definitions, continue with lzc-build.yml Specification.