Skip to content

docs: add Hono RPC + TanStack Query recipe#1159

Open
Huijiro wants to merge 1 commit intomainfrom
docs/hono-rpc-tanstack-query
Open

docs: add Hono RPC + TanStack Query recipe#1159
Huijiro wants to merge 1 commit intomainfrom
docs/hono-rpc-tanstack-query

Conversation

@Huijiro
Copy link
Member

@Huijiro Huijiro commented Mar 9, 2026

Summary

New recipe at docs/recipes/hono-rpc-tanstack-query.md covering end-to-end type-safe API calls from React to Agentuity routes using Hono RPC and TanStack Query.

Contents

  • Server setup — chained createRouter() for full type inference
  • Safe type sharing — dedicated src/shared/api-types.ts with export type to prevent server code leaking into client bundles
  • TanStack Query hooksuseQuery, useMutation, query invalidation patterns
  • Multiple route files — per-file clients and composed single-client patterns
  • Explicit routing — usage with createApp({ router }) and custom mount paths
  • Zod validation@hono/zod-validator with types flowing through to the client

Why the safe type sharing section

Even with import type, bundlers like Vite can trace the module graph and pull server-only imports (database clients, process.env, @agentuity/runtime internals) into the client bundle. The recipe recommends a src/shared/api-types.ts boundary file that uses only export type { ... } statements, which TypeScript erases completely at compile time.

Summary by CodeRabbit

  • Documentation
    • Added comprehensive guide for type-safe Hono RPC and TanStack Query integration, including setup instructions, implementation examples, validation best practices, and type inference patterns.

End-to-end type-safe API calls from React to Agentuity routes:
- Server: chained createRouter() for type inference
- Client: hc() typed client with TanStack Query hooks
- Safe type sharing via src/shared/api-types.ts (export type only)
- Multiple route files, composed routers, explicit routing
- Zod validation with types flowing to client

Includes a dedicated section on safely exporting types to prevent
server code (database clients, secrets, env vars) from leaking into
the client bundle through bundler module tracing.
@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

A new documentation file has been added describing the integration between Hono RPC and TanStack Query. The guide covers server-side route definition, client-side setup, type inference patterns, Zod validation, and best practices for maintaining type safety across the full stack.

Changes

Cohort / File(s) Summary
Hono RPC & TanStack Query Documentation
docs/recipes/hono-rpc-tanstack-query.md
New documentation file with 411 lines covering type-safe integration patterns, including server router setup with chained createRouter() calls, client-side TanStack Query configuration, typed hook creation, Zod validation, and best practices for type inference and avoiding server-side leakage to the client.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Huijiro added a commit that referenced this pull request Mar 9, 2026
Huijiro added a commit that referenced this pull request Mar 9, 2026
@github-actions
Copy link

github-actions bot commented Mar 9, 2026

📦 Canary Packages Published

version: 1.0.39-d2557a8

Packages
Package Version URL
@agentuity/frontend 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-frontend-1.0.39-d2557a8.tgz
@agentuity/postgres 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-postgres-1.0.39-d2557a8.tgz
@agentuity/drizzle 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-drizzle-1.0.39-d2557a8.tgz
@agentuity/evals 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-evals-1.0.39-d2557a8.tgz
@agentuity/runtime 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-runtime-1.0.39-d2557a8.tgz
@agentuity/server 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-server-1.0.39-d2557a8.tgz
@agentuity/workbench 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-workbench-1.0.39-d2557a8.tgz
@agentuity/opencode 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-opencode-1.0.39-d2557a8.tgz
@agentuity/react 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-react-1.0.39-d2557a8.tgz
@agentuity/core 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-core-1.0.39-d2557a8.tgz
@agentuity/auth 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-auth-1.0.39-d2557a8.tgz
@agentuity/claude-code 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-claude-code-1.0.39-d2557a8.tgz
@agentuity/coder 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-coder-1.0.39-d2557a8.tgz
@agentuity/cli 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-cli-1.0.39-d2557a8.tgz
@agentuity/schema 1.0.39-d2557a8 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-schema-1.0.39-d2557a8.tgz
Install

Add to your package.json:

{
  "dependencies": {
    "@agentuity/frontend": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-frontend-1.0.39-d2557a8.tgz",
    "@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-postgres-1.0.39-d2557a8.tgz",
    "@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-drizzle-1.0.39-d2557a8.tgz",
    "@agentuity/evals": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-evals-1.0.39-d2557a8.tgz",
    "@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-runtime-1.0.39-d2557a8.tgz",
    "@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-server-1.0.39-d2557a8.tgz",
    "@agentuity/workbench": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-workbench-1.0.39-d2557a8.tgz",
    "@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-opencode-1.0.39-d2557a8.tgz",
    "@agentuity/react": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-react-1.0.39-d2557a8.tgz",
    "@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-core-1.0.39-d2557a8.tgz",
    "@agentuity/auth": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-auth-1.0.39-d2557a8.tgz",
    "@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-claude-code-1.0.39-d2557a8.tgz",
    "@agentuity/coder": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-coder-1.0.39-d2557a8.tgz",
    "@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-cli-1.0.39-d2557a8.tgz",
    "@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-schema-1.0.39-d2557a8.tgz"
  }
}

Or install directly:

bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-frontend-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-postgres-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-drizzle-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-evals-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-runtime-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-server-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-workbench-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-opencode-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-react-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-core-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-auth-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-claude-code-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-coder-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-cli-1.0.39-d2557a8.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.39-d2557a8/agentuity-schema-1.0.39-d2557a8.tgz

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
docs/recipes/hono-rpc-tanstack-query.md (3)

21-58: Consider clarifying server-side router mounting earlier.

The server example defines routes at /users, /users/:id, etc., but doesn't show how this router is mounted on the server. The client examples use hc<UsersRoute>('/api'), implying the router is mounted at /api. While this is explained later (line 345: "Default mount is /api"), readers following the first example might be confused about the complete setup.

📝 Suggested addition to clarify mounting

Consider adding a brief note or code snippet after line 58:

 export type UsersRoute = typeof router;
 export default router;
+
+// Mount this router in your app:
+// export const app = await createApp({ router });
+// By default, the router is mounted at /api
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/recipes/hono-rpc-tanstack-query.md` around lines 21 - 58, Add a short
clarification after the createRouter() example that shows where the router is
mounted and matches the client usage: explain that the exported router (router /
UsersRoute) should be mounted on your server under the same base path the client
uses (e.g., "/api"), reference the createRouter() export (export default router
and export type UsersRoute) and the client call hc<UsersRoute>('/api'), and
instruct to mount the router on that path so the example routes (/users,
/users/:id) become /api/users and /api/users/:id.

156-170: Consider mentioning mutation error handling.

The mutation examples throw errors but don't show how to handle them in the component. While TanStack Query's useMutation returns an error property that can be used in the UI, the UserList component example (lines 196-239) doesn't demonstrate error handling for mutations.

💡 Example of mutation error handling
const createUser = useCreateUser();

// In the component:
{createUser.error && (
  <div>Error creating user: {createUser.error.message}</div>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/recipes/hono-rpc-tanstack-query.md` around lines 156 - 170, Update the
docs to demonstrate handling mutation errors from useCreateUser in the UI: in
the UserList component example, consume the return value from useCreateUser (the
mutation object from useMutation) and render its error state (e.g., show
createUser.error.message) so users see how to surface mutation errors; reference
the useCreateUser hook and its useMutation return (and keep the existing
onSuccess behavior that calls queryClient.invalidateQueries(['users'])) when
describing the fix.

363-403: Consider adding Zod validation error handling guidance.

The section shows how to set up Zod validation but doesn't demonstrate how validation errors are returned to the client or how to handle them. When validation fails, Hono's zValidator typically returns a 400 response with error details, but the example query functions always throw generic errors on !res.ok.

📖 Example of handling validation errors
mutationFn: async (data: { name: string; email: string }) => {
  const res = await client.users.$post({ json: data });
  if (!res.ok) {
    const error = await res.json();
    // Zod validation errors include details about which fields failed
    throw new Error(error.message || 'Failed to create user');
  }
  return res.json();
}

This helps users understand how to provide better error feedback to end-users when validation fails.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/recipes/hono-rpc-tanstack-query.md` around lines 363 - 403, Add guidance
showing how to handle Zod validation errors from Hono by reading the response
body when the client call is not ok and surface field-level details; update the
docs around the createUser example to demonstrate checking res.ok after
client.users.$post (or inside mutationFn), calling await res.json() to extract
the validation error payload returned by zValidator, and then throwing or
mapping error.message/error.details back to the UI (e.g., returning form field
errors) instead of throwing a generic error on !res.ok.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/recipes/hono-rpc-tanstack-query.md`:
- Around line 21-58: Add a short clarification after the createRouter() example
that shows where the router is mounted and matches the client usage: explain
that the exported router (router / UsersRoute) should be mounted on your server
under the same base path the client uses (e.g., "/api"), reference the
createRouter() export (export default router and export type UsersRoute) and the
client call hc<UsersRoute>('/api'), and instruct to mount the router on that
path so the example routes (/users, /users/:id) become /api/users and
/api/users/:id.
- Around line 156-170: Update the docs to demonstrate handling mutation errors
from useCreateUser in the UI: in the UserList component example, consume the
return value from useCreateUser (the mutation object from useMutation) and
render its error state (e.g., show createUser.error.message) so users see how to
surface mutation errors; reference the useCreateUser hook and its useMutation
return (and keep the existing onSuccess behavior that calls
queryClient.invalidateQueries(['users'])) when describing the fix.
- Around line 363-403: Add guidance showing how to handle Zod validation errors
from Hono by reading the response body when the client call is not ok and
surface field-level details; update the docs around the createUser example to
demonstrate checking res.ok after client.users.$post (or inside mutationFn),
calling await res.json() to extract the validation error payload returned by
zValidator, and then throwing or mapping error.message/error.details back to the
UI (e.g., returning form field errors) instead of throwing a generic error on
!res.ok.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93f0370c-7bc1-49c6-8354-ba8147ef4550

📥 Commits

Reviewing files that changed from the base of the PR and between cdae827 and d2557a8.

📒 Files selected for processing (1)
  • docs/recipes/hono-rpc-tanstack-query.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Storage CLI Tests
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Standalone Agent Test
  • GitHub Check: Pack & Upload
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Postgres SSL Integration Test
  • GitHub Check: Build
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Template Integration Tests
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Queue SDK Tests

@agentuity-agent
Copy link

agentuity-agent bot commented Mar 9, 2026

The latest Agentuity deployment details. Learn more about Agentuity.

Project Deployment Preview Updated (UTC)
docs 🟢 Ready Preview Mar 09, 2026 10:27 PM

@@ -0,0 +1,411 @@
# Hono RPC with TanStack Query

Copy link
Contributor

@parteeksingh24 parteeksingh24 Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be converted to an .mdx file within apps/docs/src/web/content/ (suggestion: apps/docs/src/web/content/cookbook/patterns/hono-rpc-tanstack-query.mdx).

Some more notes:

  • Add frontmatter (title, description) matching the existing pattern pages
  • Add to cookbook/patterns/meta.json so it shows up in the nav
  • Add a <CardLink> entry to cookbook/index.mdx in the Patterns section (lucide icon)


## Safely Exporting Types to the Client

⚠️ **Never import server route files directly from client code.** Even `import type` can cause bundlers to trace the module graph and pull server-only code (database clients, secrets, etc.) into the client bundle.
Copy link
Contributor

@parteeksingh24 parteeksingh24 Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: replace ⚠️ emoji with a <Callout> component (<Callout type="warning" title="...">; available in .mdx pages).

bun add @tanstack/react-query hono
```

> `hono` is already a dependency of `@agentuity/runtime`, but you need it in your app for the `hc` client import.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: replace blockquote with <Callout type="info"> (same for lines 60 and 91).

@@ -0,0 +1,411 @@
# Hono RPC with TanStack Query
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: use an action-oriented title (e.g., "Type-Safe API Calls with Hono RPC and TanStack Query").

Use method chaining on `createRouter()` so TypeScript can infer the full route tree:

```typescript
// src/api/users.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use code block title="src/api/users.ts" instead of inline comments for file paths. (can be applied to all code blocks here)

// client.posts.$get() — typed
```

## With Explicit Routing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using // [!code highlight] on the lines that differ from the previous section's code blocks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants