Fresh 2.3 is here!WebSockets, View Transitions, Temporal API, and more

Introducing Fresh:

The framework so simple, you already know it.

No config files, no build step, no node_modules. Just one file and you have a server with routing, JSX, and islands.

Get started
deno run -Ar jsr:@fresh/init

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 4/25/2026, 11:33:26 AM

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.

Forms in Fresh
routes/index.tsx
import { createDefine } from "fresh";
const define = createDefine();

export const handler = define.handlers({
  async POST(ctx) {
    const form = await ctx.req.formData();
    const treat = form.get("treat");
    await db.votes.insert({ treat });

    return new Response(null, {
      status: 303,
      headers: { location: "/thanks" },
    });
  },
});
What's your favorite treat?

Stream HTML straight from the server

Swap chunks of HTML from the server straight into the page. No full reload, no client-side routing library. Click a link or submit a form and Fresh streams just the part that changed. Perfect for interactive elements and dynamic apps.

Learn more about Partials
components/Recipes.tsx
import { Partial } from "fresh/runtime";

export const Recipes = () => (
  <div f-client-nav>
    <aside>
      <button f-partial="/recipes/lemonade">
        Lemonade
      </button>
      <button f-partial="/recipes/lemon-honey-tea">
        Lemon-honey tea
      </button>
      <button f-partial="/recipes/lemondrop">
        Lemondrop Martini
      </button>
    </aside>
    <main>
      <Partial name="recipe">
        Click a recipe to stream HTML into this spot
      </Partial>
    </main>
  </div>
);
Click a recipe to stream HTML into this spot

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
Deno is drinking Fresh lemon squash

Built on Deno

Deno is the next evolution of server-side JavaScript, with stronger security, a robust built-in toolchain, and zero-config TypeScript support. (It's faster than Node, too.)

Learn more about Deno
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