mirror of
https://github.com/mileswolfallen2/miles-web.git
synced 2026-09-08 11:23:17 +00:00
Add uses page and interactive features including toast notifications, cursor effects, and theme toggle
This commit is contained in:
+28
-92
@@ -9,9 +9,27 @@
|
||||
<meta property="og:title" content="Building Nova AI | Miles Wolf Allen">
|
||||
<meta property="og:description" content="How I built Nova AI — a local AI assistant with desktop GUI, web interface, and CLI. No cloud, no subscriptions, no data leaving your machine.">
|
||||
<meta property="og:image" content="https://milesallen.site/og.png">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="article:published_time" content="2025-09-15">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "Building Nova AI | Miles Wolf Allen",
|
||||
"description": "How I built Nova AI — a local AI assistant with desktop GUI, web interface, and CLI. No cloud, no subscriptions, no data leaving your machine.",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "Miles Wolf Allen",
|
||||
"url": "https://milesallen.site/"
|
||||
},
|
||||
"datePublished": "2025-09-15",
|
||||
"url": "https://milesallen.site/blog/nova-devlog.html",
|
||||
"mainEntityOfPage": "https://milesallen.site/blog/nova-devlog.html"
|
||||
}
|
||||
</script>
|
||||
<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="icon" type="image/svg+xml" href="../favicon.svg">
|
||||
<link rel="stylesheet" href="../projects/style.css">
|
||||
<style>
|
||||
.article-header{padding:100px 0 40px;}
|
||||
@@ -141,19 +159,23 @@
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="footer-links" style="margin-bottom: 12px;">
|
||||
<a href="../uses.html" style="color:var(--muted);text-decoration:none;">Uses</a>
|
||||
<span style="color:var(--muted);margin:0 8px;">·</span>
|
||||
<a href="../now.html" style="color:var(--muted);text-decoration:none;">Now</a>
|
||||
<span style="color:var(--muted);margin:0 8px;">·</span>
|
||||
<a href="../colophon.html" style="color:var(--muted);text-decoration:none;">Colophon</a>
|
||||
</div>
|
||||
Built by Miles · 2026 · Powered by too much coffee and the Konami code
|
||||
</footer>
|
||||
</div>
|
||||
<script>
|
||||
fetch('https://api.github.com/repos/mileswolfallen2/')
|
||||
.then(r => r.json())
|
||||
.then(d => {})
|
||||
.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="../projects/script.js"></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>
|
||||
@@ -174,92 +196,6 @@
|
||||
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