Skip to main content

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

  1. Build-Time Structure (CLI):
    • The @archibald/cli merges environment-specific files (e.g., prod.ts) into a config.js.
    • Secrets are stored as placeholders (e.g., url: "{{API_URL}}").
  2. Dotenv Loading (Server):
    • EnvironmentHelper.load() reads the .env file and populates process.env.
  3. Secret Injection (Server):
    • ConfigService requires the config.js and uses the fillInWithSecrets utility to replace placeholders with actual values from process.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()

  1. 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.
  2. Sequential Async Initialization: Server setup involves multiple async operations (loading remote configs, preloading assets, registering plugins). The async nature of bootstrap ensures that the server is only considered "Ready" after the entire chain is successfully completed.
  3. Adapter Layer for Serverless: In the template implementation, bootstrap is passed to the handler() 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.