Skip to content

Server-Side API with Hono

see [1]

This below is a citation

Here is a citation [2]

That above was a citation

This is the galore paper [1]

[1]

this is

This is [@http://localhost:4322/meta/authoring/guides/server-side/] [@http://localhost:4322/meta/authoring/guides/server-side/]

This page demonstrates a server-side API powered by Hono running inside Astro. The component below fetches live data from a Hono API route at /api/git-log, which executes git log on the server and returns JSON.

foobar
foobar

The server-side setup has three parts: the Node adapter, the Hono API route, and the client component.

Astro is static by default — it pre-renders every page at build time. To run server-side code at request time, you need an adapter. The @astrojs/node adapter lets Astro run as a standalone Node.js server.

Terminal window
bun add @astrojs/node

Then add it to astro.config.mjs:

import node from "@astrojs/node";
export default defineConfig({
adapter: node({ mode: "standalone" }),
// ...
});

The mode: 'standalone' option builds a self-contained server you can run directly:

Terminal window
node ./dist/server/entry.mjs

With the adapter in place, any route that exports prerender = false will be rendered on the server at request time. All other pages remain static — you get the best of both worlds.

A catch-all endpoint at src/pages/api/[...route].ts delegates all /api/* requests to a Hono app:

import { Hono } from "hono";
import { execSync } from "node:child_process";
import type { APIRoute } from "astro";
export const prerender = false;
const app = new Hono().basePath("/api");
app.get("/git-log", (c) => {
const log = execSync("git log ...", { encoding: "utf-8" });
// parse and return as JSON
return c.json(commits);
});
const handler: APIRoute = async (context) => {
return app.fetch(context.request);
};
export const GET = handler;
export const POST = handler;

Key points:

  • export const prerender = false opts this route into SSR
  • The Hono app handles routing under /api
  • execSync runs server-side only — never shipped to the browser

A SolidJS component fetches from the API and renders the result. The wrapper uses client:only="solid-js" instead of client:visible — this is important because fetch('/api/git-log') uses a relative URL, which fails during server-side rendering (no origin to resolve against). client:only skips SSR entirely and only renders in the browser.

GitLogWrapper.astro
<GitLog client:only="solid-js" />
GitLog.tsx
const [commits] = createResource(async () => {
const res = await fetch("/api/git-log");
return res.json();
});

Visit /api/git-log to see the raw JSON response, or /api/health for a health check.

[1]
J. Zhao, Z. Zhang, B. Chen, Z. Wang, A. Anandkumar, and Y. Tian, “GaLore: Memory-Efficient LLM Training by Gradient Low-Rank Projection,” 2024, arXiv. doi: 10.48550/ARXIV.2403.03507.
[2]
github.com, “GitHub - race2infinity/The-Documentation-Compendium: 📢 Various README templates &amp; tips on writing high-quality documentation that people want to read.” Accessed: Mar. 29, 2026. [Online]. Available: https://github.com/race2infinity/The-Documentation-Compendium