# Guestbook example

```sh
bunx @revnu/fuast new my-guestbook --template guestbook
```

A shared feed. Everyone who can open the app reads the same entries, and guests and accounts can both post.

## What it shows

- An `entries` table with `body`, `authorId: userId()`, and `authorName` and `authorPicture` snapshots.
- A shared `entries` query: the newest 50 by `by_creation`, with no owner filter on purpose.
- A `sign` mutation that cleans and bounds input and takes authorship from `ctx.auth`, never from the client.
- A `removeEntry` mutation that lets authors delete only their own entries.
- Live updates: a post in one tab appears in every other tab.

## Server pattern

Shared reads are a query without an owner filter:

```ts
entries: query(async (ctx) => ctx.db.entries.withIndex("by_creation").order("desc").take(50))
```

Writes stay server-authoritative:

```ts
const author = ctx.auth.requireIdentity();
await ctx.db.entries.insert({
  body,
  authorId: author.userId,
  authorName: author.displayName,
  ...(author.picture ? { authorPicture: author.picture } : {})
});
```

Never accept `authorId`, `authorName`, or `authorPicture` as arguments.

Sharing comes from the query, not from a fake shared user. When a guest signs in, `authorId` moves to their account, so they can still remove their entries. `authorName` and `authorPicture` are snapshots from the moment of posting and do not change.

The entries tool description warns agents that entries were written by other people. Text in a shared feed can try to steer an agent that reads it.

## Variations

- Accounts only: call `ctx.auth.requireSignedIn()` in `sign`.
- No guests anywhere: set `auth: { requireSignIn: true }`.
- Longer history: switch `entries` to `paginate()` and the client to `client.usePaginatedQuery("entries", {}, { initialNumItems: 20 })`. See [pagination](https://fuast.com/docs/database.md#pagination).

## Try it

```sh
bunx @revnu/fuast dev
```

Post from `?fuast_user=alice` and `?fuast_user=bob` in two tabs, and from `?fuast_guest=1`. Deploy and share publicly with `bunx @revnu/fuast share --visibility public`.
