Skip to content

Getting Started

Welcome to Karin! This guide will help you set up your first project. You can choose between the CLI (Recommended) for a quick start or a Manual Setup if you want to understand every piece of the puzzle.

Prerequisites

Before we begin, ensure you have the following installed:

  • Runtime: Bun (v1.0+).
  • Package Manager: bun (recommended), npm, yarn, or pnpm.

Note: Karin is optimized for Bun's native primitives and filesystem operations.


The Karin CLI is the fastest way to scaffold a production-ready project with best practices pre-configured.

1. Installation

Install the CLI globally:

bash
# Using Bun
bun install -g @project-karin/cli

# Using npm
npm install -g @project-karin/cli

2. Create a Project

Run the new command:

bash
karin new my-awesome-api

The interactive wizard will guide you:

  • Project Name: The folder name for your app.
  • Environment:
    • Traditional Server: Standard setup (VPS, Docker). Uses file scanning.
    • Serverless: Optimized for Edge (Cloudflare/Lambda). Uses explicit registration.
  • Framework Adapter:
    • H3: Default, high-performance adapter (used by Nuxt).
    • Hono: Best for Edge and compatibility with Hono middlewares.
  • Git & Dependencies: Initialize git and install packages automatically.

3. Run It

bash
cd my-awesome-api
bun run dev

Your server is now running! 🚀


Option 2: Manual Installation

If you prefer to build from scratch to understand how Karin works under the hood, follow these steps.

1. Initialize Project

Create a directory and initialize your package manager:

bash
mkdir karin-manual
cd karin-manual
bun init -y

2. Install Dependencies

You need the core framework, and an HTTP adapter.

bash
bun add @project-karin/core @project-karin/platform-h3
bun add -d typescript @types/node

3. Configure TypeScript

Karin relies heavily on decorators. You must configure your tsconfig.json correctly.

Create or edit tsconfig.json:

json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,

    // ⚠️ CRITICAL SETTINGS FOR DECORATORS ⚠️
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

    "outDir": "./dist",
    "rootDir": "./src"
  }
}

Why is this needed? emitDecoratorMetadata allows Karin to know the types of your dependencies at runtime, enabling Dependency Injection.

4. Create Your First Controller

Create src/app.controller.ts. This class will handle incoming requests.

typescript
import { Controller, Get } from "@project-karin/core";

@Controller()
export class AppController {
  @Get()
  getHello(): string {
    return "Hello from Karin!";
  }

  @Get("/json")
  getJson() {
    return { message: "Automatic JSON serialization works!" };
  }
}

5. Create the Entry Point

Create src/main.ts. This is where we bootstrap the application.

typescript
import { KarinFactory } from "@project-karin/core";
import { H3Adapter } from "@project-karin/platform-h3";
import { JwtStrategy } from "./auth/jwt.strategy";

async function bootstrap() {
  // Create the application instance
  const app = await KarinFactory.create(new H3Adapter(), {
    // 1. Auto-scan (Recommended for Dev)
    // Automatically finds controllers and services.
    // You can still use 'providers' to manually register specific classes (like Strategies)
    scan: "./src/**/*.ts",
    providers: [JwtStrategy],

    // 2. Manual Registration (Recommended for Serverless/Production)
    // scan: false,
    // controllers: [AppController],
    // providers: [JwtStrategy, AppService],
  });

  const port = 3000;

  app.listen(port, () => {
    console.log(`Server running on http://localhost:${port}`);
  });
}

bootstrap();

6. Run the Application

Add a script to your package.json:

json
"scripts": {
  "dev": "bun run --watch src/main.ts"
}

Run it:

bash
bun run dev

Understanding Adapters

Karin is platform-agnostic. It doesn't handle HTTP requests directly; instead, it uses an Adapter. This allows you to switch underlying frameworks without rewriting your application logic.

Available Adapters

AdapterPackageDescription
H3@project-karin/platform-h3Default. Extremely lightweight and fast. Used by Nuxt. Best for standard Node.js/Bun servers.
Hono@project-karin/platform-honoEdge-First. Best for Cloudflare Workers, Deno Deploy, and Vercel Edge.

Hono Compatibility 🤝

If you choose the Hono adapter, you gain access to the entire Hono ecosystem. You can use any Hono middleware directly within Karin.

Example: Using Hono Logger

typescript
import { HonoAdapter } from "@project-karin/platform-hono";
import { logger } from "hono/logger";
import { prettyJSON } from "hono/pretty-json";

async function bootstrap() {
  const adapter = new HonoAdapter();

  // Access the underlying Hono instance
  const hono = adapter.getInstance();

  // Use standard Hono middlewares
  hono.use("*", logger());
  hono.use("*", prettyJSON());

  const app = await KarinFactory.create(adapter, { scan: "./src/**/*.ts" });

  // ...
}

Project Structure

A typical Karin project looks like this:

my-project/
├── src/
│   ├── common/             # Shared logic (Guards, Pipes, Filters)
│   │   ├── auth.guard.ts
│   │   └── validation.pipe.ts
│   ├── users/              # Feature module
│   │   ├── dtos/           # Data Transfer Objects
│   │   ├── entities/       # Database models
│   │   ├── users.controller.ts
│   │   └── users.service.ts
│   └── main.ts             # Entry point
├── .env                    # Environment variables
├── package.json
└── tsconfig.json

Next Steps

Now that you have your project running, explore the core concepts:

Released under the MIT License.