A web-based visual modeling and simulation tool that enables users to construct, test, and simulate block diagram models directly in the browser, then generate C code for embedded deployment.
Important Note: This project was almost entirely generated using Claude Opus and Sonnet 4 LLMs. It is an exploration of how LLMs might help humans generate - the code this application generates and the overall security of the application have not been formally verified. In short, you'd be crazy to try to use this application for anything other than research.
obliq-2 is a browser-based application, designed for creating and simulating visual block diagram models. Users can drag and drop various block types onto a canvas, connect them with wires to define signal flow, run simulations to see how signals propagate through the system, and generate PlatformIO-compatible C code for deployment on embedded systems.
- Drag-and-drop interface for building block diagrams
- Multiple block types including:
- Mathematical operations (Sum, Multiply, Matrix Multiply, Scale, Trig functions, Vector functions, general math expressions)
- Dynamic systems (Integrators and Laplace Transfer Functions)
- Data operations (1D/2D Lookup Tables)
- Visualization (Signal Display with plotting)
- Signal generation (Source blocks for constants and generators)
- Hierarchical composition (Subsystem blocks)
- Conditional Signal Flow Control
- Signal type conversion
- Support for C-style data types:
float,double,long,bool - 1D vector and 2D matrix support (e.g.,
double[3],float[3][3]) - Automatic type propagation through connections
- Type validation with visual error indicators
| Block Type | Display Name | Category | Description |
|---|---|---|---|
source |
Source | Sources | Provides constant or signal generator output (step, ramp, sine, chirp, noise) |
clock |
Clock | Sources | Outputs current simulation time in seconds as a double scalar |
input_port |
Input Port | Ports | External input to a model or subsystem |
output_port |
Output Port | Ports | External output from a model or subsystem |
sum |
Sum | Math | Sums multiple input signals with configurable signs (+/-) |
multiply |
Multiply | Math | Element-wise multiplication of multiple input signals |
scale |
Scale | Math | Multiplies input by a scalar constant (gain) |
abs |
Absolute Value | Math | Absolute value of scalar input |
uminus |
Unary Minus | Math | Negates input (element-wise for vectors/matrices) |
limit |
Limit | Math | Clamps signal values to specified upper/lower range |
evaluate |
Evaluate | Math | Evaluates custom C-style expression with multiple inputs |
trig |
Trig | Math | Trigonometric functions (sin, cos, tan, asin, acos, atan, atan2) |
transfer_function |
Transfer Function | Dynamic | Laplace transfer function with RK4 integration |
discrete_transform |
Discrete Transform | Dynamic | Discrete-time z-transform transfer function |
integrator |
Integrator | Dynamic | Integrator block (1/s) with optional limits and reset |
lookup_1d |
1-D Lookup | Lookup | 1-D lookup table with linear interpolation |
lookup_2d |
2-D Lookup | Lookup | 2-D lookup table with bilinear interpolation |
matrix_multiply |
Matrix Multiply | Matrix | Matrix multiplication (A×B) or scalar multiplication |
transpose |
Transpose | Matrix | Matrix transpose; vectors [n] become [n][1] matrices |
mux |
Mux | Matrix | Multiplexer: combines scalars into vector or matrix |
demux |
Demux | Matrix | Demultiplexer: splits matrix/vector into scalar outputs |
cross |
Cross Product | Vector | 3D vector cross product (A × B) |
dot |
Dot Product | Vector | Vector dot product (A · B) |
mag |
Magnitude | Vector | Vector magnitude (Euclidean norm) |
if |
If | Control | Conditional selection based on control signal |
condition |
Condition | Control | Compares input against constant (>, <, >=, <=, ==, !=) |
subsystem |
Subsystem | Hierarchical | Encapsulates another sheet as a reusable block |
signal_display |
Signal Display | Sinks | Real-time signal visualization during simulation |
signal_logger |
Signal Logger | Sinks | Logs signal values for CSV export |
no_connection |
No Connection | Sinks | Marks a signal as intentionally unused |
sheet_label_sink |
Sheet Label Sink | Sheet Labels | Receives signal for wireless routing within a sheet |
sheet_label_source |
Sheet Label Source | Sheet Labels | Outputs signal from corresponding sheet label sink |
orientation_conversion |
Orientation Conversion | Aerospace | Converts between Euler angles, DCM, and Quaternion (AIAA convention) |
units_conversion |
Units Conversion | Aerospace | Converts between SI and Imperial units |
body2quaternion_rates |
Body2Quat Rates | Aerospace | Converts body angular rates to quaternion rates |
comment |
Comment | Annotation | Text annotation with Markdown and LaTeX math support |
- Client-side simulation - Models are compiled dynamically and executed as Web Assemblies
- Real-time signal visualization with Recharts
- Configurable time steps, duration, and integration methods
- Signal logging with CSV export capability
- Support for both continuous and discrete-time systems
- PlatformIO-compatible C code generation
- Preserves signal and block names for readable code
- Generates structured APIs with input/output/state structs
- Support for Runge-Kutta 4th order or Euler integration in generated code
- User authentication via Supabase
- Isolated model storage per user
- Auto-save functionality every 5 minutes
- Model management dashboard
- RESTful API for CI/CD integration and model building
- Supports construction, automated validation, simulation, and code generation
- Token-based authentication for external systems
- per-user API Key management
- Includes an MCP server capable of interacting with these APIs
- Frontend: Mantine, Next.js (App Router), React, ReactFlow, TypeScript
- Backend: Next.js API Routes (serverless functions)
- Database: Supabase (PostgreSQL with JSONB for model storage)
- Authentication: Supabase Auth
- State Management: Zustand
- Visualization: Recharts for signal charting
- Code Generation: Server-side TypeScript to C transpilation
- Model Compilation: Custom Docker image with gcc and WASM tooling
- Node.js 20+ and npm/yarn
- Supabase account (or local Supabase instance)
- Docker Desktop
- Clone the repository:
git clone https://github.com/rrainey/obliq-2.git
cd obliq-2- Install dependencies:
npm install
# or
yarn install- Set up environment variables:
Create a
.env.localfile in the project root:
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
# Automation API Token (generate a secure token)
AUTOMATION_API_TOKEN=your_secure_automation_token- Set up the database: In your Supabase project, create the models table:
CREATE TABLE models (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
data JSONB NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Enable Row Level Security
ALTER TABLE models ENABLE ROW LEVEL SECURITY;
-- Create policy for users to manage their own models
CREATE POLICY "Users can manage their own models" ON models
FOR ALL USING (auth.uid() = user_id);- Start the development server:
npx supabase start -x vector
# then,
npm run dev
# or
yarn dev- Open your browser and navigate to:
http://localhost:3000
- Create an account or log in to start building models.
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Build for production
npm run build
# Start production server
npm start
# Run linter
npm run lintobliq-2/
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── api/
│ │ │ ├── automations/ # Automation API (CI/CD, external triggers)
│ │ │ ├── compile-wasm/ # WASM compilation endpoint
│ │ │ ├── compile-wasm-stream/ # SSE-based WASM compilation
│ │ │ ├── generate-code/ # C code generation endpoint
│ │ │ ├── model-builder/ # Model Builder API (programmatic model construction)
│ │ │ └── tokens/ # API token management
│ │ ├── admin/ # Admin pages (API metrics)
│ │ ├── login/ # Authentication page
│ │ ├── models/ # Model editor and dashboard
│ │ └── tokens/ # Token management UI
│ │
│ ├── components/ # React components
│ │ ├── BlockNode.tsx # Main block rendering component
│ │ ├── CanvasReactFlow.tsx # ReactFlow canvas wrapper
│ │ ├── BlockLibrarySidebar.tsx # Drag-and-drop block palette
│ │ ├── SignalDisplay.tsx # Real-time signal visualization
│ │ ├── SimulationDisplayPanel.tsx
│ │ ├── *Config.tsx # Block configuration dialogs
│ │ └── ...
│ │
│ ├── lib/
│ │ ├── blocks/ # Block module implementations
│ │ │ ├── BlockModule.ts # Base block interface
│ │ │ ├── BlockModuleFactory.ts # Factory for creating block modules
│ │ │ └── *BlockModule.ts # Individual block implementations
│ │ │
│ │ ├── codegen/ # C code generation pipeline
│ │ │ ├── CodeGenerator.ts # Main code generator orchestrator
│ │ │ ├── ModelFlattener.ts # Flattens hierarchical models
│ │ │ ├── AlgebraicEvaluator.ts # Topological sort and evaluation order
│ │ │ ├── StateIntegrator.ts # RK4 integration code generation
│ │ │ ├── HeaderGenerator.ts # Header file generation
│ │ │ ├── SubsystemCodeGenerator.ts # Segregated subsystem support
│ │ │ └── ...
│ │ │
│ │ ├── simulation/ # Browser-side simulation engine
│ │ │ ├── WasmSimulationEngine.ts # WASM-based simulation
│ │ │ ├── SimulationWorker.ts # Web Worker for off-main-thread
│ │ │ ├── SimulationWorkerManager.ts # Worker lifecycle management
│ │ │ └── SimulationEngineFactory.ts # Factory for engine creation
│ │ │
│ │ ├── wasm/ # WebAssembly infrastructure
│ │ │ ├── ServerWasmExecutor.ts # Server-side WASM execution
│ │ │ ├── WasmErrorParser.ts # Emscripten error parsing
│ │ │ ├── cache/ # WASM module caching (Supabase Storage)
│ │ │ └── codegen/ # WASM-specific code generation
│ │ │
│ │ ├── blockTypeRegistry.ts # Block type definitions and metadata
│ │ ├── blockFactory.ts # Unified block creation
│ │ ├── blockParameterValidator.ts # Parameter validation/sanitization
│ │ ├── modelStore.ts # Zustand state management
│ │ ├── signalTypePropagation.ts # Type inference through connections
│ │ ├── connectionValidation.ts # Wire validation logic
│ │ ├── c99Expression*.ts # C99 expression parser/evaluator
│ │ └── ...
│ │
│ ├── hooks/ # React hooks
│ └── types/ # TypeScript type definitions
│
├── mcp-server/ # MCP Server (Model Context Protocol)
│ └── src/
│ ├── index.ts # Server entry point (STDIO + HTTP modes)
│ ├── tools/
│ │ ├── model-management.ts # create_model, get_model, list_models
│ │ ├── model-construction.ts # add_block, add_connection, etc.
│ │ ├── block-types.ts # list_block_types (parameter discovery)
│ │ ├── simulation.ts # run_simulation
│ │ ├── code-generation.ts # generate_code
│ │ ├── validation.ts # validate_model
│ │ └── batch-operations.ts # batch_execute
│ ├── modelBuilderClient.ts # Model Builder API client
│ └── client.ts # Automation API client
│
├── __tests__/ # Test suites
│ ├── blocks/ # Block module unit tests
│ ├── codegen/ # Code generation tests
│ ├── simulation/ # Simulation engine tests
│ ├── wasm/ # WASM compilation and execution tests
│ ├── integration/ # Integration tests (Docker/PlatformIO)
│ └── utils/ # Test utilities (TestModelBuilder, etc.)
│
├── design/ # Architecture documentation
│ └── 00-architecture.md # Comprehensive system architecture
│
├── docs/ # API documentation
│ ├── automation-api.md
│ ├── model-builder-api.md
│ └── wasm-*.md # WASM documentation
│
├── examples/ # Example scripts
│ └── model-builder-api/ # API usage examples
│
└── database-scripts/ # Supabase SQL setup
The project includes comprehensive test suites for both the simulation engine and C code generation.
Run the standard test suite:
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverageThe C code generation tests use Docker to ensure consistent compilation environments. These tests:
- Generate C code from test models
- Compile the generated code using PlatformIO in a Docker container
- Execute the compiled binaries to verify correctness
- Docker: Ensure Docker is installed and running on your system
- Docker Desktop for Windows/Mac
- Docker Engine for Linux
Obliq-2 leverages Docker to compile and link a simulation model for execution. Thee compiled Web Assenblies are cached in Supabase.
- Initial Setup: The test suite will automatically build the required Docker image on first run
# Run C code generation and compilation tests
npm run test:codegen
# Run with verbose output
npm run test:codegen -- --verboseNEW: The project now supports compiling models to WebAssembly for high-performance browser simulation.
WASM tests verify that:
- C code can be compiled to WebAssembly using Emscripten
- WASM modules load and execute correctly in both Node.js and browsers
- Generated models produce identical results when run as WASM
# Build Emscripten Docker image (first time only)
npm run wasm:build-docker
# Run all WASM tests
npm run test:wasm
# Run specific WASM test suites
npm run test:wasm:setup # Basic Emscripten setup
npm run test:wasm:model # Full model compilationSee __tests__/wasm/QUICKSTART.md for a step-by-step verification guide.
Documentation:
- Quick Start:
__tests__/wasm/QUICKSTART.md - Full Documentation:
__tests__/wasm/README.md - Architecture:
docs/wasm-simulation-architecture_1.md - Implementation Roadmap:
docs/wasm-implementation-roadmap.md
The tests will:
- Build a Docker image with PlatformIO if not already present
- Generate C code for various test models
- Create proper PlatformIO library structures
- Compile the generated code in isolated Docker containers
- Execute the compiled programs and verify outputs
Test models are stored in __tests__/integration/code-generation/models/ as JSON files. Each model can include:
metadata.testInputs: Input values for testingmetadata.expectedOutput: Expected output for validationmetadata.description: Test case description
If tests fail:
- Check Docker is running:
docker --version - Verify the Docker image exists:
docker images | grep platformio-test - Check test output for compilation errors
- Create a Model: Click "New Model" from the dashboard
- Build Your Diagram: Drag blocks from the library and connect them with wires
- Configure Blocks: Click blocks to set parameters (e.g., transfer function coefficients)
- Run Simulation: Click "Run Simulation" to see signals propagate in real-time
- Generate Code: Click "Generate C Code" to download a PlatformIO-compatible library
- Export Data: Use Signal Logger blocks to capture and export simulation data
This project is covered by the MIT License.
This project was almost entirely generated using Claude Opus, demonstrating the capabilities of large language models in software development.
