a minimal web framework for deno
TypeScript 100.0%
45 2 0

Clone this repository

https://tangled.org/cute.kyu.re/snarl https://tangled.org/did:plc:baxmqv3ddi3pg5iolx77lofv/snarl
git@tangled.org:cute.kyu.re/snarl git@tangled.org:did:plc:baxmqv3ddi3pg5iolx77lofv/snarl

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
readme.md

snarl#

a minimal web framework for deno

features#

  • tiny core, zero runtime bloat; built entirely on top of deno's stdlib
  • flexible type-safe routing with first-class support for path parameters, route groups, and wildcard methods
  • chainable context helpers and type-safe request/response handling
  • composable middleware stack with built-in support for CORS, logging, security headers, rate limiting
  • robust file serving featuring ETag caching, Range requests, and security options (e.g. dotfile protection)
  • native SSE and WebSockets support
  • built-in precompiled jsx/tsx renderer
  • multipart file uploads and automatic body parsing
  • global error handling and cookie jar management

performance comparison#

frameworks were benchmarked using autocannon. snarl 0.3.0 is set as baseline (1x).

Scenario snarl hono oak express
plain text 1.00x
73,554 req/s
1.36x
100,346 req/s
0.53x
38,960 req/s
0.30x
22,398 req/s
JSON 1.00x
73,005 req/s
0.88x
64,200 req/s
0.53x
38,842 req/s
0.26x
18,982 req/s
path params 1.00x
73,062 req/s
0.80x
58,573 req/s
0.48x
34,903 req/s
0.25x
18,190 req/s
query params 1.00x
71,830 req/s
0.87x
62,502 req/s
0.43x
30,702 req/s
0.28x
20,362 req/s

quick start#

// ... deno.json
{
	"imports": {
		"@july/snarl": "jsr:@july/snarl"
	},
	"compilerOptions": {
		"jsx": "precompile",
		"jsxImportSource": "@july/snarl",
		"lib": ["deno.ns", "dom", "dom.iterable"]
	}
}
import { createRouter, logger } from "@july/snarl";

const app = createRouter();

app.use(logger());

app.get("/", (ctx) => {
	return ctx.html(
		"<!DOCTYPE html>" + (
			<html>
				<head>
					<title>example paige</title>
				</head>
				<body>
					<h1>welcom</h1>
					<p>i meant page* haiiiii</p>
				</body>
			</html>
		),
	);
});

app.get("/users/:id", (ctx) => {
	const { id } = ctx.params;
	return ctx.json({ user: id });
});

app.post("/users", async (ctx) => {
	const body = await ctx.body();
	return ctx.created(body);
});

Deno.serve(app.fetch);