Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

803 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenHW Studio — React Frontend

The interactive web-based UI for the OpenHW Studio electronics simulation platform. Built with React + Vite, it renders a drag-and-drop circuit editor, streams live simulation state from the emulator, and drives Wokwi web components in real time.


Table of Contents


Overview

OpenHW Studio Frontend is the visual client of the simulator platform. It allows users to:

  • Design circuits by placing and wiring components on a canvas
  • Write and edit Arduino C++ code in a built-in syntax-highlighted editor
  • Compile and run simulations powered by the backend compiler and the in-browser Web Worker emulator
  • Watch simulation output in real time (LEDs blinking, NeoPixels lighting up, servo movement, etc.)
  • Save and load projects locally — guests included — using IndexedDB

It connects to one backend service:

  • Compiler Backend (http://localhost:5001) — compiles C++ code to .hex

The simulation itself runs entirely in the browser via a Web Worker powered by avr8js.


Tech Stack

Technology Purpose
React 18 UI framework
Vite 5 Build tool and dev server
React Router DOM Client-side routing
Axios HTTP requests to compiler backend
avr8js AVR CPU emulation (used in Web Worker)
intel-hex Parsing .hex firmware files
Prism.js Syntax highlighting in code editor
react-simple-code-editor Embedded code editor component
@react-oauth/google Google OAuth login
jwt-decode Decoding JWT auth tokens
@openhw/emulator Shared component definitions (workspace package)
JSZip Client-side ZIP extraction for custom components
@babel/standalone In-browser transpilation of custom component TypeScript/JSX
IndexedDB (native) Project persistence, hex cache, offline upload queue
Service Worker (native) App shell caching for offline support

Project Structure

OpenHW-studio-frontend/
├── index.html                  # App entry HTML
├── vite.config.js              # Vite configuration
├── package.json
└── src/
    ├── main.jsx                # React app bootstrap + Service Worker registration
    ├── App.jsx                 # Route definitions
    ├── index.css               # Global styles
    ├── pages/
    │   ├── LandingPage.jsx     # Public home/landing page
    │   ├── LoginPage.jsx       # Google OAuth login
    │   ├── RoleSelectPage.jsx  # Student / Teacher role selection
    │   ├── SimulatorPage.jsx   # Main circuit editor + simulation runner
    │   ├── admin/              # Admin Portal (Login, Landing, & Dashboard)
    │   ├── StudentDashboard.jsx
    │   └── TeacherDashboard.jsx
    ├── context/
    │   └── AuthContext.jsx     # Global authentication state
    ├── services/
    │   ├── authService.js      # Login, logout, token management (localStorage)
    │   ├── simulatorService.js # POST /api/compile and component API calls
    │   ├── offlineCache.js     # IndexedDB: compiled hex cache + ZIP upload queue
    │   └── projectStore.js     # IndexedDB: full project CRUD (save/load/list/delete)
    ├── worker/
    │   ├── simulation.worker.ts   # Web Worker entry point
    │   └── execute.ts             # AVR CPU execution loop inside worker
    └── components/             # Shared UI components

Static files:

public/
├── sw.js                       # Service Worker (app shell caching, offline routing)
└── _redirects                  # Deployment redirect rules

Pages

SimulatorPage.jsx

The core of the application. Responsibilities include:

  • Circuit Canvas — drag, drop, and wire Wokwi components
  • Resizable Explorer — The file explorer panel is resizable for better code editing space
  • Tabbed Interface — Right panel features high-visibility interactive tabs for Editor, Explorer, and Console
  • Code Editor — write Arduino sketches with syntax highlighting; diagram.json is protected as read-only
  • Undo/Redo — Quick toolbar actions for circuit design with updated iconography
  • Run/Stop — triggers compilation → .hex delivery → Web Worker START message
  • Live State Rendering — receives { type: "state", pins: {...} } at 60 FPS and updates component visual attributes (LEDs, NeoPixels, etc.)
  • Component Registry — maps component type names to their imported index definitions from @openhw/emulator
  • Project Save/Load — auto-saves to IndexedDB every 2.5 s; "My Projects" modal for named saves; auto-loads last project on mount
  • Offline resilience — hex cache survives page refresh; ZIP uploads queue while offline

LoginPage.jsx

Google OAuth 2.0 login page. Decodes JWT and stores user info in AuthContext.

AdminPage.jsx

A powerful administrative hub for platform maintenance:

  • 3-Column Management: Independent scrollable panels for Libraries, Pending Submissions, and Installed Components.
  • Review Workflow: Admins can check submissions with live Transpile feedback, download source ZIPs, or open them in a live Simulator "Test" tab.
  • Real-time Actions: Approval instantly moves components to the backend; rejection removes specific submissions (unique per upload).
  • Library Manager: Search and uninstall system-level C++ libraries for the Arduino compiler.

LandingPage.jsx

Public-facing landing page describing the platform.

StudentDashboard.jsx / TeacherDashboard.jsx

Role-specific dashboards shown after login.


Key Features

Real-time Simulation Rendering (60 FPS)

The Web Worker runs the AVR CPU and posts state messages back to the main thread every frame. The frontend maps pin voltages to DOM attribute changes on Wokwi custom HTML elements.

{ "type": "state", "pins": { "D13": true, "D6": false }, "neopixels": [...] }

NeoPixel Matrix Support

  • Wires NeoPixel components with GND, VCC, DIN, DOUT pins
  • Sends matrix topology (component ID, Arduino pin, size) in the Web Worker START message
  • Calls element.setPixel(row, col, {r, g, b}) directly on the Wokwi DOM element

Analog Plotter / Logic Graph

A native high-performance <canvas> rendering engine tab traces simulated logic and analog signals. Users can dynamically specify which pins to track.

Serial Monitor Integration

A built-in terminal streams AVRUSART traffic bidirectionally into the .hex loop.

Physical Workspace Controls

The Arduino Uno Reset Button is fully interactive inside the workspace SVG visualizer, triggering a targeted runner.cpu.reset() reboot in the Web Worker.

Web Worker Simulation

AVR simulation runs entirely in-browser via src/worker/execute.ts inside a Web Worker, keeping the UI thread completely unblocked.

Pico / RP2040 Workflow

  • Each Pico board folder now includes both <boardId>.ino and main.py starter files.
  • File menu supports Disable file / Enable file by renaming with .disabled suffix.
  • Disabled files are excluded from compile and MicroPython source selection.
  • If backend RP2040 Arduino core is missing, .ino compile failures automatically fall back to MicroPython UF2 + main.py.

Explorer Stability

  • Project files are normalized and deduplicated when loading saved projects to prevent duplicate file entries after refresh.

Zero-Touch Component Sync

The simulator polls the backend every 12 seconds for newly approved community components:

  • Dynamic Injection: New components are transpiled and injected into the registry and palette without a page refresh.
  • Live Deletion: If a component is uninstalled from the admin panel, it is purged from all active simulator sessions automatically.
  • Admin "Test" Mode: An isolated preview mechanism uses sessionStorage to test pending components before approval.

Auth Flow

  • Google OAuth → JWT stored in context
  • Role selection (Student / Teacher / Admin) → role-specific entry points
  • Protected routes via AuthContext and ProtectedRoute components

Offline & Storage Features

All storage features use the browser-native IndexedDB API and Service Worker API. No extra npm packages are required, and no backend changes are needed.

Project Persistence (IndexedDB — openhw-projects)

Every circuit is automatically saved to a local IndexedDB database every 2.5 seconds after any change. This works for both authenticated users and guest users with no login required.

User type Owner key What happens
Guest (no login) 'guest' Projects saved locally, visible under "My Projects" on every visit
Authenticated user user.email Projects saved locally, scoped to that email

Buttons added to the header:

  • Save — opens a name dialog; pressing Enter or clicking Save commits the name
  • My Projects — opens a modal listing all saved projects (name, board, components count, last-saved time) with Load and Delete actions
  • New — starts a blank canvas (current project is preserved in IDB)
  • Project name chip — shows the current project name in the header; click to rename

On page load, the most-recently saved project for the current user (or guest) is automatically restored.

Compiled Hex Cache (IndexedDB — openhw-offline)

Compiled .hex results are saved to IndexedDB after every successful compile. On subsequent runs:

  1. Check in-memory lastCompiledRef (fastest — same session)
  2. Check IndexedDB cache (survives page refresh and offline)
  3. Compile via POST /api/compile (requires network)

This means: run your simulation offline after compiling at least once while online.

Offline ZIP Component Upload Queue (IndexedDB — openhw-offline)

If you upload a custom component ZIP while offline:

  • The component is injected into the local registry immediately (usable right away)
  • The backend submission is queued in IndexedDB
  • When the internet is restored, the queue is automatically drained

Service Worker (public/sw.js)

Cached on first load. Strategies:

Request Strategy
Navigation (/, any route) Network-first → fallback to cached index.html
JS / CSS / images Stale-while-revalidate (instant load + background update)
CDN scripts (wokwi-elements) Stale-while-revalidate
/api/* Network-only (never cached — hex caching is at the app layer)

See OFFLINE_AND_STORAGE.md for full technical details.


Setup & Running Locally

Prerequisites

  • Node.js 18+
  • npm 9+
  • The Compiler Backend running at http://localhost:5001
  • For Pico .ino compilation, backend must have rp2040:rp2040 core installed.

Installation

cd OpenHW-studio-frontend
npm install

Local Development & NPM Linking

During local development, you will want the frontend to immediately see changes you make to the emulator source code, without having to push those changes to GitHub first.

We achieve this using Vite Resolve Aliases, which tell the frontend to use your local emulator repository folder. This is controlled by the VITE_EMULATOR_PATH variable in your .env file and bypasses the need for npm link.

Set the path to your own emulator repo name. It can be relative or absolute, as long as it points at the emulator repository root.

To set up your local development:

  1. Ensure your .env file has the correct path:
        VITE_EMULATOR_PATH=../path-to-openhw-studio-emulator
  2. Restart the Vite dev server. The @openhw/emulator package will now point directly to your local source.

Note: You can still use npm link if preferred, but the environment variable approach is more portable across different machines.

Production Deployment (Vercel / Docker)

For production builds (like on Vercel), the VITE_EMULATOR_PATH variable should be left unset. The vite.config.js is designed to automatically fallback to the @openhw/emulator package installed in node_modules (fetched from GitHub) if the local path is not found.

Note: Once deployed to Vercel/Netlify, these local symlinks will be ignored and the remote server will correctly fetch the package directly from GitHub.

Start Development Server

npm run dev

The app will be available at http://localhost:5173

Build for Production

npm run build

Preview Production Build

npm run preview

Environment Variables

The frontend uses Vite environment variables. Create a .env file in the project directory:

Variable Description Default
VITE_GOOGLE_CLIENT_ID Google OAuth 2.0 Client ID
VITE_API_BASE_URL Base URL for the Backend API http://localhost:5001/api
VITE_EXAMPLES_BASE_URL Base URL for example assets served by the backend EXAMPLES_PATH route http://localhost:5001/examples
VITE_EMULATOR_PATH Local path to the emulator repository root used by Vite aliasing ../path-to-openhw-studio-emulator
VITE_ADMIN_EMAILS Comma-separated list of admin emails

Sample .env Setup:

VITE_GOOGLE_CLIENT_ID=your_id.apps.googleusercontent.com
VITE_API_BASE_URL=http://localhost:5001/api
VITE_EXAMPLES_BASE_URL=http://localhost:5001/examples
VITE_ADMIN_EMAILS=admin@example.com,user@example.com
VITE_EMULATOR_PATH=../path-to-openhw-studio-emulator

How It Works

User writes C++ code
        │
        ▼
POST /api/compile  ──►  Compiler Backend (port 5001)
                                │
                         Returns .hex file
                                │ also cached to IndexedDB
                                ▼
        Frontend sends START + .hex + wiring topology
                                │
                         Web Worker (browser)
                                │
                    Runs AVR CPU at 16 MHz in-browser
                    Streams pin states at 60 FPS
                                │
                                ▼
        Frontend updates Wokwi component DOM attributes
                    (LEDs, NeoPixels, Servo, etc.)

Part of the OpenHW Studio platform. See also: openhw-studio-backend and openhw-studio-emulator.

Releases

Packages

Used by

Contributors

Languages