DEV Community

Alex Spinov
Alex Spinov

Posted on

Fresh Has a Free API That Makes Deno the Best Runtime for Web Apps

Fresh is the Deno-native web framework with island architecture, zero build step, and just-in-time rendering.

Routes: File-Based

// routes/index.tsx
export default function Home() {
  return (
    <div>
      <h1>Scraping Dashboard</h1>
      <p>Real-time product monitoring</p>
    </div>
  );
}

// routes/products/[id].tsx
import { Handlers, PageProps } from "$fresh/server.ts";

export const handler: Handlers = {
  async GET(req, ctx) {
    const product = await db.getProduct(ctx.params.id);
    if (!product) return ctx.renderNotFound();
    return ctx.render(product);
  },
};

export default function ProductPage({ data }: PageProps<Product>) {
  return (
    <div>
      <h1>{data.title}</h1>
      <p>${data.price}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Islands: Interactive Components

// islands/SearchBar.tsx — ONLY this ships JS to the browser
import { useState } from "preact/hooks";

export default function SearchBar() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);

  async function search() {
    const res = await fetch(`/api/search?q=${query}`);
    setResults(await res.json());
  }

  return (
    <div>
      <input value={query} onInput={(e) => setQuery(e.currentTarget.value)} />
      <button onClick={search}>Search</button>
      {results.map(r => <div key={r.id}>{r.title}</div>)}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Everything outside islands/ is server-rendered with zero client JS.

API Routes

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

export const handler: Handlers = {
  async GET(req) {
    const url = new URL(req.url);
    const category = url.searchParams.get("category");
    const products = await db.getProducts({ category });
    return Response.json(products);
  },
  async POST(req) {
    const body = await req.json();
    const product = await db.createProduct(body);
    return Response.json(product, { status: 201 });
  },
};
Enter fullscreen mode Exit fullscreen mode

Middleware

// routes/_middleware.ts
import { MiddlewareHandlerContext } from "$fresh/server.ts";

export async function handler(req: Request, ctx: MiddlewareHandlerContext) {
  const start = Date.now();
  const resp = await ctx.next();
  const duration = Date.now() - start;
  resp.headers.set("X-Response-Time", `${duration}ms`);
  console.log(`${req.method} ${new URL(req.url).pathname}${duration}ms`);
  return resp;
}
Enter fullscreen mode Exit fullscreen mode

Signals: Preact Reactivity

import { signal, computed } from "@preact/signals";

const products = signal([]);
const filter = signal("");
const filtered = computed(() =>
  products.value.filter(p => p.title.toLowerCase().includes(filter.value.toLowerCase()))
);
Enter fullscreen mode Exit fullscreen mode

Deploy: Deno Deploy

# Deploy globally in seconds
deno task build
deployctl deploy --project=my-app --prod main.ts
Enter fullscreen mode Exit fullscreen mode

Build data apps with Deno? My Apify tools work with any runtime.

Custom Deno solution? Email spinov001@gmail.com

Top comments (0)