Skip to content

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:

  1. Server — Owns data integrity and business logic
  2. Verity (Backend of Frontend) — Fetches, coalesces, tracks staleness, reacts to directives, exposes stable references
  3. 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.

{
  "op": "refresh_item",
  "name": "todo",
  "id": 42
}
  • 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, status
  • detailed — adds description, assignee
  • full — 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):

<head>
  <script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/lib/core.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/adapters/alpine.min.js"></script>
</head>

Install:

npm install verity-dl

Import:

import { createRegistry } from 'verity-dl'
import { installAlpine } from 'verity-dl/adapters/alpine'
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/lib/core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/adapters/react.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/lib/core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/verity-dl@latest/verity/shared/static/adapters/vue.min.js"></script>

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

2. Learn Core Concepts

3. Get Building

4. Go Deeper

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


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.