# Structure an Effect codebase by domain

> For agents: start with the [agent guide](https://ratstack.sh/llms.txt). Every page is Markdown by default; add `Accept: text/html` for HTML.

Free workshop: [how to burn a trillion tokens and get good results](/tokenmaxx#interested).

Group files by domain: `src/coding/edit.ts` puts an edit operation with the coding work it belongs to.
Keep one service and its Layer in each file. Capture dependencies when building the service, so callers need only that service.

At each entrypoint, assemble and provide Layers in a composition root. Keep platform adapters behind service ports.

[Justin Bennett asked about folders and service organization](https://x.com/just_be_dev/status/2107194260860613059).
[Sam Goodwin's answer](https://x.com/samgoodwin89/status/2107204053151428850):

> src/{domain} instead of src/{mechanism}. E.g. src/coding/edit.ts instead of src/tools/edit.ts. "tools" is the mechanism, "coding" is the domain.

## The shape in one tree

A small app can use this layout:

```text
src/
├── files/
│   ├── file-inspector.ts    Service, dependency capture, Layer
│   ├── stats.ts             Schema and expected errors
│   └── inspect-machine.ts   Optional finite lifecycle
├── platform/
│   └── files-node.ts        Platform adapter Layer
└── main.ts                  Composition root and runtime entrypoint
test/
└── files/
    └── file-inspector.test.ts
```

Domain folders own behavior. `platform` supplies implementations.
rat-stack separates these jobs into packages; a small app can keep them in one package.

## The rules that hold it together

### Capture dependencies when constructing a service

Keep the service interface and its Layer together.
`FileInspector` captures `FileSystem` during construction. Its methods have no filesystem requirement.

packages/core/src/file-inspector.ts at 54d356037c994f89698760a4727be71d0005a087; lines 6-16,33-35; highlighted none.

```typescript
export class FileInspector extends Context.Service<
  FileInspector,
  {
    readonly inspect: (
      path: string
    ) => Effect.Effect<FileStats, FileStatsError>;
  }
>()("@rat-stack/core/FileInspector", {
  make: Effect.gen(function* makeFileInspector() {
    const fileSystem = yield* FileSystem.FileSystem;

}) {
  static readonly layer = Layer.effect(this, this.make);
}
```

**What to notice:** Construction needs the dependency; callers need only `FileInspector`.
See [service construction](/lore/services-capture-dependencies) for the full pattern.

### Provide Layers at the entrypoint

The composition root chooses implementations and supplies the application's service graph.
Give each entrypoint its own root. Our CLI assembles dependencies before running the program.

apps/cli/src/cli.ts at 54d356037c994f89698760a4727be71d0005a087; lines 16-25; highlighted none.

```typescript
  Effect.provide(
    Layer.mergeAll(
      Layer.provideMerge(FileInspector.layer, NodeServices.layer),
      remoteJoinInterestLayer,
      Approval.denyAll
    )
  )
);

NodeRuntime.runMain(program);
```

`Effect.provide` resolves requirements before `NodeRuntime.runMain` runs the final Effect.
See [Layer composition](/lore/layers-make-dependencies-explicit).

### Keep ports inside and adapters outside

Domain code uses a service interface that names the application's job.
Core owns `SubscriberIntake`; `packages/subscriber-delivery` implements it. Apps provide that implementation.
See [hexagonal architecture](/lore/hexagonal-architecture).

### Keep related definitions with the domain

- Put input, output, and failure schemas in the domain's contract. [Decode at boundaries with Schema](/lore/schemas-define-the-boundary).
- Declare expected failures with useful context. `FileStatsError` keeps the failed path and filesystem reason. See [the error model](/lore/error-model).
- In rat-stack, a [machine](/lore/lifecycles-are-machines) owns finite modes, cancellation, or legal event sequences. Keep it beside the behavior it controls.
- Mirror domain folders in tests. [Supply test services through Layers](/lore/tests-that-earn-their-place).

## House style versus Effect idiom

| Take the Effect idiom             | rat-stack adds                                       |
| --------------------------------- | ---------------------------------------------------- |
| Services and composable Layers    | Colocated `make` and `static layer`                  |
| Schema-backed boundaries          | Capability contracts and derived surface projections |
| Replaceable implementations       | Cartridges with an add/remove test                   |
| Typed failures and scoped effects | XState lifecycles through `@xstate/effect`           |
| Effect-aware tests                | Property/model testing and a manual-runtime ban      |
| Explicit requirements             | A type-aware lint fence                              |
| No prescribed comment policy      | No prose comments in code                            |

## Where disagreement lives

Sam favors domain folders. Effect leaves folder layout to the application.
Sam also calls one API route per file potentially controversial. rat-stack keeps one capability per file and derives routes.
Choose monorepo versus single-package layout separately from the service graph.

New to Effect? Start with [Effect basics](/lore/effect-basics).

## Sources

1. [Folder layout and service organization](https://x.com/just_be_dev/status/2107194260860613059)
   Justin Bennett. Asks about both concerns and gives src/platform as an example. Accessed 2026-10-06.

2. [One service and Layer per file](https://x.com/samgoodwin89/status/2107204053151428850)
   Sam Goodwin. Recommends domain folders, colocated services and Layers, and entrypoint-level provision. Accessed 2026-10-06.

3. [Effect documentation](https://effect.website/docs)
   Effect. Starting point for maintained concepts and versioned documentation. Accessed 2026-10-05.

4. [Effect contributors. 2026. Context.Service. Effect 4.0.0.](https://github.com/Effect-TS/effect/blob/67ba4e46a11ccda0b6761578bfd22c04ae00167d/ai-docs/src/01_effect/03_services/01_service.ts)
   Effect-TS. Exact-tag service guidance colocates a service interface and its Layer. Accessed 2026-10-06.

5. [Services and Layers](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/04-services-and-layers.md)
   Kit Langton / Effect Solutions. Service contracts, implementations, and explicit dependency composition. Accessed 2026-10-05.

6. [Data Modeling](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/05-data-modeling.md)
   Kit Langton / Effect Solutions. Schema as runtime validation and a shared data model. Accessed 2026-10-05.

7. [Error Handling](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/06-error-handling.md)
   Kit Langton / Effect Solutions. Expected failures and defects; API spellings need checking against the installed version. Accessed 2026-10-05.

8. [Testing](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/08-testing.md)
   Kit Langton / Effect Solutions. Effect tests, scoped resources, and test services. Accessed 2026-10-05.

9. [Services and Layers: test isolation](https://www.effect.solutions/services-and-layers)
   Effect Solutions. Fresh test Layers by default; shared Layers for expensive suite resources. Accessed 2026-10-05.

10. [Project Structure draft](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/09-project-structure.md)
    Kit Langton / Effect Solutions. Unfinished folder and package guidance; does not establish a community layout rule. Accessed 2026-10-05.

11. [Incremental Adoption](https://github.com/kitlangton/effect-solutions/blob/main/packages/website/docs/10-incremental-adoption.md)
    Kit Langton / Effect Solutions. Runners bridge existing imperative code at integration boundaries. Accessed 2026-10-05.

12. [rat-stack source snapshot](https://github.com/joelhooks/rat-stack/tree/54d356037c994f89698760a4727be71d0005a087)
    rat-stack. Services, contracts, adapters, composition roots, lifecycle machines, tests, and repository policy. Accessed 2026-10-06.

## Lore on this page

- [One schema, three surfaces](/lore/one-schema-three-surfaces)
- [Cartridges](/lore/cartridges)
- [Handle expected failures without hiding defects](/lore/error-model)
- [The fence](/lore/the-fence)

## Linked from

- A service captures its construction dependencies → Build a service with its dependencies, then expose methods that callers can use without rebuilding the graph. → [Read page](https://ratstack.sh/lore/services-capture-dependencies)

- add-a-capability → Learn how one contract and its handler become a command, HTTP route, MCP tool, browser RPC, and sandbox call. → [Read page](https://ratstack.sh/skills/add-a-capability)

- add-a-store → Add persistence behind a job-shaped service with schema validation, vendor Layers, migrations, bounded reads, and shared backend tests. → [Read page](https://ratstack.sh/skills/add-a-store)

- Agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms.txt)

- Agent rules for rat-stack (AGENTS.md) → What you may change, which commands to run, and which changes need approval. → [Read page](https://ratstack.sh/AGENTS.md)

- Build and run rat-stack (README.md) → What is in the repo, how the example works, and how to run it. → [Read page](https://ratstack.sh/README.md)

- Change log → What changed in the files served here, newest first. → [Read page](https://ratstack.sh/log)

- Effect 4 study: September 2026 → Dated Effect 4 source studies from September 2026; current versions live in pins.md. → [Read page](https://ratstack.sh/resources/effect-4-reference-projects)

- Effect keeps the surfaces on one contract → Schema owns values, projections build interfaces, and Layers supply implementations. → [Read page](https://ratstack.sh/lore/how-we-do-it-with-effect)

- Full agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms-full.txt)

- Layer composition makes dependencies explicit → Supply a service's dependencies, choose which services remain visible, and reuse Layer identity within a build. → [Read page](https://ratstack.sh/lore/layers-make-dependencies-explicit)

- Rat Stack lore | rat-stack → Short, source-grounded notes on the ideas and decisions behind rat-stack. → [Read page](https://ratstack.sh/lore)

- Run Effect at the integration boundary → Build the runtime where foreign code enters, reuse its services, and dispose it when that integration ends. → [Read page](https://ratstack.sh/lore/run-effect-at-the-boundary)

- Schema projections: 2026-09-18 history → Historical Effect rc.115 proposal and implementation receipts from 2026-09-18; use the one-capability-every-surface lore page for the current pattern. → [Read page](https://ratstack.sh/resources/schema-projections-and-code-mode)

- Source change history (log.md) → The generated change log as Markdown. → [Read page](https://ratstack.sh/log.md)

## Unlinked mentions

- [Agent rules for rat-stack (AGENTS.md)](https://ratstack.sh/AGENTS.md) → devtools(capabilities, \&#123; runAs \&#125;) records each call’s identity and lets rat\_call take as; the composition root passes runAsPerson from @rat-stack/auth/devtools, so devtools never imports auth.
