App Roots and Runtime
Every Slingshot app starts at the app root. This is where you assemble your packages, set config, and start the server.
If you have not built anything yet, start with the Quick Start.
Come back here when you want to understand what defineApp(...) actually does.
The app root
Section titled “The app root”// @skip-typecheckimport { defineApp } from '@lastshotlabs/slingshot';import { createAuthPlugin } from '@lastshotlabs/slingshot-auth';import { adminPackage } from './src/packages/admin';import { blogPackage } from './src/packages/blog';
export default defineApp({ port: 3000, security: { signing: { secret: process.env.JWT_SECRET! }, cors: { origin: 'https://myapp.com' }, }, db: { default: { adapter: 'postgres', url: process.env.DATABASE_URL! }, }, plugins: [ createAuthPlugin({ auth: { roles: ['user', 'admin'], defaultRole: 'user' }, }), ], packages: [blogPackage, adminPackage],});This one file controls:
- What runs — which packages and plugins to load
- How it connects — database, secrets, ports
- How it is secured — auth, CORS, rate limits
- What it supports — events, WebSockets, SSE, jobs
The app root stays small. Feature logic lives in packages. Boot it with slingshot start.
What the framework does on boot
Section titled “What the framework does on boot”When slingshot start loads your app.config.ts, the framework:
- Validates your config
- Resolves secrets from the configured provider
- Connects databases and infrastructure
- Boots plugins and packages in dependency order
- Registers middleware, routes, and OpenAPI docs
- Starts the HTTP server, WebSocket endpoints, and SSE
- Wires graceful shutdown
You get all of this from one function call.
defineApp, createApp, and createServer
Section titled “defineApp, createApp, and createServer”| Function | Use when |
|---|---|
defineApp() | Authoring app.config.ts — the canonical path |
createServer() | Custom imperative entry points (rare) |
createApp() | Testing, custom hosting, or programmatic use |
defineApp() is a typed identity helper for the config object. The CLI runner picks up the
default export and calls createServer() for you.
createApp() does everything except start the network server. Use it in tests:
// @skip-typecheckconst { app, ctx } = await createApp({ packages: [blogPackage] });const response = await app.request('/posts');await ctx.destroy();What you can configure
Section titled “What you can configure”The top-level config covers everything your app needs:
| Config area | What it controls |
|---|---|
port | Server port |
security | JWT signing, CORS, CSRF, rate limits, helmet |
db | Database connections (Postgres, SQLite, MongoDB, etc) |
packages | Feature packages to load |
plugins | Raw plugins (auth, permissions, etc) |
ws | WebSocket endpoints |
eventBus | Event bus adapter (in-process, BullMQ, Redis) |
secrets | Secret provider (env, vault, etc) |
jobs | Orchestration adapter |
multiTenancy | Tenant resolver and isolation settings |
See App Config for the full reference.
Learn this section
Section titled “Learn this section”Next in your journey
Section titled “Next in your journey”You understand the app root and runtime layer. The canonical journey continues into per-route concerns:
- Authoring Routes — every concern that applies to a single route: validation, DTO mapping, idempotency, exception handling.
- Working with Data — when a route should be generated from an entity model.
- Security — auth and permissions.
Adjacent reference:
- Package-First Authoring — feature module composition (revisit if you skipped here from Quick Start).
- Entity System — the full entity authoring story.
- Examples — complete apps to study.