v0.1.3-betaMIT License
Beta ReleaseView Roadmap

Bidirectional API Contracts

Put frontend in control. Stop consuming APIs. Start negotiating contracts.

npm install @reactive-contracts/core

The Problem

Today's frontend is a second-class citizen. We consume whatever the backend decides to expose, deal with overfetching and underfetching, and pray that API changes don't break production.

The Solution

Reactive Contracts inverts this relationship. The frontend declares exactly what it needs, how it needs it, and the compiler ensures both sides honor the agreement—at build time, not runtime.

Type Safety First

Catch errors before they reach production. Reactive Contracts provides end-to-end type safety from contract definition to runtime execution.

Without Contracts

// Traditional API - No type safety
const data = await fetch('/api/users/123')
  .then(r => r.json());

// What fields exist? What's the shape?
// Typos caught only at runtime
console.log(data.usrename); // Runtime error!

With Contracts

// With Reactive Contracts - Full type safety
const { data } = useContract('getUser', { id: '123' });

// TypeScript knows exact shape
// Autocomplete, refactoring, errors at build time
console.log(data.username); // Type-safe!
//           ^^^^^^^^ Autocomplete works!

Contract Violations Caught at Build Time

// Contract changes caught at BUILD TIME
export const getUser = contract({
  name: 'getUser',
  input: { id: z.string() },
  output: { username: z.string() }, // Changed from "name"
});

// Backend forgot to update:
implementContract(getUser, async ({ id }) => {
  return { name: 'John' }; // Type error!
  //       ^^^^ Property 'username' is missing
});
Auto-completion

IDEs provide full autocomplete for contract inputs, outputs, and constraints.

Refactoring Safety

Rename fields with confidence. TypeScript ensures all usages are updated.

Zero Runtime Errors

Contract mismatches caught at compile time, not in production logs.

Key Features

Build-time validation, zero runtime overhead

Bidirectional Contracts

Frontend declares needs, backend provides capabilities. Compiler validates compatibility.

Build-Time Validation

API mismatches fail compilation, not production. Catch errors before deployment.

Latency Contracts

Declare acceptable latency with automatic fallback strategies for degraded performance.

Derived Fields

Compute values at the optimal layer—client, edge, or origin—automatically.

Selective Reactivity

Specify which fields need real-time updates vs. static fetching with precision.

Zero Runtime Overhead

Contracts compile away. No reflection, no runtime negotiation, just pure performance.

Quick Start

Define your contract in minutes

1Define a Contract

import { contract, derive, max } from '@reactive-contracts/core';

export const UserProfileContract = contract({
  name: 'UserProfile',
  intent: 'Display user profile with activity summary',

  shape: {
    user: {
      id: 'string',
      name: 'string',
      avatar: 'URL',
      joinedAt: 'Date',
    },
    activity: {
      postsCount: 'number',
      lastActive: 'Date',
      status: derive(ctx =>
        ctx.lastActive > daysAgo(7) ? 'active' : 'inactive'
      ),
    },
  },

  constraints: {
    latency: max('100ms', { fallback: 'cachedVersion' }),
  },

  reactivity: {
    realtime: ['activity.status'],
    static: ['user.name', 'user.avatar'],
    polling: [{ field: 'activity.postsCount', interval: '30s' }],
  },
});

2Use in React

import { useContract } from '@reactive-contracts/react';
import { UserProfileContract } from '../contracts/user-profile.contract';

export function UserProfile({ userId }: { userId: string }) {
  const { data, loading, contractStatus } = useContract(UserProfileContract, {
    params: { userId },
  });

  if (contractStatus.latency === 'degraded') {
    return ;
  }

  return (
    

{data.user.name}

); }

Installation

Get started in seconds

1

Install the packages

npm install @reactive-contracts/core @reactive-contracts/compiler
2

Initialize your project

npx rcontracts init

This creates contracts/, rcontracts.config.ts, and generated/ directories.

3

Compile your contracts

npx rcontracts compile

Validates contracts and generates types, resolvers, and negotiators.

Examples

Ready-to-run examples for different frameworks. Each includes contracts, generated code, and a working server.

Basic Usage

React + Express

Simple setup with React + Express server. Perfect for learning the fundamentals.

Contract definitionsMock serverBasic hooks
View Example

Next.js

Next.js 16

App Router with Client Components. Full-stack TypeScript with server actions.

App RouterServer ComponentsTypeScript
View Example

Vite

Vite + React

Fast development with HMR and auto-compile plugin. Instant feedback loop.

HMR supportVite pluginFast builds
View Example

Astro

Astro + React

Server-rendered with React islands. Perfect for content-heavy sites.

Islands architecturePartial hydrationSSR
View Example

Packages

A complete toolkit for bidirectional API contracts. Install only what you need, from core types to build-time validation.

@reactive-contracts/core

Core types and contract definitions. Zero dependencies, framework-agnostic foundation.

Zero dependenciesType-safe contractsFramework agnostic
npm install @reactive-contracts/core
View on npm

@reactive-contracts/react

React hooks for consuming contracts. Includes useContract, useContractSuspense, and useContractMutation.

useContract hookSuspense supportMutation helpers
npm install @reactive-contracts/react
View on npm

@reactive-contracts/server

Backend utilities for implementing contracts. Type-safe resolver functions with full validation.

implementContractType validationError handling
npm install @reactive-contracts/server
View on npm

@reactive-contracts/compiler

CLI tool and build-time validation. Ensures both frontend and backend honor the contract agreement.

Build-time checksCode generationCLI commands
npm install -D @reactive-contracts/compiler
View on npm

Why Reactive Contracts?

vs. GraphQL

GraphQL exposes a schema that frontend queries. Reactive Contracts inverts this: frontend declares requirements, backend proves it can satisfy them.

vs. tRPC

tRPC shares types but doesn't validate constraints (latency, freshness) or support declarative reactivity at build time.

vs. REST + OpenAPI

OpenAPI documents what exists. Reactive Contracts enforce what's required—and fail builds when requirements can't be met.

Build-time vs Runtime Validation

Most tools validate at runtime when errors are expensive. Reactive Contracts validates at build time when errors are free.

Runtime Validation
  • Errors discovered in production
  • Manual type synchronization required
  • API changes break silently
  • Performance issues found by users
Build-time Validation
  • Errors caught during compilation
  • Types auto-generated and synced
  • Breaking changes fail the build
  • Latency constraints verified upfront

Frequently Asked Questions

Common questions about Reactive Contracts and how it compares to other solutions.

Why not just use GraphQL?

How does this compare to tRPC?

Can I use this with an existing REST API?

What happens when a contract changes?

Is this production-ready?

Does this work with [my framework]?

What about server-side rendering (SSR)?

How does this impact bundle size?

Have more questions? Open an issue on GitHub