Contract-first Runtime-portable OpenAPI 3.1

[Start here Installation Set up DaloyJS without wandering through ten setup guides.](/docs/installation) [Quick path Getting started Build the first route and see the contract shape immediately.](/docs/getting-started) [Hands-on Bookstore tutorial Route-by-route walkthrough with a practical API shape.](/docs/tutorials/bookstore)

# Introduction to DaloyJS

**DaloyJS** is a runtime-portable TypeScript web framework with built-in contract-first routing, validation, OpenAPI 3.1 generation, [Hey API](https://heyapi.dev/docs/openapi/typescript/get-started) typed client codegen, large-scale maintainability, and core security guardrails plus first-party security middleware, backed by[pnpm](https://pnpm.io/motivation) plus hardened install and release controls.

The name comes from the Tagalog word **daloy**, meaning **flow**, pronounced **da-loy**. The project also uses the Baybayin spelling **ᜇᜎᜓᜌ᜔**. See [About the name](/about-the-name) for the short version.

## Why another framework?

Each existing stack is excellent at one thing and forces trade-offs everywhere else. DaloyJS combines the best ideas without the lock-in:

- OpenAPI ergonomics on par with FastAPI, built into the core, not bolted on.
- Vercel/serverless/edge fit on par with [Hono](https://hono.dev/docs/) - web-standard `Request -> Response`.
- Mature plugin/lifecycle/ops story on par with [Fastify](https://fastify.dev/docs/latest/Reference/).
- TS-first DX on par with [Elysia](https://elysiajs.com/at-glance): without forcing you onto Bun.
- Hey API typed client generation as a first-class workflow.
- Supply-chain-hardened installs and publishing via pnpm plus hardened repo defaults.

## The 30-second taste

```ts
import { App } from "@daloyjs/core";
import { z } from "zod";
import { serve } from "@daloyjs/core/node";

const app = new App();

app.get(
  "/hello/:name",
  {
    operationId: "sayHello",
    request: { params: z.object({ name: z.string() }) },
    responses: {
      200: { description: "Greeting", body: z.object({ msg: z.string() }) },
    },
  },
  async ({ params }) => ({
    status: 200,
    body: { msg: `Hello, ${params.name}` },
  }),
);

serve(app, { port: 3000 });
```

That single route definition gives you:

**Diagram: One route, five outputs**

- **app.get(path, contract, handler)** (source, single declaration) - method, path, request, responses, handler
- **Typed params** (handler) - params.name is string
- **Typed response** (return) - 200 to { msg: string }
- **OpenAPI 3.1 entry** (spec) - operationId: sayHello
- **Typed client method** (consumers) - client.sayHello(...)
- **Introspection entry** (tooling) - app.introspect()

You write one contract-first route. The handler types, the response type, the OpenAPI entry, the typed client method, and the introspection record are all derived from it.

- Strict, typed `params` in your handler.
- A typed return - TypeScript knows `200 -> { msg: string }`.
- An OpenAPI 3.1 entry under `operationId: sayHello`.
- A typed client method `client.sayHello({ params: { name: string } })`.
- An entry in `app.introspect()` for tooling and contract tests.

## Where to next?

- [Installation](/docs/installation): get DaloyJS into your project.
- [Getting started](/docs/getting-started): your first server in 5 minutes.
- [Tutorial: build a bookstore API](/docs/tutorials/bookstore).
- [API reference](/docs/api-reference).

---

Source: https://daloyjs.dev/docs