`. For a param-less name the argument is omitted; for a name with params the argument is `{ [paramName]: string }`. |
### `publish(topic, message?)`
Publishes to a typed topic from a server action or server agent. Every live loader subscribed to `topic` re-runs its `load` and pushes the result to connected clients.
```ts
import { publish } from 'hono-preact';
publish(boardChannel.key({ boardId }), { taskId, to }); // payload channel
publish(counterChannel.key()); // signal channel
```
| Argument | Type | Description |
| --------- | ---------- | -------------------------------------------------------------------- |
| `topic` | `Topic` | The topic to publish to. Built with `channel.key(params)`. |
| `message` | `P` | Required for payload channels; omitted for `void` (signal) channels. |
### `route.liveLoader({ topic, load })`
Defines a channel-driven live loader inside a `serverLoaders` object. Yields the result of `load` once on connect, then re-runs and pushes on every publish to `topic`.
| Option | Type | Description |
| ----------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------- |
| `topic` | `(ctx: LoaderCtx) => Topic` | Returns the topic this loader subscribes to. Called with the same context as `load`. |
| `load` | `(ctx: LoaderCtx) => Promise` | Produces the data snapshot. Called on connect and on every publish. |
| `use` | `ReadonlyArray` | Optional guard/middleware chain run on the subscription (same inheritance as a non-live loader's `use`). |
| `cache` | `LoaderCache` | Optional cache shared across `load` calls. |
| `timeoutMs` | `number \| false` | Timeout per `load` call. Defaults to `false` (no cap). |
Returns a `LoaderRef`. Consume it with the accumulating form `ref.View(render, { initial, reduce })`. The `StreamStatus` and `.View` option table are described on the [Live Loaders](/docs/live-loaders) page.
### Type exports
```ts
import type { Channel, Topic, LiveLoaderOptions } from 'hono-preact';
import type { StreamStatus } from 'hono-preact';
```
## See also
- [Live Loaders](/docs/live-loaders): the persistent-layout streaming pattern, `.View` accumulating form, and `StreamStatus` reference.
- [Server Loaders](/docs/loaders): non-live loaders and the full `defineLoader` option table.
- [Server Actions](/docs/actions): where `publish` is typically called.
---
> Source: https://framework.sbesh.com/docs/actions
# Server Actions
Pages often need to mutate data: adding a record, toggling a flag, deleting a row. Server actions let you define those mutations as typed functions in your `.server.ts` file and call them from a form or a hook. No manual `fetch` wiring, no API route plumbing.
For long-running operations that emit progress or results incrementally, see [Streaming](/docs/streaming).
## Defining actions
**`src/pages/movies.server.ts`** (assumes `type MovieList = { results: { id: number; title: string }[] }`):
```ts
import { getMovies } from '@/server/movies.js';
import { defineAction } from 'hono-preact';
const serverLoader = async () => {
const movies = await getMovies();
return { movies };
};
export default serverLoader;
export const serverActions = {
addMovie: defineAction<{ title: string }, { ok: boolean }>(
async (_ctx, payload) => {
await db.insert({ title: payload.title });
return { ok: true };
}
),
};
```
`defineAction` is a no-op at runtime; it just returns the function unchanged. Its only job is to brand the function with phantom types so `useAction` and `
);
const MoviesView = dataLoader.View(({ data }) => (
{data.movies.results.map((m) => (
- {m.title}
))}
));
export default definePage(MoviesView);
```
`