Creating Apps
Apps are the building blocks of StratusTS applications. This guide explains what apps are, how to create them, and best practices for organizing your code.
What is an App?
Section titled “What is an App?”An app in StratusTS is a self-contained module that handles a specific domain or feature of your application. Think of apps as reusable packages of functionality.
Examples of Apps
Section titled “Examples of Apps”Good app examples:
users- User authentication and managementblog- Blog posts and commentsapi- External API endpointsadmin- Admin panel functionalitypayments- Payment processingnotifications- Email and push notifications
Each app focuses on one responsibility, making your code easier to understand, test, and maintain.
Why Use Apps?
Section titled “Why Use Apps?”1. Organization
Section titled “1. Organization”Apps keep related code together:
Directoryusers/
- controllers.ts # User-related request handlers
- routes.ts # User-related URLs
- models.ts # User database models
- services.ts # Services related to User models
Everything about users lives in one place.
2. Reusability
Section titled “2. Reusability”Apps can be moved between projects:
# Copy entire app to another projectcp -r users/ ../other-project/src/users/Share common functionality across projects without code duplication.
3. Scalability
Section titled “3. Scalability”Add features without touching existing code:
// Beforeconst APPS = ['users', 'blog'];
// After - just add new appconst APPS = ['users', 'blog', 'payments', 'notifications'];Each app is independent—adding one doesn’t break others.
4. Team Collaboration
Section titled “4. Team Collaboration”Different developers can work on different apps without conflicts:
- Alice works on
usersapp - Bob works on
blogapp - Charlie works on
apiapp
No stepping on each other’s toes!
5. Testing
Section titled “5. Testing”Test apps independently:
import { test } from 'node:test';import { listUsers } from '../controllers';
// Test user functionality in isolationtest('listUsers returns all users', () => { // ...});Creating an App
Section titled “Creating an App”Using the CLI
Section titled “Using the CLI”The easiest way to create an app is with the CLI:
st create app usersor the full command:
stratus-ts create app usersThis creates a new directory with the standard structure.
Where to Run the Command
Section titled “Where to Run the Command”Run this command from your project root directory (where src/ folder exists):
my-first-app/├── src/ # You should be here│ └── settings.ts└── package.json
# Run from here:$ pwd/path/to/my-first-app
$ st create app usersWhat Gets Created
Section titled “What Gets Created”The CLI generates this structure:
Directorysrc/
Directoryusers/
- controllers.ts # Request handlers
- routes.ts # URL routing
- models.ts # Database models (optional)
- services.ts # If
models.tsis presend then required
Generated Files
Section titled “Generated Files”controllers.ts - Empty file ready for your controllers:
import { type ControllerType } from 'stratus-ts';
// Add your controllers hereroutes.ts - Basic router setup:
import { Router } from 'stratus-ts';
const { routes, route } = Router();
// Define your routes here// Example: route.get('/', yourController);
export default routes;models.ts - Empty file for database models:
// Define your database models hereLinking Your App to the Project
Section titled “Linking Your App to the Project”Creating an app isn’t enough—you must register it in settings.
Step 1: Open Settings
Section titled “Step 1: Open Settings”Edit src/settings.ts:
import type { DatabaseType, SettingsType } from 'stratus-ts';
const PORT = 2000;const APPS = []; // ← Currently emptyconst DATABASE: DatabaseType = false;const TEMPLATE_DIR = 'templates';
export default { PORT, APPS, DATABASE, TEMPLATE_DIR,} satisfies SettingsType;Step 2: Add Your App
Section titled “Step 2: Add Your App”Add the app name to the APPS array:
const APPS = ['users']; // ← Added!Full example:
import type { DatabaseType, SettingsType } from 'stratus-ts';
const PORT = 2000;const APPS = ['users']; // Your app is now registeredconst DATABASE: DatabaseType = false;const TEMPLATE_DIR = 'templates';
export default { PORT, APPS, DATABASE, TEMPLATE_DIR,} satisfies SettingsType;Step 3: Restart Your Server ?
Section titled “Step 3: Restart Your Server ?”If your server is running and doesn’t load new app, restart it to load the new app:
# Stop the server (Ctrl+C)# Start it againnpm run devYour app’s routes are now active!
How Automatic Route Registration Works
Section titled “How Automatic Route Registration Works”StratusTs automatically registers routes from all apps in the APPS array. Here’s how:
1. Framework Scans Apps
Section titled “1. Framework Scans Apps”When your server starts, StratusTS:
- Reads the
APPSarray from settings - Looks for each app directory in
src/ - Imports
routes.tsfrom each app - Registers all routes automatically
2. Combine URL
Section titled “2. Combine URL”Combine all the routes in one place:
// App name: users// Route defined as: route.get('/', controller)// Actual URL: /
// App name: blog// Route defined as: route.get('/posts', controller)// Actual URL: /posts3. Route Examples
Section titled “3. Route Examples”// users/routes.tsimport { route } from 'stratus-ts';
route.get('/', listUsers); // → /route.get('/<id:str>', getUser); // → /:idroute.post('/create', createUser); // → /create
// blog/routes.tsroute.get('/blog', listPosts); // → /blog/route.get('/blog/<slug:str>', getPost); // → /blog/:slugCreating Multiple Apps
Section titled “Creating Multiple Apps”You can create as many apps as needed:
st create app usersst create app blogst create app apist create app adminRegister all of them in settings:
const APPS = [ 'users', 'blog', 'api', 'admin',];App Naming Conventions
Section titled “App Naming Conventions”Good Names
Section titled “Good Names”✅ Lowercase, no special characters:
st create app usersst create app blogst create app api✅ Use hyphens for multi-word apps:
st create app user-managementst create app blog-postsst create app payment-gatewayBad Names
Section titled “Bad Names”❌ Uppercase letters:
st create app Users # Don't do thisst create app BlogPosts # Don't do this❌ Spaces or special characters:
st create app "user management" # Don't do thisst create app blog_posts # Use hyphens insteadBest Practices
Section titled “Best Practices”1. Keep Apps Focused
Section titled “1. Keep Apps Focused”Each app should have one clear purpose.
Good:
const APPS = [ 'users', // User management only 'blog', // Blog functionality only 'payments', // Payment processing only];Bad:
const APPS = [ 'everything', // Users, blog, payments all mixed together];2. Make Apps Independent
Section titled “2. Make Apps Independent”Apps should work without depending on each other’s internals.
Good:
import { User } from './models'; // Import from own app
// blog/controllers.tsimport { Post } from './models'; // Import from own appAcceptable:
// If you need user data, import the public APIimport { getUserById } from '../users/services';Bad:
import { User } from '../users/models'; // Tight coupling3. Use Clear, Descriptive Names
Section titled “3. Use Clear, Descriptive Names”App names should instantly convey their purpose.
Good:
users- Obviousblog- Clearnotifications- Self-explanatory
Less Good:
stuff- Too vaguemisc- What does it do?utils- Utility functions don’t need an app
4. Group Related Features
Section titled “4. Group Related Features”If features are closely related, keep them in one app.
Good:
Directoryblog/
Directorycontrollers.ts
- listPosts()
- createPost()
- listComments()
- createComment()
Directorymodels.ts
- Post
- Comment
Posts and comments are related—they belong together.
Debatable:
Directoryblog-posts/ # Separate app for posts…
- …
Directoryblog-comments/ # …and comments
- …
Only separate if they’re truly independent features.
5. Don’t Over-Engineer
Section titled “5. Don’t Over-Engineer”Start simple. One app is fine for small projects.
For small projects:
const APPS = ['api']; // Everything in one app is OKAs you grow:
const APPS = ['users', 'blog', 'api'];Split apps when complexity demands it, not before.
Common Patterns
Section titled “Common Patterns”Pattern 1: Feature-Based Apps
Section titled “Pattern 1: Feature-Based Apps”Organize by feature/domain:
const APPS = [ 'users', // User authentication 'blog', // Blog posts 'shop', // E-commerce 'admin', // Admin panel];When to use: Most applications benefit from this approach.
Pattern 2: API Versioning
Section titled “Pattern 2: API Versioning”Separate apps for API versions:
const APPS = [ 'api-v1', // Version 1 endpoints 'api-v2', // Version 2 endpoints];When to use: When maintaining multiple API versions.
Pattern 3: Client Separation
Section titled “Pattern 3: Client Separation”Different apps for different clients:
const APPS = [ 'web', // Web application routes 'mobile-api', // Mobile app API 'admin', // Admin panel];When to use: When different clients need different functionality.
Example: Building a Blog
Section titled “Example: Building a Blog”Let’s walk through creating a complete blog app.
Step 1: Create the App
Section titled “Step 1: Create the App”st create app blogStep 2: Register the App
Section titled “Step 2: Register the App”const APPS = ['blog'];Step 3: Create Controllers
Section titled “Step 3: Create Controllers”import { type ControllerType, ok, created, notFound } from 'stratus-ts';
const posts = [ { id: 1, title: 'First Post', author: 'Alice' }, { id: 2, title: 'Second Post', author: 'Bob' },];
// List all postsexport const listPosts: ControllerType = (question, reply) => { reply.status(ok()).json({ success: true, data: posts });};
// Get single postexport const getPost: ControllerType = (question, reply) => { const { id } = question.params;
const post = posts.find(p => p.id === parseInt(id));
if (!post) { return reply.status(notFound()).json({ success: false, error: 'Post not found', }); }
reply.status(ok()).json({ success: true, data: post });};
// Create postexport const createPost: ControllerType = (question, reply) => { const { title, content, author } = question.body;
const newPost = { id: Date.now(), title, content, author, createdAt: new Date(), };
posts.push(newPost);
reply.status(created()).json({ success: true, data: newPost });};Step 4: Define Routes
Section titled “Step 4: Define Routes”import { Router } from 'stratus-ts';import { listPosts, getPost, createPost } from './controllers';
const { routes, route } = Router();
route.get('/', listPosts);route.get('/<id:int>', getPost);route.post('/create', createPost);
export default routes;Step 5: Test Your Blog
Section titled “Step 5: Test Your Blog”# Start servernpm run dev
# Test endpointscurl http://localhost:2000/curl http://localhost:2000/1curl -X POST http://localhost:2000/create \-H 'Content-Type: application/json' \-d '{"title":"New Post","content":"Content","author":"Charlie"}'Your blog app is complete!
Troubleshooting
Section titled “Troubleshooting”App Not Loading
Section titled “App Not Loading”Problem: Routes return 404.
Solution: Check that:
- App is added to
APPSarray in settings - App name matches directory name exactly
routes.tsexportsdefault- Server was restarted after adding app
Routes Conflict
Section titled “Routes Conflict”Problem: One route overrides another.
Solution: Check app order in APPS array. The first app wins conflicts.
Import Errors
Section titled “Import Errors”Problem: Cannot import from app.
Solution: Use correct relative paths:
import { controller } from './controllers'; // Same directoryimport { User } from './models'; // Same directoryNext Steps
Section titled “Next Steps”Now that you understand apps, explore:
- Controllers - Build request handlers