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
parent
dc779c46ad
commit
b8bdaf4c65
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 */}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue