Actyx RPC is a lightweight, fully type-safe RPC framework for TypeScript that replaces boilerplate around server actions, API route handlers, and client hooks. Traditional APIs force a compromise between developer ergonomics and type safety — Actyx provides both. The framework is architected into two specialized packages: @explita/actyx-rpc for the core procedure engine, execution policies, validation resolvers, and server adapters; and @explita/actyx-rpc-react for client-side state management, in-memory caching, typed client proxies, and reactive hooks.
At its core, Actyx centers around a fluent procedure builder created with createProcedure(). Builders encapsulate shared concerns such as authentication and tenant resolution via createContext (supporting typed success and failure reasons), centralized error redirection (onContextError), and flexible schema modes (strict, form, or partial). Builders can be inherited with .extend() and named via .name(), which infers strictly typed string literals into ctx.handlerName. TypeScript enforces compile-time builder ordering: Setup methods (.name(), .summary(), .description(), .meta(), .input(), .output()) chain into Middlewares and Plugins (.use()), then Execution Policies, and finally Terminal Handlers.
Side effects and pre-flight logic are handled via pluggable middlewares (procedure.middleware()) and plugins (procedure.plugin()). Middlewares can extend context with typed fields using next() or abort early with automatic underscore promotion (_message, _reason, _statusCode). Plugins hook into the full lifecycle (validate, onBefore, onAfter, and onError) and can override error responses. Actyx also ships with a built-in observabilityPlugin and OpenTelemetry tracing integration (.telemetry()).
Actyx provides a comprehensive suite of declarative resilience and execution policies: declarative authorization (.authorize()), built-in caching (.cache()) with in-memory and Redis adapters, stale-while-revalidate, and in-procedure invalidation via ctx.cache.invalidate(), automatic retries (.retry()) with exponential, linear, or custom backoff, operation timeouts (.timeout()), rate limiting (.rateLimit()), circuit breakers (.circuitBreaker()) for isolating failing dependencies, response compression (.compress()), and procedure mocking (.mock()) for offline development and testing.
Terminal handlers support versatile communication protocols: standard queries (.query()), mutations (.mutation()), chunked streaming (.stream()), Server-Sent Events (.sse()), bidirectional WebSockets (.ws()) with pub/sub channel support (ctx.pubsub), and standard HTTP web routes (.webRoute()). All procedures return Go/Rust-style [data, error] tuples with strongly typed FailureReason and HTTP status codes — eliminating try/catch boilerplate at call sites. Procedures are schema-library agnostic with first-class resolvers for Zod, Valibot, ArkType, Joi, and Yup, support internal inter-procedure calling without network overhead (procedure.caller()), and automatically generate OpenAPI 3.0 specifications.
For client applications, @explita/actyx-rpc-react offers both direct Server Action consumption and an end-to-end typed client proxy (createClient<AppRouter>()) paired with Next.js route handlers (createHandler(appRouter)) or WebSocket servers (createWsHandler). It features a built-in QueryClient, request batching (BatchClient), optimistic mutations with automatic rollback, SSR hydration boundaries, a React DevTools inspector, and a rich hook library including useQuery, useMutation, useInfiniteQuery, usePaginatedQuery, useSSE, useSubscription, and useRealtimeInfiniteQuery.