diff --git a/frontend/index.html b/frontend/index.html index b8b6f1a..9060566 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -279,6 +279,10 @@
  • Getting Started — Hosted editor, Docker, and manual setup
  • Emulator Architecture — AVR8 and RP2040 CPU emulation internals
  • Components Reference — All 48+ interactive electronic components
  • +
  • Project Architecture — System design, data flows, and stores
  • +
  • Wokwi Libraries — avr8js, wokwi-elements, rp2040js integration
  • +
  • MCP Server — AI agent integration via Model Context Protocol
  • +
  • Project Status — All implemented features and troubleshooting
  • Roadmap — Implemented, in-progress, and planned features
  • diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml index 1710363..f203b87 100644 --- a/frontend/public/sitemap.xml +++ b/frontend/public/sitemap.xml @@ -51,6 +51,34 @@ 0.6 + + https://velxio.dev/docs/architecture + 2026-03-11 + monthly + 0.7 + + + + https://velxio.dev/docs/wokwi-libs + 2026-03-11 + monthly + 0.7 + + + + https://velxio.dev/docs/mcp + 2026-03-11 + monthly + 0.7 + + + + https://velxio.dev/docs/setup + 2026-03-11 + monthly + 0.6 + + https://velxio.dev/examples 2026-03-06 diff --git a/frontend/src/pages/DocsPage.tsx b/frontend/src/pages/DocsPage.tsx index 9f4e078..86c51f0 100644 --- a/frontend/src/pages/DocsPage.tsx +++ b/frontend/src/pages/DocsPage.tsx @@ -4,6 +4,8 @@ import { useAuthStore } from '../store/useAuthStore'; import './DocsPage.css'; const GITHUB_URL = 'https://github.com/davidmonterocrespo24/velxio'; +const BASE_URL = 'https://velxio.dev'; +const AUTHOR = { '@type': 'Person', name: 'David Montero Crespo', url: 'https://github.com/davidmonterocrespo24' } as const; /* ── Icons ─────────────────────────────────────────────── */ const IcoChip = () => ( @@ -21,9 +23,28 @@ const IcoGitHub = () => ( ); /* ── Doc sections ──────────────────────────────────────── */ -type SectionId = 'intro' | 'getting-started' | 'emulator' | 'components' | 'roadmap'; +type SectionId = + | 'intro' + | 'getting-started' + | 'emulator' + | 'components' + | 'roadmap' + | 'architecture' + | 'wokwi-libs' + | 'mcp' + | 'setup'; -const VALID_SECTIONS: SectionId[] = ['intro', 'getting-started', 'emulator', 'components', 'roadmap']; +const VALID_SECTIONS: SectionId[] = [ + 'intro', + 'getting-started', + 'emulator', + 'components', + 'roadmap', + 'architecture', + 'wokwi-libs', + 'mcp', + 'setup', +]; interface NavItem { id: SectionId; @@ -35,6 +56,10 @@ const NAV_ITEMS: NavItem[] = [ { id: 'getting-started', label: 'Getting Started' }, { id: 'emulator', label: 'Emulator Architecture' }, { id: 'components', label: 'Components Reference' }, + { id: 'architecture', label: 'Project Architecture' }, + { id: 'wokwi-libs', label: 'Wokwi Libraries' }, + { id: 'mcp', label: 'MCP Server' }, + { id: 'setup', label: 'Project Status' }, { id: 'roadmap', label: 'Roadmap' }, ]; @@ -61,6 +86,22 @@ const SECTION_META: Record = { title: 'Roadmap — Velxio Documentation', description: "Velxio's feature roadmap: what's implemented, what's in progress, and what's planned for future releases.", }, + 'architecture': { + title: 'Project Architecture — Velxio Documentation', + description: 'Detailed overview of the Velxio system architecture: frontend, backend, AVR8 emulation pipeline, data flows, Zustand stores, and wire system.', + }, + 'wokwi-libs': { + title: 'Wokwi Libraries — Velxio Documentation', + description: 'How Velxio integrates the official Wokwi open-source libraries: avr8js, wokwi-elements, and rp2040js. Covers configuration, updates, and the 48 available components.', + }, + 'mcp': { + title: 'MCP Server — Velxio Documentation', + description: 'Velxio MCP Server reference: integrate AI agents (Claude, Cursor) with Velxio via Model Context Protocol. Covers tools, transports, circuit format, and example walkthroughs.', + }, + 'setup': { + title: 'Project Status — Velxio Documentation', + description: 'Complete status of all implemented Velxio features: AVR emulation, component system, wire system, code editor, example projects, and next steps.', + }, }; /* ── Section content ───────────────────────────────────── */ @@ -478,12 +519,514 @@ const RoadmapSection: React.FC = () => ( ); -const SECTION_MAP: Record = { +/* ── Architecture Section ─────────────────────────────── */ +const ArchitectureSection: React.FC = () => ( +
    + // system design +

    Project Architecture

    +

    + Velxio is a fully local Arduino emulator using official Wokwi repositories for maximum + compatibility. It features real AVR8 CPU emulation, 48+ interactive electronic components, + a comprehensive wire system, and a build-time component discovery pipeline. +

    + +

    High-Level Overview

    +
    {`Browser (React + Vite)
    +  ├── Monaco Editor ──► useEditorStore (Zustand)
    +  ├── SimulatorCanvas ──► useSimulatorStore (Zustand)
    +  │     ├── AVRSimulator (avr8js)   16 MHz AVR8 CPU
    +  │     ├── RP2040Simulator (rp2040js)
    +  │     ├── PinManager              pin → component mapping
    +  │     ├── PartSimulationRegistry  16 interactive parts
    +  │     └── 48+ wokwi-elements      Lit Web Components
    +  └── HTTP (Axios) ──► FastAPI Backend (port 8001)
    +        └── ArduinoCLIService ──► arduino-cli subprocess`}
    + +

    Data Flows

    + +

    1. Compilation

    +
    {`Click "Compile"
    +  → EditorToolbar reads all workspace files
    +  → POST /api/compile/  { files, board_fqbn }
    +  → Backend: ArduinoCLIService writes temp dir
    +  → arduino-cli compile --fqbn  --output-dir build/
    +  → Returns hex_content (Intel HEX string)
    +  → useSimulatorStore.setCompiledHex() → loadHex()`}
    + +

    2. Simulation Loop

    +
    {`Click "Run"
    +  → AVRSimulator.start()
    +  → requestAnimationFrame loop @ ~60 FPS
    +  → Each frame: Math.floor(267 000 × speed) cycles
    +    ├── avrInstruction(cpu)   — decode + execute one AVR instruction
    +    └── cpu.tick()            — advance Timer0/1/2, USART, ADC
    +  → PORTB/C/D write listeners fire
    +  → PinManager.updatePort() → per-pin callbacks
    +  → PartSimulationRegistry.onPinStateChange()
    +  → wokwi-elements update visually`}
    + +

    3. Input Components

    +
    {`User presses button on canvas
    +  → wokwi web component fires 'button-press' event
    +  → DynamicComponent catches event
    +  → PartSimulationRegistry.attachEvents() handler
    +  → AVRSimulator.setPinState(arduinoPin, LOW)
    +  → AVRIOPort.setPin() injects external pin state
    +  → CPU reads pin in next instruction`}
    + +

    Key Frontend Stores (Zustand)

    + + + + + + + + + + +
    StoreKey StatePurpose
    useEditorStorefiles[], activeFileIdMulti-file Monaco workspace
    useSimulatorStoresimulator, components, wires, runningSimulation + canvas state
    useAuthStoreuser, tokenAuth (persisted localStorage)
    useProjectStoreprojectId, slugCurrently open project
    + +

    Backend Routes

    + + + + + + + + + + + + +
    RouteDescription
    POST /api/compile/Compile sketch files → Intel HEX / UF2
    GET /api/compile/boardsList available boards
    GET/POST /api/auth/*Email/password + Google OAuth
    GET/POST /api/projects/*CRUD project persistence (SQLite)
    GET /api/libraries/*Arduino Library Manager integration
    GET /healthHealth check endpoint
    + +

    Wire System

    +

    Wires are stored as objects with start/end endpoints tied to component pin positions:

    +
    {`{
    +  id: string
    +  start: { componentId, pinName, x, y }
    +  end:   { componentId, pinName, x, y }
    +  color: string
    +  signalType: 'digital' | 'analog' | 'power-vcc' | 'power-gnd'
    +}`}
    +
      +
    • Orthogonal routing — no diagonal segments
    • +
    • Segment drag — drag perpendicular to segment orientation
    • +
    • Auto-update — wire positions recalculate when components move
    • +
    • Grid snapping — 20 px grid for all wire endpoints
    • +
    + +
    + Full details:{' '} + See{' '} + + docs/ARCHITECTURE.md + {' '} + in the repository. +
    +
    +); + +/* ── Wokwi Libraries Section ──────────────────────────── */ +const WokwiLibsSection: React.FC = () => ( +
    + // open-source libs +

    Wokwi Libraries

    +

    + Velxio uses official Wokwi open-source repositories cloned locally in wokwi-libs/. + This gives you up-to-date, compatible emulation engines and visual components without npm registry + dependencies. +

    + +

    Cloned Repositories

    + + + + + + + + + + + + + + + + + + + + + +
    LibraryLocationPurpose
    wokwi-elementswokwi-libs/wokwi-elements/48+ Lit Web Components (LEDs, LCDs, sensors, buttons…)
    avr8jswokwi-libs/avr8js/ATmega328p / ATmega2560 CPU emulator at 16 MHz
    rp2040jswokwi-libs/rp2040js/Raspberry Pi Pico (RP2040) emulator
    + +

    Vite Configuration

    +

    frontend/vite.config.ts uses path aliases so imports resolve to the local builds:

    +
    {`resolve: {
    +  alias: {
    +    'avr8js':          '../wokwi-libs/avr8js/dist/esm',
    +    '@wokwi/elements': '../wokwi-libs/wokwi-elements/dist/esm',
    +  },
    +}`}
    + +

    Updating the Libraries

    +

    All at once (recommended)

    +
    {`# Windows
    +update-wokwi-libs.bat`}
    + +

    Manually

    +
    {`cd wokwi-libs/wokwi-elements
    +git pull origin main
    +npm install && npm run build
    +
    +cd ../avr8js
    +git pull origin main
    +npm install && npm run build
    +
    +cd ../rp2040js
    +git pull origin main
    +npm install && npm run build`}
    + +

    After updating wokwi-elements

    +

    Regenerate component metadata so new components appear in the picker:

    +
    {`cd frontend
    +npx tsx ../scripts/generate-component-metadata.ts`}
    + +

    Available Wokwi Components (48)

    + + + + + + + + + + + + + + +
    CategoryComponents
    BoardsArduino Uno, Mega, Nano, ESP32 DevKit
    SensorsDHT22, HC-SR04, PIR, Photoresistor, NTC, Joystick
    DisplaysLCD 16×2, LCD 20×4, 7-Segment
    InputPush button, 6mm button, Slide switch, DIP switch 8, Potentiometer
    OutputLED, RGB LED, LED bar graph, Buzzer, NeoPixel
    MotorsServo, Stepper motor
    PassiveResistor, Slide potentiometer, LED ring, Matrix keypad
    OtherIR receiver, DS1307 RTC, breadboards, etc.
    + +

    How avr8js Powers the Simulation

    +
    {`import { CPU, avrInstruction, AVRTimer, AVRUSART, AVRADC, AVRIOPort } from 'avr8js';
    +
    +const cpu   = new CPU(programMemory);          // ATmega328p at 16 MHz
    +const portB = new AVRIOPort(cpu, portBConfig); // digital pins 8-13
    +const portC = new AVRIOPort(cpu, portCConfig); // analog pins A0-A5
    +const portD = new AVRIOPort(cpu, portDConfig); // digital pins 0-7
    +
    +function runFrame() {
    +  const cycles = Math.floor(267_000 * speed);
    +  for (let i = 0; i < cycles; i++) {
    +    avrInstruction(cpu); // execute one AVR instruction
    +    cpu.tick();          // advance timers + peripherals
    +  }
    +  requestAnimationFrame(runFrame);
    +}`}
    + +
    + Full details:{' '} + See{' '} + + docs/WOKWI_LIBS.md + {' '} + in the repository. +
    +
    +); + +/* ── MCP Server Section ───────────────────────────────── */ +const McpSection: React.FC = () => ( +
    + // AI integration +

    MCP Server

    +

    + Velxio exposes a{' '} + + Model Context Protocol + {' '} + (MCP) server that lets AI agents (Claude, Cursor, and others) create circuits, + generate code, and compile Arduino sketches directly. +

    + +

    Available Tools

    + + + + + + + + + + + + + +
    ToolDescription
    compile_projectCompile Arduino sketch files → Intel HEX / binary
    run_projectCompile and mark artifact as simulation-ready
    import_wokwi_jsonParse a Wokwi diagram.json → Velxio circuit
    export_wokwi_jsonSerialise a Velxio circuit → Wokwi diagram.json
    create_circuitCreate a new circuit definition
    update_circuitMerge changes into an existing circuit
    generate_code_filesGenerate starter .ino code from a circuit
    + +

    Transport Options

    + +

    1. stdio — Claude Desktop / CLI agents

    +
    {`cd backend
    +python mcp_server.py`}
    +

    Claude Desktop config (~/.claude/claude_desktop_config.json):

    +
    {`{
    +  "mcpServers": {
    +    "velxio": {
    +      "command": "python",
    +      "args": ["/absolute/path/to/velxio/backend/mcp_server.py"]
    +    }
    +  }
    +}`}
    + +

    2. SSE / HTTP — Cursor IDE / web agents

    +
    {`cd backend
    +python mcp_sse_server.py --port 8002`}
    +

    MCP client config:

    +
    {`{
    +  "mcpServers": {
    +    "velxio": { "url": "http://localhost:8002/sse" }
    +  }
    +}`}
    + +

    Circuit Data Format

    +

    Velxio circuits are plain JSON objects:

    +
    {`{
    +  "board_fqbn": "arduino:avr:uno",
    +  "version": 1,
    +  "components": [
    +    { "id": "led1", "type": "wokwi-led", "left": 200, "top": 100,
    +      "rotate": 0, "attrs": { "color": "red" } }
    +  ],
    +  "connections": [
    +    { "from_part": "uno", "from_pin": "13",
    +      "to_part": "led1", "to_pin": "A", "color": "green" }
    +  ]
    +}`}
    + +

    Supported Board FQBNs

    + + + + + + + + + + +
    BoardFQBN
    Arduino Unoarduino:avr:uno
    Arduino Megaarduino:avr:mega
    Arduino Nanoarduino:avr:nano
    Raspberry Pi Picorp2040:rp2040:rpipico
    + +

    Example — Blink LED from Scratch

    +
    {`// Step 1 — Create a circuit
    +{
    +  "tool": "create_circuit",
    +  "arguments": {
    +    "board_fqbn": "arduino:avr:uno",
    +    "components": [
    +      { "id": "led1", "type": "wokwi-led",
    +        "left": 150, "top": 100, "attrs": { "color": "red" } },
    +      { "id": "r1", "type": "wokwi-resistor",
    +        "left": 150, "top": 180, "attrs": { "value": "220" } }
    +    ],
    +    "connections": [
    +      { "from_part": "uno", "from_pin": "13",
    +        "to_part": "led1", "to_pin": "A", "color": "green" },
    +      { "from_part": "led1", "from_pin": "C",
    +        "to_part": "r1",   "to_pin": "1", "color": "black" },
    +      { "from_part": "r1",   "from_pin": "2",
    +        "to_part": "uno",  "to_pin": "GND.1", "color": "black" }
    +    ]
    +  }
    +}
    +
    +// Step 2 — Generate code
    +{
    +  "tool": "generate_code_files",
    +  "arguments": {
    +    "circuit": "",
    +    "sketch_name": "blink",
    +    "extra_instructions": "Blink the red LED every 500ms"
    +  }
    +}
    +
    +// Step 3 — Compile
    +{
    +  "tool": "compile_project",
    +  "arguments": {
    +    "files": [
    +      {
    +        "name": "blink.ino",
    +        "content": "void setup(){pinMode(13,OUTPUT);}\\nvoid loop(){digitalWrite(13,HIGH);delay(500);digitalWrite(13,LOW);delay(500);}"
    +      }
    +    ],
    +    "board": "arduino:avr:uno"
    +  }
    +}`}
    + +

    Setup

    +
    {`cd backend
    +pip install -r requirements.txt
    +
    +# Ensure arduino-cli is installed
    +arduino-cli version
    +arduino-cli core update-index
    +arduino-cli core install arduino:avr
    +
    +# Run tests
    +python -m pytest tests/test_mcp_tools.py -v`}
    + +
    + Full reference:{' '} + See{' '} + + docs/MCP.md + {' '} + in the repository. +
    +
    +); + +/* ── Setup / Project Status Section ──────────────────── */ +const SetupSection: React.FC = () => ( +
    + // project status +

    Project Status

    +

    A comprehensive overview of all features currently implemented in Velxio.

    + +

    AVR Emulation (avr8js)

    + + + + + + + + + + + + + +
    FeatureStatus
    ATmega328p CPU at 16 MHz✅ Working
    Timer0, Timer1, Timer2✅ Working
    USART (Serial)✅ Working
    ADC (analogRead)✅ Working
    Full GPIO (PORTB / PORTC / PORTD)✅ Working
    ~60 FPS loop (267k cycles/frame)✅ Working
    Speed control (0.1× – 10×)✅ Working
    PWM monitoring (6 channels)✅ Working
    External pin injection (inputs)✅ Working
    + +

    Component System (48+)

    + + + + + + + + + + + + +
    FeatureStatus
    Automatic discovery via AST✅ 48 components detected
    ComponentPickerModal with search✅ Working
    9 categories with filters✅ Working
    Generic DynamicComponent renderer✅ Working
    Drag-and-drop on canvas✅ Working
    Rotation (90° increments)✅ Working
    Properties dialog (single-click)✅ Working
    Pin overlay (clickable cyan dots)✅ Working
    + +

    Interactive Parts (16 simulated)

    + + + + + + + + + + + + + + + + + + + + +
    PartTypeStatus
    LEDOutput
    RGB LEDOutput (digital + PWM)
    LED Bar Graph (10 LEDs)Output
    7-Segment DisplayOutput
    PushbuttonInput
    Pushbutton 6mmInput
    Slide SwitchInput
    DIP Switch 8Input
    PotentiometerInput (ADC)
    Slide PotentiometerInput (ADC)
    PhotoresistorInput / Output
    Analog JoystickInput (ADC + digital)
    ServoOutput
    BuzzerOutput (Web Audio)
    LCD 1602Output (full HD44780)
    LCD 2004Output (full HD44780)
    + +

    Wire System

    + + + + + + + + + + + + +
    FeatureStatus
    Pin-to-pin creation with click✅ Working
    Real-time preview (green dashed)✅ Working
    Orthogonal routing (no diagonals)✅ Working
    Segment editing (perpendicular drag)✅ Working
    8 colours by signal type✅ Working
    Auto-update when moving components✅ Working
    Grid snapping (20 px)✅ Working
    Wire selection and deletion✅ Working
    + +

    Example Projects (8)

    + + + + + + + + + + + + +
    ExampleCategoryDifficulty
    Blink LEDBasicsBeginner
    Traffic LightBasicsBeginner
    Button ControlBasicsBeginner
    Fade LED (PWM)BasicsBeginner
    Serial Hello WorldCommunicationBeginner
    RGB LED ColorsBasicsIntermediate
    Simon Says GameGamesAdvanced
    LCD 20×4 DisplayDisplaysIntermediate
    + +

    Troubleshooting

    + + + + + + + + + + + + + + + + + + + + +
    ProblemSolution
    Components not displayed
    cd wokwi-libs/wokwi-elements{'\n'}npm run build
    Cannot find module 'avr8js'
    cd wokwi-libs/avr8js{'\n'}npm install && npm run build
    LED doesn't blinkCompile first, then click Run. Check pin assignment in the component property dialog.
    New component not in picker
    cd frontend{'\n'}npx tsx ../scripts/generate-component-metadata.ts
    + +
    + Full status:{' '} + See{' '} + + docs/SETUP_COMPLETE.md + {' '} + in the repository. +
    +
    +); intro: IntroSection, 'getting-started': GettingStartedSection, emulator: EmulatorSection, components: ComponentsSection, roadmap: RoadmapSection, + architecture: ArchitectureSection, + 'wokwi-libs': WokwiLibsSection, + mcp: McpSection, + setup: SetupSection, }; /* ── Page ─────────────────────────────────────────────── */ @@ -511,18 +1054,18 @@ export const DocsPage: React.FC = () => { const origTitle = document.title; // Helper to capture an element and its original attribute value - const snap = (selector: string, attr: string): [E | null, string] => { + const captureAttr = (selector: string, attr: string): [E | null, string] => { const el = document.querySelector(selector); return [el, el?.getAttribute(attr) ?? '']; }; - const [descEl, origDesc] = snap('meta[name="description"]', 'content'); - const [canonicalEl, origCanonical] = snap('link[rel="canonical"]', 'href'); - const [ogTitleEl, origOgTitle] = snap('meta[property="og:title"]', 'content'); - const [ogDescEl, origOgDesc] = snap('meta[property="og:description"]', 'content'); - const [ogUrlEl, origOgUrl] = snap('meta[property="og:url"]', 'content'); - const [twTitleEl, origTwTitle] = snap('meta[name="twitter:title"]', 'content'); - const [twDescEl, origTwDesc] = snap('meta[name="twitter:description"]', 'content'); + const [descEl, origDesc] = captureAttr('meta[name="description"]', 'content'); + const [canonicalEl, origCanonical] = captureAttr('link[rel="canonical"]', 'href'); + const [ogTitleEl, origOgTitle] = captureAttr('meta[property="og:title"]', 'content'); + const [ogDescEl, origOgDesc] = captureAttr('meta[property="og:description"]', 'content'); + const [ogUrlEl, origOgUrl] = captureAttr('meta[property="og:url"]', 'content'); + const [twTitleEl, origTwTitle] = captureAttr('meta[name="twitter:title"]', 'content'); + const [twDescEl, origTwDesc] = captureAttr('meta[name="twitter:description"]', 'content'); return () => { document.title = origTitle; @@ -542,7 +1085,7 @@ export const DocsPage: React.FC = () => { // and on a section change the next run of this effect immediately overwrites. useEffect(() => { const meta = SECTION_META[activeSection]; - const pageUrl = `https://velxio.dev/docs/${activeSection}`; + const pageUrl = `${BASE_URL}/docs/${activeSection}`; document.title = meta.title; @@ -580,15 +1123,15 @@ export const DocsPage: React.FC = () => { headline: meta.title, description: meta.description, url: pageUrl, - isPartOf: { '@type': 'WebSite', url: 'https://velxio.dev/', name: 'Velxio' }, + isPartOf: { '@type': 'WebSite', url: `${BASE_URL}/`, name: 'Velxio' }, inLanguage: 'en-US', - author: { '@type': 'Person', name: 'David Montero Crespo', url: 'https://github.com/davidmonterocrespo24' }, + author: AUTHOR, }, { '@type': 'BreadcrumbList', itemListElement: [ - { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://velxio.dev/' }, - { '@type': 'ListItem', position: 2, name: 'Documentation', item: 'https://velxio.dev/docs/intro' }, + { '@type': 'ListItem', position: 1, name: 'Home', item: `${BASE_URL}/` }, + { '@type': 'ListItem', position: 2, name: 'Documentation', item: `${BASE_URL}/docs/intro` }, { '@type': 'ListItem', position: 3, name: sectionLabel, item: pageUrl }, ], },