Skip to main content

Overview

Polaris IDE is built as a modern cloud-based development environment with real-time collaboration, AI-powered code assistance, and multi-platform support (web + Electron desktop). Polaris Architecture

Technology Stack

Frontend Layer

Next.js 16

App Router architecture with React Server Components

React 19

Latest features including concurrent rendering

TypeScript

Strict mode enabled for type safety

Tailwind CSS 4

PostCSS integration for styling

Backend Services

Convex

Real-time database with optimistic updates

Trigger.dev

Background job processing and workflows

Stack Auth

Authentication with GitHub OAuth

Editor & AI

CodeMirror 6

Extensible code editor with custom extensions

Kimi K2.5/Cerebras

AI-powered code suggestions and chat

WebContainer

In-browser Node.js runtime

xterm.js

Terminal emulation

System Architecture Diagram

Based on ARCHITECTURE_DIAGRAM.md, here’s the complete data flow:

Database Schema

Polaris uses Convex for real-time data synchronization:

Core Tables

users: {
  stackUserId: string          // Stack Auth user ID
  email: string                // User email
  autumnCustomerId?: string    // Billing customer ID
  subscriptionStatus: "free" | "trialing" | "active" | "paused" | "canceled" | "past_due"
  subscriptionTier: "free" | "pro_monthly" | "pro_yearly"
  projectLimit: number         // -1 for unlimited
  trialEndsAt?: number        // Unix timestamp
  createdAt: number
  updatedAt: number
}

Indexes:
- by_stack_user (stackUserId)
- by_autumn_customer (autumnCustomerId)

Authentication Flow

Web Application

1

User visits application

StackProvider checks authentication status
2

Redirect to Stack Auth if unauthenticated

User signs in via /handler/sign-in
3

Stack Auth creates JWT token

Token stored in browser and sent with all requests
4

Convex uses JWT for authorization

ctx.auth.getUserIdentity() extracts stackUserId
5

API routes verify authentication

requireAuth() middleware validates JWT

Electron Desktop App

1

Main process gets M2M token

Server-to-server authentication with Stack Auth
2

Token stored in electron-store

Persisted securely on user’s machine
3

File operations use stored token

getConvexAuthForElectron() provides auth headers
4

Token refresh on expiration

Automatic re-authentication when token expires

Data Flow Patterns

Creating a Project

// 1. User clicks "New Project"
// 2. Frontend calls Convex mutation
const projectId = await convex.mutation(api.projects.create, {
  name: "My Project"
});

// 3. Convex verifies authentication
const identity = await verifyAuth(ctx);
const stackUserId = identity.subject;

// 4. Check project limits
const user = await ctx.db
  .query("users")
  .withIndex("by_stack_user", (q) => q.eq("stackUserId", stackUserId))
  .first();

if (user.projectLimit !== -1) {
  const existingProjects = await ctx.db
    .query("projects")
    .withIndex("by_owner", (q) => q.eq("ownerId", stackUserId))
    .collect();
  
  if (existingProjects.length >= user.projectLimit) {
    throw new Error("Project limit reached");
  }
}

// 5. Create project record
await ctx.db.insert("projects", {
  name: args.name,
  ownerId: stackUserId,
  userId: user._id,
  updatedAt: Date.now()
});

AI Message Processing

// 1. User sends message in chat
// 2. Create message record in Convex
const messageId = await convex.mutation(api.messages.create, {
  conversationId,
  content: userMessage,
  role: "user"
});

// 3. Trigger background job
await trigger.invoke("process-message", {
  messageId
});

// 4. Trigger.dev task processes message
export const processMessage = task({
  id: "process-message",
  run: async (payload) => {
    // Get message context
    const context = await convex.query(api.system.getMessageContext, {
      messageId: payload.messageId
    });
    
    // Stream AI response
    const response = await streamTextWithTools({
      messages: context.messages,
      tools: { readFile, writeFile, ... },
      onTextChunk: async (chunk) => {
        // Update message in real-time
        await convex.mutation(api.system.streamMessageContent, {
          messageId,
          content: chunk
        });
      }
    });
  }
});

// 5. Frontend receives real-time updates via Convex
useQuery(api.messages.getByConversation, { conversationId });

Component Architecture

Feature-Based Organization

Polaris uses a feature-based folder structure:
src/features/
├── auth/              # Authentication logic
│   ├── components/    # Auth UI components
│   └── hooks/         # useUser, useAuth
├── editor/            # Code editor
│   ├── components/    # Editor UI
│   ├── extensions/    # CodeMirror extensions
│   ├── hooks/         # useEditor
│   └── store/         # Tab state (Zustand)
├── conversations/     # AI chat
│   ├── components/    # Chat UI
│   └── hooks/         # useConversation
├── projects/          # Project management
│   ├── components/    # File explorer, dashboard
│   └── hooks/         # useProject
└── preview/           # Code preview
    └── components/    # Preview panel

Shared Components

src/components/
├── ui/                # shadcn/ui components
│   ├── button.tsx
│   ├── dialog.tsx
│   └── ...
└── ai-elements/       # AI-specific components
    ├── message-list.tsx
    ├── suggestion-widget.tsx
    └── ...

Background Job Processing

All heavy operations run as background jobs via Trigger.dev:
Handles AI chat responses with tool execution:
  • Fetches conversation context from Convex
  • Streams AI response with real-time updates
  • Executes file tools (read, write, delete)
  • Executes LSP tools (find symbols, diagnostics)
  • Executes search tools (code search, file search)
Creates complete project from description:
  • Validates input
  • Generates config files (package.json, tsconfig.json)
  • Creates source structure (main.tsx, App.tsx)
  • Generates components, pages, hooks
  • Writes README documentation

Subscription Management

Autumn handles billing and subscriptions:

Subscription Tiers

TierProjectsPriceStatus
Free10$0/mofree
Pro MonthlyUnlimited$29/moactive/trialing
Pro YearlyUnlimited$290/yractive/trialing

Integration Flow

  1. User clicks “Upgrade to Pro”
  2. Frontend calls /api/autumn/checkout
  3. Autumn creates checkout session with stackUserId in metadata
  4. User completes payment
  5. Autumn sends webhook to /api/webhooks/autumn
  6. Webhook updates Convex user record:
    await convex.mutation(api.users.updateSubscription, {
      stackUserId,
      subscriptionStatus: "active",
      projectLimit: -1  // Unlimited
    });
    

Error Tracking

Sentry monitors errors and AI performance:
// sentry.server.config.ts
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 1,
  enableLogs: true,
  integrations: [
    Sentry.vercelAIIntegration,  // AI monitoring
    Sentry.consoleLoggingIntegration()
  ]
});

Next Steps

Setup Guide

Set up your development environment

Background Jobs

Learn about Trigger.dev integration

Custom Extensions

Build CodeMirror extensions

Contributing

Contribute to Polaris

Build docs developers (and LLMs) love