Quick Start
Build your first JustScale application in 5 minutes
Create a New Project
Bash
mkdir my-app && cd my-app
pnpm init -y
pnpm add @justscale/core @justscale/http @justscale/cluster
pnpm add --save-dev typescript @types/nodeCreate Your First Service
Services contain your business logic. Create src/services/greeting.ts:
Files
src/services/greeting.tsTypeScript
import { createService } from '@justscale/core'
export const GreetingService = createService({
inject: {},
factory: () => ({
greet: (name: string) => `Hello, ${name}!`,
farewell: (name: string) => `Goodbye, ${name}!`,
}),
})Create a Controller
Controllers group related routes. Create src/controllers/greeting.ts:
Files
src/controllers/greeting.tsTypeScript
import { createController } from '@justscale/core'
import { Get } from '@justscale/http'
import { z } from 'zod'
import { GreetingService } from '../services/greeting'
// Response schema for type safety & OpenAPI generation
const MessageResponse = z.object({
message: z.string(),
})
export const GreetingController = createController('/greet', {
inject: { greeting: GreetingService },
routes: (services) => ({
hello: Get('/:name')
.returns(MessageResponse)
.handle(({ params, res }) => {
const message = services.greeting.greet(params.name)
res.json({ message })
}),
goodbye: Get('/bye/:name')
.returns(MessageResponse)
.handle(({ params, res }) => {
const message = services.greeting.farewell(params.name)
res.json({ message })
}),
}),
})Create the Application
Wire everything together in src/index.ts:
Files
src/index.tsTypeScript
import { createClusterBuilder, wrapWithCluster } from '@justscale/cluster'
import { GreetingController } from './controllers/greeting'
import { GreetingService } from './services/greeting'
const built = createClusterBuilder()
.add(GreetingService)
.add(GreetingController)
.build()
const cluster = wrapWithCluster(built.compile())
await cluster.serve({ http: 3000 })
console.log('Server running on http://localhost:3000')Run It
Bash
npx tsx src/index.tsTest your API:
Bash
curl http://localhost:3000/greet/World
# {"message":"Hello, World!"}
curl http://localhost:3000/greet/bye/World
# {"message":"Goodbye, World!"}What's Next?
Add Validation
Use Zod schemas to validate request body and declare response types:
users-controller.tsTypeScript
import { createController } from '@justscale/core';
import { Post } from '@justscale/http';
import { body } from '@justscale/http/builder';
import { z } from 'zod';
import { UserService } from './user-service';
// Request body schema
const CreateUserBody = z.object({
email: z.string().email(),
name: z.string().min(2),
});
// Response schemas
const UserResponse = z.object({
user: z.object({
id: z.string(),
email: z.string(),
name: z.string(),
}),
});
const ErrorResponse = z.object({ error: z.string() });
const UsersController = createController('/users', {
inject: { users: UserService },
routes: (services) => ({
create: Post('/')
.apply(body(CreateUserBody))
.returns(UserResponse, 201)
.returns(ErrorResponse, 400)
.handle(async ({ body, res }) => {
// body is typed as { email: string; name: string }
const user = await services.users.create(body);
res.status(201).json({ user });
}),
}),
});Add Features
Use Features for production-ready functionality like pub/sub channels, interactive shell, and more.
Add Database
Use the Repository Pattern for database access.