End-to-End Data Flow
Relevant source files
The following files were used as context for generating this wiki page:
This document outlines the end-to-end data flow within the contract-based-monorepo project. The architecture is designed around a "contract-first" approach, utilizing a shared TypeScript contract to ensure type safety between the frontend and backend services. The system comprises a React frontend (web), a Hono API server (api), a shared API contract (contract), and a database access layer (db).
The core principle is that the contract package serves as the single source of truth for API procedure definitions and data schemas. The api backend implements this contract, and the web frontend consumes it via a type-safe client. This structure is facilitated by a Turborepo monorepo, which manages the dependencies and build processes for all the interconnected packages and applications. Note that the project is a work in progress, and the connection between the frontend and backend is not yet fully implemented.
Sources: README.md:3-10
High-Level Architecture
The project is structured as a monorepo with distinct applications and shared packages. The data flow originates from a user interaction in the web application, which triggers a request to the api server. The api server processes the request, interacts with the db layer, and returns a response, with all interactions governed by the shared contract.
The following diagram illustrates the high-level component interaction.
Sources: README.md:41-48
Key Components
| Package/App | Role | Technologies |
|---|---|---|
apps/web | Frontend application for user interaction and data presentation. | React, TanStack Router, TanStack Query, Tailwind CSS |
apps/api | Backend Hono server that implements the API logic via ORPC. | Hono, ORPC, Better Auth |
packages/contract | Defines the type-safe API contract (procedures and schemas) shared between frontend and backend. | ORPC, Zod |
packages/db | Manages the database schema and provides the data access layer. | Drizzle ORM, PostgreSQL |
packages/ui | A set of shared, unstyled, and accessible UI components. | Radix UI, Tailwind CSS |
Sources: README.md:12-39, apps/web/package.json, apps/api/package.json, packages/contract/package.json, packages/db/package.json
Detailed Data Flow
1. API Contract Definition (packages/contract)
The foundation of the type-safe data flow is the @contract-based-monorepo/contract package. It uses zod for schema validation and @orpc/contract to define the API procedures. This package acts as the single source of truth for what the API looks like, what data structures it uses, and what operations it exposes.
Although the specific contract definitions are not detailed in the provided files, its dependencies confirm its role in the architecture.
Sources: packages/contract/package.json:14-16
2. API Backend Implementation (apps/api)
The apps/api service is a Hono web server that implements the procedures defined in the contract package. It uses @orpc/server to create RPC handlers and exposes them over HTTP.
Data Access Layer
The API interacts with the database through a middleware-injected data access layer.
- DB Interface: The file
apps/api/src/middlewares/db.tsdefines aDBinterface that abstracts the database operations. This interface specifies methods for interacting withplanetsdata. - Middleware: An ORPC middleware,
dbProviderMiddleware, is responsible for creating and injecting aDBinstance into the request context. - Fake DB: Currently, a
createFakeDBfunction provides an in-memory implementation of theDBinterface for development purposes. It contains a hardcoded list ofPlanetobjects and logic for CRUD operations.
The Planet data model is defined implicitly through the Planet type used in the DB interface and the fake data.
| Field | Type | Description |
|---|---|---|
id | number | Unique identifier for the planet. |
name | string | The name of the planet. |
description | string | A short description of the planet. |
imageUrl | string | URL for an image of the planet. |
creator | User | The user who created the record. |
Sources: apps/api/src/middlewares/db.ts:7-14, 41-68
The following sequence diagram shows how a request for a list of planets is handled by the API.
Sources: apps/api/src/middlewares/db.ts:19-31
Authentication Data Flow
Authentication is managed by better-auth. It integrates with the database using better-auth/adapters/drizzle, connecting the authentication logic directly to the Drizzle schema defined in the @contract-based-monorepo/db package. This handles data flow for users, sessions, and accounts.
// apps/api/src/lib/auth.ts
export const auth = betterAuth({
// ...
database: drizzleAdapter(db, {
provider: "pg",
schema: {
user: schema.user,
session: schema.session,
account: schema.account,
verification: schema.verification,
},
}),
});
Sources: apps/api/src/lib/auth.ts:5-16
API Documentation Generation
A key feature of the contract-based approach is the ability to auto-generate API documentation. The handleOpenAPISpec function uses @orpc/openapi to generate an OpenAPI specification directly from the shared contract. This specification is then served as interactive documentation using @scalar/hono-api-reference.
3. Web Frontend (apps/web)
The apps/web application is a React-based single-page application. It is responsible for rendering the user interface and fetching data from the api backend.
Data Fetching
The frontend uses TanStack libraries for data fetching and state management:
@tanstack/react-query: For managing asynchronous operations and caching server state. The frontend would typically use a generated ORPC client with React Query hooks to call API procedures in a type-safe manner.@tanstack/react-router: For routing, which can also handle data loading for routes via itsloaderfunctionality.
Sources: apps/web/package.json:23-27
Frontend API Routes
The web application can also define its own server-side API routes using @tanstack/react-start/api. The file apps/web/src/routes/api.demo-names.ts provides an example of this, creating a GET /api/demo-names endpoint that returns a static JSON array. This is a separate data flow path from the main Hono API but demonstrates another way data can be served to the client.
// apps/web/src/routes/api.demo-names.ts
import { createAPIFileRoute } from "@tanstack/react-start/api";
export const APIRoute = createAPIFileRoute("/api/demo-names")({
GET: async ({ request }) => {
return new Response(JSON.stringify(["Alice", "Bob", "Charlie"]), {
headers: {
"Content-Type": "application/json",
},
});
},
});
Sources: apps/web/src/routes/api.demo-names.ts:1-11
Summary
The end-to-end data flow in this project is architected for type safety and developer efficiency. By defining a strict contract, the system ensures that data structures and API procedures are consistent between the Hono backend and the React frontend. The backend implements this contract, handling business logic and data persistence through an abstracted data layer, which is currently a mock but designed for a real database like PostgreSQL via Drizzle. The frontend consumes the API using type-safe clients, providing a seamless and error-resistant development experience from the database all the way to the UI.