Skip to main content
SkyTeam ROBLOX is built as a Turborepo monorepo, enabling shared code, coordinated development, and efficient builds across multiple applications and packages.

Monorepo Structure

The project is organized into two main directories: apps/ for standalone applications and packages/ for shared libraries.
skyteam/
├── apps/
│   ├── admin/          # Next.js admin panel
│   ├── api/            # Express REST API
│   ├── client/         # Discord bot
│   ├── models/         # ROBLOX module
│   └── web/            # Next.js web app
├── packages/
│   ├── database/       # Drizzle ORM + schema
│   └── ui/             # Shared React components
├── turbo.json          # Turborepo configuration
├── pnpm-workspace.yaml # PNPM workspace config
└── package.json        # Root package.json
All applications and packages are managed with PNPM workspaces and orchestrated by Turborepo for optimal build caching and parallelization.

Applications

Web Application (@skyteam/web)

Next.js 15 application serving the public-facing website for passengers.

Framework

Next.js 15 with React 19

Styling

TailwindCSS 4

Port

3000

Dependencies

@skyteam/database, @skyteam/ui
Key Features:
  • Flight browsing and search
  • Miles balance checking
  • Product marketplace
  • Responsive design with Radix UI components
Package.json scripts:
{
  "dev": "next dev",
  "build": "next build",
  "start": "next start"
}

Admin Panel (@skyteam/admin)

Next.js 15 application for airline operators to manage their operations.

Framework

Next.js 15 with React 19

UI Library

Headless UI + Heroicons

Port

3001

Dependencies

@skyteam/database, @skyteam/ui
Key Features:
  • Airline and brand management
  • Flight scheduling and monitoring
  • Miles product configuration
  • User management and analytics
Package.json scripts:
{
  "dev": "next dev -p 3001",
  "build": "next build",
  "start": "next start"
}

API Server (@skyteam/api)

Express.js REST API providing backend services for ROBLOX game integration.

Framework

Express 4

Security

Helmet + CORS

Port

4000

Dependencies

@skyteam/database
API Structure (apps/api/src/):
index.ts                 // Main Express app
middleware/
  └── auth.ts           // airlineAuth middleware
routes/
  ├── status.ts         // Health checks
  ├── airline.ts        // Airline/brand data
  ├── flight.ts         // Flight management
  └── users.ts          // User data & purchases
Authentication: All routes (except /health) require the x-api-key header:
// From apps/api/src/index.ts
app.use(airlineAuth); // Validates airline token
Package.json scripts:
{
  "build": "tsup src/index.ts",
  "dev": "tsup src/index.ts --watch --onSuccess \"node dist/index.js\"",
  "start": "node dist/index.js"
}

Discord Bot (@skyteam/client)

Discord.js bot with Discordx for slash commands and event handling.

Framework

Discord.js 14 + Discordx

Features

Slash commands, embeds

Type

ESM module

Dependencies

@skyteam/database
Bot Configuration (apps/client/src/index.ts):
export const bot = new Client({
  intents: [
    IntentsBitField.Flags.Guilds,
    IntentsBitField.Flags.GuildMembers,
    IntentsBitField.Flags.GuildMessages,
    // ... more intents
  ],
  botGuilds: [process.env.DISCORD_HOME_GUILD_ID],
  guards: [NotBot],
  simpleCommand: { prefix: "st!" }
});
Available Commands:
  • /ping - Test bot responsiveness (apps/client/src/commands/public/ping.ts)
  • /setupchannel - Configure flight channels (apps/client/src/commands/private/setupchannel.ts)

ROBLOX Module (@skyteam/models)

TypeScript module compiled to Lua for integration into ROBLOX games.

Language

TypeScript (roblox-ts)

Compiler

roblox-ts 3.0

Sync

Rojo

Framework

Roact + Ripple
Module Structure:
// apps/models/src/module/index.ts
export default class SkyTeamModule {
  constructor(Settings: Settings) {
    this.Settings = Settings;
  }
  
  public Initialize(): void {
    // Set up RemoteEvent
    // Connect PlayerAdded
    // Test HTTP services
  }
}
Usage in ROBLOX:
import SkyTeamModule from "@rbxts/skyteam-module";

const skyteam = new SkyTeamModule({
  TOKEN: "your-airline-token",
  Flags: []
});

skyteam.Initialize();
Package.json scripts:
{
  "build": "rbxtsc",
  "dev:watch": "rbxtsc --type game -w",
  "dev:serve": "rojo serve",
  "dev": "concurrently \"pnpm run dev:watch\" \"pnpm run dev:serve\""
}

Shared Packages

Database Package (@skyteam/database)

Centralized database access layer using Drizzle ORM with PostgreSQL.

ORM

Drizzle ORM 0.40

Database

PostgreSQL

Type Safety

Full TypeScript types

Tools

Drizzle Kit + Studio
Schema (packages/database/src/schema.ts):
export const users = pgTable("users", {
  userId: text("userId").primaryKey(),
  username: text("username").notNull().unique(),
  displayName: text("displayName").notNull(),
  miles: integer("miles").notNull().default(0),
  avatarUrl: text("avatarUrl"),
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().notNull(),
});
Package.json scripts:
{
  "build": "tsup src/index.ts",
  "dev": "tsup src/index.ts --watch",
  "db:generate": "drizzle-kit generate",
  "db:push": "drizzle-kit push",
  "db:studio": "drizzle-kit studio"
}

UI Package (@skyteam/ui)

Shared React components used across web and admin applications.

Framework

React 19

Styling

TailwindCSS compatible

Consumers

@skyteam/web, @skyteam/admin

Type

TypeScript library

System Flow

Flight Lifecycle

1

Flight Creation

Airline creates a flight in the admin panel with:
  • Flight code, aircraft type
  • Departure and arrival airports
  • Brand and codeshare settings
  • Discord event link
2

ROBLOX Game Start

When the ROBLOX server starts, it:
  1. Calls GET /flight/fetchUpcomingFlights
  2. Displays available flights to pilots
  3. Calls POST /flight/:id/serverStart when flight begins
3

In-Flight Operations

During the flight:
  1. Server sends heartbeat: POST /flight/:id/tick
  2. Passengers are tracked via flightPassengers table
  3. Miles are calculated based on distance/duration
4

Flight Completion

When landing:
  1. Server calls POST /flight/:id/serverEnd
  2. Miles are distributed to passengers
  3. Transaction records created in milesTransactions
  4. Discord bot notifies completion

Miles Rewards Flow

Authentication Flow

1

Airline Registration

Airline is created in the admin panel with a unique API token generated.
2

ROBLOX Configuration

Token is added to the ROBLOX module settings:
new SkyTeamModule({ TOKEN: "abc123..." })
3

API Request

Every API request includes the token:
headers: { "x-api-key": "abc123..." }
4

Middleware Validation

The airlineAuth middleware validates the token and attaches airline data to res.locals.airline.

Data Flow Diagram

Build System

Turborepo Configuration

The turbo.json file orchestrates builds across the monorepo:
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
Key features:
  • Parallel builds - Independent tasks run simultaneously
  • Smart caching - Rebuilds only changed packages
  • Dependency ordering - Builds packages before apps

Environment Variables

Global environment variables are defined in turbo.json:
"globalEnv": [
  "DATABASE_URL",
  "DISCORD_TOKEN",
  "DISCORD_HOME_GUILD_ID",
  "DISCORD_CLIENT_ID",
  "NEXT_PUBLIC_API_URL",
  "ADMIN_JWT_SECRET"
]
These are automatically passed to all workspaces during builds.

Deployment

Docker Compose

The docker-compose.yml defines all services:
services:
  web:      # Next.js web app (port 3000)
  admin:    # Next.js admin panel (port 3001)
  api:      # Express API (port 4000)
  client:   # Discord bot (no port)
Deploy all services:
docker-compose up -d

Technology Choices

Turborepo provides intelligent caching and parallel execution for monorepos. When you change a package, only dependent apps rebuild, saving significant time in development.
PNPM uses a content-addressable store, meaning packages are stored once and hard-linked everywhere. This saves disk space and speeds up installs compared to npm/yarn.
Drizzle provides type-safe database queries with minimal overhead. It generates TypeScript types from your schema, catching errors at compile time.
Next.js 15 offers React Server Components, improved performance, and excellent developer experience. The App Router simplifies routing and layouts.
roblox-ts brings TypeScript’s type safety to ROBLOX development. It compiles to Lua while providing modern language features and tooling.

Next Steps

Setup Prerequisites

Detailed environment setup guide

Database Configuration

Learn about schema and migrations

ROBLOX Integration

Connect your ROBLOX game

Development Workflow

Best practices for development

Build docs developers (and LLMs) love