Introducing Fresh 3:

The framework so simple, you already know it.

Preact and Vite, with file-system routing and signals. Server-render by default, and ship JavaScript only for the islands that need it.

Get started
npm create @frsh/app@latest
pnpm create @frsh/app
yarn create @frsh/app
deno run -A npm:@frsh/create-app

Take a tour of Fresh

Server-rendered by default

Every route renders on the server as a Preact component. Zero JavaScript hits the browser unless you opt in with an island. Pages are fast because they start as plain HTML.

routes/index.tsx
export default function HomePage() {
  const now = Temporal.Now.plainDateTimeISO()
    .toLocaleString("en-US");
  return (
    <p>Freshly server-rendered {now}</p>
  );
}

Freshly server-rendered 6/21/2026, 4:00:53 PM

Interactive where it matters

Most of your page is static HTML. Islands are the small, interactive parts that get hydrated with JavaScript. You choose exactly what runs on the client.

Built on Preact and Signals, so islands are tiny and reactive out of the box.

Learn more about islands
islands/Counter.tsx
import { useSignal } from "@preact/signals";

export default function Counter(props) {
  const count = useSignal(props.start);

  return (
    <div>
      <h3>Interactive island</h3>
      <p>The server supplied the initial value of {props.start}.</p>
      <div>
        <button onClick={() => count.value -= 1}>-</button>
        <div>{count}</div>
        <button onClick={() => count.value += 1}>+</button>
      </div>
    </div>
  );
}

Interactive island

The server supplied the initial value of 3.

3

Forms that just work

Handle submissions server-side with standard Request and FormData. No client-side state management, no serialization headaches. Progressive enhancement comes free.

Routes and forms in Fresh
routes/index.tsx
import { handler } from "./$index.ts";

export const handlers = handler({
  async POST(ctx) {
    const form = await ctx.req.formData();
    const treat = form.get("treat");
    await db.votes.insert({ treat });
    return ctx.redirect("/thanks", 303);
  },
});
What's your favorite treat?

Swap parts of the page during navigation

Click a link or submit a form and Fresh replaces just the parts of the page that need to change. No full reload, no client-side routing library. The browser navigation UI still works: address bar, back and forward buttons, loading indicator.

Learn more about Partials
routes/docs/[id].tsx
import { handler, page } from "./$[id].ts";
import { Partial } from "fresh/runtime";

export const handlers = handler({
  async GET(ctx) {
    const content = await loadDoc(ctx.params.id);
    return { data: { content } };
  },
});

export default page(({ data }) => (
  <div f-client-nav>
    <aside>
      <a href="/docs/introduction">Introduction</a>
      <a href="/docs/routing">Routing</a>
      <a href="/docs/islands">Islands</a>
    </aside>
    <main>
      <Partial name="content">
        {data.content}
      </Partial>
    </main>
  </div>
));

Introduction

Fresh is a small, fast, full-stack web framework for Preact, built on Vite. Routes render on the server, and islands hydrate the parts that need to be interactive.

And so much more

(…and even more)

Built for the edge

Fresh is the secret sauce behind production-grade, enterprise-ready software like Deco.cx, Brazil's top eCommerce platform

Deco.cx screenshot
The team also used Fresh, a next-gen Deno-native full stack web framework that sends zero JavaScript to the client, for its modern developer experience and snappy performance…

This stack unlocked 5x faster page load speeds and a 30% jump in conversion rates for their clients.
Read the case study
A lemon-squash illustration symbolizing Fresh running on any runtime

Runtime agnostic

Fresh builds with Nitro and runs anywhere Nitro does. Node, Deno, Cloudflare Workers, containers, or a static export for a CDN. Pick a host and deploy.

No custom runtime, no fork of the standard library, no host-specific entry file. The same project ships to all of them.

Get started
Illustration of a lemon sliced cleanly in half, suspended in midair as though frozen in time the instant after the cut, the juice flung from the edges

Time for a Fresh start

Jump right in and build your website with Fresh. Learn everything you need to know in seconds.

Get started