Skip to content
nooh
Esc
↑↓navigate↵open⌘Jpreview
On this page

RPC Client

Build end-to-end type-safe applications using Hono's native client (hc) and Nooh's generated AppType.

Nooh is designed to work seamlessly with Hono’s RPC system. Because Nooh compiles your filesystem routes into a standard Hono application instance, the generated code is 100% compatible with Hono’s official type-safe client (hono/client).

You do not need to install custom client generation tools, build adapters, or learn a proprietary RPC API. Standard hono/client works out of the box.


Setting Up the Client

To consume your Nooh API from a client (React, Vue, Svelte, Next.js, React Native, or a Node/Bun service), import hc from hono/client and AppType from .nooh/app:

import { hc } from "hono/client";
import type { AppType } from "../.nooh/app";

// Create a type-safe RPC client
export const client = hc<AppType>("http://localhost:3000");

In a monorepo setup, you can export AppType from your backend package and import it directly into your frontend or API SDK.


End-to-End Example

1. Define a Validated Route

Create a route handler in your Nooh project with path and query parameters using Standard Schema:

import { z } from "zod";
import { get } from "@router/users/[id]";

export default get({
  validation: {
    param: z.object({
      id: z.string(),
    }),
    query: z.object({
      includePosts: z.boolean().optional(),
    }),
  },
  handler: async ({ c }) => {
    const { id } = c.req.valid("param");
    const { includePosts } = c.req.valid("query");

    return c.json({
      id,
      name: "Alex",
      includePosts: includePosts ?? false,
    });
  },
});

2. Consume with hc

Use the generated client to make calls with automatic type checking and autocompletion:

import { hc } from "hono/client";
import type { AppType } from "../.nooh/app";

const client = hc<AppType>("http://localhost:3000");

// Path parameters, query params, and responses are fully typed!
const res = await client.users[":id"].$get({
  param: {
    id: "user_123",
  },
  query: {
    includePosts: true,
  },
});

if (res.ok) {
  const data = await res.json();
  // data is automatically typed as { id: string; name: string; includePosts: boolean }
  console.log(`User: ${data.name}`);
}

Inferring Request & Response Types

Hono provides utility types InferRequestType and InferResponseType to derive types directly from client methods. This is useful when defining props for frontend components or SDK helper functions:

import type { InferRequestType, InferResponseType } from "hono/client";
import { client } from "./client";

const getUserMethod = client.users[":id"].$get;

// Inferred request payload type (params, query, body, headers)
export type GetUserRequest = InferRequestType<typeof getUserMethod>;

// Inferred response data type
export type GetUserResponse = InferResponseType<typeof getUserMethod>;

You can then use these types in your UI components:

import type { GetUserResponse } from "../types";

interface UserProfileProps {
  user: GetUserResponse;
}

export function UserProfile({ user }: UserProfileProps) {
  return <div>{user.name}</div>;
}

Key Benefits

  • Zero Custom Adapters: Works directly with Hono’s native hc client.
  • Full Standard Schema Integration: Schemas defined with Zod, Valibot, or ArkType automatically type client request parameters and payloads.
  • Strict Compile-Time Safety: Catches invalid endpoint paths, missing path variables, and payload mismatches during development.
  • Lightweight & Fast: No heavy runtime reflection or code generators required on the client.

Was this page helpful?