Native Shell
Native Shell: AI-generated UI, native in your app, on every platform. Apps on iOS, Android, macOS, Windows and Linux, GPUI apps and web pages load signed, sandboxed TSX modules at run time and draw th
Fullstack serverless data framework for DynamoDB: type-safe APIs, event-driven processors, React hooks, and Athena analytics on a single table
Developer toolsTypeScript · JavaScriptGitHub @monoristOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Build full-stack apps on DynamoDB with type-safe schemas and auto-generated APIs
Taken from the repository README
Loading the full README.
Read the full README ↗Monorise is an open-source fullstack serverless data framework for applications built on DynamoDB. Define your data models with Zod schemas, and get:
1. Create your project:
npx monorise init --name my-app
cd my-app
2. Define your entity:
// monorise/configs/member.ts
import { createEntityConfig } from 'monorise/base';
import { z } from 'zod/v4';
const baseSchema = z.object({
name: z.string(),
email: z.string().email(),
role: z.enum(['admin', 'member']),
}).partial();
export default createEntityConfig({
name: 'member',
displayName: 'Member',
baseSchema,
searchableFields: ['name', 'email'],
uniqueFields: ['email'],
});
3. Query from React:
// apps/web/app/page.tsx
import { useEntities, createEntity } from 'monorise/react';
import { Entity } from '#/monorise';
export default function MembersPage() {
const { entities: members, isLoading } = useEntities(Entity.MEMBER);
return (
<div>
{members?.map((m) => (
<div key={m.entityId}>{m.data.name} — {m.data.email}</div>
))}
</div>
);
}
That's it — relational queries on DynamoDB without the design doc. Single-table performance without the single-table pain.
# Create a new project with everything set up
npx monorise init --name my-app
# Start development
cd my-app
npx sst dev
# Deploy to production
npx sst deploy --stage prod
monorise init scaffolds a production-ready monorepo:
my-app/
├── apps/web/ # Next.js frontend
│ ├── app/
│ │ ├── layout.tsx # GlobalInitializer + GlobalLoader wired in
│ │ ├── page.tsx # Example page with useEntities
│ │ ├── globals.css # Shadcn theme variables
│ │ └── api/
│ │ ├── proxy-request.ts # API proxy utility
│ │ └── [...proxy]/route.ts # Catch-all proxy to monorise backend
│ ├── components/
│ │ ├── global-initializer.tsx # Monorise store config
│ │ ├── global-loader.tsx # Interruptive loading overlay
│ │ └── ui/ # Shadcn UI (button, card, input, label)
│ └── lib/utils.ts # cn() helper
├── services/core/
│ └── routes.ts # Hono backend routes
├── monorise/configs/
│ ├── user.ts # Starter entity — has a Team mutual
│ └── team.ts # Starter entity — has a User mutual
├── monorise/mutuals/
│ └── team-membership.ts # createMutualConfig, shared by both sides
├── sst.config.ts # SST + Monorise configured
└── .monorise/ # Generated types (config.ts + index.ts)
Import generated types via #/monorise (or #/monorise/config — both work, #/monorise is just shorter).
Read the Getting Started Guide for the complete walkthrough.
| Feature | Description |
|---|---|
| 🗄️ Single-Table DynamoDB | One table, O(1) performance for every query. Denormalization handled automatically. |
| 🔄 Zero Schema Drift | One Zod config drives DB, backend, and frontend. monorise dev auto-regenerates types on every change. |
| 🚀 Ship in Hours | From git init to production API. No migration scripts, no access pattern spreadsheets. |
| 🔗 Relational Patterns | Entity, Mutual, and Tag concepts for relational-style queries on DynamoDB. |
| 📦 Full-Stack SDK | Backend (Hono), React hooks, SST v4 infrastructure — one package. |
| 📊 Built-In Analytics | Opt-in CDC pipeline streams every change to S3 + Athena — current state and full history, queryable with SQL. |
| 🧠 Token-Efficient | Built-in CRUD, relationships, and tagging. Less code to write, fewer tokens to generate/review. |
user, order)learner enrolled in course)┌─────────┐ ┌─────────────┐ ┌─────────────────┐
│ Client │────▶│ Hono API │────▶│ Entity/Mutual/ │
│ │ │ /core/* │ │ Tag Services │
└─────────┘ └─────────────┘ └────────┬────────┘
│
┌───────────────────┴──────────┐
▼ ▼
┌─────────────┐ ┌────────────────┐
│ DynamoDB │◀────────────▶│ EventBridge │
│ Single Table│ │ Bus │
└─────────────┘ └───────┬────────┘
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ SQS Mutual │ │ SQS Tag │ │ SQS Tree │
│ Processor │ │ Processor │ │ Processor │
└─────────────┘ └─────────────┘ └─────────────┘
See Architecture for the detailed design.
├── packages/
│ ├── base/ # Entity config + schemas (Zod)
│ ├── core/ # Hono API, DynamoDB repos, processors
│ ├── cli/ # CLI for generating artifacts
│ ├── react/ # React hooks and client SDK
│ └── sst/ # SST v4 infrastructure module
├── www/ # Documentation site (VitePress)
└── examples/ # Example projects
Monorise uses a small build step to turn entity configs into runnable handlers.
flowchart LR
Config["monorise.config.ts + entity config files"] --> CLI["monorise dev/build (CLI)"]
CLI --> Out[".monorise/config.ts + .monorise/handle.ts"]
Out --> SST["SST stack (v2 or v3)"]
Notes:
monorise.config.ts points to your entity config directory and optional
custom routes (Hono)..monorise/handle.ts which exports Lambda handlers used by SST
(API + processors + replication).flowchart LR
Client --> Api["Hono API /core/*"]
Api --> CoreSvc["Entity/Mutual/Tag services"]
CoreSvc --> DDB[(DynamoDB single table)]
CoreSvc --> Bus["EventBridge bus"]
Bus --> SQS["SQS processors (mutual/tag/tree)"]
SQS --> DDB
DDB --> Stream["DynamoDB stream"]
Stream --> Replicator["replication processor"]
Replicator --> DDB
flowchart TB
subgraph Build["Build-time"]
Config["Entity configs (zod + mutual/tag/tree)"]
Cli["monorise CLI (dev/build)"]
Handle[".monorise/handle.ts"]
Config --> Cli --> Handle
end
subgraph Runtime["Runtime (SST)"]
API["/core API (Hono)"]
Services["Entity/Mutual/Tag services"]
Table[(DynamoDB single table)]
Bus["EventBridge bus"]
MutualQ["Mutual processor"]
TagQ["Tag processor"]
TreeQ["Tree processor"]
Stream["DynamoDB stream"]
Replicator["Replication processor"]
end
Client["App / Backoffice / Services"] --> API
Handle --> API
API --> Services --> Table
Services --> Bus
Bus --> MutualQ --> Table
Bus --> TagQ --> Table
Bus --> TreeQ --> Bus
Table --> Stream --> Replicator --> Table
Key behavior:
These are the main access patterns in the single table:
PK = <entityType>#<entityId>, SK = #METADATA#PK = LIST#<entityType>, SK = <entityType>#<entityId>MUTUAL#<id> item plus two directional lookup
items (byEntity -> entity and the reverse).PK = TAG#<entityType>#<tagName>[#group],
SK = <sortValue?>#<entityType>#<entityId> plus reverse lookup by entity.PK = UNIQUE#<field>#<value>, SK = <entityType>The replication indexes (R1PK/R2PK) support fast updates of denormalized items.
The default Hono API exposes:
GET/POST /core/entity/:entityTypeGET/PUT/PATCH/DELETE /core/entity/:entityType/:entityIdGET/POST/PATCH/DELETE /core/mutual/:byEntityType/:byEntityId/:entityType/:entityIdGET /core/tag/:entityType/:tagNameCustom routes can be mounted under /core/app/* via customRoutes.
PATCH /core/entity/:entityType/:entityId supports optional conditional
preconditions through a top-level $where object. This lets you do atomic
compare-and-set style updates.
Use $where in PATCH /core/entity/:entityType/:entityId when updates should
only apply if current values match your preconditions. Monorise compiles this
to a DynamoDB ConditionExpression and executes it atomically in one write.
Without $where (existing behavior):
{
"status": "confirmed"
}
With $where:
{
"status": "confirmed",
"confirmedAt": "2026-04-13T00:00:00.000Z",
"$where": {
"status": { "$eq": "pending" },
"retryCount": { "$lt": 3 }
}
}
Shorthand equality is supported:
{
"status": "confirmed",
"$where": {
"status": "pending"
}
}
All $where clauses are combined with AND.
Supported operators:
| Operator | Meaning |
|---|---|
$eq | Equals |
$ne | Not equals |
$gt | Greater than |
$lt | Less than |
$gte | Greater than or equal |
$lte | Less than or equal |
$exists | Field exists / does not exist |
$beginsWith | String prefix match |
Response behavior for PATCH:
200 OK: update applied409 CONFLICT: $where precondition failed (CONDITIONAL_CHECK_FAILED)
404 NOT_FOUND: entity missing in non-conditional mode400 BAD_REQUEST: validation errors and unique-value conflictsCompatibility notes:
$where required).$where is reserved for conditional update semantics.| Package | Role |
|---|---|
@monorise/base | Entity config + schema/types (zod). |
@monorise/core | Hono API, DynamoDB repositories, processors, event utils. |
@monorise/cli | Generates .monorise/config.ts + .monorise/index.ts + .monorise/handle.ts. |
@monorise/react | Client SDK, hooks, stores, axios helpers. |
@monorise/sst | SST v4 module: API, bus, table, queues, processors. |
packages/core/*packages/sst/*packages/cli/*packages/base/*packages/react/*See Contributing Guide for workflow, changesets, and PR guidelines.
Distributed under the MIT License. See LICENSE.