For AI agents: the complete documentation index is available at https://dotpress.dev/llms.txt, the full documentation bundle is available at https://dotpress.dev/llms-full.txt, and this page is available as Markdown at https://dotpress.dev/index.md.
2.0 alpha
Dotpress
End-to-end typed backend APIs

A lightweight, decorator-free TypeScript framework. Your schemas type each request and its response, on the HTTP server you choose.

🔷

Typed from end to end

Zod schemas validate and type the params, the query, the body and the response of each route. The OpenAPI document comes from the same routes.

â†Šī¸

Errors are returned

Handlers return their errors like any other value. Every error, from a failed validation to an unexpected exception, has the same JSON format.

🔌

Any HTTP server

The core knows no HTTP server. The same app runs on Express, Fastify or Hono, and on AWS Lambda.

đŸ“Ļ

Packages when you need them

Authentication, OpenAPI, emails, events, cache and testing helpers, each in its own package.

A route, as the editor sees it

Hover the code: the types come from the schemas. This snippet is compiled against Dotpress when the site is built.

import { 
const defineRoute: <const P extends string, S extends RouteSchema = EmptyObject, TRawBody extends boolean = false, const TProvided extends readonly unknown[] = unknown[]>(route: RouteConfig<P, S, EmptyObject, TRawBody, TProvided, unknown>) => void

Declares a route on the global router.

defineRoute
,
const notFoundError: (message?: string, data?: ErrorData) => HttpError
notFoundError
} from '@dotpress/core'
declare const
const findProject: (id: string) => Promise<{
    name: string;
} | null>
findProject
: (
id: string
id
: string) =>
interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{
name: string
name
: string } | null>
defineRoute<"/projects/:projectId/tasks", {
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, false, unknown[]>(route: RouteConfig<"/projects/:projectId/tasks", {
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, EmptyObject, false, unknown[], unknown>): void

Declares a route on the global router.

defineRoute
({
RouteConfig<P extends string, S extends RouteSchema, TParentParams = EmptyObject, TRawBody extends boolean = false, TProvided extends readonly unknown[] = unknown[], TGroupContext = unknown>.method?: HttpMethod | undefined

Defaults to get.

method
: 'post',
RouteConfig<"/projects/:projectId/tasks", { body: ZodObject<{ title: ZodString; dueOn: ZodOptional<ZodISODate>; }, $strip>; }, EmptyObject, false, unknown[], unknown>.path: "/projects/:projectId/tasks"
path
: '/projects/:projectId/tasks',
RouteConfig<"/projects/:projectId/tasks", { body: ZodObject<{ title: ZodString; dueOn: ZodOptional<ZodISODate>; }, $strip>; }, EmptyObject, false, unknown[], unknown>.schema?: SchemaDefinition<{
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}> | undefined
schema
: (
z: typeof import("zod")
z
) => ({
body: ZodObject<{
    title: ZodString;
    dueOn: ZodOptional<ZodISODate>;
}, $strip>
body
:
z: typeof import("zod")
z
.
function object<{
    title: ZodString;
    dueOn: ZodOptional<ZodISODate>;
}>(shape?: {
    title: ZodString;
    dueOn: ZodOptional<ZodISODate>;
} | undefined, params?: string | {
    error?: string | $ZodErrorMap<NonNullable<$ZodIssueInvalidType<unknown> | $ZodIssueUnrecognizedKeys>> | undefined;
    message?: string | undefined | undefined;
} | undefined): ZodObject<{
    title: ZodString;
    dueOn: ZodOptional<ZodISODate>;
}, $strip>
object
({
title: ZodString
title
:
z: typeof import("zod")
z
.
function string(params?: string | $ZodStringParams): ZodString (+1 overload)
string
().
_ZodString<$ZodStringInternals<string>>.min(minLength: number, params?: string | $ZodCheckMinLengthParams): ZodString
min
(1),
dueOn: ZodOptional<ZodISODate>
dueOn
:
z: typeof import("zod")
z
.
import iso
iso
.
function date(params?: string | $ZodISODateParams): ZodISODate
date
().
ZodType<any, any, $ZodStringFormatInternals<string>>.optional(): ZodOptional<ZodISODate>
optional
(),
}), }),
RouteConfig<"/projects/:projectId/tasks", { body: ZodObject<{ title: ZodString; dueOn: ZodOptional<ZodISODate>; }, $strip>; }, EmptyObject, false, unknown[], unknown>.handler: RouteHandler<{
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, {
    projectId: string;
}, false, unknown>
handler
: async ({
req: RouteRequest<{
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, {
    projectId: string;
}, false>
req
}) => {
const
const project: {
    name: string;
} | null
project
= await
const findProject: (id: string) => Promise<{
    name: string;
} | null>
findProject
(
req: RouteRequest<{
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, {
    projectId: string;
}, false>
req
.
DotpressRequest<{ projectId: string; }, QueryValues, { title: string; dueOn?: string | undefined; }, UploadedFiles>.params: {
    projectId: string;
}
params
.
projectId: string
projectId
)
if (!
const project: {
    name: string;
} | null
project
) return
function notFoundError(message?: string, data?: ErrorData): HttpError
notFoundError
('Project not found')
const
const task: {
    project: string;
    title: string;
    dueOn?: string | undefined;
}
task
= { ...
req: RouteRequest<{
    body: ZodObject<{
        title: ZodString;
        dueOn: ZodOptional<ZodISODate>;
    }, $strip>;
}, {
    projectId: string;
}, false>
req
.
DotpressRequest<{ projectId: string; }, QueryValues, { title: string; dueOn?: string | undefined; }, UploadedFiles>.body: {
    title: string;
    dueOn?: string | undefined;
}
body
,
project: string
project
:
const project: {
    name: string;
}
project
.
name: string
name
}
return
const task: {
    project: string;
    title: string;
    dueOn?: string | undefined;
}
task
}, })