Skip to content

Commit 394441f

Browse files
bartlomiejuclaude
andcommitted
docs: fix code examples and docs from review feedback
1. Fix handlers → handler (singular) in app.route() example 2. Fix app.onError() missing path argument 3. Fix css shown inside RouteConfig → top-level export 4. Fix variable shadowing (page shadows page() import) 5. Fix ctx.redirect() in page component → move to handler 6-8. Add missing HttpError and define imports in examples 9. Add config and info to PageProps reference table 10. Add RouteData, Lazy, MaybeLazy, ResolvedBuildConfig to API reference 11. Clarify layout nesting order in architecture docs 12. Add note explaining useSignal in server-rendered route for signals Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 80ba463 commit 394441f

7 files changed

Lines changed: 42 additions & 21 deletions

File tree

docs/latest/advanced/api-reference.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import { App, createDefine, HttpError, page, staticFiles } from "fresh";
4343
| `ListenOptions` | Options for `app.listen()`. |
4444
| `Island` | Island component type. |
4545
| `Method` | HTTP method union type. |
46+
| `RouteData` | Data type returned by route handlers via `page()`. |
47+
| `Lazy` / `MaybeLazy` | Utility types for lazily-loaded routes and middleware. |
4648
| `CORSOptions` | Options for `cors()`. |
4749
| `CsrfOptions` | Options for `csrf()`. |
4850
| `CSPOptions` | Options for `csp()`. |
@@ -86,7 +88,8 @@ import { Builder } from "fresh/dev";
8688

8789
**Types:**
8890

89-
| Export | Description |
90-
| -------------------------------------------------------- | ---------------------------- |
91-
| `BuildOptions` | Options for `new Builder()`. |
92-
| `OnTransformArgs` / `OnTransformOptions` / `TransformFn` | Build plugin hook types. |
91+
| Export | Description |
92+
| -------------------------------------------------------- | ----------------------------- |
93+
| `BuildOptions` | Options for `new Builder()`. |
94+
| `ResolvedBuildConfig` | Resolved build configuration. |
95+
| `OnTransformArgs` / `OnTransformOptions` / `TransformFn` | Build plugin hook types. |

docs/latest/concepts/app.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ Register a route with a component and optional handlers for data loading.
283283
```tsx
284284
app.route("/about", {
285285
component: (ctx) => <h1>About {ctx.data.name}</h1>,
286-
handlers: {
286+
handler: {
287287
GET(ctx) {
288288
return page({ name: "Fresh" });
289289
},
@@ -317,8 +317,8 @@ app.onError("*", (ctx) => {
317317
Setting a route with a component:
318318

319319
```tsx
320-
app.onError((ctx) => {
321-
return ctx.render(<h1>Oops! Something went wrong.</h1>);
320+
app.onError("*", {
321+
component: (ctx) => <h1>Oops! {String(ctx.error)}</h1>,
322322
});
323323
```
324324

docs/latest/concepts/architecture.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,9 @@ at `routes/blog/post.tsx` inherits layouts from:
119119
1. `routes/_layout.tsx` (root layout)
120120
2. `routes/blog/_layout.tsx` (section layout)
121121

122-
The innermost layout wraps the page component, and each outer layout wraps the
123-
next. The app wrapper (`_app.tsx`) wraps everything.
122+
Layouts nest from the outside in: the root layout is outermost, each deeper
123+
layout wraps closer to the page, and the innermost layout directly wraps the
124+
page component. The app wrapper (`_app.tsx`) wraps everything.
124125

125126
### Build and deploy
126127

docs/latest/concepts/data-fetching.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A handler fetches data and returns it with `page()`. The page component receives
1313
it in `props.data`:
1414

1515
```tsx routes/projects/[id].tsx
16-
import { page } from "fresh";
16+
import { HttpError, page } from "fresh";
1717
import { define } from "@/utils.ts";
1818

1919
interface Data {
@@ -60,6 +60,7 @@ For simpler cases, you can fetch data directly in an async component without a
6060
separate handler:
6161

6262
```tsx routes/projects/[id].tsx
63+
import { HttpError } from "fresh";
6364
import { define } from "@/utils.ts";
6465

6566
export default define.page(async (ctx) => {
@@ -96,12 +97,19 @@ export default define.middleware(async (ctx) => {
9697
```
9798

9899
```tsx routes/dashboard.tsx
100+
import { page } from "fresh";
99101
import { define } from "@/utils.ts";
100102

103+
export const handler = define.handlers({
104+
GET(ctx) {
105+
if (!ctx.state.user) {
106+
return ctx.redirect("/login");
107+
}
108+
return page();
109+
},
110+
});
111+
101112
export default define.page((ctx) => {
102-
if (!ctx.state.user) {
103-
return ctx.redirect("/login");
104-
}
105113
return <h1>Welcome, {ctx.state.user.name}</h1>;
106114
});
107115
```
@@ -117,7 +125,9 @@ Page components receive these properties:
117125
| `params` | `Record<string, string>` | Route parameters (e.g. `:id`) |
118126
| `req` | `Request` | The original HTTP request |
119127
| `state` | `State` | Shared state set by middleware |
128+
| `config` | `ResolvedFreshConfig` | The resolved Fresh configuration |
120129
| `route` | `string \| null` | The matched route pattern |
130+
| `info` | `Deno.ServeHandlerInfo` | Server connection info |
121131
| `error` | `unknown \| null` | Caught error (on error pages) |
122132
| `isPartial` | `boolean` | Whether this is a partial request |
123133
| `Component` | `FunctionComponent` | Child component (in layouts) |

docs/latest/concepts/file-routing.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,11 @@ export const config: RouteConfig = {
9393
// ...
9494
```
9595

96-
You can also load additional CSS files for a specific route:
96+
You can also load additional CSS files for a specific route by exporting a `css`
97+
array. This is a top-level export, separate from `config`:
9798

9899
```ts routes/dashboard.tsx
99-
import { RouteConfig } from "fresh";
100-
101-
export const config: RouteConfig = {
102-
css: ["./assets/dashboard.css"],
103-
};
100+
export const css = ["./assets/dashboard.css"];
104101
```
105102

106103
## Route Groups

docs/latest/concepts/signals.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ Both sliders share the same signal — moving one updates the other. When the sa
8282
signal object is passed to multiple islands, Fresh preserves the reference so
8383
they stay synchronized.
8484

85+
> [!NOTE]
86+
> Using `useSignal` in a route component (not an island) is intentional here.
87+
> The signal is created during server rendering, serialized into the HTML, and
88+
> reconstructed as a live signal on the client. This is how Fresh shares
89+
> reactive state between multiple islands on the same page.
90+
8591
## Shared state across islands
8692

8793
For state that needs to be shared between unrelated islands, create a signal in

docs/latest/examples/common-patterns.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export default function handler(ctx) {
5252
Return different formats based on the `Accept` header:
5353

5454
```ts routes/api/users/[id].ts
55+
import { HttpError } from "fresh";
5556
import { define } from "@/utils.ts";
5657

5758
export const handlers = define.handlers({
@@ -105,13 +106,14 @@ session example.
105106
Access URL search params from the context:
106107

107108
```ts routes/search.tsx
109+
import { page } from "fresh";
108110
import { define } from "@/utils.ts";
109111

110112
export const handlers = define.handlers({
111113
GET(ctx) {
112114
const query = ctx.url.searchParams.get("q") ?? "";
113-
const page = Number(ctx.url.searchParams.get("page") ?? "1");
114-
const results = search(query, page);
115+
const pageNum = Number(ctx.url.searchParams.get("page") ?? "1");
116+
const results = search(query, pageNum);
115117
return page({ query, results });
116118
},
117119
});
@@ -145,6 +147,8 @@ return page(data, {
145147
Return a streaming response from a handler:
146148

147149
```ts routes/api/stream.ts
150+
import { define } from "@/utils.ts";
151+
148152
export const handlers = define.handlers({
149153
GET() {
150154
const body = new ReadableStream({

0 commit comments

Comments
 (0)