497 lines
21 KiB
TypeScript
497 lines
21 KiB
TypeScript
/**
|
|
* /v3 — Velxio 3.0 Release Landing Page
|
|
* Highlights programmable retro CPUs (Z80/8080/4004/4040/8086), MicroSD and
|
|
* ePaper emulation, true multi-board interconnect, full undo/redo, the ngspice
|
|
* WASM migration, an 88% smaller bundle, and 100+ new gallery examples.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { AppHeader } from '../components/layout/AppHeader';
|
|
import { useLocalizedHref } from '../i18n/useLocalizedNavigate';
|
|
import { useSEO } from '../utils/useSEO';
|
|
import { getSeoMeta } from '../seoRoutes';
|
|
import { trackClickCTA } from '../utils/analytics';
|
|
import './SEOPage.css';
|
|
import './Velxio2Page.css';
|
|
|
|
const GITHUB_URL = 'https://github.com/davidmonterocrespo24/velxio';
|
|
const DISCORD_URL = 'https://discord.gg/3mARjJrh4E';
|
|
|
|
/* ── SVG Icons (no emojis) ─────────────────────────────── */
|
|
const IcoRocket = () => (
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" />
|
|
<path d="M12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" />
|
|
<path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" />
|
|
<path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoChip = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<rect x="5" y="5" width="14" height="14" rx="2" />
|
|
<rect x="9" y="9" width="6" height="6" />
|
|
<path d="M9 1v4M15 1v4M9 19v4M15 19v4M1 9h4M1 15h4M19 9h4M19 15h4" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoCard = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M5 3h10l4 4v14a0 0 0 0 1 0 0H5a0 0 0 0 1 0 0V3z" />
|
|
<path d="M9 3v5M13 3v5M9 13h6M9 17h6" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoLink = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
|
|
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoBook = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
|
|
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoWave = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M2 12h3l3-9 4 18 3-12 3 6h4" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoUndo = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M3 7v6h6" />
|
|
<path d="M3 13a9 9 0 1 0 3-7.7L3 8" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoGauge = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M12 14a2 2 0 1 0 0-.001" />
|
|
<path d="M12 14l4-4" />
|
|
<path d="M4 19a8 8 0 1 1 16 0" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoLightning = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoTestTube = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5s-2.5-1.1-2.5-2.5V2" />
|
|
<path d="M8.5 2h7" />
|
|
<path d="M14.5 16h-5" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoGitHub = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61-.546-1.385-1.335-1.755-1.335-1.755-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 21.795 24 17.295 24 12c0-6.63-5.37-12-12-12z" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoDiscord = () => (
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z" />
|
|
</svg>
|
|
);
|
|
|
|
const IcoStar = () => (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
|
|
</svg>
|
|
);
|
|
|
|
const JSON_LD: object[] = [
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'SoftwareApplication',
|
|
name: 'Velxio 3.0 — Retro CPU, Multi-Board & Circuit Simulator',
|
|
applicationCategory: 'DeveloperApplication',
|
|
operatingSystem: 'Any (browser-based)',
|
|
softwareVersion: '3.0.0',
|
|
description:
|
|
'Velxio 3.0 adds programmable retro CPUs (Z80, 8080, 4004, 4040, 8086), MicroSD card emulation, ePaper displays, true multi-board UART/I2C/SPI interconnect, full undo/redo, a full ngspice WASM migration, an 88% smaller bundle, and 100+ new gallery examples. Free and open-source.',
|
|
url: 'https://velxio.dev/v3',
|
|
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
author: { '@type': 'Person', name: 'David Montero Crespo' },
|
|
license: 'https://www.gnu.org/licenses/agpl-3.0.html',
|
|
},
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'BreadcrumbList',
|
|
itemListElement: [
|
|
{ '@type': 'ListItem', position: 1, name: 'Velxio', item: 'https://velxio.dev/' },
|
|
{ '@type': 'ListItem', position: 2, name: 'Velxio 3.0', item: 'https://velxio.dev/v3' },
|
|
],
|
|
},
|
|
{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'FAQPage',
|
|
mainEntity: [
|
|
{
|
|
'@type': 'Question',
|
|
name: 'What is new in Velxio 3.0?',
|
|
acceptedAnswer: {
|
|
'@type': 'Answer',
|
|
text: 'Velxio 3.0 adds programmable retro CPUs (Z80, Intel 8080, 4004, 4040 and 8086) with custom ROM and in-editor assembly, MicroSD card emulation over SPI, ePaper display emulation (SSD168x, UC8159c 7-colour, UC8179), true multi-board UART/I2C/SPI/GPIO interconnect, ESP32-CAM with a real webcam bridge, full undo/redo, a complete ngspice WASM migration, an 88% smaller bundle, much faster ESP-IDF compiles, and 100+ new gallery examples.',
|
|
},
|
|
},
|
|
{
|
|
'@type': 'Question',
|
|
name: 'Can I run retro CPUs like the Z80 or Intel 4004 in the browser?',
|
|
acceptedAnswer: {
|
|
'@type': 'Answer',
|
|
text: 'Yes. Velxio 3.0 emulates Z80, Intel 8080, 4004, 4040 and 8086 as canvas chips. Load your own ROM, write assembly in the built-in editor, and run them board-less or wired to modern peripherals — all in the browser, no install.',
|
|
},
|
|
},
|
|
{
|
|
'@type': 'Question',
|
|
name: 'Can multiple boards talk to each other in Velxio?',
|
|
acceptedAnswer: {
|
|
'@type': 'Answer',
|
|
text: 'Yes. Velxio 3.0 has wire-aware multi-board interconnect: UART, I2C, SPI and plain GPIO links work across every supported board, so an ESP32, a Raspberry Pi Pico and an Arduino can communicate on the same canvas, solved together.',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const CHANGE_SECTIONS = [
|
|
{
|
|
icon: <IcoChip />,
|
|
title: 'Retro CPU Chips',
|
|
color: '#8957e5',
|
|
items: [
|
|
'Z80, Intel 8080, 4004, 4040 and 8086 processors',
|
|
'Programmable ROM — load your own machine code',
|
|
'Board-less operation: run a bare CPU with no host board',
|
|
'In-editor assembly support for retro targets',
|
|
'Step a classic instruction set right on the canvas',
|
|
'Pair retro CPUs with modern peripherals',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoCard />,
|
|
title: 'Storage & ePaper Displays',
|
|
color: '#007acc',
|
|
items: [
|
|
'MicroSD card emulation over SPI (AVR, RP2040, ESP32)',
|
|
'FAT16 image with an upload panel — read and write real files',
|
|
'ePaper SSD168x panels: black/white and tri-colour',
|
|
'UC8159c ACeP 7-colour ePaper',
|
|
'UC8179 mono ePaper with correct rotation and BUSY timing',
|
|
'Byte-aware panel orientation across every board',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoLink />,
|
|
title: 'Multi-Board Interconnect',
|
|
color: '#b08800',
|
|
items: [
|
|
'Wire-aware UART, I2C, SPI and digital links across boards',
|
|
'An ESP32, a Pico and an Arduino on one canvas, talking',
|
|
'SignalRouter for ESP32 GPIO Matrix routing',
|
|
'ESP32-CAM emulation with a real webcam frame bridge via QEMU',
|
|
'Board removal reconciles the running simulation cleanly',
|
|
'Every supported board can interconnect',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoBook />,
|
|
title: 'Library Manager',
|
|
color: '#1a7f37',
|
|
items: [
|
|
'Per-board library manifests scoped to each compile',
|
|
'Content-addressed cache — deduped, fast and shared',
|
|
'Version management, uninstall, and autocomplete',
|
|
'src/-layout libraries (ArduinoJson, etc.) compile correctly',
|
|
'Single unified tab with state-aware row actions',
|
|
'Add to project / In project / Remove in one place',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoWave />,
|
|
title: 'Simulation Accuracy',
|
|
color: '#4a9e6b',
|
|
items: [
|
|
'Full ngspice WASM migration — one solver path, browser and Node',
|
|
'PinResolver: SPICE-resolved digital inputs for mixed-mode',
|
|
'Oscilloscope trigger modes — Auto, Normal, Single',
|
|
'Edge selection and trigger-position control',
|
|
'RP2040 real-time: IdleSpinDetector elides busy-wait loops',
|
|
'AVR and ESP32 UART waveforms synthesized at the bit level',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoUndo />,
|
|
title: 'Editor & Canvas',
|
|
color: '#c8701a',
|
|
items: [
|
|
'Full undo/redo: components, wires, moves, rotations, properties',
|
|
'Draggable minimap with a moveable viewport',
|
|
'Drag-to-move parts while the simulation runs',
|
|
'Wires follow component rotation automatically',
|
|
'Component deletion cascades to connected wires',
|
|
'Board options modal and per-target compile console',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoGauge />,
|
|
title: 'Performance',
|
|
color: '#a8304d',
|
|
items: [
|
|
'Main bundle cut 88% — from ~23 MB to ~2.68 MB',
|
|
'manualChunks split wokwi-elements, terminal and MCU emulators',
|
|
'ESP-IDF warm compiles drop from 5-7 min to 5-30 s',
|
|
'ccache with an 8 GB cap and persistent build directories',
|
|
'Compilation dedup stops duplicate ninja jobs racing',
|
|
'Faster SPI/I2C waveform rendering via worker batching',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoStar />,
|
|
title: 'Pro & Desktop',
|
|
color: '#6e7681',
|
|
items: [
|
|
'GitHub Sync, Share/Embed modal, BOM CSV and schematic PNG export',
|
|
'Desktop app: welcome page, license gating, native menubar',
|
|
'In-app update toast and a splash screen during boot',
|
|
'i18n across 9 locales (en, es, pt-br, it, fr, zh-cn, de, ja, ru)',
|
|
'Extension hooks for private overlays (auth, session, agent chat)',
|
|
'.vlx project export/import for stateless self-hosters',
|
|
],
|
|
},
|
|
{
|
|
icon: <IcoTestTube />,
|
|
title: 'Examples & Testing',
|
|
color: '#a8304d',
|
|
items: [
|
|
'100+ new gallery examples added',
|
|
'Pico Doom, ESP32-CAM preview, ePaper dashboards, retro-CPU demos',
|
|
'A 100 Days of IoT series and dozens of analog circuits',
|
|
'Netlist snapshot tests for every gallery example',
|
|
'Visual LED test harness driven over Chrome DevTools Protocol',
|
|
'Backend end-to-end tests re-enabled in CI',
|
|
],
|
|
},
|
|
];
|
|
|
|
export const Velxio3Page: React.FC = () => {
|
|
const { t } = useTranslation();
|
|
const localize = useLocalizedHref();
|
|
useSEO({ ...getSeoMeta('/v3')!, jsonLd: JSON_LD });
|
|
|
|
return (
|
|
<div className="seo-page">
|
|
<AppHeader />
|
|
<main>
|
|
{/* ── Hero ── */}
|
|
<section className="v2-hero">
|
|
<div className="v2-version-badge">
|
|
<IcoRocket /> {t('v3.versionBadge')}
|
|
</div>
|
|
<h1>
|
|
Velxio 3.0
|
|
<br />
|
|
<span className="accent">{t('v3.heroAccent')}</span>
|
|
</h1>
|
|
<p className="subtitle">{t('v3.heroSubtitle')}</p>
|
|
<div className="seo-cta-group">
|
|
<Link
|
|
to={localize('/editor')}
|
|
className="seo-btn-primary"
|
|
onClick={() => trackClickCTA('velxio-v3', '/editor')}
|
|
>
|
|
<IcoLightning />
|
|
{t('v3.tryV3')}
|
|
</Link>
|
|
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="seo-btn-secondary">
|
|
<IcoGitHub /> {t('landing.hero.ctaGithub')}
|
|
</a>
|
|
</div>
|
|
|
|
<div className="v2-community-row">
|
|
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="v2-community-btn v2-star-btn">
|
|
<IcoStar />
|
|
<span>{t('starBanner.cta')}</span>
|
|
</a>
|
|
<a href={DISCORD_URL} target="_blank" rel="noopener noreferrer" className="v2-community-btn v2-discord-btn">
|
|
<IcoDiscord />
|
|
<span>{t('v2.joinDiscord')}</span>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── What's new ── */}
|
|
<section className="seo-section">
|
|
<h2>{t('v3.whatsNewHeading')}</h2>
|
|
<p className="lead">{t('v3.whatsNewLead')}</p>
|
|
|
|
<div className="seo-grid">
|
|
<div className="seo-card">
|
|
<h3>{t('v3.retroTitle')}</h3>
|
|
<p>{t('v3.retroBody')}</p>
|
|
</div>
|
|
<div className="seo-card">
|
|
<h3>{t('v3.multiBoardTitle')}</h3>
|
|
<p>{t('v3.multiBoardBody')}</p>
|
|
</div>
|
|
<div className="seo-card">
|
|
<h3>{t('v3.polishTitle')}</h3>
|
|
<p>{t('v3.polishBody')}</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── Full changelog ── */}
|
|
<section className="seo-section">
|
|
<h2>{t('v3.catalogHeading')}</h2>
|
|
<p className="lead">{t('v3.catalogLead')}</p>
|
|
|
|
<div className="v2-changelog">
|
|
{CHANGE_SECTIONS.map((section) => (
|
|
<div key={section.title} className="v2-change-block">
|
|
<div className="v2-change-header" style={{ color: section.color }}>
|
|
{section.icon}
|
|
<h3>{section.title}</h3>
|
|
</div>
|
|
<ul className="v2-change-list">
|
|
{section.items.map((item) => (
|
|
<li key={item}>{item}</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── Examples ── */}
|
|
<section className="seo-section">
|
|
<h2>{t('v3.examplesHeading')}</h2>
|
|
<p className="lead">{t('v3.examplesLead')}</p>
|
|
<div style={{ textAlign: 'center', marginTop: 24 }}>
|
|
<Link to={localize('/examples')} className="seo-btn-secondary">
|
|
{t('examples.browseAll')}
|
|
</Link>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── Outcome ── */}
|
|
<section className="seo-section">
|
|
<h2>{t('v3.outcomeHeading')}</h2>
|
|
<p className="lead">{t('v3.outcomeLead')}</p>
|
|
<div className="seo-grid">
|
|
<div className="seo-card">
|
|
<h3>{t('v3.outcome.build')}</h3>
|
|
<p>{t('v3.outcome.buildBody')}</p>
|
|
</div>
|
|
<div className="seo-card">
|
|
<h3>{t('v3.outcome.learn')}</h3>
|
|
<p>{t('v3.outcome.learnBody')}</p>
|
|
</div>
|
|
<div className="seo-card">
|
|
<h3>{t('v3.outcome.openSource')}</h3>
|
|
<p>{t('v3.outcome.openSourceBody')}</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── Built on ── */}
|
|
<section className="seo-section">
|
|
<h2>{t('v2.builtOnOss')}</h2>
|
|
<p className="lead">{t('v3.builtOnOssLead')}</p>
|
|
<div className="v2-repos">
|
|
<a href="https://ngspice.sourceforge.io/" target="_blank" rel="noopener noreferrer" className="v2-repo-card">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>ngspice</h3>
|
|
<p>The open-source SPICE circuit simulator — now the single analog solver across browser and tests</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://www.qemu.org/" target="_blank" rel="noopener noreferrer" className="v2-repo-card">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>QEMU</h3>
|
|
<p>Powers ESP32 (Xtensa), RISC-V, ARM and the new ESP32-CAM webcam bridge</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://github.com/wokwi/avr8js" target="_blank" rel="noopener noreferrer" className="v2-repo-card">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>avr8js</h3>
|
|
<p>AVR8 CPU emulator in JavaScript — Arduino Uno, Nano, Mega, ATtiny85</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://github.com/wokwi/rp2040js" target="_blank" rel="noopener noreferrer" className="v2-repo-card">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>rp2040js</h3>
|
|
<p>RP2040 emulator — Raspberry Pi Pico and Pico W, now running in real time</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://github.com/wokwi/wokwi-elements" target="_blank" rel="noopener noreferrer" className="v2-repo-card">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>wokwi-elements</h3>
|
|
<p>Web Components for electronic parts — LEDs, buttons, sensors, displays</p>
|
|
</div>
|
|
</a>
|
|
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="v2-repo-card v2-repo-card--primary">
|
|
<IcoGitHub />
|
|
<div>
|
|
<h3>Velxio</h3>
|
|
<p>This project — free, open-source embedded systems & circuit simulator</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ── Bottom CTA ── */}
|
|
<div className="seo-bottom">
|
|
<h2>{t('v3.bottom.title')}</h2>
|
|
<p>{t('v3.bottom.body')}</p>
|
|
<Link
|
|
to={localize('/editor')}
|
|
className="seo-btn-primary"
|
|
onClick={() => trackClickCTA('velxio-v3', '/editor')}
|
|
>
|
|
{t('v2.bottom.cta')}
|
|
</Link>
|
|
|
|
<div className="v2-bottom-community">
|
|
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="v2-community-btn v2-star-btn">
|
|
<IcoStar />
|
|
<span>{t('starBanner.cta')}</span>
|
|
</a>
|
|
<a href={DISCORD_URL} target="_blank" rel="noopener noreferrer" className="v2-community-btn v2-discord-btn">
|
|
<IcoDiscord />
|
|
<span>{t('v2.joinDiscord')}</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div className="seo-internal-links">
|
|
<Link to={localize('/')}>{t('header.nav.home')}</Link>
|
|
<Link to={localize('/v2-5')}>Velxio 2.5</Link>
|
|
<Link to={localize('/v2')}>Velxio 2.0</Link>
|
|
<Link to={localize('/examples')}>{t('header.nav.examples')}</Link>
|
|
<Link to={localize('/docs/intro')}>{t('header.nav.documentation')}</Link>
|
|
<Link to={localize('/arduino-simulator')}>Arduino Simulator</Link>
|
|
<Link to={localize('/esp32-simulator')}>ESP32 Simulator</Link>
|
|
<Link to={localize('/about')}>{t('header.nav.about')}</Link>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
};
|