---
title: proa site
description: Validate site structure and print discovered routes.
---

`proa site` commands inspect projects that follow the generated site conventions. Use them after scaffolding, after moving route files, and in CI before deployment.

They work from the nearest parent directory that contains both `Cargo.toml` and `src/`. Pass `--root` when you want to inspect a different project.

```bash
proa site check
proa site routes
```

## Command Summary

| Command | Use it when | Exit behavior |
|---------|-------------|---------------|
| `proa site check` | You want structural diagnostics for the generated site layout. | Exits non-zero when errors are present. |
| `proa site doctor` | You want the same diagnostics using the diagnostic command name. | Same implementation and exit behavior as `site check`. |
| `proa site routes` | You want the routes the generated site registers, without running it. | Exits zero when route discovery succeeds, even when no routes are found. |

## Check

```bash
proa site check
proa site check --root ../my-site
proa site check --json
```

`site check` verifies the module structure generated by `proa new site`. For a site whose `proa.config.json` has an `application` section, that means:

- `src/pages/mod.rs`, `src/components/mod.rs`, `src/layouts/mod.rs`, `src/endpoints/mod.rs`
- `src/routes.rs`, `src/app.rs`, `src/config.rs`, `src/error.rs`, `src/static_assets.rs`
- the SQLite files, `proa.lock.json` component hashes, and paired `.up.sql` / `.down.sql` migrations when those capabilities are enabled
- the Markdown representation contract when representations are enabled
- empty `src/models` and `src/services` directories, reported as warnings

Older sites without an `application` section are checked for `src/pages/mod.rs`, `src/components/mod.rs`, `src/layouts/mod.rs`, and `src/data/mod.rs`, and the `origin` template has its own list.

It also scans Rust page files under `src/pages` and reports an error when a page file does not expose a `handler` or `render` function. `src/islands` is reported as invalid for the generated site convention because islands live in the page or component tree instead of a separate source root.

A passing text run prints:

```text
Proa site check passed for /path/to/site
```

When errors exist, each one prints as an `error:` line and the command exits non-zero.

## JSON Diagnostics

Use `--json` for CI summaries, editor tooling, or scripts:

```bash
proa site check --json > proa-site-check.json
```

The JSON report has a stable shape:

```json
{
  "root": "/path/to/site",
  "errors": [],
  "warnings": []
}
```

Example failures:

```json
{
  "root": "/path/to/site",
  "errors": [
    "missing src/layouts/mod.rs",
    "src/pages/pricing.rs does not expose a handler or render function"
  ],
  "warnings": []
}
```

## Doctor

```bash
proa site doctor
proa site doctor --json
```

`doctor` currently runs the same implementation as `site check`. Use either command for structural diagnostics.

## Routes

```bash
proa site routes
proa site routes --json
```

For a site with an `application` section in `proa.config.json`, `site routes` reads the `Route::endpoint(...)` registrations in `src/routes.rs`, adds the home page and the `/healthz` and `/readyz` endpoints every generated site has, and adds a `.md` representation route for each page when Markdown representations are enabled. The method comes from the `routing::post(...)`-style constructor on each line. Text output has five columns:

```text
METHOD  PATH                             KIND            REPRESENTATIONS             SOURCE
GET     /                                page            html · md:/index.md         src/pages/home.rs
GET     /index.md                        representation  markdown                    src/pages/home.rs
GET     /healthz                         endpoint        json                        src/endpoints/health.rs
POST    /contact                         endpoint        json                        src/endpoints/contact.rs
```

JSON output returns one object per route with the same fields:

```json
[
  {
    "method": "POST",
    "path": "/contact",
    "kind": "endpoint",
    "representations": "json",
    "file": "src/endpoints/contact.rs"
  }
]
```

## Route Mapping Rules

Older sites without an `application` section fall back to a page-file convention: Rust files under `src/pages` map to routes, and every route is `GET`:

| File | Route |
|------|-------|
| `src/pages/home.rs` | `/` |
| `src/pages/index.rs` | `/` |
| `src/pages/pricing.rs` | `/pricing` |
| `src/pages/docs/index.rs` | `/docs` |
| `src/pages/docs/getting_started.rs` | `/docs/getting-started` |

Rules:

- `home.rs` at the top level maps to `/`.
- `index.rs` maps to the containing folder route.
- Underscores become hyphens.
- Nested folders become nested route segments.
- Every discovered route uses `GET`.

Either way this is a static report. It does not execute the app, inspect Axum router state, or infer dynamic wildcard routes.

## Root Resolution

By default, `site` commands walk upward from the current directory until they find a directory with both `Cargo.toml` and `src/`. Pass `--root` to inspect a different project:

```bash
proa site routes --root /path/to/site
```

Use `--root` in monorepos when your shell is outside the site package:

```bash
proa site check --root apps/marketing
proa site routes --root apps/marketing --json
```

## CI Pattern

For generated Proa sites, add `site check` next to the normal Rust and Proa checks:

```bash
cargo fmt --all --check
proa check
proa site check
proa test
```

When publishing a route manifest, capture the route report as an artifact:

```bash
proa site routes --json > proa-routes.json
```

## What It Does Not Prove

`proa site` catches structural drift in the generated site convention. It does not replace:

- `cargo check` for Rust type errors.
- `cargo test` for route behavior.
- `proa fmt --check --verify` for template parse stability.
- `proa lint` for accessibility, composition, and render-path diagnostics.
- A live HTTP smoke test for deployed Axum routes.
