KitRocket

TypeScript Types

Key TypeScript types used throughout the KitRocket boilerplate.

These are the core types used across the KitRocket codebase. They're exported from their respective modules and can be imported with the @/ path alias.

User and Auth

interface User {
  id: string;
  email: string;
  name: string;
  avatar: string | null;
  createdAt: Date;
}

interface Session {
  id: string;
  userId: string;
  token: string;
  expiresAt: Date;
}

interface Account {
  id: string;
  userId: string;
  provider: "google" | "github" | "credential";
  providerAccountId: string;
}

Usage

import type { User, Session } from "@/lib/auth/types";

function greetUser(user: User): string {
  return `Hello, ${user.name}`;
}

Payments

type PlanName = "starter" | "pro";

type SubscriptionStatus = "active" | "cancelled" | "past_due" | "trialing";

interface Plan {
  name: string;
  priceId: string;
  price: number;
  interval: "month" | "year";
  features: readonly string[];
  popular?: boolean;
}

interface Subscription {
  id: string;
  userId: string;
  plan: PlanName;
  status: SubscriptionStatus;
  dodoCustomerId: string | null;
  dodoSubscriptionId: string | null;
  currentPeriodEnd: Date | null;
  createdAt: Date;
}

interface CheckoutRequest {
  priceId: string;
}

interface CheckoutResponse {
  url: string;
}

Usage

import type { Plan, Subscription } from "@/lib/payments/types";

function isPro(subscription: Subscription | null): boolean {
  return subscription?.plan === "pro" && subscription?.status === "active";
}

Webhooks

interface WebhookEvent {
  type: WebhookEventType;
  data: Record<string, unknown>;
  timestamp: string;
}

type WebhookEventType =
  | "payment.completed"
  | "subscription.created"
  | "subscription.updated"
  | "subscription.cancelled";

interface PaymentCompletedData {
  customerId: string;
  customerEmail: string;
  amount: number;
  currency: string;
  subscriptionId: string;
  priceId: string;
}

interface SubscriptionUpdatedData {
  subscriptionId: string;
  customerId: string;
  status: SubscriptionStatus;
  priceId: string;
  currentPeriodEnd: string;
}

AI (Pro)

type AIProvider = "anthropic" | "openai";

type MessageRole = "user" | "assistant" | "system";

interface ChatMessage {
  id: string;
  role: MessageRole;
  content: string;
  createdAt: Date;
}

interface ChatRequest {
  messages: Array<{
    role: MessageRole;
    content: string;
  }>;
}

interface ChatResponse {
  type: "text" | "done" | "error";
  content?: string;
  usage?: TokenUsage;
  error?: string;
}

interface TokenUsage {
  inputTokens: number;
  outputTokens: number;
  model: string;
}

interface UsageRecord {
  id: string;
  userId: string;
  tokensUsed: number;
  model: string;
  createdAt: Date;
}

Usage

import type { ChatMessage, TokenUsage } from "@/lib/ai/types";

function totalTokens(usage: TokenUsage): number {
  return usage.inputTokens + usage.outputTokens;
}

Email

interface EmailOptions {
  to: string;
  subject: string;
  react: React.ReactElement;
  text?: string;
}

interface WelcomeEmailProps {
  name: string;
}

interface MagicLinkEmailProps {
  url: string;
}

interface ReceiptEmailProps {
  amount: number;
  plan: string;
  date: string;
  currency: string;
}

API Response

interface ApiResponse<T> {
  data: T | null;
  error: string | null;
}

interface PaginatedResponse<T> {
  data: T[];
  total: number;
  page: number;
  limit: number;
  hasMore: boolean;
}

Usage

import type { ApiResponse, PaginatedResponse } from "@/lib/utils/types";

// Single item response:
return NextResponse.json<ApiResponse<User>>({
  data: user,
  error: null,
});

// Error response:
return NextResponse.json<ApiResponse<User>>({
  data: null,
  error: "User not found",
}, { status: 404 });

// Paginated list:
return NextResponse.json<PaginatedResponse<Subscription>>({
  data: subscriptions,
  total: 42,
  page: 1,
  limit: 10,
  hasMore: true,
});

Database (Drizzle inferred types)

Drizzle ORM infers types from your schema. You don't need to write them manually:

import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { InferSelectModel, InferInsertModel } from "drizzle-orm";

export const users = pgTable("users", {
  id: text("id").primaryKey(),
  email: text("email").notNull().unique(),
  name: text("name").notNull(),
  avatar: text("avatar"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// These types are auto-generated from the schema:
export type SelectUser = InferSelectModel<typeof users>;
export type InsertUser = InferInsertModel<typeof users>;

Use inferred types in service functions:

import type { SelectUser, InsertUser } from "@/db/schema/users";

async function createUser(data: InsertUser): Promise<SelectUser> {
  const result = await db.insert(users).values(data).returning();
  return result[0];
}

This approach keeps your types in sync with the database schema automatically. When you change a column, the type updates without manual edits.

On this page