Translate Spanish docs to English and add SEO-optimised URL routing for documentation

Co-authored-by: davidmonterocrespo24 <47928504+davidmonterocrespo24@users.noreply.github.com>
pull/25/head
copilot-swe-agent[bot] 2026-03-11 18:46:42 +00:00
parent dc779c46ad
commit b8bdaf4c65
7 changed files with 449 additions and 328 deletions

View File

@ -1,98 +1,98 @@
# Estado del Proyecto - Velxio Arduino Emulator
# Project Status - Velxio Arduino Emulator
## Resumen de Funcionalidades Implementadas
## Summary of Implemented Features
### Repositorios de Wokwi Clonados y Configurados
### Wokwi Repositories Cloned and Configured
Repositorios oficiales de Wokwi en `wokwi-libs/`:
Official Wokwi repositories in `wokwi-libs/`:
| Repositorio | Estado | Descripción |
|-------------|--------|-------------|
| **wokwi-elements** | Compilado y en uso | 48+ componentes electrónicos Web Components |
| **avr8js** | Compilado y en uso | Emulación real de AVR8 (ATmega328p) |
| **rp2040js** | Clonado | Emulador RP2040 (futuro) |
| **wokwi-features** | Clonado | Documentación y features |
| Repository | Status | Description |
|------------|--------|-------------|
| **wokwi-elements** | Built and in use | 48+ electronic Web Components |
| **avr8js** | Built and in use | Real AVR8 emulation (ATmega328p) |
| **rp2040js** | Cloned | RP2040 emulator (future use) |
| **wokwi-features** | Cloned | Documentation and feature tracking |
### Emulación AVR Real (avr8js)
### Real AVR Emulation (avr8js)
| Feature | Estado |
| Feature | Status |
|---------|--------|
| CPU ATmega328p a 16MHz | Funcionando |
| Timer0, Timer1, Timer2 | Funcionando |
| USART (Serial) | Funcionando |
| ADC (analogRead) | Funcionando |
| GPIO completo (PORTB/C/D) | Funcionando |
| Loop ~60fps (267k ciclos/frame) | Funcionando |
| Control de velocidad (0.1x - 10x) | Funcionando |
| Debugging paso a paso (step) | Funcionando |
| Monitoreo PWM (6 canales) | Funcionando |
| Inyección de pin externo (inputs) | Funcionando |
| ATmega328p CPU at 16MHz | Working |
| Timer0, Timer1, Timer2 | Working |
| USART (Serial) | Working |
| ADC (analogRead) | Working |
| Full GPIO (PORTB/C/D) | Working |
| Loop ~60fps (267k cycles/frame) | Working |
| Speed control (0.1x - 10x) | Working |
| Step-by-step debugging | Working |
| PWM monitoring (6 channels) | Working |
| External pin injection (inputs) | Working |
### Sistema de Componentes (48+)
### Component System (48+)
| Feature | Estado |
| Feature | Status |
|---------|--------|
| Descubrimiento automático por AST | 48 componentes detectados |
| ComponentPickerModal con búsqueda | Funcionando |
| 9 categorías con filtros | Functioning |
| Thumbnails en vivo (web components) | Funcionando |
| DynamicComponent renderer genérico | Funcionando |
| Drag-and-drop en el canvas | Funcionando |
| Rotación (90° incrementos) | Funcionando |
| Diálogo de propiedades (click) | Funcionando |
| Selector de pines (doble-click) | Funcionando |
| Pin overlay (puntos cyan clickeables) | Funcionando |
| Automatic discovery via AST | 48 components detected |
| ComponentPickerModal with search | Working |
| 9 categories with filters | Working |
| Live thumbnails (web components) | Working |
| Generic DynamicComponent renderer | Working |
| Drag-and-drop on canvas | Working |
| Rotation (90° increments) | Working |
| Properties dialog (click) | Working |
| Pin selector (double-click) | Working |
| Pin overlay (clickable cyan dots) | Working |
### 16 Partes con Simulación Interactiva
### 16 Parts with Interactive Simulation
| Parte | Tipo | Estado |
|-------|------|--------|
| LED | Output | |
| RGB LED | Output (digital + PWM) | |
| LED Bar Graph (10 LEDs) | Output | |
| 7-Segment Display | Output | |
| Pushbutton | Input | |
| Pushbutton 6mm | Input | |
| Slide Switch | Input | |
| DIP Switch 8 | Input | |
| Potentiometer | Input (ADC) | |
| Slide Potentiometer | Input (ADC) | |
| Photoresistor | Input/Output | |
| Analog Joystick | Input (ADC + digital) | |
| Servo | Output | |
| Buzzer | Output (Web Audio) | |
| LCD 1602 | Output (HD44780 completo) | |
| LCD 2004 | Output (HD44780 completo) | |
| Part | Type | Status |
|------|------|--------|
| LED | Output | |
| RGB LED | Output (digital + PWM) | |
| LED Bar Graph (10 LEDs) | Output | |
| 7-Segment Display | Output | |
| Pushbutton | Input | |
| Pushbutton 6mm | Input | |
| Slide Switch | Input | |
| DIP Switch 8 | Input | |
| Potentiometer | Input (ADC) | |
| Slide Potentiometer | Input (ADC) | |
| Photoresistor | Input/Output | |
| Analog Joystick | Input (ADC + digital) | |
| Servo | Output | |
| Buzzer | Output (Web Audio) | |
| LCD 1602 | Output (full HD44780) | |
| LCD 2004 | Output (full HD44780) | |
### Sistema de Cables (Wires)
### Wire System
| Feature | Estado |
| Feature | Status |
|---------|--------|
| Creación pin-a-pin con click | Funcionando |
| Preview en tiempo real (verde, punteado) | Funcionando |
| Routing ortogonal (sin diagonales) | Funcionando |
| Edición por segmentos (drag perpendicular) | Funcionando |
| 8 colores por tipo de señal | Funcionando |
| Offset automático para cables paralelos | Funcionando |
| Auto-actualización al mover componentes | Funcionando |
| Grid snapping (20px) | Funcionando |
| Selección y eliminación de cables | Funcionando |
| Pin-to-pin creation with click | Working |
| Real-time preview (green, dashed) | Working |
| Orthogonal routing (no diagonals) | Working |
| Segment editing (perpendicular drag) | Working |
| 8 colors by signal type | Working |
| Automatic offset for parallel wires | Working |
| Auto-update when moving components | Working |
| Grid snapping (20px) | Working |
| Wire selection and deletion | Working |
### Editor de Código
### Code Editor
| Feature | Estado |
| Feature | Status |
|---------|--------|
| Monaco Editor (C++, dark theme) | Funcionando |
| Syntax highlighting + autocomplete | Funcionando |
| Botones Compile/Run/Stop/Reset | Funcionando |
| Compilación via arduino-cli backend | Funcionando |
| Mensajes de error/éxito | Funcionando |
| Font size configurable | Funcionando |
| Monaco Editor (C++, dark theme) | Working |
| Syntax highlighting + autocomplete | Working |
| Compile/Run/Stop/Reset buttons | Working |
| Compilation via arduino-cli backend | Working |
| Error/success messages | Working |
| Configurable font size | Working |
### Ejemplos (8 Proyectos)
### Examples (8 Projects)
| Ejemplo | Categoría | Dificultad |
|---------|-----------|------------|
| Example | Category | Difficulty |
|---------|----------|------------|
| Blink LED | basics | beginner |
| Traffic Light | basics | beginner |
| Button Control | basics | beginner |
@ -102,41 +102,41 @@ Repositorios oficiales de Wokwi en `wokwi-libs/`:
| Simon Says Game | games | advanced |
| LCD 20x4 Display | displays | intermediate |
- Galería con filtros de categoría y dificultad
- Carga con un click (código + componentes + cables)
- Gallery with category and difficulty filters
- One-click load (code + components + wires)
### Integración Configurada
### Configured Integrations
| Item | Estado |
| Item | Status |
|------|--------|
| Vite aliases para repos locales | |
| Package.json con `file:../wokwi-libs/...` | |
| TypeScript declarations para Web Components | |
| CORS backend (puertos 5173-5175) | |
| React Router (2 rutas) | |
| Zustand stores (editor + simulator) | |
| Vite aliases for local repos | ✅ |
| Package.json with `file:../wokwi-libs/...` | ✅ |
| TypeScript declarations for Web Components | ✅ |
| Backend CORS (ports 5173-5175) | ✅ |
| React Router (2 routes) | ✅ |
| Zustand stores (editor + simulator) | |
### Documentación
### Documentation
| Archivo | Descripción |
|---------|-------------|
| `README.md` | Instrucciones de instalación y uso |
| `docs/ARCHITECTURE.md` | Arquitectura detallada del proyecto |
| `docs/WOKWI_LIBS.md` | Guía de integración con Wokwi |
| `docs/SETUP_COMPLETE.md` | Este archivo — estado del proyecto |
| `CLAUDE.md` | Guía para asistentes IA |
| `update-wokwi-libs.bat` | Script de actualización automática |
| File | Description |
|------|-------------|
| `README.md` | Installation and usage instructions |
| `docs/ARCHITECTURE.md` | Detailed project architecture |
| `docs/WOKWI_LIBS.md` | Wokwi integration guide |
| `docs/SETUP_COMPLETE.md` | This file — project status |
| `CLAUDE.md` | Guide for AI assistants |
| `update-wokwi-libs.bat` | Automatic update script |
## Cómo Empezar
## Getting Started
### 1. Asegúrate de tener arduino-cli instalado
### 1. Ensure arduino-cli is installed
```bash
arduino-cli version
arduino-cli core install arduino:avr
```
### 2. Inicia el Backend
### 2. Start the Backend
```bash
cd backend
@ -144,44 +144,44 @@ venv\Scripts\activate
uvicorn app.main:app --reload --port 8001
```
### 3. Inicia el Frontend
### 3. Start the Frontend
```bash
cd frontend
npm run dev
```
### 4. Abre en el Navegador
### 4. Open in the Browser
- Frontend: http://localhost:5173
- Backend API: http://localhost:8001
- API Docs: http://localhost:8001/docs
## Actualizar Librerías de Wokwi
## Update Wokwi Libraries
```bash
# Ejecutar script de actualización
# Run the update script
update-wokwi-libs.bat
# Regenerar metadata de componentes (si actualizaste wokwi-elements)
# Regenerate component metadata (if you updated wokwi-elements)
cd frontend
npx tsx ../scripts/generate-component-metadata.ts
```
## Próximos Pasos (Pendiente)
## Next Steps (Pending)
| Feature | Prioridad | Descripción |
|---------|-----------|-------------|
| Serial Monitor | Alta | UI para leer output USART de la simulación |
| Persistencia | Alta | SQLite para guardar/cargar proyectos |
| Undo/Redo | Media | Historial de edición para código y circuito |
| Multi-board | Media | Cambio de board en runtime (Mega, Nano, ESP32) |
| Validación de cables | Media | Validación eléctrica y resaltado de errores |
| Export/Import | Baja | Compartir proyectos como archivos |
| Feature | Priority | Description |
|---------|----------|-------------|
| Serial Monitor | High | UI for reading USART output from the simulation |
| Persistence | High | SQLite for saving/loading projects |
| Undo/Redo | Medium | Edit history for code and circuit |
| Multi-board | Medium | Board switching at runtime (Mega, Nano, ESP32) |
| Wire validation | Medium | Electrical validation and error highlighting |
| Export/Import | Low | Share projects as files |
## Troubleshooting
### Los componentes no se muestran
### Components are not displayed
```bash
cd wokwi-libs/wokwi-elements
@ -196,7 +196,7 @@ npm install
npm run build
```
### arduino-cli no funciona
### arduino-cli does not work
```bash
arduino-cli version
@ -204,29 +204,29 @@ arduino-cli core list
arduino-cli core install arduino:avr
```
### LED no parpadea en simulación
### LED does not blink in simulation
- Verifica que compilaste el código (botón Compile)
- Verifica que ejecutaste la simulación (botón Run)
- Revisa la consola del navegador para errores de port listeners
- Verifica el pin mapping en el diálogo de propiedades del componente
- Verify that you compiled the code (Compile button)
- Verify that you started the simulation (Run button)
- Check the browser console for port listener errors
- Verify the pin mapping in the component properties dialog
### Componente nuevo no aparece en el picker
### New component does not appear in the picker
```bash
cd frontend
npx tsx ../scripts/generate-component-metadata.ts
```
## Estado General
## General Status
El proyecto tiene implementadas todas las funcionalidades core:
The project has all core features implemented:
- Editor de código profesional (Monaco)
- Compilación Arduino local (arduino-cli)
- Emulación AVR8 real con periféricos completos
- 48+ componentes electrónicos con descubrimiento automático
- 16 partes con simulación interactiva (LED, LCD, buttons, potentiometers, servo, buzzer)
- Sistema de cables ortogonales con edición visual
- 8 proyectos de ejemplo con galería filtrable
- Sistema de actualización automática para librerías Wokwi
- Professional code editor (Monaco)
- Local Arduino compilation (arduino-cli)
- Real AVR8 emulation with full peripherals
- 48+ electronic components with automatic discovery
- 16 parts with interactive simulation (LED, LCD, buttons, potentiometers, servo, buzzer)
- Orthogonal wire system with visual editing
- 8 example projects with a filterable gallery
- Automatic update system for Wokwi libraries

View File

@ -1,40 +1,40 @@
# Wokwi Libraries Integration
Este proyecto utiliza los repositorios oficiales de Wokwi clonados localmente, lo que permite mantenerlos actualizados y compatibles con las últimas versiones. Los repositorios locales alimentan tanto la emulación AVR como el sistema dinámico de componentes con 48+ elementos electrónicos.
This project uses the official Wokwi repositories cloned locally, which allows keeping them up-to-date and compatible with the latest versions. The local repositories power both AVR emulation and the dynamic component system with 48+ electronic elements.
## Repositorios Clonados
## Cloned Repositories
### wokwi-elements
- **Ubicación**: `wokwi-libs/wokwi-elements/`
- **Descripción**: Web Components (Lit) para 48+ elementos electrónicos (LEDs, resistencias, botones, LCDs, sensores, etc.)
- **Repositorio**: https://github.com/wokwi/wokwi-elements
- **Licencia**: MIT
- **Uso actual**: Renderizado visual de todos los componentes en el canvas de simulación. Un script de generación de metadata (`scripts/generate-component-metadata.ts`) parsea el código fuente TypeScript para descubrir automáticamente todos los componentes, sus propiedades y pines.
- **Location**: `wokwi-libs/wokwi-elements/`
- **Description**: Web Components (Lit) for 48+ electronic elements (LEDs, resistors, buttons, LCDs, sensors, etc.)
- **Repository**: https://github.com/wokwi/wokwi-elements
- **License**: MIT
- **Current usage**: Visual rendering of all components on the simulation canvas. A metadata generation script (`scripts/generate-component-metadata.ts`) parses the TypeScript source code to automatically discover all components, their properties, and pins.
### avr8js
- **Ubicación**: `wokwi-libs/avr8js/`
- **Descripción**: Emulador completo de microcontroladores AVR8 (ATmega328p) en JavaScript
- **Repositorio**: https://github.com/wokwi/avr8js
- **Licencia**: MIT
- **Uso actual**: Emulación real del CPU a 16MHz, con Timer0/1/2, USART, ADC, y puertos GPIO (PORTB/C/D). Ejecuta ~267,000 ciclos por frame a ~60fps.
- **Location**: `wokwi-libs/avr8js/`
- **Description**: Complete AVR8 microcontroller emulator (ATmega328p) in JavaScript
- **Repository**: https://github.com/wokwi/avr8js
- **License**: MIT
- **Current usage**: Real CPU emulation at 16MHz, with Timer0/1/2, USART, ADC, and GPIO ports (PORTB/C/D). Runs ~267,000 cycles per frame at ~60fps.
### rp2040js
- **Ubicación**: `wokwi-libs/rp2040js/`
- **Descripción**: Emulador de Raspberry Pi Pico (RP2040) en JavaScript
- **Repositorio**: https://github.com/wokwi/rp2040js
- **Licencia**: MIT
- **Uso**: Clonado para futuro soporte de Raspberry Pi Pico
- **Location**: `wokwi-libs/rp2040js/`
- **Description**: Raspberry Pi Pico (RP2040) emulator in JavaScript
- **Repository**: https://github.com/wokwi/rp2040js
- **License**: MIT
- **Usage**: Cloned for future Raspberry Pi Pico support
### wokwi-features
- **Ubicación**: `wokwi-libs/wokwi-features/`
- **Descripción**: Documentación y tracking de features de Wokwi
- **Repositorio**: https://github.com/wokwi/wokwi-features
- **Location**: `wokwi-libs/wokwi-features/`
- **Description**: Wokwi documentation and feature tracking
- **Repository**: https://github.com/wokwi/wokwi-features
## Configuración del Proyecto
## Project Configuration
### Frontend (Vite)
El archivo `frontend/vite.config.ts` está configurado para usar los repositorios locales mediante aliases:
The `frontend/vite.config.ts` file is configured to use the local repositories via aliases:
```typescript
resolve: {
@ -48,7 +48,7 @@ optimizeDeps: {
}
```
El archivo `frontend/package.json` referencia los paquetes locales:
The `frontend/package.json` file references the local packages:
```json
{
@ -59,103 +59,103 @@ El archivo `frontend/package.json` referencia los paquetes locales:
}
```
### Generación Automática de Metadata
### Automatic Metadata Generation
El script `scripts/generate-component-metadata.ts` parsea el código fuente de wokwi-elements usando AST de TypeScript para extraer:
- Nombre del tag (`@customElement('wokwi-led')` → `wokwi-led`)
- Propiedades (`@property()` decorators → tipo, valor por defecto)
- Cantidad de pines
- Categoría, descripción y tags
The `scripts/generate-component-metadata.ts` script parses the wokwi-elements source code using the TypeScript AST to extract:
- Tag name (`@customElement('wokwi-led')` → `wokwi-led`)
- Properties (`@property()` decorators → type, default value)
- Number of pins
- Category, description, and tags
El resultado se almacena en `frontend/public/components-metadata.json` y es consumido por el `ComponentRegistry` en tiempo de ejecución.
The result is stored in `frontend/public/components-metadata.json` and consumed by the `ComponentRegistry` at runtime.
## Actualizar las Librerías de Wokwi
## Updating the Wokwi Libraries
Para mantener tu proyecto actualizado con las últimas versiones de Wokwi:
To keep your project up-to-date with the latest versions of Wokwi:
### Opción 1: Actualizar todas las librerías (Recomendado)
### Option 1: Update all libraries (Recommended)
```bash
# Script para actualizar todos los repositorios
# Script to update all repositories
update-wokwi-libs.bat
```
### Opción 2: Actualizar manualmente cada repositorio
### Option 2: Update each repository manually
```bash
cd wokwi-libs
# Actualizar wokwi-elements
# Update wokwi-elements
cd wokwi-elements
git pull origin main
npm install
npm run build
# Actualizar avr8js
# Update avr8js
cd ../avr8js
git pull origin main
npm install
npm run build
# Actualizar rp2040js
# Update rp2040js
cd ../rp2040js
git pull origin main
npm install
npm run build
```
### Opción 3: Actualizar a una versión específica
### Option 3: Update to a specific version
```bash
cd wokwi-libs/wokwi-elements
# Ver versiones disponibles
# View available versions
git tag -l
# Cambiar a una versión específica
# Switch to a specific version
git checkout v1.9.2
# Recompilar
# Rebuild
npm install
npm run build
```
### Después de Actualizar wokwi-elements
### After Updating wokwi-elements
Si actualizaste wokwi-elements, regenera la metadata de componentes para que nuevos componentes aparezcan en la UI:
If you updated wokwi-elements, regenerate the component metadata so that new components appear in the UI:
```bash
cd frontend
npx tsx ../scripts/generate-component-metadata.ts
```
## Script de Actualización Automática
## Automatic Update Script
El script `update-wokwi-libs.bat` facilita las actualizaciones:
The `update-wokwi-libs.bat` script simplifies updates:
```batch
@echo off
echo ========================================
echo Actualizando Wokwi Libraries
echo Updating Wokwi Libraries
echo ========================================
cd wokwi-libs
echo [1/3] Actualizando wokwi-elements...
echo [1/3] Updating wokwi-elements...
cd wokwi-elements
git pull origin main
npm install
npm run build
cd ..
echo [2/3] Actualizando avr8js...
echo [2/3] Updating avr8js...
cd avr8js
git pull origin main
npm install
npm run build
cd ..
echo [3/3] Actualizando rp2040js...
echo [3/3] Updating rp2040js...
cd rp2040js
git pull origin main
npm install
@ -163,24 +163,26 @@ npm run build
cd ..
echo ========================================
echo Actualizacion completada!
echo Update complete!
echo ========================================
pause
```
## Cómo Se Usan las Librerías
## How the Libraries Are Used
### avr8js — Emulación AVR
### avr8js — AVR Emulation
El `AVRSimulator` (`frontend/src/simulation/AVRSimulator.ts`) usa avr8js para crear:
The `AVRSimulator` (`frontend/src/simulation/AVRSimulator.ts`) uses avr8js to create:
```typescript
import { CPU, avrInstruction, AVRTimer, AVRUSART, AVRADC, AVRIOPort } from 'avr8js';
```typescript
import { CPU, avrInstruction, AVRTimer, AVRUSART, AVRADC, AVRIOPort } from 'avr8js';
// CPU ATmega328p a 16MHz
// ATmega328p CPU at 16MHz
const cpu = new CPU(programMemory);
// Periféricos
// Peripherals
const timer0 = new AVRTimer(cpu, timer0Config);
const timer1 = new AVRTimer(cpu, timer1Config);
const timer2 = new AVRTimer(cpu, timer2Config);
@ -190,67 +192,67 @@ const portB = new AVRIOPort(cpu, portBConfig); // pins 8-13
const portC = new AVRIOPort(cpu, portCConfig); // A0-A5
const portD = new AVRIOPort(cpu, portDConfig); // pins 0-7
// Loop de simulación (~60fps)
// Simulation loop (~60fps)
function runFrame() {
const cyclesToRun = Math.floor(267000 * speed);
for (let i = 0; i < cyclesToRun; i++) {
avrInstruction(cpu); // Ejecuta instrucción AVR
cpu.tick(); // Actualiza periféricos
avrInstruction(cpu); // Execute AVR instruction
cpu.tick(); // Update peripherals
}
requestAnimationFrame(runFrame);
}
```
### wokwi-elements — Componentes Visuales
### wokwi-elements — Visual Components
Los componentes se renderizan de dos formas:
Components are rendered in two ways:
**1. DynamicComponent (sistema actual — 48 componentes)**
**1. DynamicComponent (current system — 48 components)**
```typescript
import { ComponentRegistry } from './services/ComponentRegistry';
// Carga metadata desde /components-metadata.json
// Load metadata from /components-metadata.json
const registry = ComponentRegistry.getInstance();
const metadata = registry.getById('led');
// DynamicComponent crea el web component dinámicamente
// DynamicComponent creates the web component dynamically
// document.createElement(metadata.tagName) → <wokwi-led>
// Sincroniza propiedades React → web component
// Extrae pinInfo del DOM para wire connections
// Syncs React props → web component
// Extracts pinInfo from the DOM for wire connections
```
**2. React wrappers legacy (5 componentes)**
**2. Legacy React wrappers (5 components)**
```tsx
// ArduinoUno.tsx — sigue en uso activo para el board principal
// ArduinoUno.tsx — still actively used for the main board
<wokwi-arduino-uno ref={ref} led13={led13} />
```
### PartSimulationRegistry — Comportamientos de Simulación
### PartSimulationRegistry — Simulation Behaviors
16 partes tienen lógica de simulación registrada que conecta los web components con el emulador AVR:
16 parts have registered simulation logic that connects the web components to the AVR emulator:
| Parte | Tipo | Comportamiento |
|-------|------|----------------|
| Part | Type | Behavior |
|------|------|----------|
| `led` | Output | Pin state → `element.value` |
| `rgb-led` | Output | Digital + PWM en R/G/B |
| `led-bar-graph` | Output | 10 LEDs independientes |
| `7segment` | Output | 8 segmentos (A-G + DP) |
| `rgb-led` | Output | Digital + PWM on R/G/B |
| `led-bar-graph` | Output | 10 independent LEDs |
| `7segment` | Output | 8 segments (A-G + DP) |
| `pushbutton` | Input | Press/release → `setPinState()` |
| `pushbutton-6mm` | Input | Mismo que pushbutton |
| `pushbutton-6mm` | Input | Same as pushbutton |
| `slide-switch` | Input | Change event → pin state |
| `dip-switch-8` | Input | 8 switches independientes |
| `potentiometer` | Input | Valor → voltaje ADC |
| `slide-potentiometer` | Input | Misma lógica por SIG/OUT |
| `photoresistor-sensor` | Input/Output | Voltaje analógico + LED digital |
| `dip-switch-8` | Input | 8 independent switches |
| `potentiometer` | Input | Value → ADC voltage |
| `slide-potentiometer` | Input | Same logic via SIG/OUT |
| `photoresistor-sensor` | Input/Output | Analog voltage + digital LED |
| `analog-joystick` | Input | VRX/VRY (ADC) + SW (digital) |
| `servo` | Output | Registros OCR1A/ICR1 → ángulo 0-180° |
| `servo` | Output | OCR1A/ICR1 registers → angle 0-180° |
| `buzzer` | Output | Web Audio API + Timer2 |
| `lcd1602` | Output | Protocolo HD44780 4-bit completo (16×2) |
| `lcd2004` | Output | Protocolo HD44780 4-bit completo (20×4) |
| `lcd1602` | Output | Full HD44780 4-bit protocol (16×2) |
| `lcd2004` | Output | Full HD44780 4-bit protocol (20×4) |
## Componentes Wokwi Disponibles (48)
## Available Wokwi Components (48)
### Boards (4)
- `wokwi-arduino-uno` — Arduino Uno R3
@ -259,68 +261,68 @@ const metadata = registry.getById('led');
- `wokwi-esp32-devkit-v1` — ESP32 DevKit v1
### Sensors (6)
- `wokwi-dht22` — Temperatura y humedad
- `wokwi-hc-sr04` — Ultrasónico de distancia
- `wokwi-pir-motion-sensor`Sensor de movimiento PIR
- `wokwi-photoresistor-sensor`Fotoresistor (LDR)
- `wokwi-ntc-temperature-sensor`Sensor NTC
- `wokwi-analog-joystick`Joystick analógico
- `wokwi-dht22` — Temperature and humidity sensor
- `wokwi-hc-sr04` — Ultrasonic distance sensor
- `wokwi-pir-motion-sensor`PIR motion sensor
- `wokwi-photoresistor-sensor`Photoresistor (LDR)
- `wokwi-ntc-temperature-sensor`NTC temperature sensor
- `wokwi-analog-joystick`Analog joystick
### Displays (3)
- `wokwi-lcd1602` — LCD 16x2 con protocolo HD44780
- `wokwi-lcd2004` — LCD 20x4 con protocolo HD44780
- `wokwi-7segment`Display de 7 segmentos
- `wokwi-lcd1602` — LCD 16x2 with HD44780 protocol
- `wokwi-lcd2004` — LCD 20x4 with HD44780 protocol
- `wokwi-7segment`7-segment display
### Input (5)
- `wokwi-pushbutton`Botón pulsador
- `wokwi-pushbutton-6mm`Botón 6mm
- `wokwi-slide-switch`Interruptor deslizante
- `wokwi-dip-switch-8` — DIP switch de 8 posiciones
- `wokwi-potentiometer` — Potenciómetro
- `wokwi-pushbutton`Push button
- `wokwi-pushbutton-6mm` — 6mm push button
- `wokwi-slide-switch`Slide switch
- `wokwi-dip-switch-8`8-position DIP switch
- `wokwi-potentiometer` — Potentiometer
### Output (5)
- `wokwi-led`LED de colores
- `wokwi-rgb-led`LED RGB
- `wokwi-led-bar-graph`Barra de LEDs (10)
- `wokwi-buzzer`Buzzer piezoeléctrico
- `wokwi-neopixel`LED RGB direccionable (WS2812)
- `wokwi-led`Colored LED
- `wokwi-rgb-led` — RGB LED
- `wokwi-led-bar-graph`LED bar graph (10 LEDs)
- `wokwi-buzzer`Piezoelectric buzzer
- `wokwi-neopixel`Addressable RGB LED (WS2812)
### Motors (2)
- `wokwi-servo` — Servo motor
- `wokwi-stepper-motor`Motor paso a paso
- `wokwi-stepper-motor`Stepper motor
### Passive (4)
- `wokwi-resistor` — Resistencia con código de colores
- `wokwi-slide-potentiometer`Potenciómetro deslizante
- `wokwi-led-ring`Anillo de LEDs
- `wokwi-membrane-keypad`Teclado matricial
- `wokwi-resistor` — Resistor with color code
- `wokwi-slide-potentiometer`Slide potentiometer
- `wokwi-led-ring`LED ring
- `wokwi-membrane-keypad`Matrix keypad
### Other (19)
- Componentes variados incluyendo `wokwi-ir-receiver`, `wokwi-ds1307`, breadboards, etc.
- Various components including `wokwi-ir-receiver`, `wokwi-ds1307`, breadboards, etc.
## Ventajas de Este Enfoque
## Advantages of This Approach
### Ventajas
### Advantages
1. **Actualización Fácil**: Un simple `git pull` + rebuild te da las últimas mejoras
2. **Compatible con Wokwi**: Usas exactamente el mismo código que Wokwi.com
3. **Descubrimiento Automático**: Nuevos componentes aparecen automáticamente tras regenerar metadata
4. **Control de Versiones**: Puedes hacer checkout a versiones específicas
5. **Desarrollo Flexible**: Código fuente disponible para debugging y modificaciones
6. **Sin Dependencia de npm**: No dependes de que publiquen actualizaciones en npm
7. **100% Offline**: Funciona completamente sin internet después de la configuración inicial
1. **Easy Updates**: A simple `git pull` + rebuild gives you the latest improvements
2. **Wokwi Compatible**: Uses exactly the same code as Wokwi.com
3. **Automatic Discovery**: New components appear automatically after regenerating metadata
4. **Version Control**: You can checkout to specific versions
5. **Flexible Development**: Source code available for debugging and modifications
6. **No npm Dependency**: You don't depend on npm package publications
7. **100% Offline**: Works completely without internet after initial setup
### Consideraciones
### Considerations
1. **Espacio en Disco**: Los repositorios clonados ocupan más espacio (~200MB)
2. **Compilación**: Debes compilar los repositorios después de actualizarlos
3. **Metadata**: Regenerar `components-metadata.json` después de actualizar wokwi-elements
1. **Disk Space**: Cloned repositories take more disk space (~200MB)
2. **Compilation**: You must rebuild the repositories after updating them
3. **Metadata**: Regenerate `components-metadata.json` after updating wokwi-elements
## Troubleshooting
### Error: "Module not found: @wokwi/elements"
Asegúrate de que wokwi-elements esté compilado:
Make sure wokwi-elements is built:
```bash
cd wokwi-libs/wokwi-elements
@ -330,7 +332,7 @@ npm run build
### Error: "Cannot find module 'avr8js'"
Verifica que el alias en `vite.config.ts` esté correcto y que avr8js esté compilado:
Verify that the alias in `vite.config.ts` is correct and that avr8js is built:
```bash
cd wokwi-libs/avr8js
@ -338,29 +340,29 @@ npm install
npm run build
```
### Los componentes no se muestran en el picker
### Components are not shown in the picker
Regenera la metadata de componentes:
Regenerate the component metadata:
```bash
cd frontend
npx tsx ../scripts/generate-component-metadata.ts
```
### Nuevo componente de wokwi-elements no aparece
### New wokwi-elements component does not appear
1. Actualiza wokwi-elements: `cd wokwi-libs/wokwi-elements && git pull && npm run build`
2. Regenera metadata: `cd frontend && npx tsx ../scripts/generate-component-metadata.ts`
3. Si necesita simulación, registra su comportamiento en `frontend/src/simulation/parts/`
1. Update wokwi-elements: `cd wokwi-libs/wokwi-elements && git pull && npm run build`
2. Regenerate metadata: `cd frontend && npx tsx ../scripts/generate-component-metadata.ts`
3. If it needs simulation, register its behavior in `frontend/src/simulation/parts/`
### Los componentes se ven pero no responden a la simulación
### Components are visible but do not respond to simulation
Verifica que el componente tenga lógica de simulación registrada en `PartSimulationRegistry` (archivos `BasicParts.ts` o `ComplexParts.ts`). Solo los 16 componentes registrados tienen comportamiento interactivo.
Verify that the component has simulation logic registered in `PartSimulationRegistry` (files `BasicParts.ts` or `ComplexParts.ts`). Only the 16 registered components have interactive behavior.
## Referencias
## References
- [Wokwi Elements Documentation](https://elements.wokwi.com/)
- [AVR8js Repository](https://github.com/wokwi/avr8js)
- [Wokwi Simulator](https://wokwi.com)
- [Lit Documentation](https://lit.dev/) — Framework usado por wokwi-elements
- [Lit Documentation](https://lit.dev/) — Framework used by wokwi-elements
- [Web Components Guide](https://developer.mozilla.org/en-US/docs/Web/Web_Components)

View File

@ -1,11 +1,11 @@
# Example Projects
Esta carpeta contiene las imágenes de preview para los 8 proyectos de ejemplo de la galería.
This folder contains the preview images for the 8 example projects in the gallery.
## Ejemplos Disponibles
## Available Examples
| ID | Título | Categoría | Dificultad | Componentes |
|----|--------|-----------|------------|-------------|
| ID | Title | Category | Difficulty | Components |
|----|-------|----------|------------|------------|
| `blink-led` | Blink LED | basics | beginner | Arduino Uno |
| `traffic-light` | Traffic Light | basics | beginner | 3 LEDs (R/Y/G) |
| `button-led` | Button Control | basics | beginner | Button + LED |
@ -15,28 +15,28 @@ Esta carpeta contiene las imágenes de preview para los 8 proyectos de ejemplo d
| `simon-says` | Simon Says Game | games | advanced | 4 LEDs + 4 buttons |
| `lcd-hello` | LCD 20x4 Display | displays | intermediate | LCD 2004 |
Cada ejemplo incluye:
- Código Arduino completo
- Definiciones de componentes con posiciones
- Conexiones de cables con pines y colores
Each example includes:
- Complete Arduino sketch code
- Component definitions with positions
- Wire connections with pin names and colors
Los ejemplos se definen en `frontend/src/data/examples.ts` y se renderizan en la galería `ExamplesGallery.tsx` con filtros por categoría y dificultad.
The examples are defined in `frontend/src/data/examples.ts` and rendered in the `ExamplesGallery.tsx` gallery with category and difficulty filters.
## Cómo Crear Screenshots
## How to Create Screenshots
### Método 1: Captura Manual (Recomendado)
### Method 1: Manual Capture (Recommended)
1. Carga el ejemplo en el editor (http://localhost:5173/examples)
2. Haz click en el ejemplo para cargarlo
3. Ajusta el zoom del canvas si es necesario
4. Usa una herramienta de captura de pantalla para capturar solo el área del simulador
5. Guarda la imagen con el nombre correspondiente
1. Load the example in the editor (http://localhost:5173/examples)
2. Click the example to load it
3. Adjust the canvas zoom if needed
4. Use a screenshot tool to capture only the simulator area
5. Save the image with the corresponding name
### Método 2: Usando DevTools
### Method 2: Using DevTools
1. Abre el ejemplo en el navegador
2. Abre DevTools (F12)
3. Ve a la consola y ejecuta:
1. Open the example in the browser
2. Open DevTools (F12)
3. Go to the console and run:
```javascript
const canvas = document.querySelector('.canvas-content');
html2canvas(canvas).then(canvas => {
@ -47,9 +47,9 @@ html2canvas(canvas).then(canvas => {
});
```
## Nombres de Archivos
## File Names
Los archivos deben seguir el ID del ejemplo:
Files must follow the example ID:
- `blink-led.png` — Blink LED
- `traffic-light.png` — Traffic Light
@ -60,26 +60,26 @@ Los archivos deben seguir el ID del ejemplo:
- `simon-says.png` — Simon Says Game
- `lcd-hello.png` — LCD 20x4 Display
## Dimensiones Recomendadas
## Recommended Dimensions
- **Ancho**: 800px
- **Alto**: 500px
- **Formato**: PNG con fondo oscuro (#1e1e1e)
- **Width**: 800px
- **Height**: 500px
- **Format**: PNG with dark background (#1e1e1e)
## Placeholder Actual
## Current Placeholder
Mientras no haya imágenes, se muestra un placeholder con:
- Icono de la categoría (emoji grande)
- Número de componentes (azul cian)
- Número de cables (amarillo)
- Fondo degradado con borde punteado
While no images are available, a placeholder is shown with:
- Category icon (large emoji)
- Number of components (cyan blue)
- Number of wires (yellow)
- Gradient background with dashed border
## Agregar un Nuevo Ejemplo
## Adding a New Example
1. Agregar la definición en `frontend/src/data/examples.ts` con:
1. Add the definition in `frontend/src/data/examples.ts` with:
- `id`, `title`, `description`, `category`, `difficulty`
- `code`: Sketch Arduino completo
- `components[]`: Tipo, posición, propiedades
- `wires[]`: Conexiones con `startPinName`, `endPinName`, `color`
2. (Opcional) Capturar screenshot y guardarlo aquí como `{id}.png`
3. El ejemplo aparecerá automáticamente en la galería con filtrado por categoría y dificultad
- `code`: Complete Arduino sketch
- `components[]`: Type, position, properties
- `wires[]`: Connections with `startPinName`, `endPinName`, `color`
2. (Optional) Capture a screenshot and save it here as `{id}.png`
3. The example will automatically appear in the gallery with category and difficulty filtering

View File

@ -17,12 +17,40 @@
</url>
<url>
<loc>https://velxio.dev/docs</loc>
<loc>https://velxio.dev/docs/intro</loc>
<lastmod>2026-03-11</lastmod>
<changefreq>weekly</changefreq>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://velxio.dev/docs/getting-started</loc>
<lastmod>2026-03-11</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://velxio.dev/docs/emulator</loc>
<lastmod>2026-03-11</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc>https://velxio.dev/docs/components</loc>
<lastmod>2026-03-11</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc>https://velxio.dev/docs/roadmap</loc>
<lastmod>2026-03-11</lastmod>
<changefreq>monthly</changefreq>
<priority>0.6</priority>
</url>
<url>
<loc>https://velxio.dev/examples</loc>
<lastmod>2026-03-06</lastmod>

View File

@ -30,6 +30,7 @@ function App() {
<Route path="/register" element={<RegisterPage />} />
<Route path="/admin" element={<AdminPage />} />
<Route path="/docs" element={<DocsPage />} />
<Route path="/docs/:section" element={<DocsPage />} />
{/* Canonical project URL by ID */}
<Route path="/project/:id" element={<ProjectByIdPage />} />
{/* Legacy slug route — redirects to /project/:id */}

View File

@ -180,6 +180,7 @@
border-radius: var(--radius);
cursor: pointer;
transition: color 0.15s, background 0.15s;
text-decoration: none;
}
.docs-sidebar-item:hover {
@ -406,6 +407,7 @@
padding: 9px 16px;
cursor: pointer;
transition: color 0.15s, border-color 0.15s, background 0.15s;
text-decoration: none;
}
.docs-pagination-btn:hover {

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import React, { useState, useEffect } from 'react';
import { Link, useParams, useNavigate } from 'react-router-dom';
import { useAuthStore } from '../store/useAuthStore';
import './DocsPage.css';
@ -23,6 +23,8 @@ const IcoGitHub = () => (
/* ── Doc sections ──────────────────────────────────────── */
type SectionId = 'intro' | 'getting-started' | 'emulator' | 'components' | 'roadmap';
const VALID_SECTIONS: SectionId[] = ['intro', 'getting-started', 'emulator', 'components', 'roadmap'];
interface NavItem {
id: SectionId;
label: string;
@ -36,6 +38,31 @@ const NAV_ITEMS: NavItem[] = [
{ id: 'roadmap', label: 'Roadmap' },
];
/* ── Per-section SEO metadata ──────────────────────────── */
interface SectionMeta { title: string; description: string; }
const SECTION_META: Record<SectionId, SectionMeta> = {
'intro': {
title: 'Introduction — Velxio Documentation',
description: 'Learn about Velxio, the free open-source Arduino emulator with real AVR8 and RP2040 CPU emulation and 48+ interactive electronic components.',
},
'getting-started': {
title: 'Getting Started — Velxio Documentation',
description: 'Get started with Velxio: use the hosted editor, self-host with Docker, or set up a local development environment. Simulate your first Arduino sketch in minutes.',
},
'emulator': {
title: 'Emulator Architecture — Velxio Documentation',
description: 'How Velxio emulates AVR8 (ATmega328p) and RP2040 CPUs. Covers the execution loop, peripherals (GPIO, Timers, USART, ADC, SPI, I2C), and pin mapping.',
},
'components': {
title: 'Components Reference — Velxio Documentation',
description: 'Full reference for all 48+ interactive electronic components in Velxio: LEDs, displays, sensors, buttons, potentiometers, and more. Includes wiring and property details.',
},
'roadmap': {
title: 'Roadmap — Velxio Documentation',
description: "Velxio's feature roadmap: what's implemented, what's in progress, and what's planned for future releases.",
},
};
/* ── Section content ───────────────────────────────────── */
const IntroSection: React.FC = () => (
<div className="docs-section">
@ -461,11 +488,77 @@ const SECTION_MAP: Record<SectionId, React.FC> = {
/* ── Page ─────────────────────────────────────────────── */
export const DocsPage: React.FC = () => {
const [activeSection, setActiveSection] = useState<SectionId>('intro');
const { section } = useParams<{ section?: string }>();
const navigate = useNavigate();
const [sidebarOpen, setSidebarOpen] = useState(false);
const user = useAuthStore((s) => s.user);
// Derive active section from URL; fall back to 'intro'
const activeSection: SectionId =
section && VALID_SECTIONS.includes(section as SectionId)
? (section as SectionId)
: 'intro';
// Redirect bare /docs → /docs/intro so every section has a canonical URL
useEffect(() => {
if (!section) {
navigate('/docs/intro', { replace: true });
}
}, [section, navigate]);
// Capture the original <head> values once on mount and restore them on unmount
useEffect(() => {
const origTitle = document.title;
const descEl = document.querySelector<HTMLMetaElement>('meta[name="description"]');
const origDesc = descEl?.getAttribute('content') ?? '';
const canonicalEl = document.querySelector<HTMLLinkElement>('link[rel="canonical"]');
const origCanonical = canonicalEl?.getAttribute('href') ?? '';
return () => {
document.title = origTitle;
if (descEl) descEl.setAttribute('content', origDesc);
if (canonicalEl) canonicalEl.setAttribute('href', origCanonical);
document.getElementById('docs-jsonld')?.remove();
};
}, []); // runs once on mount; cleanup runs once on unmount
// Update document title, meta description, canonical, and JSON-LD per section.
// No cleanup here — the mount effect above restores defaults on unmount,
// and on a section change the next run of this effect immediately overwrites.
useEffect(() => {
const meta = SECTION_META[activeSection];
document.title = meta.title;
const descEl = document.querySelector<HTMLMetaElement>('meta[name="description"]');
if (descEl) descEl.setAttribute('content', meta.description);
const canonicalEl = document.querySelector<HTMLLinkElement>('link[rel="canonical"]');
if (canonicalEl) canonicalEl.setAttribute('href', `https://velxio.dev/docs/${activeSection}`);
// Inject / update JSON-LD structured data for this doc page
const ldId = 'docs-jsonld';
let ldScript = document.getElementById(ldId) as HTMLScriptElement | null;
if (!ldScript) {
ldScript = document.createElement('script');
ldScript.id = ldId;
ldScript.type = 'application/ld+json';
document.head.appendChild(ldScript);
}
ldScript.textContent = JSON.stringify({
'@context': 'https://schema.org',
'@type': 'TechArticle',
headline: meta.title,
description: meta.description,
url: `https://velxio.dev/docs/${activeSection}`,
isPartOf: { '@type': 'WebSite', url: 'https://velxio.dev/', name: 'Velxio' },
inLanguage: 'en-US',
author: { '@type': 'Person', name: 'David Montero Crespo', url: 'https://github.com/davidmonterocrespo24' },
});
}, [activeSection]);
const ActiveContent = SECTION_MAP[activeSection];
const activeIdx = NAV_ITEMS.findIndex((i) => i.id === activeSection);
return (
<div className="docs-page">
@ -509,13 +602,14 @@ export const DocsPage: React.FC = () => {
<div className="docs-sidebar-title">Documentation</div>
<nav className="docs-sidebar-nav">
{NAV_ITEMS.map((item) => (
<button
<Link
key={item.id}
to={`/docs/${item.id}`}
className={`docs-sidebar-item${activeSection === item.id ? ' docs-sidebar-item--active' : ''}`}
onClick={() => { setActiveSection(item.id); setSidebarOpen(false); }}
onClick={() => setSidebarOpen(false)}
>
{item.label}
</button>
</Link>
))}
</nav>
<div className="docs-sidebar-divider" />
@ -538,29 +632,23 @@ export const DocsPage: React.FC = () => {
{/* Prev / Next navigation */}
<div className="docs-pagination">
{NAV_ITEMS.findIndex((i) => i.id === activeSection) > 0 && (
<button
{activeIdx > 0 && (
<Link
to={`/docs/${NAV_ITEMS[activeIdx - 1].id}`}
className="docs-pagination-btn docs-pagination-btn--prev"
onClick={() => {
const idx = NAV_ITEMS.findIndex((i) => i.id === activeSection);
setActiveSection(NAV_ITEMS[idx - 1].id);
window.scrollTo(0, 0);
}}
onClick={() => window.scrollTo(0, 0)}
>
{NAV_ITEMS[NAV_ITEMS.findIndex((i) => i.id === activeSection) - 1].label}
</button>
{NAV_ITEMS[activeIdx - 1].label}
</Link>
)}
{NAV_ITEMS.findIndex((i) => i.id === activeSection) < NAV_ITEMS.length - 1 && (
<button
{activeIdx < NAV_ITEMS.length - 1 && (
<Link
to={`/docs/${NAV_ITEMS[activeIdx + 1].id}`}
className="docs-pagination-btn docs-pagination-btn--next"
onClick={() => {
const idx = NAV_ITEMS.findIndex((i) => i.id === activeSection);
setActiveSection(NAV_ITEMS[idx + 1].id);
window.scrollTo(0, 0);
}}
onClick={() => window.scrollTo(0, 0)}
>
{NAV_ITEMS[NAV_ITEMS.findIndex((i) => i.id === activeSection) + 1].label}
</button>
{NAV_ITEMS[activeIdx + 1].label}
</Link>
)}
</div>
</main>