Open Source Β· MIT + GPL v3

One definition.Thirteen platforms.

next-vibe turns a single TypeScript definition into thirteen platforms at once - interactive web UI, CLI command, MCP tool, mobile screen, cron job, WebSocket, admin panel, and more. Full type safety, zero drift, zero repetition.

501+

typed endpoints

0

runtime type errors

13

platforms per endpoint

2

files required

The problem

You've built the same thing thirteen times.

Every feature needs a custom web UI, CLI command, MCP tool, mobile screen, cron job, WebSocket handler, admin panel, and more. Same validation, same i18n, same error handling - just dressed differently. Every time.

βœ•Web API
βœ•React UI
βœ•CLI
βœ•AI Tool
βœ•MCP Server
βœ•React Native
βœ•Cron Job
βœ•WebSocket
βœ•Electron
βœ•Admin Panel
βœ•VibeFrame Widget
βœ•Agent Skill
βœ•Vibe Sense Node
next-vibe builds all thirteen from one file.
The pattern

Two files required. Every platform.

Each feature lives in a folder. Only definition.ts and route.ts are required - everything else is optional.

definition.ts - the contract

Declare your fields, Zod schemas, labels, error types, and examples once. This file is the single source of truth - the framework reads it at runtime on every platform.

typescript
1const { POST } = createEndpoint({
2  scopedTranslation,
3  method: Methods.POST,
4  path: ["explain", "to-my-boss"],
5  title: "post.title" as const,
6  description: "post.description" as const,
7  icon: "sparkles",
8  category: "endpointCategories.ai",
9  allowedRoles: [UserRole.CUSTOMER, UserRole.ADMIN] as const,
10  fields: customWidgetObject({
11    render: ExplainContainer,
12    usage: { request: "data", response: true } as const,
13    children: {
14      decision: requestField(scopedTranslation, {
15        type: WidgetType.FORM_FIELD,
16        fieldType: FieldDataType.TEXTAREA,
17        label: "post.decision.label" as const,
18        columns: 12,
19        schema: z.string().min(10),
20      }),
21      justification: responseField(scopedTranslation, {
22        type: WidgetType.TEXT,
23        content: "post.justification.content" as const,
24        schema: z.string(),
25      }),
26    },
27  }),
28  errorTypes: {
29    [EndpointErrorTypes.UNAUTHORIZED]:      { title: "post.errors.unauthorized.title" as const,      description: "post.errors.unauthorized.description" as const },
30    [EndpointErrorTypes.SERVER_ERROR]:      { title: "post.errors.serverError.title" as const,       description: "post.errors.serverError.description" as const },
31    // ... other error types
32  },
33  successTypes: { title: "post.success.title" as const, description: "post.success.description" as const },
34  examples: { requests: { default: { decision: "Rewrite everything in TypeScript" } }, responses: { default: { justification: "..." } } },
35});
36
37export type ExplainResponseOutput = typeof POST.types.ResponseOutput;
38const definitions = { POST } as const;
39export default definitions;

repository.ts - the logic

Business logic lives here - DB queries, auth checks, error handling with success()/fail(). The route.ts is just a thin delegator; validation, logging, and platform registration happen automatically.

typescript
1import "server-only";
2
3export class ExplainRepository {
4  static async explainToMyBoss(
5    data: ExplainRequestOutput,
6    user: JwtPayloadType,
7    logger: EndpointLogger,
8    t: ExplainT,
9  ): Promise<ResponseType<ExplainResponseOutput>> {
10    if (!user.id) {
11      return fail({ message: t("post.errors.unauthorized.title"), errorType: ErrorResponseTypes.UNAUTHORIZED });
12    }
13    try {
14      const [saved] = await db
15        .insert(explainResults)
16        .values({ userId: user.id, decision: data.decision })
17        .returning();
18      logger.info("Saved decision", { userId: user.id, id: saved.id });
19      return success({ justification: saved.justification ?? "" });
20    } catch (error) {
21      logger.error("Failed to save decision", parseError(error));
22      return fail({ message: t("post.errors.serverError.title"), errorType: ErrorResponseTypes.INTERNAL_ERROR });
23    }
24  }
25}

widget.tsx - the UI (optional)

Without a widget, the framework auto-renders your fields everywhere. Add widget.tsx to ship a fully custom interactive UI - the same component renders in admin panels, embedded widgets, and mobile screens.

tsx
1"use client";
2
3interface CustomWidgetProps {
4  field: {
5    value: ExplainResponseOutput | null | undefined;
6  } & (typeof definition.POST)["fields"];
7}
8
9export function ExplainContainer({ field }: CustomWidgetProps): JSX.Element {
10  const children = field.children;
11  const emptyField = useMemo(() => ({}), []);
12
13  return (
14    <Div className="flex flex-col gap-4 p-4">
15      <TextareaFieldWidget fieldName="decision" field={children.decision} />
16      <SubmitButtonWidget<typeof definition.POST>
17        field={{
18          text: "Explain to my boss",
19          loadingText: "Explaining...",
20          icon: "sparkles",
21          variant: "primary",
22        }}
23      />
24      <FormAlertWidget field={emptyField} />
25      <AlertWidget
26        fieldName="justification"
27        field={withValue(children.justification, field.value?.justification, null)}
28      />
29    </Div>
30  );
31}
Delete the folder. The feature disappears from every platform at once.
Every Platform

One definition. Thirteen platforms.

When you add a feature to next-vibe, it doesn't just become an API endpoint. It runs everywhere at once.

Web API

REST endpoint, fully validated and typed

React UI

Purpose-built interactive UI - no JSX required

CLI

Every endpoint is a command with auto-generated flags

AI Tool

Function-calling schema generated automatically

MCP Server

Connect Claude Desktop, Cursor, any MCP client

React Native

iOS and Android screens from the same definition

Cron Job

Schedule any endpoint on a cron expression

WebSocket

Push updates to connected clients on completion

Electron

Native desktop app via the same endpoint contracts

Admin Panel

Auto-generated admin UI - no dedicated code

VibeFrame Widget

Embeddable iframe widget for any site

Agent Skill

Callable by AI agents as a structured skill

Vibe Sense Node

Node in a live data-flow graph - same endpoint

TypeScript supremacy

No any. No unknown. No throw.

Types must align completely - no exceptions. This isn't a style preference. It's a structural rule enforced at build time by vibe check.

no any

Replace with a real typed interface. If you reach for any, your architecture has a hole.

no unknown

Same rule. unknown is just any with extra steps. Define the type.

no bare object

Bare object is meaningless. Write the shape you actually expect.

no as X

Type assertions are lies to the compiler. Fix the architecture instead.

no throw

Use ResponseType<T> with success(data) or fail({message, errorType}). Errors are data.

no hardcoded strings

Every string needs a translation key. The checker catches untranslated literals.

vibe check runs Oxlint (Rust), ESLint, and TypeScript type checking in parallel. Zero errors required before ship.

Get started

Fork, ask, ship.

You're at unbottled.ai's level from day one.

1Fork & clone

Fork on GitHub, then clone your fork locally.

bash
1git clone https://github.com/YOUR_USERNAME/next-vibe
2cd next-vibe && bun install
2Start the server

For local development, vibe dev starts PostgreSQL in Docker, runs migrations, seeds data, and gives you hot reload. For production, vibe build && vibe start does the initial deploy. vibe rebuild is what you use after that to update production with zero downtime.

bash
1# development
2vibe dev
3
4# production - first start
5vibe build && vibe start
6
7# production - after changes
8vibe rebuild
3Login as Admin

Open the app and click "Login as Admin" - the setup wizard walks you through API keys and admin password.

4Ask the AI

Open unbottled.ai chat or Claude Code and describe the feature you want. The AI writes all the files - definition, route, widget, i18n - and runs vibe check automatically.

bash
1# In unbottled.ai chat or Claude Code:
2"Build me a feature that explains decisions to my boss"
3# AI writes all files and runs vibe check automatically
Enterprise

Building something big?

We help teams with setup, custom integrations, architecture review, and ongoing development support. Same codebase, your deployment.

Contact Us
A real person will read this and reply. No bots, no runaround.