mirror of
https://github.com/asimonson1125/asimonson1125.github.io.git
synced 2026-09-22 11:35:33 -05:00
temp
This commit is contained in:
@@ -22,7 +22,7 @@ static_file_hashes = {}
|
||||
for dirpath, _, filenames in os.walk(app.static_folder):
|
||||
for filename in filenames:
|
||||
filepath = os.path.join(dirpath, filename)
|
||||
relative = os.path.relpath(filepath, app.static_folder)
|
||||
relative = os.path.relpath(filepath, app.static_folder).replace(os.sep, '/')
|
||||
with open(filepath, 'rb') as f:
|
||||
static_file_hashes[relative] = hashlib.md5(f.read()).hexdigest()[:8]
|
||||
|
||||
|
||||
@@ -1947,6 +1947,194 @@ tr {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
/* Deep-dive project panels (collapsed by default) */
|
||||
.feature-projects {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2em;
|
||||
margin-bottom: 3.5em;
|
||||
}
|
||||
|
||||
.feature-project {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-top: none;
|
||||
border-radius: 0.75em;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.feature-project::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--accent) 0%, rgba(var(--accent-rgb), 0.85) 40%, rgba(var(--accent-rgb), 0.15) 100%);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.feature-project-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.feature-project-media {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 620px;
|
||||
background-size: cover;
|
||||
background-position: right bottom;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1100px) {
|
||||
.feature-project-media {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-project-media::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(var(--bg-card-rgb), 1) 0%,
|
||||
rgba(var(--bg-card-rgb), 1) 50%,
|
||||
rgba(var(--bg-card-rgb), 0.75) 62%,
|
||||
rgba(var(--bg-card-rgb), 0.15) 82%,
|
||||
rgba(var(--bg-card-rgb), 0) 96%
|
||||
);
|
||||
}
|
||||
|
||||
.feature-project-header {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.5em;
|
||||
padding: 1.75em 2em;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.feature-project-heading {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 46em;
|
||||
}
|
||||
|
||||
.feature-project-header:hover {
|
||||
background: rgba(var(--accent-rgb), 0.06);
|
||||
}
|
||||
|
||||
.feature-project-header h3 {
|
||||
margin: 0 0 0.35em 0;
|
||||
color: var(--text-heading);
|
||||
font-size: 1.55rem;
|
||||
}
|
||||
|
||||
.feature-project-tagline {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.feature-project-toggle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
width: 2.4em;
|
||||
height: 2.4em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid rgba(var(--accent-rgb), 0.4);
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--bg-card-rgb), 0.85);
|
||||
color: var(--text-heading);
|
||||
font-size: 1.4rem;
|
||||
line-height: 1;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
transition: transform 0.3s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.feature-project.expanded .feature-project-toggle {
|
||||
transform: rotate(45deg);
|
||||
border-color: var(--accent);
|
||||
background: rgba(var(--accent-rgb), 0.18);
|
||||
}
|
||||
|
||||
.feature-project-body {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
transition: grid-template-rows 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-project.expanded .feature-project-body {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
|
||||
.feature-project-body-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.feature-project-prose {
|
||||
max-width: 46em;
|
||||
padding: 1.5em 2em 1.75em;
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.feature-project-prose p + p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.feature-project-prose code {
|
||||
background: rgba(var(--accent-rgb), 0.12);
|
||||
padding: 0.1em 0.4em;
|
||||
border-radius: 0.25em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.feature-project-stack {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.6em;
|
||||
padding: 0 2em 2em;
|
||||
}
|
||||
|
||||
.feature-project-stack-item {
|
||||
padding: 0.35em 0.9em;
|
||||
border: 1px solid rgba(var(--accent-rgb), 0.35);
|
||||
border-radius: 2em;
|
||||
background: rgba(var(--accent-rgb), 0.07);
|
||||
color: var(--text-secondary);
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.feature-project-header {
|
||||
padding: 1.5em;
|
||||
}
|
||||
|
||||
.feature-project-prose {
|
||||
padding: 1.25em 1.5em 1.5em;
|
||||
}
|
||||
|
||||
.feature-project-stack {
|
||||
padding: 0 1.5em 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.skills-certs-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
@@ -98,6 +98,12 @@ function backButton() {
|
||||
goto(path.substring(1), { push: false });
|
||||
}
|
||||
|
||||
function toggleFeatureProject(header) {
|
||||
const panel = header.closest(".feature-project");
|
||||
const expanded = panel.classList.toggle("expanded");
|
||||
header.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||||
}
|
||||
|
||||
function activeSkill(obj) {
|
||||
let skill = obj.closest(".skill");
|
||||
if (skill.classList.contains("activeSkill")) {
|
||||
|
||||
BIN
src/static/photos/deepdives/homelab-dashboard.png
Normal file
BIN
src/static/photos/deepdives/homelab-dashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
30
src/templates/partials/feature_project.html
Normal file
30
src/templates/partials/feature_project.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{% macro feature_project(id, title, tagline, body, stack, image=none) %}
|
||||
<div class="feature-project boxed{{ ' has-media' if image else '' }}" id="feature-{{ id }}">
|
||||
<div class="feature-project-content">
|
||||
<div class="feature-project-header" onclick="toggleFeatureProject(this)" onKeyDown="if(event.key==='Enter'||event.key===' ')toggleFeatureProject(this)" role="button" tabindex="0" aria-expanded="false" aria-controls="feature-{{ id }}-body">
|
||||
{% if image %}
|
||||
<div class="feature-project-media" style="background-image: url('{{ url_for('static', filename=image) }}')"></div>
|
||||
{% endif %}
|
||||
<div class="feature-project-heading">
|
||||
<h3>{{ title }}</h3>
|
||||
<p class="feature-project-tagline">{{ tagline }}</p>
|
||||
</div>
|
||||
<span class="feature-project-toggle" aria-hidden="true">+</span>
|
||||
</div>
|
||||
<div class="feature-project-body" id="feature-{{ id }}-body">
|
||||
<div class="feature-project-body-inner">
|
||||
<div class="feature-project-prose">
|
||||
{{ body | safe }}
|
||||
</div>
|
||||
{% if stack %}
|
||||
<div class="feature-project-stack">
|
||||
{% for item in stack %}
|
||||
<span class="feature-project-stack-item">{{ item }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -10,18 +10,30 @@
|
||||
<div class="homeSubContent">
|
||||
<div class="foregroundContent">
|
||||
|
||||
<!-- Intro -->
|
||||
<div style="max-width: 52em; margin-bottom: 3em;">
|
||||
<p style="color: var(--text-secondary); font-size: 0.9rem;">
|
||||
Curious who's behind these?
|
||||
<a href="about">About & certifications</a>
|
||||
·
|
||||
<a href="Resume_Simonson_Andrew.pdf" target="_blank">Resume</a>
|
||||
</p>
|
||||
<!-- Deep Dives -->
|
||||
<h2>Highlights</h2>
|
||||
<div class="feature-projects">
|
||||
{% from 'partials/feature_project.html' import feature_project %}
|
||||
{{ feature_project(
|
||||
'homelab',
|
||||
'AI Homelab',
|
||||
'Self-hosted GPU cluster serving MoE models beyond their rated VRAM, with a full LoRA fine-tuning pipeline on top',
|
||||
'<p>I\'ve refined a method to pool GPUs from different vendors and generations — an RTX 5070 and a Radeon RX 6600 XT — into a single ~20GB inference backend over Vulkan, so neither card\'s limits bottleneck the other. FreeToken, a bleeding-edge MoE inference server, fronts the cluster and handles the actual elastic inference, running Mixture-of-Experts models with far more total parameters than the cluster\'s VRAM would normally allow. My custom scripts resolve KV caching and system prompt compaction that make the setup harness-capable, so agentic tools like Claude Code can hit it over Anthropic- and OpenAI-compatible endpoints exactly like they would a paid API. GPU layer placement alone took generation from ~150s a call to ~88ms/token.</p><p>The same rig trains as well as it serves. I built a complete LoRA fine-tuning pipeline on it — base model, training config, and adapter. Used for fine-tuning Qwen3-1.7B on patent data, and training a Stable Diffusion LoRA set on curated, deduplicated image data.</p>',
|
||||
['RTX 5070', 'RX 6600 XT', 'Ollama', 'FreeToken', 'ComfyUI', 'PEFT / TRL'],
|
||||
'photos/deepdives/homelab-dashboard.png'
|
||||
) }}
|
||||
|
||||
{{ feature_project(
|
||||
'siteinfra',
|
||||
'Self-Hosted Web Tooling & Maintenance',
|
||||
'I designed, deployed, and still actively operate this site\'s stack — the app, the edge, and its own health monitoring',
|
||||
'<p>This portfolio runs on infrastructure I designed, deployed, and still operate myself — the Flask app and its container, the Cloudflare edge and reverse proxy in front of it, DNS and tunneling, and the uptime monitor watching all of it (live at <a href="status">/status</a>). None of that is a managed host\'s job here; it\'s mine.</p><p>What actually proves it\'s production-capable is the maintenance loop, not the launch. I put it through a real adversarial review periodically — most recently a live pass with Claude Code against both the deployed site and the source — and fix what it finds. The latest pass closed two real issues same-day: a database-query pattern on an internal endpoint that could be hammered into needless load, and a self-built redirect that could momentarily hand a browser plaintext HTTP instead of HTTPS. Nothing catastrophic came up — no injection, no auth bypass, no data exposure — which is exactly the point of doing this on a schedule instead of waiting for something to break.</p>',
|
||||
['Flask', 'Docker', 'PostgreSQL', 'Reverse Proxy', 'Cloudflare']
|
||||
) }}
|
||||
</div>
|
||||
|
||||
<!-- Projects -->
|
||||
<h2>Projects</h2>
|
||||
<h2>All Projects</h2>
|
||||
<div class="projectList">
|
||||
{% from 'partials/project.html' import project %} {% for i in
|
||||
var["projects"] %} {{ project(i, var["projects"][i]["classes"],
|
||||
|
||||
Reference in New Issue
Block a user