Cossack makes it easy to build backend endpoints directly within your project. You can choose between two styles: Functional API Routes for simplicity, or Class-based API Routes for shared state and advanced logic.

All API routes should be placed in the src/pages/api/ directory.

Functional API Routes (Zero-Config)

For most use cases, you can simply export a standard Hono handler.

All Methods (default export)

If you export a function as the default, it will handle all HTTP methods for that route.

// src/pages/api/echo.ts
export default (c) => {
  return c.json({ 
    message: 'Echo!',
    method: c.req.method 
  });
};

Specific Methods (Named exports)

You can export functions named GET, POST, PUT, DELETE, or PATCH to handle specific HTTP methods.

// src/pages/api/users.ts
export const GET = (c) => {
  return c.json([{ id: 1, name: 'Alice' }]);
};

export const POST = async (c) => {
  const data = await c.req.json();
  // save to DB
  return c.json({ success: true }, 201);
};

Class-based API Routes

If you need to share state between the client and server (via WebSockets) or prefer an object-oriented approach, you can extend the Cossack base class.

import { Cossack, Page } from '@cossackframework/core';

@Page({ transport: 'http' })
export default class MyApi extends Cossack {
    async get() {
        return this.c.json({ message: 'Hello from class!' });
    }
}

Routing Conventions

Cossack follows a standard file-based routing convention for API routes:

  • src/pages/api/hello.ts/api/hello
  • src/pages/api/users/index.ts/api/users
  • src/pages/api/users/[id].ts/api/users/:id

Type Safety

You can use the CloudflareBindings type (generated by cf-typegen) to get full autocompletion for your environment bindings (D1, KV, etc.) inside your handlers.

export const GET = async (c) => {
  const env = c.env as CloudflareBindings;
  const data = await env.MY_KV.get('some-key');
  return c.json({ data });
};