Four separate Vercel projects might sound like overkill until your monolith starts bleeding at the seams. The RAITHOS777 ecosystem proves that splitting your architecture isn't just about clean code—it's about deployable units that can scale independently. When one service needs more resources, you scale that service, not your entire application.
What you'll learn
- How to structure a multi-app ecosystem using Vercel
- Strategies for inter-app communication with shared types
- Environment variable management across deployments
- When to split services versus when to consolidate
Why this matters now
Modern web development has moved beyond the "one repo, one deploy" mindset. Teams need autonomy, different services require different scaling strategies, and blast radius matters—if your authentication service goes down, your marketing site shouldn't suffer. Vercel makes this trivial with its per-project deployment model, but the architecture decisions come before the infrastructure. RAITHOS777 demonstrates a real-world implementation of these principles with four distinct applications working in concert.
The Four-App Architecture
The RAITHOS777 ecosystem consists of four Vercel applications, each with a clear responsibility:
- Web Frontend – The primary user-facing application
- Admin Dashboard – Internal management interface
- API Service – Backend logic and data operations
- Marketing Site – Public-facing content and documentation
This separation means frontend changes don't require redeploying your API, and marketing updates won't touch your admin dashboard. Each app has its own deployment pipeline, its own environment variables, and its own scaling characteristics.
Shared Types Across Apps
The biggest challenge with multi-app architectures is maintaining type safety boundaries. RAITHOS777 solves this with a shared types package that all four apps import. This ensures your frontend can't accidentally send malformed data to your API, and your admin dashboard can't misinterpret API responses.
Here's how you structure a monorepo with shared types:
// packages/shared-types/src/index.ts
// Central type definitions used across all RAITHOS777 apps
export interface User {
id: string;
email: string;
role: 'admin' | 'user' | 'guest';
createdAt: Date;
}
export interface ApiResponse<T> {
data: T;
success: boolean;
error?: string;
}
// Request/response contracts for API service
export interface CreateUserRequest {
email: string;
role: User['role'];
}
export interface CreateUserResponse extends ApiResponse<User> {}
// apps/api/src/routes/users.ts
// API service consuming shared types for type-safe routes
import type { CreateUserRequest, CreateUserResponse } from '@raithos777/shared-types';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const body: CreateUserRequest = await req.json();
// Validate input against shared types
if (!body.email || !['admin', 'user', 'guest'].includes(body.role)) {
return NextResponse.json(
{ success: false, error: 'Invalid input' },
{ status: 400 }
);
}
// Database operations would happen here
const newUser = {
id: crypto.randomUUID(),
email: body.email,
role: body.role,
createdAt: new Date(),
};
const response: CreateUserResponse = {
data: newUser,
success: true,
};
return NextResponse.json(response);
}
The key insight here is that shared-types becomes your contract. If you change a type, TypeScript will immediately flag breaking changes across all four apps during development—not in production.
Inter-App Communication
With four separate Vercel deployments, your apps live on different domains. RAITHOS777 uses environment variables to manage these connections so you can have different endpoints for staging and production without code changes.
Here's the pattern for configuring API endpoints across environments:
// apps/web/src/config/api.ts
// Centralized API configuration per environment
const getApiUrl = () => {
// Vercel automatically provides environment variables
if (process.env.NEXT_PUBLIC_API_URL) {
return process.env.NEXT_PUBLIC_API_URL;
}
// Fallback for local development
if (process.env.NODE_ENV === 'development') {
return 'http://localhost:3001';
}
throw new Error('API_URL environment variable is not defined');
};
export const API_CONFIG = {
baseUrl: getApiUrl(),
timeout: 10000, // 10 second timeout for all requests
} as const;
// Type-safe fetch wrapper
export async function apiFetch<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`${API_CONFIG.baseUrl}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
return response.json();
}
This pattern means you can point your web frontend at a staging API by changing one environment variable in Vercel's dashboard—no code deployment required.
Deployment Workflow
Each RAITHOS777 app has its own GitHub repository connected to Vercel. When you push to the main branch, Vercel automatically builds and deploys that specific app. This independent deployment cycle is where the architecture pays off:
- Hotfix to the marketing site? Deploy in under 60 seconds without touching other apps
- API schema change? Deploy the API and shared types first, then update consuming apps
- Admin dashboard feature? Ship it without risking the main web application
Vercel's preview deployments work per-app too, so you can get a preview URL for just the admin dashboard changes while the rest of your ecosystem stays stable.
Common Pitfalls
Don't share runtime code in your types package
It's tempting to put utility functions in your shared package, but this creates a dependency nightmare. If you change a utility function, you have to redeploy all four apps. Keep shared packages to types and interfaces only.
Avoid direct database access from multiple apps
Only your API service should talk to your database. If your web frontend and admin dashboard both query the database directly, you'll duplicate validation logic and create security holes. The API service is your single source of truth for data operations.
Don't hardcode environment-specific values
Never hardwrite API URLs or feature flags directly in your code. Always use environment variables. A hardcoded https://api.raithos777.com will break your local development and staging environments.
Wrap-up
The RAITHOS777 ecosystem shows that multi-app architectures on Vercel aren't just for enterprise teams. The separation of concerns, independent scaling, and reduced blast radius make this approach viable even for small projects that expect to grow.
Key takeaways:
- Shared types packages maintain type safety across app boundaries
- Environment variables enable flexible staging and production configs
- Independent deployments reduce risk and speed up shipping
Next steps:
- Set up a monorepo with a shared types package using pnpm workspaces or Turborepo
- Configure environment variables in Vercel for each app's inter-app connections
- Implement a type-safe fetch wrapper to centralize your API communication logic
Top comments (0)