Skip to content

Vyuh Server

Pure-Dart Server Framework

A pure-Dart server framework with Vyuh-style plugin and feature ergonomics. Build complex backend services by composing plugins (storage, auth, telemetry, query, policy) and features (domain routes) — both speaking the same five-slot contribution language.

Why Vyuh Server?

Plugins & Features in One Mental Model

Both contribute through the same five slots — routes, middlewares, per-request context, DI bindings, and descriptors — plus an imperative escape hatch. Learn one, you know the other.

Pluggable Storage, Auth, Telemetry, Filters, Policy

Typed plugin contracts for every cross-cutting concern. Swap Postgres for SQLite, JWT for API key, console logs for OpenTelemetry — nothing else changes.

Declarative Descriptors

Features describe capabilities as data — EntityCrudDescriptor<T>, ErrorCodesDescriptor — and the matching plugin claims the type at boot. Unhandled descriptors fail fast at startup.

Built on Relic

Production-grade HTTP transport with onion middleware, request-scoped DI, graceful shutdown on SIGINT/SIGTERM, and a self-advertising banner that lists every URL each plugin owns.

Getting Started

Core Concepts

Key Components

ComponentDescription
VyuhServerThe runtime returned by bootstrap. Holds resolved plugin singletons, features, DI container, and env registry
PluginCross-cutting infrastructure contributor. Subtypes: DbPlugin, AuthPlugin, TelemetryPlugin, QueryPlugin, PolicyPlugin, EnvPlugin
FeatureDescriptorDomain-area contributor. Same five contribution slots as Plugin (routes, middlewares, context, di, descriptors)
RouteSpec / MiddlewareSpecDeclarative wire shapes for mounting handlers and onion middleware with explicit ordering
RouteModuleNamed, basePath-scoped grouping of routes with co-located auth requirements
Descriptor / DescriptorHandler<D>Open extension mechanism. Features describe capabilities as data; plugins claim the type
vyuh global accessorRoute-side accessor exposing storage, auth, telemetry, filter, policy, di, env, and errors
DbAdapterRelational-OLTP boundary: transactions, DDL, parameterized SQL, pub/sub LISTEN/NOTIFY

Learn More

The Five-Slot Contribution Model

Every plugin AND every feature contributes through the same five primitives, plus an imperative escape hatch. Anyone fluent in one is fluent in the other:

SlotTypePurpose
routesList<RouteSpec>Method + path + handler tuples
middlewaresList<MiddlewareSpec>Path-scoped middleware in onion order
contextList<ContextProvider>Per-request typed value providers
diList<DiRegistration>Server-wide DI bindings on vyuh.di
descriptorsList<Descriptor>Open extension — claimed by a Plugin<D>
extend(scope) => …Imperative escape hatch over the live RouterScope

The distinction between Plugin and Feature is identity, not capability:

  • Plugin — a singleton role for the server (one storage, one auth, one OpenAPI). Publishes typed verbs on vyuh.X.
  • Feature — a composable domain area (catalog, billing, reports). Many per server.

Quick Example

Bootstrap a SaaS API with Postgres, JWT auth, OpenTelemetry tracing, and an auto-generated OpenAPI explorer at /docs:

dart
import 'package:vyuh_server/vyuh_server.dart';
import 'package:vyuh_server_plugin_postgres/vyuh_server_plugin_postgres.dart';
import 'package:vyuh_server_plugin_auth_jwt/vyuh_server_plugin_auth_jwt.dart';
import 'package:vyuh_server_plugin_telemetry_otel/vyuh_server_plugin_telemetry_otel.dart';
import 'package:vyuh_server_plugin_openapi/vyuh_server_plugin_openapi.dart';
import 'package:cdx_query_server_postgres/cdx_query_server_postgres.dart';
import 'package:vyuh_server_plugin_entity_crud/vyuh_server_plugin_entity_crud.dart';

Future<void> main() async {
  final runtime = await VyuhServer.bootstrap(
    name: 'saas-api',
    plugins: [
      EnvPlugin(
        configs: [TypedEnvConfig.factory(PostgresConnectionConfig.new)],
      ),
      PostgresDbPlugin(),
      JwtAuthPlugin(verifier: verifyTokenWithJwks),
      OtelTelemetryPlugin(defaultServiceName: 'saas-api'),
      PostgresQueryPlugin(),
      EntityCrudPlugin(),
      OpenApiPlugin(
        title: 'SaaS API',
        version: '2.4.0',
        description: 'Multi-tenant SaaS backend',
      ),
    ],
    features: [
      catalogFeature,
      billingFeature,
      reportsFeature,
    ],
  );

  await runtime.start(
    port: 8080,
    middleware: [
      GlobalMiddleware.cors(),
      GlobalMiddleware.errorHandler(),
      GlobalMiddleware.requestLogger(),
      GlobalMiddleware.auth(),
    ],
  );
}

That's a fully wired production server. The startup banner prints:

saas-api listening on http://localhost:8080
  Docs: http://localhost:8080/docs
  Spec: http://localhost:8080/openapi.json

See the Quick Start for a step-by-step build, or the SaaS API example for the full feature breakdown.