Backend Architecture & Hono RPC
βοΈ Backend Architecture & Hono RPC
Section titled ββοΈ Backend Architecture & Hono RPCβThe Kryptofolio backend (apps/backend) is a centralized, lightweight, and ultra-fast service built on Hono.js.
It acts as the single source of truth for:
- REST API endpoints consumed by the Vue 3 frontend.
- End-to-end type safety via Hono RPC without code-generation steps.
- Encrypted API credentials storage (Vault).
- Analytical execution coordination between SQLite and DuckDB.
ποΈ Server Layout & Separation of Concerns
Section titled βποΈ Server Layout & Separation of ConcernsβThe backend is cleanly separated into two distinct entry points:
apps/backend/src/βββ app.ts # Pure Hono app: middlewares, routing, and AppType exportβββ index.ts # Bootstrapper: DB connection pooling, job triggers, port bindingβββ core/β βββ domain/ # Domain models and interfacesβ βββ application/ # Use Cases (e.g. UnlockVaultUseCase, IngestTransactionsUseCase)β βββ infrastructure/β βββ di/container.ts# Centralized Dependency Injection Composition Rootβ βββ adapters/ # SQLite & DuckDB engine adaptersβ βββ routes/ # Modular Hono route definitionsβ βββ jobs/ # Scheduled background tasks (e.g. ExchangeRateSyncJob)app.ts(Pure Application): Defines route paths, sets up CORS, logger middlewares, and exports theAppType. It contains no network listening logic, making it effortlessly testable withapp.request().index.ts(Runtime Bootstrapper): Initializes database files, runs schema migrations, verifies environment variables, and starts the Node.js HTTP server.
π End-to-End Type Safety (Hono RPC)
Section titled βπ End-to-End Type Safety (Hono RPC)βTraditional architectures often require running heavy OpenAPI/Swagger code generators (like openapi-typescript-codegen or GraphQL codegen) whenever an endpoint changes.
Kryptofolio leverages Hono RPC, sharing TypeScript types directly across monorepo boundaries with zero build-step overhead:
1. Backend Route Definition & Export (apps/backend/src/app.ts)
Section titled β1. Backend Route Definition & Export (apps/backend/src/app.ts)βimport { Hono } from 'hono';import { metricsRoutes } from './core/infrastructure/routes/metrics';import { taxRoutes } from './core/infrastructure/routes/tax';import { vaultRoutes } from './core/infrastructure/routes/vault';
const routes = new Hono() .route('/api/metrics', metricsRoutes) .route('/api/tax', taxRoutes) .route('/api/credentials', vaultRoutes);
export const app = new Hono().route('/', routes);export type AppType = typeof routes;2. Frontend Consumption (apps/frontend/.../BffClient.ts)
Section titled β2. Frontend Consumption (apps/frontend/.../BffClient.ts)βThe frontend initializes the RPC client importing only the AppType type definition:
import { hc } from 'hono/client';import type { AppType } from '@kryptofolio/backend';
export const bffClient = hc<AppType>(import.meta.env.VITE_API_URL || 'http://localhost:3001');
// Full autocomplete, argument validation, and return typing:const response = await bffClient.api.metrics.kpis.$get();if (response.ok) { const data = await response.json(); // Data is strictly typed! console.log(data.total_equity);}π Centralized Dependency Injection (container.ts)
Section titled βπ Centralized Dependency Injection (container.ts)βThe backend routes do not instantiate services directly. A centralized DI container resolves concrete adapters and injects them into Use Cases:
export interface Container { sqliteLedgerAdapter: SqliteLedgerAdapter; duckDbAdapter: DuckDbAdapter; fifoMaterializerService: FifoMaterializerService; vaultCredentialsPort: IVaultCredentialsPort; ingestAndMaterializeUseCase: IngestAndMaterializeUseCase;}This guarantees:
- Testability: In test environments, the container easily swaps file-backed databases for
:memory:instances. - Single Instance Pooling: DuckDB connections and SQLite handles are properly pooled and shared without leaks.
π‘ API Routes Overview
Section titled βπ‘ API Routes Overviewβ| Route Prefix | Method | Purpose |
|---|---|---|
/api/metrics/kpis |
GET |
Portfolio summary (equity, cost basis, realized/unrealized PnL, win rate). |
/api/metrics/risk |
GET |
Institutional metrics (Sharpe ratio, 30d volatility, ATH drawdown, Alpha, Beta). |
/api/metrics/performance |
GET |
Daily valuation time-series in the requested currency (default EUR), converted per point at that dateβs rate; points with no rate are null. |
/api/tax/import |
POST |
Ingestion pipeline submission with source format profile. |
/api/tax/lots |
GET |
Query calculated tax lots with remaining balances and custody provenance. |
/api/settings/accounts |
GET |
Lists the user-facing accounts (id as value, name as label); synthetic custody counterparties are excluded by ListAccountsUseCase. |
/api/tax/transactions/spot |
GET |
Spot transactions for the effective (edited) view, optionally filtered by accountId, through SearchSpotTransactionsUseCase. Ledger order, oldest first. |
/api/credentials/vault/* |
Multiple | Manage encrypted third-party credentials and vault lock state. |
/api/advisor/* |
Multiple | Read-only AI Portfolio Advisor: streaming chat, model chain and execution-profile configuration. See AI Advisor. |