Server Bootstrap Phase
Before the server starts, it must resolve its environment. Archibald strictly separates Static Structure from Dynamic Values to ensure secrets are never baked into build artifacts.
Configuration Flow
- Build-Time Structure (CLI):
- The
@archibald/climerges environment-specific files (e.g.,prod.ts) into aconfig.js. - Secrets are stored as placeholders (e.g.,
url: "{{API_URL}}").
- The
- Dotenv Loading (Server):
EnvironmentHelper.load()reads the.envfile and populatesprocess.env.
- Secret Injection (Server):
ConfigServicerequires theconfig.jsand uses thefillInWithSecretsutility to replace placeholders with actual values fromprocess.env.
The bootstrap() Entry Point
While the Configuration Flow handles the "what" (values), the bootstrap() function handles the "how" (execution). It is the critical orchestrator that bridges the gap between the static build and the running server.
Importance of bootstrap()
- Strategic Dependency Injection (DI) Hook: It provides a window to call
Container.provide()before any framework logic is instantiated. This allows project-specific implementations (e.g.,ProjectConfigService) to override core framework services. - Sequential Async Initialization: Server setup involves multiple async operations (loading remote configs, preloading assets, registering plugins). The
asyncnature ofbootstrapensures that the server is only considered "Ready" after the entire chain is successfully completed. - Adapter Layer for Serverless: In the template implementation,
bootstrapis passed to thehandler()from@archibald/vercel. This makes the function the bridge between a traditional long-running Node.js process and a stateless serverless execution environment.
Template Implementation
In a typical Archibald project (e.g., templates/shop), the bootstrap() function is located in src/shop/server/index.tsx. It follows a pattern of providing overrides and then delegating the heavy lifting to the Factory:
async function bootstrap() {
// Strategic Overrides
Container.provide([
{ provide: ConfigService, value: ProjectConfigService },
{ provide: PersistenceService, value: ProjectPersistenceService }
]);
// Factory Orchestration
const app = await Factory.create(Server); // Instantiates and calls .init()
await app.start(); // Starts the Hapi.js listener
return app;
}
export default handler(bootstrap);
Integration Diagram
The following diagram illustrates how the bootstrap() function integrates with the core packages and the server lifecycle.