yabasha/composable-ai-stack
The Composable AI Stack (CAS) is a production-ready monorepo template designed for developers building AI-integrated SaaS applications. It provides a structured, modular foundation that abstracts the complexity of scaling from localized prototyping to robust enterprise deployments. By standardizing the integration of LLMs, database interactions, and billing logic, it enables teams to focus on core product features rather than boilerplate architecture.
Built on a modern TypeScript stack, the project leverages Bun for high-performance execution and Turborepo for efficient workspace management. The backend is powered by Convex, providing a unified, reactive database experience, while optional ElysiaJS endpoints offer flexibility for API-level tasks like custom middleware and rate limiting. The stack emphasizes type safety and reliability, featuring a rigid "guardrail" pattern that enforces input/output validation via Zod schemas and integrates Langfuse by default for comprehensive LLM observability, prompt tracing, and performance monitoring.
This project is an excellent choice for developers seeking a "Convex-first" architecture that balances rapid development with long-term maintainability. It effectively bridges the gap between simple side projects and large-scale applications by including pre-configured evaluation harnesses, shared component libraries with shadcn/ui, and automated version-pinning tools to ensure long-term dependency stability.
- Stars
- 1
- Forks
- 0
- Language
- TypeScript
- Updated
- 1d ago
§ Readme
Edit on GitHub ↗Composable AI Stack (CAS) | (Bun + Turborepo + Convex-first)
A modular AI stack that scales from local tools to enterprise systems
- Name: Composable AI Stack
- Short: CAS
- Repo slug: cas or composable-ai-stack
- Package scope (if you publish): @cas/* or @composable-ai/*
- Docs title line: Composable AI Stack (CAS)
- One-liner tagline: A modular AI stack that scales from local tools to enterprise systems.
Overview
A reusable monorepo template for AI-Integrated SaaS apps:
- apps/web: Next.js + Tailwind + shadcn/ui
- apps/convex: Convex backend (schema + functions + HTTP endpoints)
- apps/api: Optional ElysiaJS (Bun) API gateway
- apps/worker: background tasks + eval runner CLI (Bun)
- packages/: shared prompts, schemas, AI utilities, eval harness, configs
Goal: be your modular AI stack that scales from local tools to enterprise systems
Requirements
- Bun
- A Convex project (free tier works for prototyping)
- Optional: Stripe account for memberships
Quick Start
1) Install dependencies (root)
bun install
2) Copy env and fill values
cp .env.example .env
3) Run development
In separate terminals:
bun run dev:convex
bun run dev:web
# optional
bun run dev:api
Or run everything:
bun run dev
Convex Setup
From apps/convex:
cd apps/convex
bunx convex dev
Convex will output a deployment URL. Set:
NEXT_PUBLIC_CONVEX_URLin.env(and/orapps/web/.env.local)
shadcn/ui + Tailwind
apps/web is preconfigured with Tailwind and a minimal shadcn/ui setup.
Add a shadcn component (from within apps/web):
cd apps/web
bunx shadcn@latest add button
Where to tweak:
apps/web/components.jsonapps/web/tailwind.config.tsapps/web/app/globals.css
Memberships / Billing (Convex-first)
Template includes placeholders for:
- membership fields in
apps/convex/convex/schema.ts - a webhook route in
apps/convex/convex/http.ts(/stripe/webhook)
Typical flow:
- Create checkout session in a Convex action (server-side)
- Stripe redirects user back to your app
- Stripe sends webhook events to
/stripe/webhook - Convex updates your
users.planStatus
If you want a dedicated webhook gateway with custom middleware/rate limiting, use apps/api (ElysiaJS).
Scaling the rate limiter
apps/api ships an in-memory rate limiter (apps/api/src/middleware/rate-limit.ts).
It tracks request counts in a single-process Map. For multi-worker or multi-instance
deployments, replace the backing store with Redis or Upstash:
- Install:
bun add --filter=api @upstash/ratelimit @upstash/redis - Swap the
Mapinrate-limit.tsfor an UpstashRatelimitinstance. - Set
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKENin.env.
The middleware exposes X-RateLimit-Backend: memory so you can verify which store
is in use at runtime.
Scripts (root)
bun run dev— dev for all appsbun run dev:web— Next.js onlybun run dev:convex— Convex onlybun run dev:api— Elysia onlybun run build— build all buildable appsbun run eval— run eval harness
Repo Layout
apps/
web/
convex/
api/
worker/
packages/
shared/
schemas/
prompts/
ai/
evals/
config/
See use-cases.md and apps/api/use-cases.md.
UI Stack
- Web UI uses Tailwind CSS v4.1 + shadcn/ui.
Versions (template defaults)
Pinned to your requested versions:
- Bun: 1.3.7
- Turborepo (turbo): 2.7.6
- TypeScript: 5.9.3
- Prettier: 3.8.1
- Next.js: 16.1.6 (App Router)
- React: 19.2.4
- Tailwind CSS: 4.1.18
- Elysia: 1.4.22
- Convex: 1.31.6
- ESLint: 9.39.2
Keeping versions pinned
Run:
bun run check:versions
CI will fail if any pinned dependency versions drift.
Guardrail Pattern
The @acme/ai package provides a guardrail pattern for safe, validated LLM calls:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Input │────▶│ Zod │────▶│ Moderation │────▶│ LLM Call │
│ (raw) │ │ Validation │ │ Hook │ │ │
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
│
┌─────────────┐ ┌─────────────┐ │
│ Output │◀────│ Zod │◀──────────┘
│ (typed) │ │ Validation │
└─────────────┘ └─────────────┘
Usage Example
import { z } from 'zod';
import { runWithGuardrails, openai, DEFAULT_MODELS } from '@acme/ai';
const inputSchema = z.object({ message: z.string().max(500) });
const outputSchema = z.object({ reply: z.string(), confidence: z.number() });
const result = await runWithGuardrails(
openai(DEFAULT_MODELS.openai),
'Generate a helpful reply',
{ message: 'Hello, I need help!' },
{
name: 'support-reply',
inputSchema,
outputSchema,
moderationHook: async (input) => input.message.length > 0,
}
);
console.log(result.output); // { reply: '...', confidence: 0.95 }
console.log(result.traceId); // Langfuse trace ID
All guardrail runs are automatically traced to Langfuse with full input/output logging.
Observability
This stack uses Langfuse for LLM observability and tracing:
Required Environment Variables
# LLM Providers
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-...
# Langfuse (Observability)
LANGFUSE_PUBLIC_KEY=pk-...
LANGFUSE_SECRET_KEY=sk-...
LANGFUSE_BASE_URL=https://cloud.langfuse.com # Optional: use your self-hosted instance
Features
- Automatic tracing: Every LLM call via
tracedGenerate()orrunWithGuardrails()is traced - Generation tracking: Prompts, outputs, token usage, and latency are captured
- Score logging: Eval scores are sent to Langfuse for monitoring
- Self-hosted option: Run your own Langfuse instance by changing
LANGFUSE_BASE_URL
Author
Created by Bashar Ayyash — yabasha.dev
§ Cite this project
For papers, blog posts, & AI referencesBashar Ayyash. (2026). yabasha/composable-ai-stack [Computer software]. https://yabasha.dev/open-source/composable-ai-stack§ Related repositories
yabasha/monolith
This project provides a robust, scalable architecture for modern full-stack development by combining a Laravel 12 backend with a Next.js 16 frontend in a unified monorepo. It is designed for developers who value explicit structure, clear boundaries between application layers, and high-performance workflows. By organizing the core application code within an apps directory and isolating shared UI primitives in a packages workspace, it enables teams to build complex systems while maintaining a consistent design language.
- TypeScript
- 2 stars
- 0 forks
- updated 4mo ago
yabasha/yabasha-gex
GEX is a versatile command-line interface tool designed to help developers audit, document, and manage their Node.js package environments. It provides a structured approach to generating reproducible reports for local projects and globally installed packages. By supporting multiple runtime environments—Node.js (npm), Bun, Yarn, and pnpm—it serves as a unified utility for teams needing to track dependency states, enforce license compliance, or simplify vulnerability auditing across diverse infrastructure.
- TypeScript
- 1 stars
- 0 forks
- updated 1d ago
yabasha/cas
@yabasha/cas is a command-line interface tool designed to instantly scaffold professional-grade, AI-ready monorepos. It is tailored for developers building production SaaS applications who require a standardized, high-performance foundation built on the Composable AI Stack. By providing interactive prompts and CLI-driven configuration, the tool allows users to selectively integrate complex architectural components like background workers, external API gateways, and automated evaluation harnesses without manual setup.
- TypeScript
- 0 stars
- 0 forks
- updated 1d ago