Skip to content

Smooth
TypeScript Backends

Vla is the missing backend layer for scalable TypeScript apps that integrates into any framework and existing codebases.

Vla is also a smooth, pudding-like Dutch dessert that goes with everything.

Structured Apps of any size

Organize code into layers with Actions, Services, Repos, and Facades. Scale with modules when needed. Great for both small and large apps.

Framework Agnostic

Works with Next.js, SvelteKit, Tanstack, Express, and any other server-side framework in TypeScript or JavaScript.

Testing Friendly

Clean Dependency Injection without decorators or reflection. Write code that’s easy to test without module mocks.

No Extra Tooling

Install and you’re ready. No extra tooling or plugins to configure. No incompatibility when upgrading your framework.

import { Vla } from 'vla'
// Create an action as your entry point
class ShowUser extends Vla.Action {
repo = this.inject(UserRepo)
async handle(userId: string) {
return this.repo.findById(userId)
}
}
// Define a repository for data access
class UserRepo extends Vla.Repo {
db = this.inject(Database)
// ⭐ built-in memoization
findById = this.memo((id: string) => {
return this.db.users.find({ id })
})
}
// Use Services for business rules and resources for infrastructure
class UserService extends Vla.Service {
// reusable business rules
}
class Database extends Vla.Resource {
static readonly unwrap "db"
db = this.devStable("db", () => new FavoriteOrm())
// ⭐ devStable() prevents creating new clients in hot-reload dev mode
}
// Grow your app with Modules and Facades
const Billing = Vla.createModule("Billing")
class BillingFacade extends Billing.Facade {
// Facades are public interfaces for cross-module dependencies
}
// Initialize Vla's Kernel
const kernel = new Vla.Kernel()
Vla.setGlobalInvokeKernel(kernel)
// Invoke from your framework
const user = await ShowUser.invoke(userId)

Ready to add some smooth deliciousness to your backend? Check out the Getting Started guide to begin using Vla in your project.