Harper Component Model
Overview
Harper (formerly HarperDB; the product and company now at harper.fast) is an
open-source Node.js platform that fuses database, cache, application logic, and
messaging into a single in-memory process. Fabric is Harper's distributed
deploy network: you develop locally, then deploy the same component to Fabric.
Everything you build is a component. Understanding the component hierarchy is
the prerequisite for every other Harper decision — config, resources, schema, and
deploy all hang off it.
The three tiers
Harper organizes functionality into three tiers, top to bottom:
- Applications — the user-facing product. An application is a type of
component. It implements business logic (REST/GraphQL endpoints, web UI,
real-time) by depending on extensions/plugins. This is what this project is.
- Plugins (v5) / Extensions (deprecated) — the building blocks an
application depends on. A plugin exports a single
handleApplication(scope)
method and always runs on worker threads. The deprecated Extension API used
start, handleFile, handleDirectory, and setupDirectory instead.
handleApplication() cannot coexist with Extension API methods — defining
both throws. Prefer the Plugin API for any custom building block.
- Core services — the high-performance database, networking middleware, and
the component manager. You configure these; you don't reimplement them.
An application is the component you ship. Extensions/plugins are the
capabilities it consumes. Built-in extensions (graphqlSchema, jsResource,
rest, static, …) are provided by core; you only enable them in
config.yaml. See [[harper-config-yaml]].
Built-in extensions an application typically uses
These ship with Harper and are enabled (not installed) via config.yaml:
graphqlSchema — define database tables/types from GraphQL schema files. See [[harper-schema-graphql]].
jsResource — load custom JavaScript resources (resources.js). See [[harper-resources]].
rest — auto-generate REST endpoints for exported resources/tables.
static — serve static files (the web/** directory) over HTTP.
roles — role-based access control from roles.yaml.
loadEnv — load environment variables from .env.
dataLoader — seed Harper tables from JSON/YAML.
fastifyRoutes — custom Fastify route handlers.
Where things live in this project
This project wraps Harper's native model with a fixed layout under harper-app/:
| Path |
Role |
Source or generated |
harper-app/config.yaml |
Component config — which extensions are active |
Source |
harper-app/schema.graphql |
Table/type definitions |
Source |
src/** (TypeScript) |
Resources, browser modules, shared libs, scripts |
Source |
harper-app/resources.js |
Loaded by jsResource |
Generated — never edit; build from TS |
harper-app/web/** |
Served by static |
Generated — never edit; build from TS |
The TypeScript under src/ is the source of truth. resources.js and web/**
are deploy artifacts produced by bun run build. Never hand-edit them — change
the matching TypeScript and rebuild. See [[harper-build-and-deploy]].
Decision guide
- Adding a backend behavior? It's almost always a resource (custom logic) or
a schema change (new table/field), enabled through
config.yaml. Don't ship a
client-side workaround for missing backend behavior — make the Harper change.
- Adding a reusable building block / npm-publishable capability? That's a
plugin (
pluginModule), not application code.
- Adding static UI? It belongs in
web/** (generated from src/ UI code), served
by the static extension.
- Not sure if it deploys? A deployable Harper app must keep
config.yaml,
schema.graphql, resources.js, and web/** at the component root that Fabric
packages. If your change touches that surface, build before packaging.
Sources
1---2name: harper-component-model3description: reasoning about how a Harper…4---56# Harper Component Model78## Overview910Harper (formerly HarperDB; the product and company now at harper.fast) is an11open-source Node.js platform that fuses **database, cache, application logic, and12messaging into a single in-memory process**. **Fabric** is Harper's distributed13deploy network: you develop locally, then deploy the same component to Fabric.1415Everything you build is a **component**. Understanding the component hierarchy is16the prerequisite for every other Harper decision — config, resources, schema, and17deploy all hang off it.1819## The three tiers2021Harper organizes functionality into three tiers, top to bottom:22231. **Applications** — the user-facing product. An application *is* a type of24 component. It implements business logic (REST/GraphQL endpoints, web UI,25 real-time) by depending on extensions/plugins. This is what this project is.262. **Plugins** (v5) / **Extensions** (deprecated) — the building blocks an27 application depends on. A plugin exports a single `handleApplication(scope)`28 method and always runs on worker threads. The deprecated Extension API used29 `start`, `handleFile`, `handleDirectory`, and `setupDirectory` instead.30 `handleApplication()` cannot coexist with Extension API methods — defining31 both throws. Prefer the Plugin API for any custom building block.323. **Core services** — the high-performance database, networking middleware, and33 the component manager. You configure these; you don't reimplement them.3435> An *application* is the component you ship. *Extensions/plugins* are the36> capabilities it consumes. Built-in extensions (`graphqlSchema`, `jsResource`,37> `rest`, `static`, …) are provided by core; you only *enable* them in38> `config.yaml`. See [[harper-config-yaml]].3940## Built-in extensions an application typically uses4142These ship with Harper and are enabled (not installed) via `config.yaml`:4344- `graphqlSchema` — define database tables/types from GraphQL schema files. See [[harper-schema-graphql]].45- `jsResource` — load custom JavaScript resources (`resources.js`). See [[harper-resources]].46- `rest` — auto-generate REST endpoints for exported resources/tables.47- `static` — serve static files (the `web/**` directory) over HTTP.48- `roles` — role-based access control from `roles.yaml`.49- `loadEnv` — load environment variables from `.env`.50- `dataLoader` — seed Harper tables from JSON/YAML.51- `fastifyRoutes` — custom Fastify route handlers.5253## Where things live in this project5455This project wraps Harper's native model with a fixed layout under `harper-app/`:5657| Path | Role | Source or generated |58| --- | --- | --- |59| `harper-app/config.yaml` | Component config — which extensions are active | **Source** |60| `harper-app/schema.graphql` | Table/type definitions | **Source** |61| `src/**` (TypeScript) | Resources, browser modules, shared libs, scripts | **Source** |62| `harper-app/resources.js` | Loaded by `jsResource` | **Generated** — never edit; build from TS |63| `harper-app/web/**` | Served by `static` | **Generated** — never edit; build from TS |6465The TypeScript under `src/` is the source of truth. `resources.js` and `web/**`66are deploy artifacts produced by `bun run build`. Never hand-edit them — change67the matching TypeScript and rebuild. See [[harper-build-and-deploy]].6869## Decision guide7071- **Adding a backend behavior?** It's almost always a *resource* (custom logic) or72 a *schema* change (new table/field), enabled through `config.yaml`. Don't ship a73 client-side workaround for missing backend behavior — make the Harper change.74- **Adding a reusable building block / npm-publishable capability?** That's a75 *plugin* (`pluginModule`), not application code.76- **Adding static UI?** It belongs in `web/**` (generated from `src/` UI code), served77 by the `static` extension.78- **Not sure if it deploys?** A deployable Harper app must keep `config.yaml`,79 `schema.graphql`, `resources.js`, and `web/**` at the component root that Fabric80 packages. If your change touches that surface, build before packaging.8182## Sources8384- [Components overview](https://docs.harperdb.io/reference/v5/components/overview)85- [Plugin API](https://docs.harperdb.io/reference/v5/components/plugin-api)86- [Applications](https://docs.harperdb.io/docs/developers/applications)87- [Harper platform](https://www.harper.fast/)