Core Concepts
The foundational ideas behind ObjectStack — metadata-driven development, protocol-first design, and the principles that shape every decision
Core Concepts
Before diving into code, understanding these foundational ideas will make everything else click.
Metadata-Driven Development
Metadata-driven development is a paradigm shift where application logic is defined by declarative data (metadata), not imperative code.
The Problem with Code-First
In traditional development, the "Intent" (e.g., "This field is a required email address") is scattered across multiple layers:
- Database: SQL constraints (
NOT NULL,CHECK) - Backend: ORM validation (TypeORM decorators, Prisma schemas)
- Frontend: UI validation (React Hook Form + Zod)
- Documentation: API specs (OpenAPI/Swagger)
When a business requirement changes, you must update code in three or four places. This is Implementation Coupling.
The ObjectStack Way
ObjectStack centralizes the "Intent" into a single Protocol Definition:
// ONE definition — everything else derives from it
import { defineStack } from '@objectstack/spec';
export default defineStack({
objects: [{
name: 'user',
label: 'User',
fields: {
phone: { label: 'Phone Number', type: 'phone', required: true },
},
}],
});// Map keys become the `name` field automatically
import { defineStack } from '@objectstack/spec';
export default defineStack({
objects: {
user: {
label: 'User',
fields: {
phone: { label: 'Phone Number', type: 'phone', required: true },
},
},
},
});Array or Map? defineStack() accepts both formats for all named metadata collections (objects, apps, flows, etc.). Map keys are injected as the name field — pick whichever style you prefer.
From this single definition, ObjectStack automatically:
✅ Generates database schema ✅ Creates validation rules ✅ Builds CRUD APIs ✅ Renders form fields ✅ Produces API documentation
The Three Truths
- The UI is a Projection — The form is generated from the schema, not hand-coded
- The API is a Consequence — REST/GraphQL endpoints appear automatically from object definitions
- The Schema is the Application — Your entire business logic lives in metadata files
When to Use Metadata-Driven
✅ Great for: CRUD apps, SaaS platforms, admin panels, rapid prototyping, multi-tenant systems
❌ Not ideal for: Pixel-perfect custom UIs, real-time 3D/games, highly unique domains
Design Principles
ObjectStack is governed by four unshakable principles:
I. Protocol Neutrality
The Protocol is law. The Implementation is merely an opinion.
II. Mechanism over Policy
Provide the tools to build rules, do not hardcode the rules themselves.
III. Single Source of Truth
There is no 'Code'. There is only Schema.
IV. Local-First by Default
The Cloud is a sync peer, not a master.
Protocol Neutrality
"The Protocol is neutral. The Engine is replaceable."
- Spec before Engine: Features must be defined in the Specification layer before any engine code is written
- Zero Leakage: Implementation details (React, SQL, etc.) never leak into Protocol definitions
This ensures ObjectStack apps can run on Node.js + PostgreSQL today, Python + SQLite tomorrow, or Rust WASM in the browser.
Mechanism over Policy
"Give them the physics, not the simulation."
| Layer | Responsibility | Example |
|---|---|---|
| Protocol | Defines capabilities | allowRead: string (a slot for a formula) |
| App | Defines business logic | allowRead: "$user.role == 'admin'" |
| Engine | Enforces the logic | Compiles formula to SQL WHERE clause |
Single Source of Truth
In ObjectStack, the Object Protocol is the only truth:
- The Database is a derivative of the Protocol
- The UI is a projection of the Protocol
- The API is a consequence of the Protocol
Change the Protocol → the entire system adapts automatically.
Local-First by Default
All interactions should be instant (0ms latency). The user's data lives on their device; the server is a sync hub.
Traditional: Click → Wi-Fi → ISP → Cloud → DB → Response
Local-First: Click → Local DB → UI Update (0ms)Naming Conventions
ObjectStack enforces strict naming rules for consistency:
| Element | Convention | Examples |
|---|---|---|
| Object names (machine) | snake_case | todo_task, user_profile |
| Field names (machine) | snake_case | first_name, is_active |
| Export names (constants) | PascalCase | TodoTask, UserProfile |
| Config keys (properties) | camelCase | maxLength, defaultValue |
Summary
| Aspect | Traditional | Metadata-Driven |
|---|---|---|
| Definition | Code in multiple files | Single metadata definition |
| Changes | Update 3-4 places | Update once |
| Type Safety | Manual synchronization | Automatic from Zod |
| Flexibility | Locked to tech stack | Technology agnostic |
| Boilerplate | High (300+ lines) | Low (30 lines) |
Next Steps
- Architecture — How the protocol layers work together
- Quick Start — Build your first app in 5 minutes
- Glossary — Key terminology