mirror of
https://github.com/mileswolfallen2/miles-web.git
synced 2026-09-08 11:23:17 +00:00
update
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Gelectron | Miles Wolf Allen</title>
|
||||
<meta name="description" content="Gelectron — a Firefox-engine alternative to Electron, powered by Servo. Drop-in replacement for Electron apps, just run gelectron . instead of electron.">
|
||||
<link rel="canonical" href="https://milesallen.site/projects/gelectron.html">
|
||||
<meta property="og:title" content="Gelectron | Miles Wolf Allen">
|
||||
<meta property="og:description" content="Gelectron — a Firefox-engine alternative to Electron, powered by Servo. Drop-in replacement for Electron apps.">
|
||||
<meta property="og:image" content="https://milesallen.site/og.png">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Space+Mono:wght@400;700&family=Inter:wght@400;500;600;800&display=swap" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../favicon.png">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="cursor-dot" id="cursorDot"></div>
|
||||
<div class="cursor-ring" id="cursorRing"></div>
|
||||
<div class="progress-bar" id="progressBar"></div>
|
||||
<button class="theme-toggle" id="themeToggle" aria-label="Toggle theme"></button>
|
||||
<div class="shortcut-modal" id="shortcutModal">
|
||||
<div class="shortcut-card">
|
||||
<h3>Keyboard Shortcuts</h3>
|
||||
<div class="shortcut-row"><span>Go Home</span><kbd>H</kbd></div>
|
||||
<div class="shortcut-row"><span>Go to GitHub</span><kbd>G</kbd></div>
|
||||
<div class="shortcut-row"><span>Toggle theme</span><kbd>T</kbd></div>
|
||||
<div class="shortcut-row"><span>Show shortcuts</span><kbd>?</kbd></div>
|
||||
<div class="close-hint">Press Esc or ? to close</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flash" id="flash"></div>
|
||||
<div class="toast-stack" id="toastStack"></div>
|
||||
<nav class="mobile-nav">
|
||||
<a href="../index.html">Home</a>
|
||||
<a href="fedl.html">FEDL</a>
|
||||
<a href="gelectron.html" class="active">Gelectron</a>
|
||||
<a href="omniemu.html">OmniEmu</a>
|
||||
<a href="command-move.html">CommandMove</a>
|
||||
<a href="https://github.com/mileswolfallen2" target="_blank">GitHub</a>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<nav>
|
||||
<a href="../index.html" class="nav-logo"><span class="logo-dot"></span> milesallen</a>
|
||||
<div class="nav-links">
|
||||
<a href="../index.html#about">About</a>
|
||||
<a href="../index.html#skills">Skills</a>
|
||||
<a href="../index.html#projects">Projects</a>
|
||||
<a href="../index.html#contact">Contact</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section class="project-hero">
|
||||
<div class="breadcrumb">
|
||||
<a href="../index.html">Home</a>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
||||
<span>Gelectron</span>
|
||||
</div>
|
||||
|
||||
<h1>Gelectron</h1>
|
||||
<p class="tagline">Electron, but lighter. A Firefox-engine alternative powered by Servo. Drop-in replacement — just run gelectron . instead of electron .</p>
|
||||
|
||||
<div class="project-meta-bar">
|
||||
<a href="https://github.com/mileswolfallen2/gelectron" class="meta-chip primary" target="_blank">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 00-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0020 4.77 5.07 5.07 0 0019.91 1S18.73.65 16 2.48a13.38 13.38 0 00-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 005 4.77a5.44 5.44 0 00-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 009 18.13V22"/></svg>
|
||||
View on GitHub
|
||||
</a>
|
||||
<span class="meta-chip" style="border-color: #e6a817; color: #e6a817;">Early Development</span>
|
||||
<span class="meta-chip">Rust + Node.js</span>
|
||||
<span class="meta-chip">MIT License</span>
|
||||
</div>
|
||||
<div class="stats-bar">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value accent" id="gh-stars">--</div>
|
||||
<div class="stat-label">Stars</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value green" id="gh-forks">--</div>
|
||||
<div class="stat-label">Forks</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value orange" id="gh-issues">--</div>
|
||||
<div class="stat-label">Issues</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value" id="gh-lang">--</div>
|
||||
<div class="stat-label">Language</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="section-divider"></div>
|
||||
<h2 class="section-title">Features</h2>
|
||||
<p class="section-subtitle">Why Gelectron exists</p>
|
||||
|
||||
<div class="feature-grid">
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Drop-in Replacement
|
||||
</h3>
|
||||
<p>Run gelectron . instead of electron . and your app just works. Same Node.js code, same require('electron') imports, zero changes needed.</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 10h-1.26A8 8 0 109 20h9a5 5 0 000-10z"/></svg>
|
||||
Servo Engine
|
||||
</h3>
|
||||
<p>Powered by Servo, Mozilla's next-gen browser engine. Uses Gecko's CSS engine (Stylo) and GPU compositor (WebRender) instead of bundling Chromium.</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><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>
|
||||
Electron API Compat
|
||||
</h3>
|
||||
<p>Implements core Electron APIs: app, BrowserWindow, ipcMain/ipcRenderer, Menu, Tray, Dialog, Shell, Notification, nativeImage, contextBridge, and more.</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.66 0 3-4.03 3-9s-1.34-9-3-9m0 18c-1.66 0-3-4.03-3-9s1.34-9 3-9"/></svg>
|
||||
Smaller Binaries
|
||||
</h3>
|
||||
<p>Rust static linking means smaller output than Electron's Chromium bundle. No more 150MB+ binaries for simple apps.</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
||||
Lower Memory
|
||||
</h3>
|
||||
<p>Servo's architecture is designed for embedding and uses less memory than Chromium. Your users will notice the difference.</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/></svg>
|
||||
Built with Rust
|
||||
</h3>
|
||||
<p>Core engine written in Rust for safety and performance. N-API addon bridges Rust and Node.js seamlessly.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="section-divider"></div>
|
||||
<h2 class="section-title">Tech Stack</h2>
|
||||
<ul>
|
||||
<li>Rust (core engine, N-API addon)</li>
|
||||
<li>Node.js (CLI, Electron compat layer)</li>
|
||||
<li>Servo (rendering engine)</li>
|
||||
<li>winit (window management)</li>
|
||||
<li>muda (native menus)</li>
|
||||
<li>tray-icon (system tray)</li>
|
||||
<li>rfd (file dialogs)</li>
|
||||
<li>Stylo (CSS engine)</li>
|
||||
<li>WebRender (GPU compositor)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="section-divider"></div>
|
||||
<h2 class="section-title">Status</h2>
|
||||
<div class="desc-text">
|
||||
<p>Gelectron is in very early development. This is an experiment — a proof of concept that Electron apps can run on a non-Chromium engine. Many Electron APIs are currently stubs or incomplete. Some things will break. Some things don't exist yet.</p>
|
||||
<p>The goal right now isn't to replace Electron for production apps. It's to explore whether this is possible, learn how Electron's internals work, and build a foundation that could grow into something real.</p>
|
||||
<p>If you're curious, try it out with a simple Electron app. If you find bugs, open an issue. If you want to contribute, even better.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="section-divider"></div>
|
||||
<h2 class="section-title">Known Limitations</h2>
|
||||
<ul>
|
||||
<li>Servo is still in active development; some web APIs may be missing</li>
|
||||
<li>electron-updater requires custom implementation (not yet included)</li>
|
||||
<li>Some Electron APIs are stubs</li>
|
||||
<li>Native menu integration is platform-dependent</li>
|
||||
<li>Auto-updater not yet implemented</li>
|
||||
<li>Single-window only in initial version</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="section-divider"></div>
|
||||
<h2 class="section-title">Roadmap</h2>
|
||||
<ul>
|
||||
<li>Full Servo integration</li>
|
||||
<li>Multi-window support</li>
|
||||
<li>Custom protocol handlers (gelectron://)</li>
|
||||
<li>Auto-updater implementation</li>
|
||||
<li>DevTools integration</li>
|
||||
<li>Build/package tools for distribution</li>
|
||||
<li>App sandboxing</li>
|
||||
<li>Performance optimizations</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="reveal">
|
||||
<div class="cta-group">
|
||||
<a href="https://github.com/mileswolfallen2/gelectron" class="meta-chip primary" target="_blank">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 00-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0020 4.77 5.07 5.07 0 0019.91 1S18.73.65 16 2.48a13.38 13.38 0 00-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 005 4.77a5.44 5.44 0 00-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 009 18.13V22"/></svg>
|
||||
View on GitHub
|
||||
</a>
|
||||
<a href="../index.html#projects" class="meta-chip">Back to Projects</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
Built by Miles · 2026 · Powered by too much coffee and the Konami code
|
||||
</footer>
|
||||
</div>
|
||||
<script>
|
||||
fetch('https://api.github.com/repos/mileswolfallen2/gelectron')
|
||||
.then(r => r.json())
|
||||
.then(d => {
|
||||
if (d.stargazers_count != null) document.getElementById('gh-stars').textContent = d.stargazers_count;
|
||||
if (d.forks_count != null) document.getElementById('gh-forks').textContent = d.forks_count;
|
||||
if (d.open_issues_count != null) document.getElementById('gh-issues').textContent = d.open_issues_count;
|
||||
if (d.language) document.getElementById('gh-lang').textContent = d.language;
|
||||
})
|
||||
.catch(() => {});
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('visible'); });
|
||||
}, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' });
|
||||
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/[email protected]/gsap.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/[email protected]/ScrollTrigger.min.js"></script>
|
||||
<script>
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
// Hero entrance
|
||||
const heroTl = gsap.timeline({ defaults: { ease: 'power3.out' } });
|
||||
heroTl
|
||||
.from('.breadcrumb', { x: -30, opacity: 0, duration: 0.6 })
|
||||
.from('.project-hero h1', { y: 50, opacity: 0, duration: 0.8 }, '-=0.3')
|
||||
.from('.tagline', { y: 30, opacity: 0, duration: 0.7 }, '-=0.4')
|
||||
.from('.meta-chip', { y: 20, opacity: 0, scale: 0.8, duration: 0.4, stagger: 0.06 }, '-=0.3')
|
||||
.from('.stats-bar', { y: 30, opacity: 0, duration: 0.6 }, '-=0.2')
|
||||
.from('.stat-item', { y: 20, opacity: 0, scale: 0.9, duration: 0.4, stagger: 0.08, ease: 'back.out(1.5)' }, '-=0.3');
|
||||
|
||||
// Nav entrance
|
||||
gsap.from('nav', { y: -20, opacity: 0, duration: 0.6, ease: 'power2.out' });
|
||||
|
||||
// Section titles
|
||||
document.querySelectorAll('.section-title').forEach(title => {
|
||||
gsap.from(title, {
|
||||
scrollTrigger: { trigger: title, start: 'top 85%' },
|
||||
y: 30, opacity: 0, duration: 0.7, ease: 'power3.out'
|
||||
});
|
||||
});
|
||||
|
||||
// Section dividers
|
||||
document.querySelectorAll('.section-divider').forEach(div => {
|
||||
gsap.from(div, {
|
||||
scrollTrigger: { trigger: div, start: 'top 90%' },
|
||||
width: 0, duration: 0.6, ease: 'power2.out'
|
||||
});
|
||||
});
|
||||
|
||||
// Feature cards stagger
|
||||
document.querySelectorAll('.feature-grid').forEach(grid => {
|
||||
gsap.from(grid.querySelectorAll('.feature-card'), {
|
||||
scrollTrigger: { trigger: grid, start: 'top 85%' },
|
||||
y: 50, opacity: 0, scale: 0.9, duration: 0.6, stagger: 0.1, ease: 'power3.out'
|
||||
});
|
||||
});
|
||||
|
||||
// Tech badges
|
||||
document.querySelectorAll('.tech-stack').forEach(stack => {
|
||||
gsap.from(stack.querySelectorAll('.tech-badge'), {
|
||||
scrollTrigger: { trigger: stack, start: 'top 88%' },
|
||||
y: 20, opacity: 0, scale: 0.8, duration: 0.4, stagger: 0.05, ease: 'back.out(1.5)'
|
||||
});
|
||||
});
|
||||
|
||||
// Tables
|
||||
document.querySelectorAll('.table-wrapper').forEach(wrapper => {
|
||||
gsap.from(wrapper, {
|
||||
scrollTrigger: { trigger: wrapper, start: 'top 85%' },
|
||||
y: 40, opacity: 0, duration: 0.7, ease: 'power3.out'
|
||||
});
|
||||
});
|
||||
|
||||
// Code blocks
|
||||
document.querySelectorAll('code-block').forEach(block => {
|
||||
gsap.from(block, {
|
||||
scrollTrigger: { trigger: block, start: 'top 88%' },
|
||||
y: 30, opacity: 0, duration: 0.6, ease: 'power3.out'
|
||||
});
|
||||
});
|
||||
|
||||
// Footer
|
||||
gsap.from('footer', {
|
||||
scrollTrigger: { trigger: 'footer', start: 'top 95%' },
|
||||
opacity: 0, duration: 0.8
|
||||
});
|
||||
|
||||
window.addEventListener('load', () => ScrollTrigger.refresh());
|
||||
</script>
|
||||
<script>
|
||||
var toastQueue=document.getElementById('toastStack');var shownToasts={};
|
||||
function showToast(id,title,body,icon){
|
||||
if(shownToasts[id])return;shownToasts[id]=true;
|
||||
var t=document.createElement('div');t.className='toast';
|
||||
t.innerHTML='<span class="icon">'+(icon||'!')+'</span><span><span class="title">'+title+'</span>'+body+'</span>';
|
||||
toastQueue.appendChild(t);
|
||||
gsap.to(t,{x:0,duration:.6,ease:'power3.out'});
|
||||
setTimeout(function(){gsap.to(t,{x:'-150%',opacity:0,duration:.4,ease:'power2.in',onComplete:function(){t.remove();}});},3000);
|
||||
}
|
||||
(function(){
|
||||
var seq=['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a'];
|
||||
var pos=0;
|
||||
window.addEventListener('keydown',function(e){
|
||||
var key=e.key.length===1?e.key.toLowerCase():e.key;
|
||||
if(key===seq[pos]){pos++;if(pos===seq.length){pos=0;triggerKonami();}}
|
||||
else{pos=(key===seq[0])?1:0;}
|
||||
});
|
||||
function triggerKonami(){
|
||||
showToast('konami','SECRET FOUND','Konami Code Activated','*');
|
||||
var flash=document.getElementById('flash');
|
||||
gsap.fromTo(flash,{opacity:.5},{opacity:0,duration:.5});
|
||||
gsap.to('body',{x:'random(-5,5)',y:'random(-5,5)',duration:.05,repeat:10,ease:'sine.inOut',onComplete:function(){gsap.set('body',{x:0,y:0});}});
|
||||
document.body.style.cursor='auto';
|
||||
var style=document.createElement('style');style.id='konami-cursor';
|
||||
style.textContent='*{cursor:auto !important;}';
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function(){
|
||||
var dot=document.getElementById('cursorDot');
|
||||
var ring=document.getElementById('cursorRing');
|
||||
if(!dot||!ring)return;
|
||||
var mx=0,my=0,rx=0,ry=0;
|
||||
document.addEventListener('mousemove',function(e){mx=e.clientX;my=e.clientY;dot.style.left=mx+'px';dot.style.top=my+'px';});
|
||||
(function loop(){
|
||||
rx+=(mx-rx)*0.15;ry+=(my-ry)*0.15;
|
||||
ring.style.left=rx+'px';ring.style.top=ry+'px';
|
||||
requestAnimationFrame(loop);
|
||||
})();
|
||||
document.querySelectorAll('a,button,.meta-chip,.tech-badge,.feature-card').forEach(function(el){
|
||||
el.addEventListener('mouseenter',function(){dot.classList.add('hover');ring.classList.add('hover');});
|
||||
el.addEventListener('mouseleave',function(){dot.classList.remove('hover');ring.classList.remove('hover');});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(function(){
|
||||
var bar=document.getElementById('progressBar');
|
||||
window.addEventListener('scroll',function(){
|
||||
var pct=window.scrollY/(document.body.scrollHeight-window.innerHeight)*100;
|
||||
bar.style.width=pct+'%';
|
||||
},{passive:true});
|
||||
})();
|
||||
(function(){
|
||||
var btn=document.getElementById('themeToggle');
|
||||
var saved=localStorage.getItem('theme');
|
||||
if(saved==='light')document.body.classList.add('light');
|
||||
function updateIcon(){btn.textContent=document.body.classList.contains('light')?'\u263E':'\u2600';}
|
||||
updateIcon();
|
||||
btn.addEventListener('click',function(){
|
||||
document.body.classList.toggle('light');
|
||||
localStorage.setItem('theme',document.body.classList.contains('light')?'light':'dark');
|
||||
updateIcon();
|
||||
});
|
||||
})();
|
||||
(function(){
|
||||
var modal=document.getElementById('shortcutModal');
|
||||
function toggleModal(){modal.classList.toggle('open');}
|
||||
window.addEventListener('keydown',function(e){
|
||||
if(e.key==='?'){e.preventDefault();toggleModal();}
|
||||
if(e.key==='Escape')modal.classList.remove('open');
|
||||
if(e.key==='t'||e.key==='T'){
|
||||
if(document.activeElement&&document.activeElement.tagName==='INPUT')return;
|
||||
document.body.classList.toggle('light');
|
||||
localStorage.setItem('theme',document.body.classList.contains('light')?'light':'dark');
|
||||
var btn=document.getElementById('themeToggle');
|
||||
btn.textContent=document.body.classList.contains('light')?'\u263E':'\u2600';
|
||||
}
|
||||
if(e.key==='h'||e.key==='H')window.location.href='../index.html';
|
||||
if(e.key==='g'||e.key==='G')window.location.href='https://github.com/mileswolfallen2';
|
||||
});
|
||||
modal.addEventListener('click',function(e){if(e.target===modal)modal.classList.remove('open');});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user