App Startup Guide
Why app startup matters
In Zova, application startup is a structured lifecycle rather than a single opaque bootstrap step.
That matters because routing, guards, business initialization, and extension hooks often need to run at different startup phases.
App startup vs system startup
App startup is not the same as system startup.
In SSR scenarios especially, app startup can be request-scoped, while system startup is not.
This guide focuses on the application lifecycle after the lower-level system wiring is already in place. For system-level lifecycle hooks such as route registration and config loading, see System Startup Guide.
App startup timings
Zova provides three main app startup timings:
appInitializeappInitializedappReady
These timings allow business modules to run initialization logic at the earliest appropriate stage.
App shutdown timing
App shutdown is represented by:
appClose
Module load timings
The app lifecycle also intersects with module loading:
moduleLoadingmoduleLoaded
These allow module-aware logic to participate before or after the app becomes fully ready.
Hook response scenarios
Zova supports several implementation locations for these hooks:
- Module Main in a module-local main file
- Module Monkey in a module-local monkey file
- App Monkey in the project frontend config area
This makes startup behavior extensible at both module and project levels.
Hook interface model
Different hooks correspond to different interfaces depending on where they are implemented.
The important architectural point is not the exact interface matrix alone, but that startup behavior is typed and structured rather than improvised.
A compact mental model is:
- Module Main handles a module’s own loading lifecycle
- Module Monkey lets a module participate in app-wide hook timings
- App Monkey lets the project frontend config layer participate in the same hook system
Module Main
A module can provide its own main lifecycle entrypoints.
Representative creation command:
npm run zova :init:main demo-studentRepresentative pattern:
export class Main extends BeanSimple implements IModuleMain {
async moduleLoading() {}
async moduleLoaded() {}
}Module Monkey
A module can also provide broader app hook behavior through a monkey entry.
Representative creation command:
npm run zova :init:monkey demo-studentRepresentative pattern:
export class Monkey
extends BeanSimple
implements
IMonkeyModule,
IMonkeyAppInitialize,
IMonkeyAppInitialized,
IMonkeyAppReady,
IMonkeyAppClose
{
async moduleLoading(_module: IModule) {}
async moduleLoaded(_module: IModule) {}
async appInitialize() {}
async appInitialized() {}
async appReady() {}
async appClose() {}
}App Monkey
Project-level app lifecycle customization can be placed in the frontend config area.
This is useful when startup behavior belongs to the application as a whole rather than to one module.
Representative creation command:
npm run zova :init:appMonkeyRepresentative file location:
src/front/config/monkey.tsPractical interpretation of the phases
A useful rule of thumb is:
- use the earliest timing that still satisfies the need
- reserve later timings for behavior that depends on earlier framework or module setup already being finished
That keeps initialization extensible without creating unnecessary ordering coupling.
A representative lifecycle interpretation is:
appInitializefor the earliest app-level service setupappInitializedwhen other modules should be able to react to the initialized stateappReadyfor behavior that depends on the app becoming operational, such as final router-facing readinessappClosefor teardown and listener cleanup
Relationship to routing and guards
This page is the second half of the startup story: once system startup has registered routes and loaded config, app startup makes router services, guards, and first-screen navigation operational.
Startup timing is closely related to frontend routing and guards, because route services and route-guard behavior often need to be initialized before the app is considered ready.
The legacy startup docs explicitly used the router module as the core example:
appInitializeas an early route-guard service setup pointappInitializedas the point where route-guard events can begin involving other business modulesappReadyas the point where Vue Router can be injected and initial navigation can runappCloseas the teardown point for route-guard listeners
Read this guide together with Navigation Guards Guide when route lifecycle is involved.
A practical reading sequence is:
- System Startup Guide
- this page for router/guard readiness
- Page Route Guide
- Navigation Guards Guide
Relationship to environment/config selection
The chosen scripts, mode, appMode, and flavor determine which config and env values are active while startup hooks run.
Read this guide together with Environment and Config Guide.
Implementation checks for app-startup changes
When editing frontend startup behavior, ask:
- does this logic belong to app startup or system startup?
- what is the earliest safe hook timing for this behavior?
- should the logic live in module main, module monkey, or app monkey?
- does the behavior depend on routing, SSR, or environment-specific config already being ready?
That helps AI place initialization logic correctly instead of pushing everything into one late-stage bootstrap step.