惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
The GitHub Blog
The GitHub Blog
美团技术团队
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Register - Security
The Register - Security
Stack Overflow Blog
Stack Overflow Blog
Attack and Defense Labs
Attack and Defense Labs
G
Google Developers Blog
I
InfoQ
博客园 - 司徒正美
T
Troy Hunt's Blog
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
S
Security Affairs
M
MIT News - Artificial intelligence
Simon Willison's Weblog
Simon Willison's Weblog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Tailwind CSS Blog
量子位
Vercel News
Vercel News
月光博客
月光博客
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LangChain Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 最新话题
F
Full Disclosure
The Hacker News
The Hacker News
Hacker News: Ask HN
Hacker News: Ask HN
T
Tor Project blog
A
Arctic Wolf
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Forbes - Security
Forbes - Security
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
GbyAI
GbyAI
B
Blog RSS Feed
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Design Principles of nop-chaos-flux, a Next-Generation Low-Code Rendering Framework
canonical · 2026-05-19 · via DEV Community

Introduction

nop-chaos-flux is the rendering layer of the Nop platform—a low‑code runtime driven by declarative DSLs, designed to render and execute application pages described by Schema in the browser. Its DSL surface syntax resembles that of Baidu AMIS, but achieves conceptual unification (e.g., eliminating the xxxOn suffix family). Its internal compilation model, runtime architecture, and expression engine have all been redesigned.

Most low‑code platforms treat the Schema as the runtime input configuration. The runtime then simultaneously carries authoring‑time structures, domain semantics, and scheduling logic. Every new capability adds another set of primitives, a new global provider, another authoritative Schema channel, and the core keeps bloating.

Flux starts from a different path: elevating the DSL from a runtime input format to an independent, first‑class structural layer.

1. DSL First

The DSL is not an input format fed to the runtime; it is a first‑class artifact of the platform: an independent, operable structural layer. Before ever entering the runtime, it already possesses its own lifecycle, transformation space, and organization rules.

Many systems have a DSL, but it is only used as a runtime input format—there is no independent structural manipulation. Flux does not see it that way. Flux’s DSL is a structural layer that can be edited, composed, trimmed, and transformed even outside the runtime:

Operation Meaning
Edit Source location retention, aliases, editor metadata, round‑trip fidelity
Merge / Inherit x:extends inheritance, override expansion, fragment composition
Trim Permission trimming, feature flag trimming, profile assembly
Transform i18n string replacement, static default expansion
Meta‑programming Express variations through structural conventions (not by growing runtime interfaces)

DSL transformations are layered: permission trimming, i18n replacement, and default expansion each operate independently. Removing authoring‑time metadata must not change runtime behavior.


2. Authoring–Execution Separation

Even when adopting a DSL‑first approach, many systems still maintain only one model, forcing the runtime to directly carry authoring‑time structures. Flux deliberately does not do this. Instead, it places the Authoring Model and the Execution Model on opposite sides of a pre‑compilation boundary.

The point of this principle is not “having two models” per se, but acknowledging that the two sides have different optimisation goals: authoring time serves understanding, editing, composition, and fidelity; execution time serves conceptual simplification, reduced runtime overhead, and stable execution semantics.

Two‑sided optimisation goals

Aspect Authoring Model Execution Model
Optimisation goal Understandability, domain expressiveness, editing fidelity Performance, unified internal concepts, minimal runtime overhead
Structural form Retains source location, aliases, editor metadata, domain‑specific edit structures Final assembled Execution Schema, no redundancy
Correctness Round‑trip fidelity, author intent never lost Behavioural equivalence, deterministic execution
Replaceability Many editors/designers/collaborative engines can produce the same DSL The same Final Execution Schema can execute on different runtime hosts

Significance of the boundary

The pre‑compilation boundary means more than “do some optimisation early”. It ensures that structural problems that should never land on the runtime surface are resolved at the structural layer:

  1. Compile‑time structural decisions — type resolution, renderer binding, default expansion are done during the loading phase; runtime overhead is zero.
  2. Compile‑time policy trimming — permission nodes, feature flag branches are removed before entering the runtime; the runtime never sees them.
  3. Compile‑time action DAG assemblythen / onError / parallel are assembled at compile time into a cycle‑free execution graph; no graph discovery or cycle detection at runtime.
  4. Unified Value IR — All forms of Value (literal/expression/template/array/object) are compiled into a unified IR; evaluation is unified at runtime.

If a problem can be solved at the structural transformation layer, it must never be dragged onto the runtime surface.


3. Reactive Data‑Driven

Flux’s core execution model is reactive and declarative. The author does not need to explicitly build imperative linkage logic: whenever a dynamic value reads a path from the scope via a field path, name, or ${expr}, it automatically falls into the dependency graph and will be re‑evaluated when the dependency changes.

Basic rhythm: evaluate → collect dependencies → propagate changes → targeted re‑evaluation / invalidation → republish.

Dependency tracking is a built‑in design semantic of the Value primitive. Dependencies are automatically collected during evaluation, not declared statically beforehand. Value, Resource, and Reaction all use this mechanism, but with different consequences: Value is re‑evaluated, Resource is marked dirty and refreshed, a Reaction may trigger a Capability.

The current implementation uses React and useSyncExternalStore to interface with the rendering host, but the principle itself is not tied to any UI framework.

Read/Write and Effect Separation

  • Read: Value / Resource published values / Host Projection snapshots are all read‑only via ScopeRef.
  • Write: User edits, FormRuntime.setValue, ScopeRef.update, Resource publication—these modify owner‑owned data and belong to the data owner side; they will publish store/scope changes, but that is not equivalent to triggering an action.
  • Command / Effect: Schema‑authored commands (API calls, setValue action, submission, navigation, host commands, etc.) are dispatched only through Capability.
  • Change → Effect: Data changes do not directly trigger actions; they must pass through a Reaction or a Semantic Lifecycle Entry.

Rendering Host Interfacing

The Store layer runs the reactive logic self‑consistently; React is merely a rendering host that subscribes to Store snapshots.

  • Settled Update Turn is a runtime‑store concept, not a React useEffect ordering concept.
  • React concurrent mode can interrupt, replay, and discard renders; Flux does not constrain such scheduling behaviour—it only defines when the store settles an update turn and when a stable snapshot is published.
  • The rendering host consumes the published results; it does not directly hold reactive protocol objects.

4. Gradual Evolution

Complex capabilities in Flux should not be obtained by continually inventing new primitives; they should grow naturally from simpler existing forms. This principle constrains two things at the same time:

  • The author‑visible DSL naturally extends from simple forms to complex forms without frequent mental model switches.
  • Complex capabilities inside the runtime should be composed from existing primitives (derived system) as much as possible, instead of expanding the primitive set under pressure.

DSL‑level evolution: natural growth from simple forms

Concept Simple form Complex form
Value literal → expression → anonymous source named data-source (Resource)
Action single‑step dispatch when guard → then/onError branches → parallel fan‑out → compilable to DAG execution graph
Structure visible (display level) when (lifecycle activation) → loop (collection expansion) → dynamic-renderer (remote assembly)
Host write semantic command generic patch‑style applyPatch

Value evolution

The same property chooses the appropriate form based on complexity. How the consumer reads the value stays the same: ${countries} remains uniform from literal to data‑source.

// literal
{ "options": ["draft", "published", "archived"] }

// expression
{ "options": "${role === 'admin' ? adminOptions : userOptions}" }

// source: field‑level anonymous request, not published to scope
{ "options": {
  "type": "source",
  "action": "ajax",
  "args": { "url": "/api/countries", "params": { "region": "${form.region}" } }
}}

// data-source: named Resource with producer lifecycle & scheduling policy
{ "type": "data-source", "name": "countries",
  "action": "ajax",
  "args": { "url": "/api/countries" },
  "interval": 3000,
  "stopWhen": "${countries.complete}" }

Enter fullscreen mode Exit fullscreen mode

Action evolution

The compiler recursively assembles nested schemas into a CompiledActionNode DAG (flux-compiler/action-compiler.ts). The runtime simply traverses edges to execute; no graph discovery or cycle detection is needed.

// single-step dispatch
{ "action": "setValue", "args": { "path": "name", "value": "test" } }

// when guard: skip if condition not met, result marked skipped
{ "action": "setValue", "when": "${isEnabled}",
  "args": { "path": "name", "value": "test" } }

// then/onError branches: different paths based on ActionResult triage
{ "action": "ajax", "args": { "url": "/api/users" },
  "then":     { "action": "showToast", "args": { "message": "Save successful" } },
  "onError":  { "action": "showToast", "args": { "message": "${error.message}" } } }

// parallel fan-out + onSettled aggregation
{ "action": "parallel",
  "parallel": [
    { "action": "ajax", "args": { "url": "/api/notify/email" } },
    { "action": "ajax", "args": { "url": "/api/notify/sms" } }
  ],
  "onSettled": { "action": "showToast", "args": { "message": "Notifications complete" } } }

// form submission: submitAction owned by the form node; button is only a thin component:submit trigger
{ "type": "form", "id": "profile-form",
  "submitAction": {
    "action": "ajax", "args": { "url": "/api/profile", "method": "post" } },
  "onSubmitSuccess": { "action": "closeSurface" },
  "onSubmitError":   { "action": "showToast", "args": { "message": "${error.message}" } } }

Enter fullscreen mode Exit fullscreen mode

Branch contexts (result / error / prevResult) are automatically injected into the evaluation environment during dispatching (flux-action-core/action-core.ts createBranchEvaluationBindings).

Structure evolution

visible and when are not synonyms: fields hidden by visible still participate in validation; subtrees with when=false are entirely inactive and do not participate in the lifecycle.

// visible: display‑level toggle, node still exists
{ "type": "input-text", "name": "adminCode", "visible": "${role === 'admin'}" }

// when: lifecycle activation, affects existence and subtree validation
{ "type": "fragment", "when": "${showSummary}",
  "body": [{ "type": "text", "text": "Summary content" }] }

// loop: collection expansion, each iteration gets its own repeated‑item scope
{ "type": "loop", "items": "${users}", "itemName": "user", "indexName": "idx",
  "body": [{ "type": "text", "text": "${idx + 1}. ${user.name}" }],
  "empty": [{ "type": "text", "text": "No data" }] }

// dynamic-renderer: runtime remote assembly, decides which fragment to render
// Note: it is not a second Resource facet — data‑source produces named values, dynamic‑renderer assembles fragments
{ "type": "dynamic-renderer",
  "loadAction": { "action": "ajax", "args": { "url": "/api/schema/${componentType}" } },
  "body": { "type": "text", "text": "Loading..." } }

Enter fullscreen mode Exit fullscreen mode


5. Lexical Ownership

This principle is an organisational constraint for Principle 3. Data, capabilities, resources, reactions, and runtime sidecars belong to the lexical scope or subtree boundary; they are not held by a global runtime mega‑object.

Three resolution mechanisms

Data lookup (ScopeRef), action lookup (ActionScope), and instance location (ComponentHandleRegistry) are architecturally separate resolution mechanisms, each with its own scoping rules.

Lexical shadowing

Child scopes override parent publications through natural lexical shadowing, not global overrides. Bindings with the same name can independently exist in different lexical scopes:

// page scope has items
{
  "type": "page",
  "data": { "items": ["a", "b"] },
  "body": [
    // dialog child scope also has items, shadows parent
    {
      "type": "dialog",
      "data": { "items": ["x", "y"] },
      "body": [{ "type": "text", "text": "${items}" }],
    }, // → ["x", "y"]
  ],
}

Enter fullscreen mode Exit fullscreen mode

Resource publication ownership

Within the same owning scope, the same binding target should not be long‑term co‑occupied by two simultaneously active publishing producers. This constraint applies to authoritative publication (continuous publication by a Resource), not ordinary writes:

// compliant: two forms write to the same path at different times
{ "type": "dialog", "body": [
  { "type": "form", "id": "createForm",
    "onSubmitSuccess": { "action": "setValue", "args": { "path": "result", "value": "${result}" } } },
  { "type": "form", "id": "editForm",
    "onSubmitSuccess": { "action": "setValue", "args": { "path": "result", "value": "${result}" } } }
]}

// violation: two data‑sources simultaneously claim to publish "status"
{ "type": "page", "body": [
  { "type": "data-source", "name": "status", "action": "ajax", "args": { "url": "/api/a" } },
  { "type": "data-source", "name": "status", "action": "ajax", "args": { "url": "/api/b" } }
]}

Enter fullscreen mode Exit fullscreen mode

Runtime sidecars (Resource state, Reaction state, caches, diagnostics) follow lexical ownership, but they must not become methods or mutable protocol objects attached to a ScopeRef. The Scope hosts the data environment; it does not carry bridges, controllers, handles, or other command‑like objects.


6. Domain Isolation & Abstraction

The Flux core maintains a small, stable abstraction layer. Its goal is not to absorb all frontend domain semantics, but to provide a sufficiently stable execution kernel that allows different domains to grow outside the core.

The litmus test for this principle is not “can the core directly describe all complex systems?” but “can the core provide a stable embedding surface for complex systems without pushing domain complexity back into the core vocabulary?”

Isolation contract

Interactions between domain systems (Flow Designer, Report Designer, Spreadsheet Editor, collaborative engines, CRDT/OT, etc.) and the Flux core are narrowed down to:

Direction Mechanism Meaning
Core → Domain (read) Host Projection Read‑only snapshot projection, host‑driven refresh
Domain → Core (write) Capability Namespaced command dispatch (e.g., designer:*)
Instance location ComponentHandleRegistry Explicit target component instance method invocation
Host‑private DomainBridge getSnapshot/subscribe/dispatch, does NOT enter Schema‑visible Scope

Why the core stays stable

  • Graph algorithms, layout, collision detection, collaboration protocols, CRDT/OT, local‑first sync, gesture loops—these are all important, but they are domain systems and should not become core primitives. From Flux’s perspective, they are just production strategies behind a Resource, host snapshots behind a Host Projection, or command systems behind a Capability.
  • New domains plug in by declaring a host type + projection fields + capability namespace, without needing to introduce new global provider families, environment registries, or new authoritative Schema channels.
  • Cross‑domain generic write pattern for editable hosts: read Host Projection → write Capability (structured patch DTO) → DomainBridge host‑private.

Business semantics ownership

Business pipelines (form submission, dialog confirmation, page entry) belong to the node that owns that lifecycle boundary, not to the UI trigger. Concrete examples are given in Section 4 (Semantic Lifecycle Entry). This is a concrete manifestation of lexical ownership and domain isolation.


Summary

# Principle One‑liner
1 DSL First The DSL is a first‑class structural layer independent of the runtime: editable, composable, and transformable before execution.
2 Authoring–Execution Separation Authoring and execution serve different optimisation goals; they should be separated by a pre‑compilation boundary, not mixed in the runtime.
3 Reactive Data‑Driven The Value primitive has built‑in dependency tracking, read/write separation, and side effects are funnelled through Capability.
4 Gradual Evolution Complexity should grow naturally from simple DSL forms and existing primitives, not by expanding the primitive set under pressure.
5 Lexical Ownership Data, capabilities, resources, reactions, and their sidecars belong to lexical/subtree boundaries, not to a global runtime mega‑object.
6 Domain Isolation & Abstraction The core provides a small, stable execution kernel; domain complexity stays outside the core and embeds through a narrow contract.

nop-chaos-flux is open source: