Inside the entry file at main.ts we collect all the layers and execute them in a nodejs server (node:http).
We create a ConfigProvider that extracts environmental variables from dotenv using PlatformConfigProvider.fromDotEnv:
With
@effect/platformyou don't need to installdotenv.
const DotEnvConfigProvider = PlatformConfigProvider.fromDotEnv(".env").pipe(
  Effect.map(Layer.setConfigProvider), // 👈 Layer from `ConfigProvider`
  Layer.unwrapEffect // 👈 From `Effect` to `Layer`
);We compose the main app layer from HttpApiBuilder.api, providing all the required dependencies:
const MainApiLive = HttpApiBuilder.api(MainApi).pipe(
  Layer.provide(PaddleApiLive),
  Layer.provide(DotEnvConfigProvider)
);It's recommended to provide all the dependencies at the service level, so that the final
mainonly contains the coreHttplayers:
dependencieswhen usingEffect.Service
Layer.providewhen usingContext.Tag
The server is based on HttpApiBuilder.serve, providing a NodeHttpServer layer that creates the server using node:http on port 3000:
const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe(
  Layer.provide(HttpApiBuilder.middlewareCors()),
  Layer.provide(MainApiLive),
  HttpServer.withLogAddress,
  Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 }))
);main.ts is then executed using NodeRuntime to start the server:
Layer.launch(HttpLive).pipe(NodeRuntime.runMain);The final result is as follows:
import { MainApi } from "@app/api-client";
import {
  HttpApiBuilder,
  HttpMiddleware,
  HttpServer,
  PlatformConfigProvider,
} from "@effect/platform";
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node";
import { Effect, Layer } from "effect";
import { createServer } from "node:http";
import { PaddleApiLive } from "./paddle-api";
const DotEnvConfigProvider = PlatformConfigProvider.fromDotEnv(".env").pipe(
  Effect.map(Layer.setConfigProvider),
  Layer.unwrapEffect
);
const MainApiLive = HttpApiBuilder.api(MainApi).pipe(
  Layer.provide(PaddleApiLive),
  Layer.provide(DotEnvConfigProvider)
);
const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe(
  Layer.provide(HttpApiBuilder.middlewareCors()),
  Layer.provide(MainApiLive),
  HttpServer.withLogAddress,
  Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 }))
);
Layer.launch(HttpLive).pipe(NodeRuntime.runMain);Now executing pnpm run dev will use tsx to execute main.ts and start the server.
"scripts": {
  "dev": "tsx watch src/main.ts",
  "typecheck": "tsc"
}pnpm run dev