Docs / Programming & Development / Deno Fresh Application

Deno Fresh Application

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 417 views · 3 min read

Deno Fresh is a next-generation web framework built on Deno that uses just-in-time rendering and an island architecture for optimal performance. It ships zero JavaScript to the client by default, hydrating only interactive components. This guide covers building and deploying Fresh applications on a VPS.

Project Setup

# Install Deno
curl -fsSL https://deno.land/install.sh | sh

# Create Fresh project
deno run -A https://fresh.deno.dev my-app
cd my-app

# Start development server
deno task start

Project Structure

my-app/
├── components/       # Shared components (server-rendered)
├── islands/          # Interactive components (client-hydrated)
├── routes/           # File-based routing
│   ├── _app.tsx      # App wrapper
│   ├── _layout.tsx   # Layout
│   ├── index.tsx     # Home page
│   ├── api/          # API routes
│   │   └── users.ts
│   └── users/
│       └── [id].tsx  # Dynamic route
├── static/           # Static assets
├── fresh.config.ts
├── deno.json
└── dev.ts

Page Routes

// routes/index.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

interface Data {
  users: Array;
}

export const handler: Handlers<Data> = {
  async GET(_req, ctx) {
    const resp = await fetch("https://api.example.com/users");
    const users = await resp.json();
    return ctx.render({ users });
  },
};

export default function Home({ data }: PageProps<Data>) {
  return (
    <div class="p-4 mx-auto max-w-screen-md">
      <h1 class="text-4xl font-bold">Users</h1>
      <ul>
        {data.users.map((user) => (
          <li key={user.id}>
            <a href={`/users/${user.id}`}>{user.name}</a>
          </li>
        ))}
      </ul>
    </div>
  );
}

API Routes

// routes/api/users.ts
import { Handlers } from "$fresh/server.ts";

export const handler: Handlers = {
  GET(_req) {
    const users = [
      { id: 1, name: "Alice", email: "alice@example.com" },
      { id: 2, name: "Bob", email: "bob@example.com" },
    ];
    return new Response(JSON.stringify(users), {
      headers: { "content-type": "application/json" },
    });
  },

  async POST(req) {
    const body = await req.json();
    // Validate and insert...
    return new Response(JSON.stringify({ id: 3, ...body }), {
      status: 201,
      headers: { "content-type": "application/json" },
    });
  },
};

Islands (Interactive Components)

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

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

  return (
    <div class="flex gap-4 items-center">
      <button => count.value--} class="btn">-</button>
      <span class="text-2xl">{count}</span>
      <button => count.value++} class="btn">+</button>
    </div>
  );
}

// Use in a page (only this island ships JS to client):
// <Counter start={3} />

Deployment on VPS

# Build for production (optional, Fresh can run from source)
deno task build

# Run production server
deno run -A main.ts

# Systemd service
[Unit]
Description=Deno Fresh Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/fresh-app
ExecStart=/home/appuser/.deno/bin/deno run -A main.ts
Environment=DENO_DEPLOYMENT_ID=production
Restart=always

[Install]
WantedBy=multi-user.target

Docker Deployment

FROM denoland/deno:1.45.5
WORKDIR /app
COPY . .
RUN deno cache main.ts
USER deno
EXPOSE 8000
CMD ["run", "-A", "main.ts"]

Summary

Deno Fresh represents a paradigm shift in web frameworks: zero JavaScript shipped by default, server-side rendering for all pages, and islands for surgical client-side interactivity. The result is extremely fast page loads with minimal client-side overhead. Combined with Deno is built-in TypeScript support, secure-by-default permissions, and web-standard APIs, Fresh is an excellent choice for content-heavy sites and applications where performance and SEO matter.

Was this article helpful?