Guides

Application services

A guide to structuring application logic and dependencies with Effect services.

Use Effect services to keep application logic separate from the Pages that call it. The greeting example gives a Page a replaceable service, with its implementation and lifetime managed through an Effect Layer.

Use a service in a Page

Create src/greeting.ts:

import { Context, Effect, Layer } from "effect";

export class Greeting extends Context.Service<
  Greeting,
  { readonly message: (name: string) => Effect.Effect<string> }
>()("app/services/Greeting") {
  static readonly layer = Layer.succeed(Greeting, {
    message: (name) => Effect.succeed(`Hello, ${name}.`),
  });
}

In src/entry.effront.tsx, declare Greeting, read it in the Page, and provide its Layer:

// src/entry.effront.tsx: add to the imports.
import { Greeting } from "./greeting";

// Replace EFFRONT.
const EFFRONT = Application.effront<Greeting>();

// Replace HomePage.
const HomePage = EFFRONT.Page.make({
  render: Effect.fn("HomePage.render")(function* () {
    const greeting = yield* Greeting;
    const message = yield* greeting.message("Ada");
    return <h1>{message}</h1>;
  }),
});

// Replace the default export with this route declaration and export.
const routes = EFFRONT.Routes.make({ layout: RootLayout }).page("/", HomePage);

export default EFFRONT.make({ routes, layer: Greeting.layer });

Open / to see Hello, Ada. To replace the implementation, pass another Layer that provides Greeting without changing the Page.

Choose the service scope

Application services are available to Pages, Layouts, Components, and Server Functions created from the same EFFRONT. For multiple services, declare a union such as Application.effront<ServiceA | ServiceB>() and supply a Layer that provides both. See Effect's Services and Layers guides for composition.

Effront builds the application Layer for each request. Scoped resources remain available through response-body completion, failure, or cancellation, not just until a Page returns JSX.

Fix missing-service errors

Error locationCheck
Page renderDeclare the service in Application.effront<Services>(), or use a Middleware-equipped definition.
EFFRONT.makeSupply layer when application services are declared.
The supplied LayerProvide every declared service. Layer.empty cannot provide Greeting.

For Middleware-provided services, fix the active scope rather than adding an application-wide implementation to suppress the error.