Stacks

The trailhead is almost ready.

We are clearing the last stretch: framework, docs, CMS, and the deploy path. Leave your email and we will let you know the moment the trail opens.

New Introducing Stacks

The whole stack, one framework.

Models, auth, CMS, commerce, AI, queues, and cloud deploys, in one typed codebase that ships to web, desktop, and mobile.

app/Models/Post.ts
import { defineModel } from '@stacksjs/orm'
import { schema } from '@stacksjs/validation'

export default defineModel({
  name: 'Post',
  table: 'posts',

  traits: {
    useUuid: true,
    useTimestamps: true,
    useApi: { uri: 'posts', routes: ['index', 'show'] },
  },

  belongsTo: ['Author'],

  attributes: {
    title: {
      fillable: true,
      required: true,
      validation: { rule: schema.string().max(160) },
      factory: faker => faker.lorem.sentence(),
    },
  },
})
app/Jobs/SendWelcomeEmail.ts
import { mail, template } from '@stacksjs/email'
import { Job } from '@stacksjs/queue'

export default new Job({
  name: 'SendWelcomeEmail',
  tries: 3,
  backoff: 30,

  async handle({ userId }: { userId: number }) {
    const user = await User.find(userId)
    if (!user)
      return

    const { html, text } = await template('welcome', {
      variables: { name: user.name },
    })

    await mail.send({
      to: user.email,
      subject: 'Welcome to the stack',
      html,
      text,
    })
  },
})
app/Actions/SummarizePostAction.ts
import { Action } from '@stacksjs/actions'
import { anthropic } from '@stacksjs/ai'

export default new Action({
  name: 'SummarizePost',
  description: 'Summarize a post with Claude',

  async handle(request) {
    const post = await Post.find(Number(request.input('id')))
    if (!post)
      return { error: 'Post not found' }

    const summary = await anthropic.prompt(
      `Summarize in two sentences:\n\n${post.content}`,
    )

    return { summary }
  },
})
tests/feature/posts.test.ts
import { beforeEach, describe, expect, it } from 'bun:test'
import { actingAs } from '@stacksjs/testing'
import {
  factory,
  refreshDatabase,
} from '@stacksjs/testing/database'

describe('posts API', () => {
  beforeEach(refreshDatabase)

  it('lists posts for a signed-in user', async () => {
    const user = await factory('User').create()
    await factory('Post').createMany(3)

    const response = await actingAs(user as { id: number })
      .get('/api/posts')

    response.assertStatus(200)
    const body = await response.json<{ data: unknown[] }>()
    expect(body.data).toHaveLength(3)
  })
})
config/cloud.ts
import type { CloudConfig } from '@stacksjs/ts-cloud'

export const tsCloud: CloudConfig = {
  project: { name: 'app', slug: 'app', region: 'us-east-1' },
  cloud: { provider: 'hetzner' }, // or 'aws', 'ssh'
  mode: 'server',
  environments: {
    production: { type: 'production', deployBranch: 'main' },
  },

  infrastructure: {
    dns: { domain: 'example.com' },
    ssl: { enabled: true, provider: 'letsencrypt' },
    email: { domain: 'example.com', enableDkim: true },
  },

  sites: {
    main: { domain: 'example.com', port: 3000 },
    docs: { domain: 'example.com', path: '/docs' },
    api: { domain: 'api.example.com', port: 3008 },
  },
}
$ buddy dev ready web, api, docs, dashboard on stacks.localhost
100+ built-in models, from users to orders to campaigns
650+ ready-made actions you can call, override, or route to
110+ agent skills, one for each subsystem
50+ typed config files, every one optional

Everything a product needs, in one install.

Each system is first-party and shares the same types, config, and tooling. No glue code, no plugin roulette.

Application core

Routing, STX views, models, actions, middleware, and validation in one typed application.

$ buddy make:model Post

Queues and mail

Jobs, batches, schedules, events, notifications, and worker-ready background workflows.

$ buddy make:job SendWelcomeEmail

Native apps

The same STX UI ships as a web app, an iOS or Android app, and a desktop app with a system tray, from one codebase.

$ buddy dev:desktop

CMS

Posts, pages, taxonomy, media, a real dashboard, and generated content APIs.

$ buddy make:model Article

Auth

Sessions, tokens, passkeys, social login, magic links, policies, guards, and rate limiting.

$ buddy auth:setup

Commerce

Products, orders, customers, coupons, payments, shipping, tax, and gift cards, as models you already know how to query.

$ buddy make:model Product

Dashboard

A generated admin panel for every model, plus analytics, operations, kanban, and marketing, in 300-plus components.

$ buddy dev dashboard

Storage

Local, S3, signed URLs, uploads, visibility, and file utilities.

$ buddy make:action UploadAvatar

AI

Anthropic, OpenAI, and Ollama behind one chat driver, Bedrock alongside for AWS-hosted models, plus RAG, embeddings, and MCP.

$ buddy env:set ANTHROPIC_API_KEY sk-ant-...

Testing

Unit, feature, HTTP, browser, and database tests with factories and helpers.

$ buddy test

Realtime and search

Channels, broadcasts, websocket drivers, and app-level search workflows.

$ buddy make:job ReindexArticles

Cloud deploys

Hetzner, AWS, or any box over SSH, with DNS, TLS, and mail, described in TypeScript config and shipped by Buddy.

$ buddy deploy

Environment setup

Pantry installs Bun, the database, the mail server, and every tool a project declares, per project, then starts and migrates the database.

$ curl -fsSL https://pantry.dev | bash

Automated upgrades

buddy upgrade moves an app to the next release: framework, dependencies, migrations, and CI, previewed first and never over your uncommitted edits.

$ buddy upgrade --dry-run

Write the UI once. Ship it five ways.

The STX views, components, and routes you wrote for the web are the app. Craft wraps that same UI in a desktop window, a system tray, or a native iOS and Android shell.

How native builds work
  • Web Server-rendered, hydrated where it needs to be buddy dev
  • macOS desktop A native Craft window around the same views buddy dev:desktop
  • System tray A menu-bar utility from the same views buddy build:desktop
  • iOS An Xcode project generated from config/mobile.ts buddy build:ios
  • Android A Gradle project from the same config buddy build:android

And the long tail, already in the box.

The packages most apps end up hunting for one at a time, on the same config and types as everything above. Whole bundles install or uninstall with one command, so what you do not use is not loaded.

$ buddy commerce:uninstall
  • Stripe billing and Connect
  • OAuth 2 server
  • GDPR export and erasure
  • Cache
  • Validation
  • i18n
  • Feature flags
  • Analytics
  • Newsletters
  • SMS
  • Push
  • Phone numbers
  • Slack, Discord, Teams
  • Social posting
  • Scheduler
  • Database backups
  • Deploy rollback
  • Maintenance mode
  • Public share tunnels
  • Domains and DNS
  • Encrypted env
  • Encryption and hashing
  • Logging
  • Error pages
  • Kanban boards
  • Forms
  • Charts
  • Multisite
  • OG images and app icons
  • Browser extensions
  • 150+ composables
  • Tinker REPL
  • VS Code extension
  • Linting and formatting

From an empty folder to production.

Pantry installs the toolchain, Buddy does the rest. Four commands, and the last one is a deploy.

  1. Install Pantry

    Provisions Bun, Git, SQLite, and every tool the project declares.

    curl -fsSL https://pantry.dev | bash
  2. Create a project

    Scaffolds the app, its config, and its toolchain in one pass.

    panx buddy new my-app
  3. Develop

    Serves the frontend, API, docs, and dashboard with hot reload.

    buddy dev
  4. Deploy

    Builds every surface and publishes the infrastructure behind it.

    buddy deploy
Developer and agent experience

Written for you. Legible to the agent next to you.

buddy setup:ai turns one checked-in AGENTS.md into the files Claude Code, Codex, Cursor, Copilot, and Gemini each read, so every agent works from the same source.

  • AGENTS.md, checked inThe file a coding agent reads first, versioned with the code it describes.
  • A skill per subsystemFrom auth to deploys, so an agent reaches for the real API instead of guessing one.
  • Typed end to endModel, migration, API, and view are typed against each other. A rename is everywhere or it does not compile.
  • One way to checkbuddy lint, typecheck, and test gate a human pull request and an agent the same way.
$ buddy setup:ai
  • AGENTS.md you write this
  • CLAUDE.md generated
  • .claude/skills/ 115 skills
  • stacks-models/SKILL.md
  • stacks-deploy/SKILL.md
  • .cursor/rules/ generated
$ buddy lint && buddy typecheck 0 errors

One command to production.

buddy deploy builds the site, docs, blog, and API, then publishes DNS, TLS, storage, and mail from config/cloud.ts, to servers you own. A bad release rolls back with one command.

$ buddy deploy
  • Hetzner
  • AWS
  • Any box over SSH
  • A Raspberry Pi
  1. Web app stacksjs.com
  2. Docs stacksjs.com/docs
  3. Blog, RSS, sitemap stacksjs.com/blog
  4. API stacksjs.com/api
  5. Infrastructure DNS, TLS, storage, mail
  6. Rollback buddy deploy:rollback

Two ways to size it up.

What people build with it, and how it lines up against what you use today.

Coming from Laravel? Models, migrations, queues, mail, and a CLI that will feel familiar, in TypeScript, with the dashboard, deploys, and your own mail server in the same install. Stacks vs Laravel

Start building.

Free and open source under the MIT license.

$ panx buddy new my-app