Add project highlights section and update project stats

- Introduced a new "Project Highlights" section in index.html with detailed stats for FEDL and OmniEmu 2.0.
- Implemented a grid layout for other projects with highlight cards.
- Enhanced project pages (decompilations, fedl, geode-mod, issue-tracker, moon-gaming, music-app, noto, nova, omniemu, rhythm-game) to display GitHub stats (stars, forks, issues, language).
- Updated styles in style.css for the new stats bar, including animations and responsive design adjustments.
- Changed the site logo from "miles.dev" to "milesallen.site" in the navigation.
This commit is contained in:
2026-07-25 16:32:15 -05:00
parent 345542936e
commit d73ac305eb
12 changed files with 667 additions and 12 deletions
+27
View File
@@ -47,6 +47,24 @@
<span class="meta-chip">HTML</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">
@@ -107,6 +125,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/Decompilations-web')
.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' });
+59 -3
View File
@@ -13,7 +13,7 @@
<div class="container">
<nav>
<a href="../index.html" class="nav-logo"><span class="logo-dot"></span> miles.dev</a>
<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>
@@ -42,11 +42,28 @@
Live Site
</a>
<span class="meta-chip">HTML / JS / CSS</span>
<span class="meta-chip">196 commits</span>
<span class="meta-chip">2 stars</span>
</div>
</section>
<div class="stats-bar">
<div class="stat-item">
<div class="stat-value accent" id="fedl-levels">--</div>
<div class="stat-label">Levels</div>
</div>
<div class="stat-item">
<div class="stat-value green" id="fedl-runs">--</div>
<div class="stat-label">Runs Submitted</div>
</div>
<div class="stat-item">
<div class="stat-value orange" id="fedl-commits">196</div>
<div class="stat-label">Commits</div>
</div>
<div class="stat-item">
<div class="stat-value" id="fedl-stars">2</div>
<div class="stat-label">Stars</div>
</div>
</div>
<section class="reveal">
<div class="section-divider"></div>
<h2 class="section-title">What It Includes</h2>
@@ -149,6 +166,45 @@
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));
const API = 'https://server.fedl.site/fedl/api';
fetch(`${API}/list`)
.then(r => r.json())
.then(data => {
const items = data.items || [];
document.getElementById('fedl-levels').textContent = items.length;
})
.catch(() => {
document.getElementById('fedl-levels').textContent = '150+';
});
fetch(`${API}/runs`)
.then(r => r.json())
.then(data => {
const runs = Array.isArray(data) ? data : [];
document.getElementById('fedl-runs').textContent = runs.length;
})
.catch(() => {
document.getElementById('fedl-runs').textContent = '--';
});
fetch('https://api.github.com/repos/mileswolfallen2/fedl')
.then(r => r.json())
.then(data => {
if (data.stargazers_count != null) {
document.getElementById('fedl-stars').textContent = data.stargazers_count;
}
if (data.default_branch) {
fetch(`https://api.github.com/repos/mileswolfallen2/fedl/commits?sha=${data.default_branch}&per_page=1`)
.then(r => {
const total = r.headers.get('x-total-count');
if (total) document.getElementById('fedl-commits').textContent = total;
})
.catch(() => {});
}
})
.catch(() => {});
</script>
</body>
</html>
+27
View File
@@ -44,6 +44,24 @@
<span class="meta-chip">C++</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">
@@ -139,6 +157,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/FEDL-Geode-mod')
.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' });
+27
View File
@@ -43,6 +43,24 @@
<span class="meta-chip">HTML / JavaScript</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">
@@ -104,6 +122,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/Issue-tracker')
.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' });
+27
View File
@@ -43,6 +43,24 @@
<span class="meta-chip">HTML</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">
@@ -130,6 +148,15 @@
</a>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/moon-gaming')
.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' });
+27
View File
@@ -47,6 +47,24 @@
<span class="meta-chip">JavaScript</span>
<span class="meta-chip">Apache-2.0</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">
@@ -124,6 +142,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/music-app')
.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' });
+27
View File
@@ -48,6 +48,24 @@
<span class="meta-chip">Dart</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">
@@ -170,6 +188,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/Noto')
.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' });
+27
View File
@@ -52,6 +52,24 @@
<span class="meta-chip">Python</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">
@@ -153,6 +171,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/nova')
.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' });
+27
View File
@@ -49,6 +49,24 @@
<span class="meta-chip">MIT License</span>
<span class="meta-chip">v0.3.2</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">
@@ -188,6 +206,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/OmniEmu2.0')
.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' });
+27
View File
@@ -49,6 +49,24 @@
<span class="meta-chip">64 commits</span>
<span class="meta-chip">1 star</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">
@@ -118,6 +136,15 @@
</footer>
</div>
<script>
fetch('https://api.github.com/repos/mileswolfallen2/new-game')
.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' });
+70 -3
View File
@@ -199,14 +199,78 @@ nav {
background: var(--accent);
border-color: var(--accent);
color: #fff;
box-shadow: 0 0 20px rgba(124, 92, 255, 0.3);
box-shadow: 0 0 20px rgba(14, 165, 233, 0.3);
}
.meta-chip.primary:hover {
background: #6a4ae8;
box-shadow: 0 0 30px rgba(124, 92, 255, 0.5);
background: #0284c7;
box-shadow: 0 0 30px rgba(14, 165, 233, 0.5);
transform: translateY(-1px);
}
/* STATS BAR */
.stats-bar {
display: flex;
gap: 0;
margin-top: 32px;
border-radius: 14px;
overflow: hidden;
background: var(--surface);
backdrop-filter: blur(12px);
position: relative;
z-index: 1;
}
.stats-bar::before {
content: '';
position: absolute;
inset: 0;
border-radius: 14px;
padding: 1px;
background: linear-gradient(
var(--rainbow-angle, 90deg),
#ff0000, #ff8800, #ffff00, #00ff00, #0088ff, #8800ff, #ff00ff, #ff0000
);
background-size: 300% 300%;
animation: rainbowShift 6s linear infinite;
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
z-index: 1;
}
@keyframes rainbowShift {
0% { background-position: 0% 50%; }
100% { background-position: 300% 50%; }
}
.stat-item {
flex: 1;
padding: 20px 24px;
text-align: center;
border-right: 1px solid var(--border);
transition: background 0.3s;
}
.stat-item:last-child { border-right: none; }
.stat-item:hover { background: rgba(255, 255, 255, 0.02); }
.stat-value {
font-family: 'Fraunces', serif;
font-size: 1.8rem;
font-weight: 900;
letter-spacing: -0.03em;
color: var(--text);
line-height: 1;
margin-bottom: 4px;
}
.stat-value.accent { color: var(--accent); }
.stat-value.green { color: var(--green); }
.stat-value.orange { color: var(--orange); }
.stat-label {
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-dim);
}
section { padding: 48px 0; }
.section-divider {
@@ -390,4 +454,7 @@ footer a { color: var(--accent); text-decoration: none; }
.project-hero h1 { font-size: 2rem; }
.nav-links { display: none; }
.feature-grid { grid-template-columns: 1fr; }
.stats-bar { flex-direction: column; }
.stat-item { border-right: none; border-bottom: 1px solid var(--border); }
.stat-item:last-child { border-bottom: none; }
}