Build portable full-stack libraries
Define routes, schemas, and client hooks once. Ship fragments that integrate into any framework with a few lines of code.
Just integrating fragments? Visit the user landing
Assistant Skill
Install the Fragno Author Skill
npx skills add https://github.com/rejot-dev/fragno --skill fragno-authorThen ask: "Use fragno-author to scaffold a fragment with routes and hooks."
When to build a fragment
More than an API client
Full-stack SDKs
Most SDKs simply wrap API calls. Developers still have to write things like webhook handlers that persist events or build their own frontend hooks.
With Fragno you can ship a pre-built integration for your product.
Do not repeat yourself
Full-stack Components
Build components that can be reused across applications regardless of their stack.
Use community-made Fragments like the Stripe Fragment to add functionality you don't want to maintain yourself.
Full-Stack Libraries
Traditional libraries integrate on either the frontend or the backend, and the user is responsible for the glue-code.
A full-stack library does both. Users integrate with only a couple of lines of code. No glue.
10x the developer experience.
Define your API routes with full type safety. Routes are embedded directly in your user's application.
import { defineRoute } from "@fragno-dev/core";import { z } from "zod";export const route = defineRoute({ method: "POST", path: "/ai-chat", inputSchema: z.string(), outputSchema: z.array(/* ... */), handler: async ({ input }, { jsonStream }) => { const message = await input.valid(); const eventStream = await openai.responses.create({ /* ... */ }); return jsonStream(async (stream) => { // ... await stream.write( /* ... */ ); }); },});Embed Routes
HTTP Routes with automatic frontend bindings
State Management
Reactive client-side stores with invalidation built in
Streaming Support
Real-time newline-delimited JSON streaming
Middleware Support
Users can intercept and process requests before they reach your handlers
Framework-agnostic
Works with React, Vue, Svelte, Solid and related full-stack frameworks.
End-to-end type safety
From server to client to database, everything is typed.
Automatic code splitting
Server code never reaches the client bundle.
Built-in state management
Reactive stores with caching built in.
Streaming support
Real-time NDJSON streaming for live data.
Middleware support
Compose auth and custom request processing.
Database-Agnostic Data Persistence
Define schemas, query with type safety, and write directly to the user's database
Define Your Schema
Type-safe tables with automatic migrations and support for indexes and relations
import { schema, idColumn, column } from "@fragno-dev/db/schema";export const commentSchema = schema("comment", (s) => { return s .addTable("comment", (t) => { return t .addColumn("id", idColumn()) .addColumn("content", column("string")) .addColumn("userId", column("string")) .addColumn("postId", column("string")) .addColumn( "createdAt", column("timestamp") .defaultTo((b) => b.now()) ) .createIndex("idx_post", ["postId"]); }) .addTable("user", (t) => { return t .addColumn("id", idColumn()) .addColumn("name", column("string")); }) .addReference("author", { type: "one", from: { table: "comment", column: "userId" }, to: { table: "user", column: "id" } });});Query with Type Safety
Joins, filtering, and cursor-based pagination
// Find comments with author dataconst comments = await orm.find( "comment", (b) => b .whereIndex("idx_post", (eb) => eb("postId", "=", postId) ) .orderByIndex("idx_created", "desc") .join((j) => j.author((authorBuilder) => authorBuilder.select(["name"]) ) ) .pageSize(20));// Fully typed resultsfor (const comment of comments) { console.log(comment.content); console.log(comment.author?.name); // ^? { name: string } | null}Atomic Transactions
Optimistic concurrency control with version checking
const uow = orm.createUnitOfWork();// Phase 1: Retrieve with version infouow.find("user", (b) => b.whereIndex("primary", (eb) => eb("id", "=", userId) ));const [users] = await uow.executeRetrieve();// Phase 2: Update with optimistic lockconst user = users[0];uow.update("user", user.id, (b) => b .set({ balance: user.balance + 100 }) .check() // Fails if version changed);const { success } = await uow.executeMutations();if (!success) { // Concurrent modification detected console.error("Retry transaction");}Test Everything
In-memory database for fast tests
import { buildDatabaseFragmentsTest } from "@fragno-dev/test";import { instantiate } from "@fragno-dev/core";describe("auth fragment", async () => { const { fragments, test } = await buildDatabaseFragmentsTest() .withTestAdapter({ type: "drizzle-sqlite" }) .withFragment("auth", instantiate(authFragmentDefinition) .withRoutes(routes) .withConfig({}), ) .build(); afterAll(async () => { await test.cleanup(); }); it("creates user and session", async () => { const response = await fragments.auth.callRoute( "POST", "/signup", { body: { email: "test@test.com", password: "password" } } ); expect(response.data).toMatchObject({ sessionId: expect.any(String), userId: expect.any(String) }); });});Frameworks
These frameworks and more are already supported
Database Support
Fragments ship schema outputs for your ORM workflow and integrate with the databases you already run.
Author documentation
Learn the author workflow and ship your first fragment.
Join the Community
Connect with other developers and stay updated with the latest news
Discord
Join the conversation
Connect with the community, get help with your projects, and stay updated on the latest features and releases.
Join Discord→Newsletter
Get email updates
Receive notifications about new features, releases, and important announcements.
Integrating fragments?
Go to the user landing
Find ready-made fragments and integration steps for your app.