The Full Plures Application Framework
| Category | Status |
|---|---|
| CI/CD | β Automated testing & builds |
| Version | 1.0.2 (Stable) |
| Runtime Support | Node.js 18+, Deno (experimental), .NET 8+ |
| Package Registries | npm β / NuGet β / JSR β |
| Test Coverage | 327 TypeScript + 95 C# tests passing |
| Documentation | π Comprehensive guides available |
| Language | Package | Registry | Status |
|---|---|---|---|
| TypeScript | @plures/praxis | npm | β Available |
| C# | Plures.Praxis | NuGet | β Available |
| PowerShell | Praxis.psm1 | GitHub | β Available |
| Integration | Status | Notes |
|---|---|---|
| Praxis Cloud | β Available | Azure-hosted relay for sync & monetization |
| PluresDB | β Available | Local-first reactive datastore with 32 tests |
| Unum | β Available | Identity & channels integration |
| Svelte 5 | β Full Support | Runes API, stores, history, time-travel |
| Tauri | β Available | Cross-platform desktop runtime |
| CodeCanvas | β Available | Visual schema editor & FSM enforcement |
| State-Docs | β Available | Documentation generation from schemas |
Praxis is not just a logic engineβit's a complete framework for building modern, local-first, distributed applications. It provides:
Praxis 1.0 introduces a schema-driven, modular architecture where the Praxis Schema Format (PSF) serves as the single source of truth.
PSF is the canonical JSON/AST format that defines your entire application:
{
"$version": "latest",
"id": "my-app",
"name": "My Application",
"facts": [...],
"events": [...],
"rules": [...],
"constraints": [...],
"models": [...],
"components": [...],
"flows": [...]
}
From this schema, Praxis generates:
/praxis
βββ core/ # Core framework modules
β βββ schema-engine/ # PSF types, compiler, generator, validator
β βββ logic-engine/ # Rules, constraints, engine, PSF adapter
β βββ db-adapter/ # PluresDB sync engine
β βββ codegen/ # Documentation and code generators
βββ ui/ # UI modules
β βββ svelte-generator/ # PSF-aware Svelte component generation
β βββ canvas/ # Visual canvas state and projection
βββ tools/ # Developer tools
β βββ cli/ # Command-line interface
β βββ watcher/ # File watching and live sync
βββ extensions/ # Optional integrations
β βββ dsc/ # DSC/MCP orchestration
β βββ azure/ # Azure integration
β βββ devtools/ # Developer tools
βββ examples/ # Example applications
βββ hero-shop/ # Full e-commerce example
βββ todo/ # Minimal todo example
Praxis provides these integrated capabilities:
Schema-Driven Development
Local-First Architecture
Strong typing and functional programming
Fact<Tag, Payload>, Event<Tag, Payload>, Rule<Context, InFact, OutFact>Visual and Code Workflows
Cross-Platform and Cross-Language
praxis create, praxis generate, praxis canvas commands$state, $derived, $effect supportstep functionsnpm install @plures/praxis
dotnet add package Plures.Praxis
Or add to your .csproj:
<PackageReference Include="Plures.Praxis" Version="0.2.1" />
See C# Documentation for detailed usage.
# Coming soon - JSR publishing in progress
deno add @plures/praxis
For now, you can use Praxis with Deno via import maps:
// import_map.json
{
"imports": {
"@plures/praxis": "npm:@plures/praxis@^0.2.1"
}
}
# Clone the repository
git clone https://github.com/plures/praxis.git
cd praxis
# TypeScript
npm install
npm run build
npm test
# C#
cd csharp
dotnet build
dotnet test
The Praxis CLI provides commands for creating and managing applications.
# Install Praxis globally
npm install -g @plures/praxis
# Create a new application
praxis create app my-app
cd my-app
npm install
# Generate code from schemas
praxis generate --schema src/schemas/app.schema.ts
# Open CodeCanvas for visual editing
praxis canvas src/schemas/app.schema.ts
# Start development server
npm run dev
# Build for production
npm run build
Available CLI commands:
praxis login - Authenticate with GitHub (device flow or token)praxis logout - Log out from Praxis Cloudpraxis whoami - Show current authenticated userpraxis create app [name] - Create new applicationpraxis create component [name] - Create new componentpraxis generate - Generate code from schemaspraxis canvas [schema] - Open visual editorpraxis orchestrate - Manage distributed systemspraxis cloud init - Connect to Praxis Cloudpraxis cloud status - Check cloud connectionpraxis cloud sync - Manually sync to cloudpraxis cloud usage - View cloud usage metricspraxis dev - Start development serverpraxis build - Build for productionSee docs/guides/getting-started.md for detailed instructions.
Connect your application to Praxis Cloud for automatic synchronization with GitHub-native authentication and billing:
# Authenticate with GitHub
npx praxis login
# Initialize cloud connection
npx praxis cloud init
# In your code
import { connectRelay } from "@plures/praxis/cloud";
const relay = await connectRelay("https://praxis-relay.azurewebsites.net", {
appId: "my-app",
authToken: process.env.GITHUB_TOKEN,
autoSync: true
});
// Sync automatically handles CRDT merge
await relay.sync({
type: "delta",
appId: "my-app",
clock: {},
facts: [...],
timestamp: Date.now()
});
See src/cloud/README.md and examples/cloud-sync for details.
import {
createPraxisEngine,
PraxisRegistry,
defineFact,
defineEvent,
defineRule,
} from '@plures/praxis';
// Define the context type
interface AuthContext {
currentUser: string | null;
}
// Define facts and events
const UserLoggedIn = defineFact<'UserLoggedIn', { userId: string }>('UserLoggedIn');
const Login = defineEvent<'LOGIN', { username: string }>('LOGIN');
// Define rules
const loginRule = defineRule<AuthContext>({
id: 'auth.login',
description: 'Process login event',
impl: (state, events) => {
const loginEvent = events.find(Login.is);
if (loginEvent) {
state.context.currentUser = loginEvent.payload.username;
return [UserLoggedIn.create({ userId: loginEvent.payload.username })];
}
return [];
},
});
// Create engine
const registry = new PraxisRegistry<AuthContext>();
registry.registerRule(loginRule);
const engine = createPraxisEngine({
initialContext: { currentUser: null },
registry,
});
// Dispatch events
const result = engine.step([Login.create({ username: 'alice' })]);
console.log(result.state.facts); // [{ tag: "UserLoggedIn", payload: { userId: "alice" } }]
console.log(engine.getContext()); // { currentUser: "alice" }
import { defineConstraint } from '@plures/praxis';
const maxSessionsConstraint = defineConstraint<AuthContext>({
id: 'auth.maxSessions',
description: 'Only one user can be logged in at a time',
impl: (state) => {
return state.context.currentUser === null || 'User already logged in';
},
});
registry.registerConstraint(maxSessionsConstraint);
import { createPraxisStore, createDerivedStore } from '@plures/praxis/svelte';
const stateStore = createPraxisStore(engine);
const userStore = createDerivedStore(engine, (ctx) => ctx.currentUser);
// In Svelte component:
// $: currentUser = $userStore;
// <button on:click={() => stateStore.dispatch([Login.create({ username: "alice" })])}>
// Login
// </button>
<script lang="ts">
import { usePraxisEngine } from '@plures/praxis/svelte';
import { createMyEngine, Login } from './my-engine';
const engine = createMyEngine();
const {
context, // Reactive context
dispatch, // Dispatch events
undo, // Undo last action
redo, // Redo action
canUndo, // Boolean: can undo?
canRedo, // Boolean: can redo?
} = usePraxisEngine(engine, {
enableHistory: true, // Enable undo/redo
maxHistorySize: 50, // Keep last 50 snapshots
});
</script>
<div>
<p>User: {context.currentUser || 'Guest'}</p>
<button onclick={() => dispatch([Login.create({ username: 'alice' })])}>
Login
</button>
<button onclick={undo} disabled={!canUndo}>
β² Undo
</button>
<button onclick={redo} disabled={!canRedo}>
β³ Redo
</button>
</div>
See the Advanced Todo Example for a complete demo with:
For comprehensive guides:
The language-neutral core protocol forms the foundation of Praxis:
// Facts and Events
interface PraxisFact {
tag: string;
payload: unknown;
}
interface PraxisEvent {
tag: string;
payload: unknown;
}
// State
interface PraxisState {
context: unknown;
facts: PraxisFact[];
meta?: Record<string, unknown>;
}
// Step Function (the conceptual core)
type PraxisStepFn = (
state: PraxisState,
events: PraxisEvent[],
config: PraxisStepConfig
) => PraxisStepResult;
This protocol is:
/praxis
βββ core/ # Core framework
β βββ schema/ # Schema system
β β βββ types.ts # Schema type definitions
β βββ logic/ # Logic engine (existing src/core/)
β β βββ protocol.ts # Language-neutral protocol
β β βββ rules.ts # Rules, constraints, and registry
β β βββ engine.ts # LogicEngine implementation
β β βββ actors.ts # Actor system
β β βββ introspection.ts # Introspection and visualization
β βββ component/ # Component generation
β β βββ generator.ts # Svelte component generator
β βββ pluresdb/ # PluresDB integration core
β β βββ adapter.ts # Database adapter interface
β β βββ store.ts # Reactive store implementation
β β βββ schema-registry.ts # Schema registry for PluresDB
β β βββ generator.ts # PluresDB config generator
β βββ runtime/ # Runtime abstractions
βββ cloud/ # Praxis Cloud integration
β βββ auth.ts # GitHub OAuth authentication
β βββ billing.ts # Tier-based billing
β βββ provisioning.ts # Tenant provisioning
β βββ relay/ # Azure relay service
βββ integrations/ # Ecosystem integrations
β βββ pluresdb.ts # PluresDB integration exports
β βββ svelte.ts # Svelte 5 integration
β βββ unum/ # Unum identity and channels
β βββ adp/ # Architectural Decision Protocol
β βββ state-docs/ # State-Docs documentation
β βββ canvas/ # CodeCanvas visual editor
βββ components/ # Svelte components
β βββ TerminalNode.svelte # Terminal node component
βββ cli/ # Command-line interface
β βββ index.ts # CLI entry point
β βββ commands/ # Command implementations
βββ templates/ # Project templates
β βββ basic-app/ # Basic application template
β βββ fullstack-app/ # Full-stack template
βββ examples/ # Example applications
β βββ offline-chat/ # Offline-first chat demo
β βββ knowledge-canvas/ # Knowledge management with Canvas
β βββ distributed-node/ # Self-orchestrating node demo
β βββ terminal-node/ # Terminal node demo
β βββ terminal-canvas/ # Terminal + canvas demo
β βββ cloud-sync/ # Cloud sync demo
β βββ github-monetization/ # GitHub monetization demo
β βββ simple-app/ # Simple app demo
β βββ auth-basic/ # Login/logout example
β βββ cart/ # Shopping cart example
β βββ svelte-counter/ # Svelte integration example
β βββ hero-ecommerce/ # Comprehensive e-commerce demo
βββ docs/ # Framework documentation
βββ guides/ # User guides
β βββ getting-started.md # Getting started guide
β βββ canvas.md # CodeCanvas guide
β βββ orchestration.md # Orchestration guide
βββ api/ # API reference
βββ architecture/ # Architecture documentation
See FRAMEWORK.md for complete architecture documentation.
The repository includes multiple complete examples:
src/examples/hero-ecommerce)Comprehensive example demonstrating all Praxis features in a single application:
npm run build
node dist/examples/hero-ecommerce/index.js
examples/offline-chat)Demonstrates local-first architecture with PluresDB:
See examples/offline-chat/README.md
examples/knowledge-canvas)Showcases CodeCanvas integration for visual knowledge management:
See examples/knowledge-canvas/README.md
examples/distributed-node)Demonstrates distributed orchestration with DSC/MCP:
See examples/distributed-node/README.md
examples/terminal-node)Demonstrates the terminal node feature for command execution:
npm run build
node examples/terminal-node/index.js
See examples/terminal-node/README.md and docs/TERMINAL_NODE.md
src/examples/auth-basic)Login/logout with facts, rules, and constraints.
npm run build
node dist/examples/auth-basic/index.js
src/examples/cart)Shopping cart with multiple rules, constraints, and complex state management.
npm run build
node dist/examples/cart/index.js
src/examples/svelte-counter)Counter example showing Svelte v5 integration with reactive stores.
npm run build
node dist/examples/svelte-counter/index.js
examples/terminal-canvas)Combines terminal nodes with visual canvas features in a Svelte app.
See examples/terminal-canvas/README.md
examples/github-monetization)Example of GitHub-based monetization integration with Praxis Cloud.
See examples/github-monetization/README.md
examples/simple-app)A minimal example demonstrating basic Praxis schema usage.
See examples/simple-app/README.md
examples/cloud-sync)Demonstrates real-time synchronization with Praxis Cloud relay service.
See examples/cloud-sync/README.md
PraxisFact, PraxisEvent, PraxisState - Protocol typesLogicEngine<TContext> - Main engine classPraxisRegistry<TContext> - Rule and constraint registryActor<TContext> - Actor interfaceActorManager<TContext> - Actor lifecycle managementdefineFact<TTag, TPayload>(tag) - Define a typed factdefineEvent<TTag, TPayload>(tag) - Define a typed eventdefineRule<TContext>(options) - Define a ruledefineConstraint<TContext>(options) - Define a constraintdefineModule<TContext>(options) - Bundle rules and constraintsfindEvent(events, definition) - Find first matching eventfindFact(facts, definition) - Find first matching factfilterEvents(events, definition) - Filter events by typefilterFacts(facts, definition) - Filter facts by typeTools for examining and visualizing your Praxis logic:
import { createIntrospector, PRAXIS_PROTOCOL_VERSION } from '@plures/praxis';
const introspector = createIntrospector(registry);
// Get statistics
const stats = introspector.getStats();
console.log(`Rules: ${stats.ruleCount}, Constraints: ${stats.constraintCount}`);
// Generate JSON schema
const schema = introspector.generateSchema(PRAXIS_PROTOCOL_VERSION);
// Generate graph visualization
const graph = introspector.generateGraph();
// Export to Graphviz DOT format
const dot = introspector.exportDOT();
fs.writeFileSync('registry.dot', dot);
// Export to Mermaid format
const mermaid = introspector.exportMermaid();
// Search rules and constraints
const authRules = introspector.searchRules('auth');
const maxConstraints = introspector.searchConstraints('max');
Available methods:
getStats() - Get registry statisticsgenerateSchema(protocolVersion) - Generate JSON schemagenerateGraph() - Generate graph representationexportDOT() - Export to Graphviz DOT formatexportMermaid() - Export to Mermaid diagram formatgetRuleInfo(id) - Get detailed rule informationgetConstraintInfo(id) - Get detailed constraint informationsearchRules(query) - Search rules by textsearchConstraints(query) - Search constraints by textPraxis integrates with the full Plures ecosystem:
Local-first reactive datastore for offline-capable applications. Now fully implemented with 32 tests covering all features.
import {
createInMemoryDB,
createPraxisDBStore,
createPluresDBAdapter,
attachToEngine,
} from '@plures/praxis/pluresdb';
// Create an in-memory database
const db = createInMemoryDB();
// Create a PraxisDB store for facts and events
const store = createPraxisDBStore({ db });
// Or create an adapter to attach to an engine
const adapter = createPluresDBAdapter({
db,
registry,
initialContext: {},
});
// Attach adapter to engine for automatic persistence
adapter.attachEngine(engine);
// Persist facts and events
await adapter.persistFacts([{ tag: 'UserLoggedIn', payload: { userId: 'alice' } }]);
await adapter.persistEvents([{ tag: 'LOGIN', payload: { username: 'alice' } }]);
// Subscribe to changes
adapter.subscribeToEvents((events) => {
console.log('New events:', events);
});
Features:
Status: β
Available (src/core/pluresdb/, src/integrations/pluresdb.ts)
Tests: 32 tests covering adapter, store, registry, and engine integration
Identity and channels for distributed systems.
import { createUnumIdentity, createChannel } from '@plures/unum';
// Create identity
const identity = await createUnumIdentity({
name: 'my-app-node',
keys: await generateKeys(),
});
// Create channel for messaging
const channel = await createChannel({
name: 'app-events',
participants: [identity.id],
});
// Integrate with Praxis actors
const unumActor = createActor('unum-bridge', identity, async (event) => {
// Bridge Praxis events to Unum channels
await channel.publish(event);
});
Status: Planned
Use Cases: Distributed messaging, identity management, authentication
Architectural Decision Protocol for guardrails and governance.
import { createADP } from '@plures/adp';
// Track architectural decisions from schemas
const adp = createADP({
source: 'praxis-schema',
decisions: [
{
id: 'ADR-001',
title: 'Use PluresDB for local-first storage',
context: 'Need offline-capable data storage',
decision: 'Adopt PluresDB',
consequences: ['Offline support', 'Sync complexity'],
},
],
});
// Enforce guardrails
adp.enforce({
rule: 'no-direct-database-access',
check: (code) => !code.includes('direct-sql'),
});
Status: Planned
Use Cases: Architecture documentation, compliance checking, guardrails
Living documentation generated from Praxis schemas.
import { generateStateDocs } from '@plures/state-docs';
// Generate documentation from schema
const docs = await generateStateDocs({
schema: appSchema,
logic: logicDefinitions,
components: componentDefinitions,
output: './docs',
format: 'markdown', // or 'html', 'pdf'
});
// Documentation includes:
// - Data model diagrams
// - Logic flow diagrams
// - Component catalog
// - API reference
// - Usage examples
Status: Planned
Documentation: See examples for State-Docs integration patterns
Visual IDE for schema and logic editing.
# Open Canvas for visual editing
praxis canvas src/schemas/app.schema.ts
# Features:
# - Visual schema design
# - Logic flow editor
# - Component preview
# - Real-time collaboration
# - Export to code
Status: Planned
Documentation: docs/guides/canvas.md
Cross-platform runtime for web, desktop, and mobile.
// Svelte v5 integration (available now)
import { createPraxisStore } from '@plures/praxis/svelte';
const stateStore = createPraxisStore(engine);
const userStore = createDerivedStore(engine, (ctx) => ctx.currentUser);
// In Svelte component:
// $: currentUser = $userStore;
// Desktop app with Tauri
npm run tauri:dev // Development
npm run tauri:build // Production
Status: Svelte integration available, Tauri templates planned
Platform Support: Web (now), Desktop (planned), Mobile (future)
Full PowerShell adapter for using Praxis from PowerShell scripts:
# Import module
Import-Module ./powershell/Praxis.psm1
# Initialize adapter
Initialize-PraxisAdapter -EnginePath "./dist/adapters/cli.js"
# Create state and events
$state = New-PraxisState -Context @{ count = 0 }
$event = New-PraxisEvent -Tag "INCREMENT" -Payload @{}
# Process step
$result = Invoke-PraxisStep -State $state -Events @($event) -ConfigPath "./config.json"
# Use result
Write-Host "Count: $($result.state.context.count)"
See powershell/README.md for complete documentation and examples.
Full C# implementation with functional, immutable design:
using Praxis.Core;
using Praxis.Dsl;
// Define facts and events
var UserLoggedIn = PraxisDsl.DefineFact<UserPayload>("UserLoggedIn");
var Login = PraxisDsl.DefineEvent<LoginPayload>("LOGIN");
record UserPayload(string UserId);
record LoginPayload(string Username);
// Define rules
var loginRule = PraxisDsl.DefineRule<AuthContext>(
id: "auth.login",
description: "Process login event",
impl: (state, context, events) =>
{
var loginEvent = events.FindEvent(Login);
if (loginEvent != null)
{
var payload = Login.GetPayload(loginEvent);
return [UserLoggedIn.Create(new UserPayload(payload?.Username ?? "unknown"))];
}
return [];
});
// Create engine
var registry = new PraxisRegistry<AuthContext>();
registry.RegisterRule(loginRule);
var engine = PraxisEngine.Create(new PraxisEngineOptions<AuthContext>
{
InitialContext = new AuthContext(null),
Registry = registry
});
// Dispatch events
var result = engine.Step([Login.Create(new LoginPayload("alice"))]);
Console.WriteLine($"Facts: {result.State.Facts.Count}"); // Facts: 1
See csharp/Praxis/README.md for complete documentation.
The core protocol is implemented across multiple languages:
TypeScript (Primary, npm: @plures/praxis)
import { createPraxisEngine, PraxisRegistry } from '@plures/praxis';
const engine = createPraxisEngine({
initialContext: {},
registry: new PraxisRegistry(),
});
const result = engine.step(events);
C# (.NET 8+, NuGet: Plures.Praxis)
var engine = PraxisEngine.Create(new PraxisEngineOptions<TContext> { ... });
var result = engine.Step(events);
See csharp/Praxis/README.md for full documentation.
PowerShell (GitHub: Praxis.psm1)
$newState = Invoke-PraxisStep -State $state -Events $events
See powershell/README.md for full documentation.
All implementations share the same protocol version and JSON format for interoperability. See CROSS_LANGUAGE_SYNC.md for details on keeping implementations in sync.
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Type check
npm run typecheck
# Run with Deno
deno task dev
# Run tests
deno task test
# Lint and format
deno task lint
deno task fmt
For more detailed development information, see CONTRIBUTING.md.
MIT License - see LICENSE for details.
Contributions are welcome! Please read our Contributing Guide to get started.
Please review our Code of Conduct before participating.
Praxis β Because application logic should be practical, provable, and portable.
Built with β€οΈ by the plures team