Verity¶
One strong idea: the server is the only source of truth.
One clear boundary: truth-state (server-owned) is not the same as view-state (client-owned).
One purpose: a composable data layer that mediates between them—protocol-agnostic, framework-agnostic, and honest.
Verity is the backend of your frontend. It sits between your server and view layer, handling caching, staleness, fan-out, and directive processing so your UI can focus purely on rendering.
If a piece of data cannot be proven, Verity keeps it in a loading state. Truth beats speed.
The Problem¶
State Confusion in Modern Frontends
Most applications blur two fundamentally different kinds of state, creating bugs and user confusion.
Modern frontends mix:
Server-owned, authoritative data
- User profiles and account information
- Order status and transaction history
- Inventory counts and product catalogs
- Permissions and access control
- Any data multiple clients must agree on
Client-owned, ephemeral UI concerns
- Which menu is open
- Which row is expanded
- Current tab selection
- Form draft values (before submission)
- Sidebar collapse state
The Result
Teams end up mixing "what the server says" with "what the UI is doing," then try to paper over races and stale views with optimistic updates. That creates flicker, mismatch, and user distrust.
The Solution¶
Verity Separates the Lanes
Clear boundaries between server, data layer, and view—each doing what it does best.
graph LR
A[Server<br/>Domain Logic] -->|Directives| B[Verity<br/>Data Layer]
B -->|Stable Refs| C[View<br/>Rendering]
C -->|Mutations| A
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#f0e1ff
The Three Layers:
- Server — Owns data integrity and business logic
- Verity (Backend of Frontend) — Fetches, coalesces, tracks staleness, reacts to directives, exposes stable references
- View Layer — Renders truth-state, manages view-state—without fetching, caching, or coordinating invalidation
Not Just Conceptual
This separation shows up in Verity's public API, internal guarantees, and strict UX policy.
Why Verity?¶
The UI changes after the server confirms change.
- Unknowns render as skeletons
- Work in progress shows spinners
- No temporary lies
- No speculation
Result: Users trust what they see.
Servers emit semantic directives that describe what changed.
- Not DOM patches
- Not field-level diffs
- Just: "This thing changed"
- Decouples server from view structure
- Fan-out over SSE keeps all clients in sync
One fetch can satisfy multiple detail levels.
Levels: Different detail amounts for same entity
summary— id, name, statusdetailed— adds description, assigneefull— adds comments, history
Conversion graphs: Derive summary from full without refetch
Smart planning: Directives trigger minimal refetches
Same core, different adapters.
Core: Stable refs + subscribe API
Adapters: Thin wrappers for:
- Alpine.js
- React
- Vue
- Svelte
Benefit: Switch frameworks, keep the data layer
Perceived snappiness never justifies lying.
If you need instant feedback:
✅ Make server respond faster
✅ Show honest loading states
✅ Use good skeletons/spinners
❌ Don't fake it client-side
What's Included¶
- Flask Blueprint: Exposes shared static assets (core library, adapters, devtools)
- Framework-Agnostic JavaScript Core: Enforces Verity's invariants (truth-only, latest-wins, coalescing)
- Multiple Framework Adapters: Bridge the core to Alpine, React, Vue, and Svelte with identical semantics
- Realistic Examples: Full-stack demos spanning finance, manufacturing, and telehealth domains
- Devtools: Lifecycle tracing, directive logs, cache inspection, and SSE monitoring
Design Guarantees¶
- Latest-wins: stale network results won't clobber newer state
- Coalesced: identical in-flight requests reuse one promise
- Deterministic: the same sequence of directives + responses yields the same cache
- Isolated: truth-state doesn't leak view concerns; view-state doesn't influence server truth
- Pluggable: fetchers and directive sources are replaceable without touching views
When to Use Verity¶
Use Verity for Truth-State
Where server truth matters—shared, audited, multi-client data.
Multi-client, server-owned data:
- User records and profiles
- Order status and transactions
- Inventory counts and catalogs
- Permissions and access control
- Audit logs and compliance data
- Multi-user dashboards
- Real-time operations centers
- Any data where flicker erodes trust
Local, client-owned UI state:
- Menu open/closed state
- Current tab index
- Form draft values (before submit)
- UI animations and transitions
- Sidebar collapse state
- Dark mode preference (unless persisted server-side)
The Smell Test
If changing tabs or reloading should reset it: view-state
If a coworker on another device must see it: truth-state
Quick Start¶
No Build Tools Required
Drop script tags in your HTML and start using Verity immediately.
Development:
<head>
<!-- Alpine.js -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
<!-- Verity -->
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/lib/core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/adapters/alpine.js"></script>
</head>
Production (minified):
Install:
Import:
Complete Example (No Build Tools)¶
<!DOCTYPE html>
<html>
<head>
<!-- Alpine.js -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
<!-- Verity -->
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/lib/core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/adapters/alpine.js"></script>
</head>
<body>
<div x-data="verity.collection('todos')">
<template x-if="state.loading">
<p>Loading todos...</p>
</template>
<template x-for="todo in state.items" :key="todo.id">
<div>
<input type="checkbox" :checked="todo.completed">
<span x-text="todo.title"></span>
</div>
</template>
</div>
<script>
// Create and configure registry
const registry = Verity.createRegistry()
registry.registerCollection('todos', {
fetch: () => fetch('/api/todos').then(r => r.json())
})
registry.registerType('todo', {
fetch: ({ id }) => fetch(`/api/todos/${id}`).then(r => r.json())
})
// Install Alpine adapter
VerityAlpine.install(window.Alpine, { registry })
</script>
</body>
</html>
Run Examples¶
The repository includes full-stack examples you can run locally:
# Clone the repository
git clone https://github.com/YidiDev/verity.git
cd verity
# Set up Python environment for examples
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Run an example
python verity/examples/invoices_alpine/app.py
# Or try: python verity/examples/manufacturing_monitor/app.py
Learning Path¶
1. Understand the Foundation¶
- Read Philosophy for the full mental model
- Study Architecture to see how the three layers interact
- Master Truth-State vs View-State distinction
2. Learn Core Concepts¶
- Directives — the server-authored invalidation contract
- Levels & Conversions — minimal fetching strategy
- Concurrency Model — latest-wins, coalescing, and consistency
3. Get Building¶
- Getting Started — wire Verity into a new project
- State Model — types, collections, and caching
- UX Patterns — honest loading states and user feedback
4. Go Deeper¶
- API Reference — full API surface
- Framework Adapters — Alpine, React, Vue, Svelte integration
- Directive Reference — complete directive contract
5. See It in Action¶
- Examples Overview — production-scale demos
- Study baseline comparisons to see the difference
How This Differs from Alternatives¶
✅ What They Get Right
Server is the source of truth
❌ What's Missing
- Server dictates DOM structure
- Tight coupling backend ↔ view
- Hard to support multiple clients
Verity's Approach
- Pushes data intent (directives)
- View-state stays client-owned
- Same backend, any frontend
✅ What They Get Right
- Mature caching
- Good tooling
- Multi-framework support
❌ What's Missing
- Optimistic updates encouraged
- App-defined invalidation (glue code)
- No level conversion planning
- Server doesn't author contract
Verity's Approach
- Server authors invalidation contract
- No optimistic updates
- Minimal refetch planning
- Explicit truth-state boundary
✅ What You Get
Maximum control
❌ What You Re-implement
- Coalescing
- Latest-wins guards
- Push integration
- Multi-client convergence
- UX semantics
- Memory management
- Again. And again. And again.
Verity's Approach
The boring, correct default
Detailed Comparison
See Why Verity? for in-depth analysis.
Community and Support¶
- Documentation: verity.yidi.sh
- Source Code: github.com/YidiDev/verity
- Issues: github.com/YidiDev/verity/issues
- Contributing: See CONTRIBUTING.md
The Short Version¶
Verity treats the data layer as the backend of your frontend. It draws a hard line between server truth and client view, uses directives to keep them in sync, plans minimal fetches with levels and conversions, and refuses to lie to the user.
If that's the kind of correctness and clarity you want, this library is for you.