Initial commit

This commit is contained in:
Blake Ridgway 2025-07-05 15:29:33 -05:00
commit 315e731234
27 changed files with 3403 additions and 0 deletions

148
templates/about.html Normal file
View file

@ -0,0 +1,148 @@
{% extends "base.html" %}
{% block title %}About - Blake Ridgway{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h1>About Me</h1>
<p class="lead">Welcome! I'm Blake Ridgway, a Systems Administrator passionate about cybersecurity, technology, and ultra endurance cycling.</p>
<h3>Background</h3>
<p>
As a Systems Administrator, I focus on ensuring the stability, integrity, and performance of critical IT infrastructure.
Through hands-on experience managing Linux, AWS, and Azure environments, I've learned that true system stability
is impossible without robust security. This realization has driven me to actively develop my skills in both
offensive and defensive security, with a particular focus on application security and secure infrastructure.
</p>
<p>
I believe that understanding how to break systems is the best way to learn how to build unbreakable ones.
I'm currently documenting my entire cybersecurity learning journey, including all notes and projects, in my
<a href="https://gitlab.com/blakeridgway/cybersec-odyssey" target="_blank" rel="noopener noreferrer">
CyberSec Odyssey Repository <i class="fas fa-external-link-alt ms-1"></i>
</a>.
</p>
<h3>Core Competencies</h3>
<div class="row g-3 mb-4">
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-server text-primary me-2"></i>Systems Administration</h5>
<p class="small mb-0">Expertise in deploying, managing, and troubleshooting Linux and Windows server environments.</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-cloud text-success me-2"></i>Cloud Technologies</h5>
<p class="small mb-0">Hands-on experience with AWS and Azure, including EC2, S3, Azure VMs, and virtual networking.</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-shield-alt text-danger me-2"></i>Security & Monitoring</h5>
<p class="small mb-0">Implementing monitoring solutions and security practices to proactively identify and resolve issues.</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-network-wired text-info me-2"></i>Network Management</h5>
<p class="small mb-0">Practical knowledge of Cisco, Fortigate, and Netgate solutions for network optimization.</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-code text-warning me-2"></i>Automation & Scripting</h5>
<p class="small mb-0">Using Bash, PowerShell, and Python to automate tasks and improve efficiency.</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-3 bg-light rounded-3 shadow-sm h-100">
<h5><i class="fas fa-bicycle text-success me-2"></i>Ultra Endurance Cycling</h5>
<p class="small mb-0">Combining passion for cycling with data-driven insights and secure development practices.</p>
</div>
</div>
</div>
<h3>Technologies & Tools</h3>
<div class="row g-3">
<div class="col-md-6 col-lg-3">
<div class="tech-category p-3 bg-white rounded-3 shadow-sm h-100">
<h6 class="text-center mb-3">OS & Cloud</h6>
<div class="tech-icons d-flex justify-content-center flex-wrap gap-2">
<img alt="Linux" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/linux/linux-original.svg" title="Linux" />
<img alt="Fedora" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/fedora/fedora-plain.svg" title="Fedora" />
<img alt="Debian" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/debian/debian-plain.svg" title="Debian" />
<img alt="AWS" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/amazonwebservices/amazonwebservices-original-wordmark.svg" title="AWS" />
<img alt="Azure" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/azure/azure-original.svg" title="Azure" />
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="tech-category p-3 bg-white rounded-3 shadow-sm h-100">
<h6 class="text-center mb-3">DevOps & Automation</h6>
<div class="tech-icons d-flex justify-content-center flex-wrap gap-2">
<img alt="Docker" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/docker/docker-plain.svg" title="Docker" />
<img alt="Kubernetes" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/kubernetes/kubernetes-plain.svg" title="Kubernetes" />
<img alt="Git" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/git/git-plain.svg" title="Git" />
<img alt="Bash" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/bash/bash-original.svg" title="Bash" />
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="tech-category p-3 bg-white rounded-3 shadow-sm h-100">
<h6 class="text-center mb-3">Languages & Frameworks</h6>
<div class="tech-icons d-flex justify-content-center flex-wrap gap-2">
<img alt="C#" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/csharp/csharp-original.svg" title="C#" />
<img alt=".NET" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/dotnetcore/dotnetcore-original.svg" title=".NET" />
<img alt="Python" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/python/python-original.svg" title="Python" />
<img alt="Ruby" width="30" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/ruby/ruby-plain.svg" title="Ruby" />
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="tech-category p-3 bg-white rounded-3 shadow-sm h-100">
<h6 class="text-center mb-3">Security & Monitoring</h6>
<div class="tech-icons d-flex justify-content-center flex-wrap gap-2">
<i class="fab fa-linux fa-2x text-dark" title="Linux Security"></i>
<i class="fas fa-shield-alt fa-2x text-primary" title="Security"></i>
<i class="fas fa-chart-line fa-2x text-success" title="Monitoring"></i>
<i class="fas fa-lock fa-2x text-danger" title="Encryption"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body text-center">
<img src="{{ url_for('static', filename='images/profile.jpg') }}"
alt="Blake Ridgway Profile Picture" class="img-fluid rounded-circle mb-3"
style="max-width: 200px;">
<h5>Blake Ridgway</h5>
<p class="text-muted">Systems Administrator & Cybersecurity Enthusiast</p>
<div class="d-flex justify-content-center gap-2 flex-wrap">
<span class="badge bg-primary">Systems Admin</span>
<span class="badge bg-success">Cybersecurity Enthusiast</span>
<span class="badge bg-info">Linux & Open Source Advocate</span>
<span class="badge bg-warning">Ultra Endurance Cyclist</span>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h5>Quick Links</h5>
</div>
<div class="card-body">
<ul class="list-unstyled">
<li><a href="{{ url_for('hardware') }}" class="text-decoration-none"><i class="fas fa-desktop me-2"></i>Hardware Setup</a></li>
<li><a href="{{ url_for('biking') }}" class="text-decoration-none"><i class="fas fa-bicycle me-2"></i>Cycling Adventures</a></li>
<li><a href="{{ url_for('blog') }}" class="text-decoration-none"><i class="fas fa-blog me-2"></i>Blog Posts</a></li>
<li><a href="https://gitlab.com/blakeridgway/cybersec-odyssey" target="_blank" rel="noopener noreferrer" class="text-decoration-none"><i class="fab fa-gitlab me-2"></i>CyberSec Repository</a></li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,76 @@
{% extends "base.html" %}
{% block title %}Admin Dashboard - Your Name{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Admin Dashboard</h1>
<div>
<a href="{{ url_for('admin_new_post') }}" class="btn btn-primary">New Post</a>
<a href="{{ url_for('admin_logout') }}" class="btn btn-outline-secondary">Logout</a>
</div>
</div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else category }} alert-dismissible fade show">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="card">
<div class="card-header">
<h5 class="mb-0">Blog Posts ({{ posts|length }})</h5>
</div>
<div class="card-body">
{% if posts %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Title</th>
<th>Category</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<td>
<strong>{{ post.title }}</strong><br>
<small class="text-muted">{{ post.excerpt[:100] }}...</small>
</td>
<td><span class="badge bg-secondary">{{ post.category }}</span></td>
<td>{{ post.date }}</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{{ url_for('blog_post', post_id=post.id) }}"
class="btn btn-outline-primary" target="_blank">View</a>
<a href="{{ url_for('admin_edit_post', post_id=post.id) }}"
class="btn btn-outline-warning">Edit</a>
<form method="POST" action="{{ url_for('admin_delete_post', post_id=post.id) }}"
style="display: inline;"
onsubmit="return confirm('Are you sure you want to delete this post?')">
<button type="submit" class="btn btn-outline-danger">Delete</button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<p class="text-muted">No blog posts yet.</p>
<a href="{{ url_for('admin_new_post') }}" class="btn btn-primary">Create Your First Post</a>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,98 @@
{% extends "base.html" %}
{% block title %}{{ title }} - Admin{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>{{ title }}</h1>
<a href="{{ url_for('admin_dashboard') }}" class="btn btn-outline-secondary">Back to Dashboard</a>
</div>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.title.label(class="form-label") }}
{{ form.title(class="form-control") }}
{% if form.title.errors %}
<div class="text-danger">
{% for error in form.title.errors %}
<small>{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
{{ form.category.label(class="form-label") }}
{{ form.category(class="form-select") }}
</div>
</div>
</div>
<div class="mb-3">
{{ form.excerpt.label(class="form-label") }}
{{ form.excerpt(class="form-control", rows="3", placeholder="Auto-generated if left blank") }}
<div class="form-text">Brief description shown in blog listings</div>
</div>
<div class="mb-3">
{{ form.content.label(class="form-label") }}
{{ form.content(class="form-control") }}
{% if form.content.errors %}
<div class="text-danger">
{% for error in form.content.errors %}
<small>{{ error }}</small>
{% endfor %}
</div>
{% endif %}
</div>
<div class="d-flex gap-2">
{{ form.submit(class="btn btn-primary") }}
{% if post %}
<a href="{{ url_for('blog_post', post_id=post.id) }}"
class="btn btn-outline-info" target="_blank">Preview</a>
{% endif %}
</div>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h6 class="mb-0">Writing Tips</h6>
</div>
<div class="card-body">
<ul class="small">
<li>Use clear, descriptive titles</li>
<li>Break up long paragraphs</li>
<li>Include code examples when relevant</li>
<li>Add personal insights and experiences</li>
</ul>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h6 class="mb-0">Markdown Support</h6>
</div>
<div class="card-body">
<p class="small">You can use basic HTML in your posts:</p>
<code>&lt;strong&gt;bold&lt;/strong&gt;</code><br>
<code>&lt;em&gt;italic&lt;/em&gt;</code><br>
<code>&lt;code&gt;code&lt;/code&gt;</code><br>
<code>&lt;pre&gt;code block&lt;/pre&gt;</code>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% block title %}Admin Login - Your Name{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h4 class="mb-0">Admin Login</h4>
</div>
<div class="card-body">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else category }} alert-dismissible fade show">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.username.label(class="form-label") }}
{{ form.username(class="form-control") }}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control") }}
</div>
<div class="d-grid">
{{ form.submit(class="btn btn-primary") }}
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,216 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Traffic Analytics - Admin</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
.stat-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.stat-number { font-size: 2em; font-weight: bold; color: #2563eb; }
.stat-label { color: #666; margin-top: 5px; }
.chart-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 30px; }
.table-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
h1 { color: #333; margin-bottom: 30px; }
h2 { color: #333; margin-bottom: 15px; }
.controls { margin-bottom: 20px; }
.controls select { padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; }
.real-time-btn { background: #10b981; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; }
.real-time-btn:hover { background: #059669; }
.activity-item { padding: 8px; margin: 4px 0; background: #f8f9fa; border-radius: 4px; font-size: 0.9em; }
.activity-time { color: #666; font-size: 0.8em; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 768px) { .grid-2 { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="container">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
<h1>Traffic Analytics Dashboard</h1>
<div class="controls">
<select id="dateRange">
<option value="7" {% if days == 7 %}selected{% endif %}>Last 7 days</option>
<option value="30" {% if days == 30 %}selected{% endif %}>Last 30 days</option>
<option value="90" {% if days == 90 %}selected{% endif %}>Last 90 days</option>
</select>
<button id="realTimeBtn" class="real-time-btn">
Real-time: <span id="activeUsers">0</span> active
</button>
</div>
</div>
<!-- Stats Cards -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number">{{ "{:,}".format(stats.total_views) }}</div>
<div class="stat-label">Total Page Views</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ "{:,}".format(stats.unique_visitors) }}</div>
<div class="stat-label">Unique Visitors</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ stats.avg_response_time }}ms</div>
<div class="stat-label">Avg Response Time</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ stats.bounce_rate }}%</div>
<div class="stat-label">Bounce Rate</div>
</div>
</div>
<!-- Daily Traffic Chart -->
<div class="chart-container">
<h2>Daily Traffic (Last {{ days }} Days)</h2>
<canvas id="dailyTrafficChart" width="400" height="100"></canvas>
</div>
<!-- Tables -->
<div class="grid-2">
<div class="table-container">
<h2>Top Pages</h2>
<table>
<thead>
<tr>
<th>Page</th>
<th>Views</th>
</tr>
</thead>
<tbody>
{% for page, views in top_pages %}
<tr>
<td>{{ page }}</td>
<td>{{ views }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="table-container">
<h2>Top Referrers</h2>
<table>
<thead>
<tr>
<th>Referrer</th>
<th>Views</th>
</tr>
</thead>
<tbody>
{% for referrer, views in top_referrers %}
<tr>
<td>{{ referrer[:50] }}{% if referrer|length > 50 %}...{% endif %}</td>
<td>{{ views }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Recent Activity -->
<div class="table-container">
<h2>Recent Activity (Last 24 Hours)</h2>
<div id="recentActivity" style="max-height: 300px; overflow-y: auto;">
{% for activity in recent_activity %}
<div class="activity-item">
<strong>{{ activity.path }}</strong>
{% if activity.referrer %}
from {{ activity.referrer[:30] }}{% if activity.referrer|length > 30 %}...{% endif %}
{% endif %}
<div class="activity-time">{{ activity.timestamp.strftime('%Y-%m-%d %H:%M:%S') }} - {{ activity.ip_address[:8] }}...</div>
</div>
{% endfor %}
</div>
</div>
</div>
<script>
// Chart.js configurations - Fixed tojsonfilter to tojson
const dailyData = {{ daily_views | tojson | safe }};
// Daily Traffic Chart
const ctx = document.getElementById('dailyTrafficChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: dailyData.map(d => d.date),
datasets: [{
label: 'Page Views',
data: dailyData.map(d => d.views),
borderColor: 'rgb(37, 99, 235)',
backgroundColor: 'rgba(37, 99, 235, 0.1)',
tension: 0.1,
fill: true
}, {
label: 'Unique Visitors',
data: dailyData.map(d => d.unique_visitors),
borderColor: 'rgb(16, 185, 129)',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
tension: 0.1,
fill: false
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
},
plugins: {
legend: {
display: true
}
}
}
});
// Real-time updates
function updateRealTime() {
fetch('/admin/traffic/api/realtime')
.then(response => response.json())
.then(data => {
document.getElementById('activeUsers').textContent = data.active_users;
const activityDiv = document.getElementById('recentActivity');
if (data.recent_views && data.recent_views.length > 0) {
activityDiv.innerHTML = data.recent_views.map(view => `
<div class="activity-item">
<strong>${view.path}</strong>
<div class="activity-time">
${new Date(view.timestamp).toLocaleString()} - ${view.ip_address}
${view.country ? ' (' + view.country + ')' : ''}
</div>
</div>
`).join('');
}
})
.catch(error => {
console.log('Real-time update failed:', error);
});
}
// Update every 30 seconds
setInterval(updateRealTime, 30000);
updateRealTime(); // Initial load
// Date range selector
document.getElementById('dateRange').addEventListener('change', function() {
window.location.href = `?days=${this.value}`;
});
// Real-time button click
document.getElementById('realTimeBtn').addEventListener('click', function() {
updateRealTime();
});
</script>
</body>
</html>

70
templates/base.html Normal file
View file

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Blake Ridgway - Personal Website{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="{{ url_for('index') }}">Blake Ridgway</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('index') }}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('about') }}">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('hardware') }}">Hardware</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('biking') }}">Biking Adventures</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('blog') }}">Blog</a>
</li>
{% if current_user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_dashboard') }}">Admin</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<main class="container mt-4">
{% block content %}{% endblock %}
</main>
<footer class="bg-dark text-light mt-5 py-4">
<div class="container">
<div class="row align-items-center">
<div class="col-md-6 text-center text-md-start">
<p class="mb-0">&copy; 2025 Blake Ridgway. All rights reserved.</p>
</div>
<div class="col-md-6 text-center text-md-end">
<div class="social-links">
<a href="mailto:blake@blakeridway.com" class="social-link" title="Email"><i class="fas fa-envelope"></i></a>
<a href="https://gitlab.com/blakeridgway" class="social-link" title="GitLab" target="_blank" rel="noopener"><i class="fab fa-gitlab"></i></a>
<a href="https://floss.social/@blake" class="social-link" title="Mastodon" target="_blank" rel="noopener"><i class="fab fa-mastodon"></i></a>
<a href="https://youtube.com/@BlakeRidgway" class="social-link" title="YouTube" target="_blank" rel="noopener"><i class="fab fa-youtube"></i></a>
</div>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body>
</html>

354
templates/biking.html Normal file
View file

@ -0,0 +1,354 @@
{% extends "base.html" %}
{% block title %}Biking Adventures - Blake Ridgway{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h1>Biking Adventures</h1>
<p class="lead">Exploring the world on two wheels as an ultra endurance cyclist - powered by real-time Strava data!</p>
<div class="d-flex justify-content-between align-items-center mb-4">
<h3><i class="fas fa-route text-primary me-2"></i>Recent Adventures</h3>
<button class="btn btn-outline-primary btn-sm" onclick="refreshStravaData()">
<span id="refresh-icon">🔄</span> Refresh Data
</button>
</div>
<div id="recent-activities">
{% if recent_activities %}
{% for activity in recent_activities %}
<div class="card mb-3 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div>
<h5 class="card-title">
<i class="fas fa-bicycle text-success me-2"></i>{{ activity.name }}
</h5>
<p class="card-text text-muted">Latest ride from Strava - automatically synced!</p>
</div>
<span class="badge bg-primary">{{ activity.date }}</span>
</div>
<div class="row g-2 mt-2">
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-road text-primary"></i>
<div><strong>{{ activity.distance }}</strong></div>
<small class="text-muted">Miles</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-mountain text-warning"></i>
<div><strong>{{ activity.elevation }}</strong></div>
<small class="text-muted">Feet</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-clock text-info"></i>
<div><strong>{{ activity.time }}</strong></div>
<small class="text-muted">Duration</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-tachometer-alt text-success"></i>
<div><strong>{{ activity.avg_speed or 'N/A' }}</strong></div>
<small class="text-muted">Avg MPH</small>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="alert alert-info border-start border-primary border-4">
<i class="fas fa-info-circle me-2"></i>Loading Strava data...
</div>
{% endif %}
</div>
<h3 class="mt-5 mb-4"><i class="fas fa-chart-line text-success me-2"></i>2025 Cycling Performance</h3>
<div class="row g-4" id="cycling-stats">
{% if ytd_stats %}
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-road fa-2x text-primary"></i>
</div>
<h4 class="text-primary mb-2">{{ ytd_stats.distance }}</h4>
<p class="mb-0">Miles This Year</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-bicycle fa-2x text-success"></i>
</div>
<h4 class="text-success mb-2">{{ ytd_stats.count }}</h4>
<p class="mb-0">Rides Completed</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-mountain fa-2x text-warning"></i>
</div>
<h4 class="text-warning mb-2">{{ ytd_stats.elevation }}</h4>
<p class="mb-0">Feet Climbed</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-clock fa-2x text-info"></i>
</div>
<h4 class="text-info mb-2">{{ ytd_stats.time }}</h4>
<p class="mb-0">Hours Riding</p>
</div>
</div>
{% else %}
<div class="col-12">
<div class="alert alert-warning border-start border-warning border-4">
<i class="fas fa-exclamation-triangle me-2"></i>Unable to load Strava stats. Please check your API connection.
</div>
</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 shadow-sm">
<div class="card-header bg-success text-white">
<h5 class="mb-0"><i class="fas fa-bicycle me-2"></i>My Bikes</h5>
</div>
<div class="card-body">
<div class="bike-item mb-4">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-road fa-lg text-primary me-3"></i>
<div>
<h6 class="mb-1">Road Bike</h6>
<p class="mb-0 text-muted">Giant TCR Advanced 2</p>
</div>
</div>
<div class="bike-specs">
<span class="badge bg-light text-dark me-1">Carbon Frame</span>
<span class="badge bg-light text-dark me-1">Aero</span>
<span class="badge bg-light text-dark">Racing</span>
</div>
</div>
<div class="bike-item">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-mountain fa-lg text-warning me-3"></i>
<div>
<h6 class="mb-1">Gravel Bike</h6>
<p class="mb-0 text-muted">Canyon Endurace CF SL 8</p>
</div>
</div>
<div class="bike-specs">
<span class="badge bg-light text-dark me-1">Endurance</span>
<span class="badge bg-light text-dark me-1">All-Road</span>
<span class="badge bg-light text-dark">Adventure</span>
</div>
</div>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="fas fa-trophy me-2"></i>Cycling Goals 2025</h5>
</div>
<div class="card-body">
<div class="goal-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span><i class="fas fa-road text-primary me-2"></i>Annual Distance</span>
<span class="badge bg-primary">5,000 mi</span>
</div>
</div>
<div class="goal-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span><i class="fas fa-mountain text-warning me-2"></i>Elevation Gain</span>
<span class="badge bg-warning">250,000 ft</span>
</div>
</div>
<div class="goal-item mb-3">
<div class="d-flex justify-content-between align-items-center">
<span><i class="fas fa-bicycle text-success me-2"></i>Total Rides</span>
<span class="badge bg-success">200 rides</span>
</div>
</div>
<div class="goal-item">
<div class="d-flex justify-content-between align-items-center">
<span><i class="fas fa-medal text-danger me-2"></i>Ultra Events</span>
<span class="badge bg-danger">3 events</span>
</div>
</div>
</div>
</div>
<div class="card shadow-sm">
<div class="card-header bg-secondary text-white">
<h5 class="mb-0"><i class="fas fa-info-circle me-2"></i>Data Source</h5>
</div>
<div class="card-body">
<p class="mb-2">
<i class="fab fa-strava text-danger me-2"></i>
<strong>Powered by Strava API</strong>
</p>
<p class="small text-muted mb-3">
Real-time cycling data automatically synced from my Strava account.
</p>
<p class="small text-muted mb-0">
<strong>Last updated:</strong> <span id="last-updated">Just now</span>
</p>
</div>
</div>
</div>
</div>
<script>
async function refreshStravaData() {
const refreshIcon = document.getElementById('refresh-icon');
refreshIcon.style.animation = 'spin 1s linear infinite';
try {
const response = await fetch('/api/strava-stats');
const data = await response.json();
// Update stats
if (data.ytd_stats) {
updateStats(data.ytd_stats);
}
// Update recent activities
if (data.recent_activities) {
updateRecentActivities(data.recent_activities);
}
// Update timestamp
document.getElementById('last-updated').textContent = new Date().toLocaleString();
} catch (error) {
console.error('Error refreshing Strava data:', error);
} finally {
refreshIcon.style.animation = '';
}
}
function updateStats(stats) {
const statsContainer = document.getElementById('cycling-stats');
statsContainer.innerHTML = `
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-road fa-2x text-primary"></i>
</div>
<h4 class="text-primary mb-2">${stats.distance}</h4>
<p class="mb-0">Miles This Year</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-bicycle fa-2x text-success"></i>
</div>
<h4 class="text-success mb-2">${stats.count}</h4>
<p class="mb-0">Rides Completed</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-mountain fa-2x text-warning"></i>
</div>
<h4 class="text-warning mb-2">${stats.elevation}</h4>
<p class="mb-0">Feet Climbed</p>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="skill-card text-center p-4 bg-light rounded-3 shadow-sm h-100">
<div class="stat-icon mb-3">
<i class="fas fa-clock fa-2x text-info"></i>
</div>
<h4 class="text-info mb-2">${stats.time}</h4>
<p class="mb-0">Hours Riding</p>
</div>
</div>
`;
}
function updateRecentActivities(activities) {
const container = document.getElementById('recent-activities');
if (activities.length === 0) {
container.innerHTML = '<div class="alert alert-info border-start border-primary border-4"><i class="fas fa-info-circle me-2"></i>No recent activities found.</div>';
return;
}
container.innerHTML = activities.map(activity => `
<div class="card mb-3 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div>
<h5 class="card-title">
<i class="fas fa-bicycle text-success me-2"></i>${activity.name}
</h5>
<p class="card-text text-muted">Latest ride from Strava - automatically synced!</p>
</div>
<span class="badge bg-primary">${activity.date}</span>
</div>
<div class="row g-2 mt-2">
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-road text-primary"></i>
<div><strong>${activity.distance}</strong></div>
<small class="text-muted">Miles</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-mountain text-warning"></i>
<div><strong>${activity.elevation}</strong></div>
<small class="text-muted">Feet</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-clock text-info"></i>
<div><strong>${activity.time}</strong></div>
<small class="text-muted">Duration</small>
</div>
</div>
<div class="col-6 col-md-3">
<div class="stat-box p-2 bg-light rounded text-center">
<i class="fas fa-tachometer-alt text-success"></i>
<div><strong>${activity.avg_speed || 'N/A'}</strong></div>
<small class="text-muted">Avg MPH</small>
</div>
</div>
</div>
</div>
</div>
`).join('');
}
// Auto-refresh every 5 minutes
setInterval(refreshStravaData, 300000);
</script>
<style>
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.stat-box {
transition: transform 0.2s ease;
}
.stat-box:hover {
transform: translateY(-2px);
}
</style>
{% endblock %}

78
templates/blog.html Normal file
View file

@ -0,0 +1,78 @@
{% extends "base.html" %}
{% block title %}Blog - Blake Ridgway{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h1><i class="fas fa-blog text-primary me-2"></i>Blog</h1>
<p class="lead">Thoughts on cybersecurity, systems administration, technology, cycling, and the journey of continuous learning.</p>
{% if posts %}
{% for post in posts %}
<article class="card mb-4 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-3">
<div class="flex-grow-1">
<h2 class="card-title h4 mb-2">
<a href="{{ url_for('blog_post', post_id=post.id) }}" class="text-decoration-none">
{{ post.title }}
</a>
</h2>
<div class="post-meta mb-2">
<small class="text-muted">
<i class="fas fa-calendar-alt me-1"></i>{{ post.date }}
<i class="fas fa-user ms-3 me-1"></i>Blake Ridgway
</small>
</div>
</div>
<span class="badge bg-primary ms-3">{{ post.category }}</span>
</div>
<p class="card-text">{{ post.excerpt }}</p>
<div class="d-flex justify-content-between align-items-center mt-3">
<a href="{{ url_for('blog_post', post_id=post.id) }}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-arrow-right me-1"></i>Read More
</a>
<div class="post-tags">
{% if post.tags %}
{% for tag in post.tags %}
<span class="badge bg-light text-dark me-1">#{{ tag }}</span>
{% endfor %}
{% endif %}
</div>
</div>
</div>
</article>
{% endfor %}
<!-- Pagination implement it later)
<nav aria-label="Blog pagination" class="mt-4">
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
<li class="page-item active">
<span class="page-link">1</span>
</li>
<li class="page-item disabled">
<span class="page-link">Next</span>
</li>
</ul>
</nav>
-->
{% else %}
<div class="alert alert-info border-start border-primary border-4 shadow-sm">
<div class="d-flex align-items-center">
<i class="fas fa-info-circle fa-2x text-primary me-3"></i>
<div>
<h4 class="alert-heading mb-2">No posts yet!</h4>
<p class="mb-0">I'm currently working on some exciting content about cybersecurity, systems administration, and my cycling adventures. Check back soon for new posts!</p>
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}

287
templates/blog_post.html Normal file
View file

@ -0,0 +1,287 @@
{% extends "base.html" %}
{% block title %}{{ post.title }} - Blake Ridgway{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<article>
<header class="mb-4">
<nav aria-label="breadcrumb" class="mb-3">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{{ url_for('index') }}" class="text-decoration-none">
<i class="fas fa-home me-1"></i>Home
</a>
</li>
<li class="breadcrumb-item">
<a href="{{ url_for('blog') }}" class="text-decoration-none">
<i class="fas fa-blog me-1"></i>Blog
</a>
</li>
<li class="breadcrumb-item active" aria-current="page">{{ post.title }}</li>
</ol>
</nav>
<h1 class="display-5 mb-3">{{ post.title }}</h1>
<div class="post-meta mb-4 p-3 bg-light rounded-3">
<div class="row align-items-center">
<div class="col-md-8">
<div class="d-flex align-items-center mb-2 mb-md-0">
<img src="{{ url_for('static', filename='images/profile.jpg') }}"
alt="Blake Ridgway"
class="rounded-circle me-3"
width="40" height="40">
<div>
<div class="fw-bold">Blake Ridgway</div>
<small class="text-muted">
<i class="fas fa-calendar-alt me-1"></i>{{ post.date }}
<i class="fas fa-clock ms-3 me-1"></i>~5 min read
</small>
</div>
</div>
</div>
<div class="col-md-4 text-md-end">
<span class="badge bg-primary fs-6 px-3 py-2">
<i class="fas fa-tag me-1"></i>{{ post.category }}
</span>
</div>
</div>
</div>
</header>
<div class="blog-content">
<div class="content-wrapper p-4 bg-white rounded-3 shadow-sm">
{{ post.content|safe }}
</div>
</div>
<!-- Post Tags (if available) -->
{% if post.tags %}
<div class="post-tags mt-4">
<h6 class="mb-2">Tags:</h6>
{% for tag in post.tags %}
<span class="badge bg-light text-dark me-2 mb-2">#{{ tag }}</span>
{% endfor %}
</div>
{% endif %}
</article>
<hr class="my-5">
<!-- Navigation and Actions -->
<div class="post-actions">
<div class="row g-3">
<div class="col-md-6">
<a href="{{ url_for('blog') }}" class="btn btn-outline-primary">
<i class="fas fa-arrow-left me-2"></i>Back to Blog
</a>
</div>
<div class="col-md-6 text-md-end">
<button class="btn btn-outline-success me-2" onclick="sharePost()">
<i class="fas fa-share-alt me-2"></i>Share Post
</button>
<button class="btn btn-outline-info" onclick="printPost()">
<i class="fas fa-print me-2"></i>Print
</button>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<!-- Table of Contents -->
<!-- Post Information -->
<div class="card mb-4 shadow-sm">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="fas fa-info-circle me-2"></i>Post Details</h5>
</div>
<div class="card-body">
<div class="detail-item mb-3">
<div class="d-flex justify-content-between">
<span><i class="fas fa-tag text-primary me-2"></i>Category:</span>
<span class="badge bg-primary">{{ post.category }}</span>
</div>
</div>
<div class="detail-item mb-3">
<div class="d-flex justify-content-between">
<span><i class="fas fa-calendar-alt text-success me-2"></i>Published:</span>
<span>{{ post.date }}</span>
</div>
</div>
<div class="detail-item mb-3">
<div class="d-flex justify-content-between">
<span><i class="fas fa-clock text-warning me-2"></i>Reading Time:</span>
<span>~5 min</span>
</div>
</div>
<div class="detail-item">
<div class="d-flex justify-content-between">
<span><i class="fas fa-user text-info me-2"></i>Author:</span>
<span>Blake Ridgway</span>
</div>
</div>
</div>
</div>
<!-- Share This Post -->
<div class="card mb-4 shadow-sm">
<div class="card-header bg-success text-white">
<h5 class="mb-0"><i class="fas fa-share-alt me-2"></i>Share This Post</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button class="btn btn-outline-primary btn-sm" onclick="sharePost()">
<i class="fas fa-link me-2"></i>Copy Link
</button>
<button class="btn btn-outline-info btn-sm" onclick="shareTwitter()">
<i class="fab fa-twitter me-2"></i>Share on Twitter
</button>
<button class="btn btn-outline-primary btn-sm" onclick="shareLinkedIn()">
<i class="fab fa-linkedin me-2"></i>Share on LinkedIn
</button>
</div>
</div>
</div>
<!-- Author Bio -->
<div class="card shadow-sm">
<div class="card-header bg-secondary text-white">
<h5 class="mb-0"><i class="fas fa-user-circle me-2"></i>About the Author</h5>
</div>
<div class="card-body text-center">
<img src="{{ url_for('static', filename='images/profile.jpg') }}"
alt="Blake Ridgway"
class="rounded-circle mb-3"
width="80" height="80">
<h6>Blake Ridgway</h6>
<p class="small text-muted mb-3">
Systems Administrator & Cybersecurity Enthusiast passionate about secure infrastructure and continuous learning.
</p>
<div class="d-flex justify-content-center gap-2">
<a href="{{ url_for('about') }}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-user me-1"></i>About
</a>
<a href="https://gitlab.com/blakeridgway/" target="_blank" rel="noopener noreferrer" class="btn btn-outline-secondary btn-sm">
<i class="fab fa-gitlab me-1"></i>GitLab
</a>
</div>
</div>
</div>
</div>
</div>
<script>
function sharePost() {
if (navigator.share) {
navigator.share({
title: '{{ post.title }}',
text: 'Check out this blog post by Blake Ridgway',
url: window.location.href
});
} else {
// Fallback: copy to clipboard
navigator.clipboard.writeText(window.location.href).then(() => {
showToast('Link copied to clipboard!');
}).catch(() => {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = window.location.href;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showToast('Link copied to clipboard!');
});
}
}
function shareTwitter() {
const url = encodeURIComponent(window.location.href);
const text = encodeURIComponent('{{ post.title }} by @BlakeRidgway');
window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank');
}
function shareLinkedIn() {
const url = encodeURIComponent(window.location.href);
window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}`, '_blank');
}
function printPost() {
window.print();
}
function showToast(message) {
// Simple toast notification
const toast = document.createElement('div');
toast.className = 'alert alert-success position-fixed';
toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 250px;';
toast.innerHTML = `<i class="fas fa-check-circle me-2"></i>${message}`;
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// Smooth scrolling for table of contents
document.querySelectorAll('.toc a').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
}
});
});
</script>
<style>
.blog-content {
line-height: 1.8;
}
.blog-content h2, .blog-content h3, .blog-content h4 {
margin-top: 2rem;
margin-bottom: 1rem;
}
.blog-content p {
margin-bottom: 1.5rem;
}
.blog-content code {
background-color: #f8f9fa;
padding: 0.2rem 0.4rem;
border-radius: 0.25rem;
font-size: 0.9em;
}
.blog-content pre {
background-color: #f8f9fa;
padding: 1rem;
border-radius: 0.5rem;
overflow-x: auto;
}
.blog-content blockquote {
border-left: 4px solid #007bff;
padding-left: 1rem;
margin: 1.5rem 0;
font-style: italic;
color: #6c757d;
}
@media print {
.col-md-4 {
display: none;
}
.col-md-8 {
width: 100%;
}
}
</style>
{% endblock %}

201
templates/hardware.html Normal file
View file

@ -0,0 +1,201 @@
{% extends "base.html" %}
{% block title %}Hardware - Blake Ridgway{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h1>My Hardware Setup</h1>
<p class="lead">A showcase of my current tech setup and hardware projects focused on systems administration, cybersecurity, and development.</p>
<h3>Current PC Build</h3>
<div class="card mb-4 shadow-sm">
<div class="card-header bg-primary text-white">
<h4 class="mb-0"><i class="fas fa-desktop me-2"></i>Main Workstation</h4>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fab fa-fedora text-primary me-2"></i>OS:</strong> Fedora 42 Workstation
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-microchip text-info me-2"></i>CPU:</strong> Intel Core i9-12900K
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-tv text-success me-2"></i>GPU:</strong> Intel Arc A770
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-memory text-warning me-2"></i>RAM:</strong> Corsair LPX 64GB (3200 MHz)
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-hdd text-danger me-2"></i>NVMe:</strong> Samsung 980 PRO 1TB
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-hdd text-secondary me-2"></i>SSD:</strong> Samsung 860 EVO 500GB
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-hdd text-secondary me-2"></i>HDD:</strong> WD Green 1TB
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-hdd text-secondary me-2"></i>Storage:</strong> Seagate Constellation 4TB
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-microchip text-info me-2"></i>Mobo:</strong> ASRock B660M PRO
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-plug text-warning me-2"></i>PSU:</strong> Corsair CX750M
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-cube text-dark me-2"></i>Case:</strong> CORSAIR 4000D
</div>
</div>
</div>
</div>
</div>
<h3>Peripherals & Accessories</h3>
<div class="card mb-4 shadow-sm">
<div class="card-header bg-success text-white">
<h4 class="mb-0"><i class="fas fa-keyboard me-2"></i>Input & Output Devices</h4>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-desktop text-primary me-2"></i>Primary:</strong> LG 34WQ500-B - 34"
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-desktop text-secondary me-2"></i>Secondary:</strong> ASUS VS248H - 24"
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-keyboard text-info me-2"></i>Keyboard:</strong> System76 Launch
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-mouse text-warning me-2"></i>Mouse:</strong> Logitech G305
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-headphones text-success me-2"></i>Headset:</strong> CCZ DC01 PRO
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-sliders-h text-danger me-2"></i>Mixer:</strong> Pupgsis T12
</div>
</div>
<div class="col-md-6">
<div class="spec-item p-2 bg-light rounded">
<strong><i class="fas fa-video text-primary me-2"></i>Webcam:</strong> Logitech C920x
</div>
</div>
</div>
</div>
</div>
<h3>Current Hardware Projects</h3>
<div class="row g-4">
<div class="col-md-6">
<div class="skill-card p-4 bg-light rounded-3 shadow-sm h-100">
<div class="project-icon mb-3">
<i class="fas fa-server fa-2x text-primary"></i>
</div>
<h5>Home Server Re-setup</h5>
<p class="mb-0">
Reinstalling Proxmox on my PowerEdge R720 to host containers and VMs for expanding
knowledge in cybersecurity, systems administration, and development projects.
</p>
</div>
</div>
<div class="col-md-6">
<div class="skill-card p-4 bg-light rounded-3 shadow-sm h-100">
<div class="project-icon mb-3">
<i class="fas fa-shield-alt fa-2x text-danger"></i>
</div>
<h5>Open Source SOC</h5>
<p class="mb-0">
Building a Security Operations Center using open source tools like ELK Stack,
Wazuh, and MISP for threat detection and incident response.
</p>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 shadow-sm">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="fas fa-chart-pie me-2"></i>System Stats</h5>
</div>
<div class="card-body">
<div class="stat-item mb-3">
<div class="d-flex justify-content-between">
<span><strong>Total Storage:</strong></span>
<span class="badge bg-primary">6.5TB</span>
</div>
</div>
<div class="stat-item mb-3">
<div class="d-flex justify-content-between">
<span><strong>RAM:</strong></span>
<span class="badge bg-success">64GB</span>
</div>
</div>
<div class="stat-item mb-3">
<div class="d-flex justify-content-between">
<span><strong>CPU Cores:</strong></span>
<span class="badge bg-warning">16C/24T</span>
</div>
</div>
<div class="stat-item mb-3">
<div class="d-flex justify-content-between">
<span><strong>Display Area:</strong></span>
<span class="badge bg-info">58" Total</span>
</div>
</div>
</div>
</div>
<div class="card shadow-sm">
<div class="card-header bg-secondary text-white">
<h5 class="mb-0"><i class="fas fa-tools me-2"></i>Hardware Focus</h5>
</div>
<div class="card-body">
<ul class="list-unstyled">
<li class="mb-2"><i class="fas fa-server text-primary me-2"></i>Enterprise Server Hardware</li>
<li class="mb-2"><i class="fas fa-network-wired text-success me-2"></i>Network Infrastructure</li>
<li class="mb-2"><i class="fas fa-shield-alt text-danger me-2"></i>Security Appliances</li>
<li class="mb-2"><i class="fas fa-cloud text-info me-2"></i>Virtualization Platforms</li>
<li class="mb-2"><i class="fab fa-linux text-warning me-2"></i>Linux Workstations</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

61
templates/index.html Normal file
View file

@ -0,0 +1,61 @@
{% extends "base.html" %}
{% block content %}
<div class="hero-section text-center">
<div class="container">
<!-- Animated Greeting -->
<div class="hero-greeting mb-3">
<h1 class="mb-3">
Greetings, I'm Blake Ridgway
<img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif"
width="35" height="35"
alt="Waving hand"
class="wave-animation">
</h1>
<div class="hero-tagline">
<span class="badge bg-primary me-2">Systems Administrator</span>
<span class="badge bg-success me-2">Cybersecurity Enthusiast</span>
<span class="badge bg-info me-2">Linux & Open Source Advocate</span>
<span class="badge bg-warning">Ultra Endurance Cyclist</span>
</div>
</div>
<!-- Mission Statement -->
<div class="hero-mission my-4">
<p class="lead mb-3">
As a Systems Administrator, my focus is on ensuring the stability, integrity, and performance of critical IT infrastructure.
Through hands-on experience managing Linux, AWS, and Azure environments, I've learned that
<strong class="text-light">true system stability is impossible without robust security</strong>.
</p>
</div>
</div>
</div>
<!-- Personal Projects -->
<div class="text-center mb-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card border-0 shadow-lg bg-gradient">
<div class="card-body text-white p-4">
<h3 class="card-title mb-3">🚴 Personal Projects</h3>
<p class="card-text mb-4">
Beyond my professional endeavors, I'm an avid cyclist and open-source enthusiast.
I'm currently developing a platform to help cyclists train smarter, combining
data-driven insights with a strong emphasis on
<strong>end-to-end data encryption, user privacy, and secure development practices.</strong>
</p>
<div class="d-flex justify-content-center gap-3">
<a href="/biking" class="btn btn-light">
<i class="fas fa-bicycle me-2"></i>View My Cycling Stats
</a>
<a href="/blog" class="btn btn-outline-light">
<i class="fas fa-blog me-2"></i>Read My Blog
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}