# Architecture

Iwf does not force one project layout, but the canonical example follows an
IHP-style layout because it is easy to navigate in real applications.

## Recommended Layout

| Path | Purpose |
| --- | --- |
| `Application/Schema.sql` | PostgreSQL schema source of truth. |
| `Application/Fixtures.sql` | Development and test seed data. |
| `Application/Migrations/` | Ordered SQL files for schema evolution. |
| `Application/*.idr` | App runner, current-user auth, domain data, SQL queries, mail, jobs, scripts, and shared logic. |
| `Config/Config.idr` | App config, session policy, database policy, and route-specific settings. |
| `Web/Types.idr` | Shared web input/output records and route-facing types. |
| `Web/Routes.idr` | Typed route declarations and route registry. |
| `Web/Controller/*` | Request handlers grouped by product area. |
| `Web/View/*.idrx` | HTML views compiled into Idris. |
| `build/generated/` | Machine-owned generated Idris source. |

`iwf build` preprocesses IDRX, runs typegen, describes TypedSQL, and builds the
app.

Use `Application/` for code shared by web handlers, jobs, scripts, tests, and
mail. Use `Web/` for request handling, route definitions, web records, and
views.

## Generated Source

Generated files are build artifacts:

```text
Web/View/*.idrx        -> build/generated/Web/View/*.idr
Application/Schema.sql -> build/generated/Generated/Schema.idr
src/Main.idrx          -> build/generated/Main.idr
```

The package points at `build/generated` as a source directory. This keeps the
source tree clean and makes it obvious which files are owned by the developer
and which files are owned by tools.

If generated `.idr` files appear beside `.idrx` files, fix the app build
configuration instead of editing the generated file.

## Request Flow

An HTTP request follows this path:

1. `runApp` starts the configured app and reads the request up to
   `maxRequestBytes`.
2. The parser builds an `Iwf.Http.Request`.
3. Framework assets and Auto Refresh endpoints are checked before app routes.
4. Native POST form method override fields are canonicalized before route
   matching.
5. The router matches path, then method.
6. Typed route decoders parse path captures, query params, body params, JSON
   bodies, form bodies, or multipart bodies.
7. Advanced dispatch hooks can short-circuit.
8. The controller handler returns a `Response`.
9. The server logs and writes the response.

The built-in server is deliberately small. It handles one request per accepted
connection, writes complete responses with `Content-Length`, and closes the
connection. It does not provide streaming responses or HTTP keep-alive.

## Where Types Connect

The same route metadata is reused by several parts of the framework:

- dispatch uses it to match requests.
- `pathTo` uses it to build links.
- forms use it to derive actions, methods, encodings, and field checks.
- request decoding uses it to build typed handler inputs.
- OpenAPI uses it to document parameters, request bodies, and responses.

That is the main Iwf bet: define the boundary once and let Idris check the
places that depend on it.

## What Is Not Generated

Iwf does not generate relationship helpers, model-backed forms, controller
classes, or validation metadata on generated database records. Keep those as
explicit Idris functions. SQL relationships stay in the schema, generated typed
IDs keep joins honest, and application code decides how to load or render data.

For framework internals, dependent-type mechanics, subsystem organization, and
known shortcomings, see [Technical Architecture](../technical-architecture.md).

## Next

Read [Routing](routing.md).
