# Step 4: Detail route + guards

In this step you will add a parameterized detail route and guard it with `canLoad` and `canUnload`.

## 1. Add the detail route

Update `src/pages/projects-page.ts` to add the detail child route:

```typescript
import { route } from '@aurelia/router';
import { ProjectDetailPage } from './project-detail-page';
import { ProjectsActivityPage } from './projects-activity-page';
import { ProjectsOverviewPage } from './projects-overview-page';

@route({
  routes: [
    { path: ['', 'overview'], component: ProjectsOverviewPage, title: 'Overview' },
    { path: 'activity', component: ProjectsActivityPage, title: 'Activity' },
    { id: 'project-detail', path: 'detail/:id', component: ProjectDetailPage, title: 'Project Detail' }
  ]
})
export class ProjectsPage {}
```

We keep `detail` in the URL to keep the child routes explicit and readable. The `id: 'project-detail'` value is what the Overview page uses in its `route:` instruction, with a `../` prefix to resolve against the parent context.

## 2. Build the detail page

Create `src/pages/project-detail-page.ts`:

```typescript
import { IRouteViewModel, Params } from '@aurelia/router';
import { Project } from '../models';
import { PROJECTS } from '../project-data';

export class ProjectDetailPage implements IRouteViewModel {
  projectId = '';
  project: Project | null = null;
  noteDraft = '';

  canLoad(params: Params): boolean | string {
    const candidate = PROJECTS.find(item => item.id === params.id);
    return candidate ? true : 'projects';
  }

  loading(params: Params): void {
    this.projectId = params.id ?? '';
    this.project = PROJECTS.find(item => item.id === this.projectId) ?? null;
  }

  canUnload(): boolean {
    if (!this.noteDraft.trim()) return true;
    return confirm('You have an unsaved note. Leave this page?');
  }

  saveNote(): void {
    this.noteDraft = '';
  }
}
```

Create `src/pages/project-detail-page.html`:

```html
<import from="../components/app-shell"></import>

<app-shell>
  <h1 au-slot="title">${project?.name ?? 'Project'}</h1>
  <a au-slot="actions" load="../overview">Back to Projects</a>

  <section if.bind="project">
    <p class="project-meta">Project id: ${projectId}</p>

    <label class="note">
      <span>Note</span>
      <textarea value.bind="noteDraft" placeholder="Add a quick note"></textarea>
    </label>
    <button if.bind="noteDraft" click.trigger="saveNote()">Save Note</button>

    <ul class="task-list">
      <li repeat.for="task of project.tasks">
        <span class.bind="task.done ? 'task-item__done' : ''">${task.title}</span>
      </li>
    </ul>
  </section>

  <p if.bind="!project">Project not found.</p>
</app-shell>
```

**Guard recap:**

* `canLoad` prevents invalid IDs and redirects to `projects`.
* `canUnload` prompts when there is unsaved user input.

Next step: [Step 5: Router events + polish](/getting-started/extended-tutorial/step-5-router-events-and-polish.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aurelia.io/getting-started/extended-tutorial/step-4-project-detail-and-guards.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
