413 lines
12 KiB
Vue
Raw Normal View History

2025-12-18 01:13:04 -03:00
<template>
<div class="page">
<section class="card about">
<div class="left">
2025-12-19 16:53:29 -03:00
<div class="portrait">
<img src="@/assets/profile-avatar.jpg" alt="Brad Stein" />
</div>
2025-12-18 01:13:04 -03:00
<div class="contact">
<div class="name">Brad Stein</div>
2026-06-29 13:23:07 -03:00
<div class="role">{{ about.role }}</div>
<div class="role">{{ about.focusLine }}</div>
2025-12-18 01:13:04 -03:00
<div class="meta">US Citizen · Remote</div>
<div class="links">
2026-06-29 13:23:07 -03:00
<a href="https://www.linkedin.com/in/steinbradley/" target="_blank" rel="noopener noreferrer">LinkedIn</a>
<a href="https://scm.bstein.dev/bstein" target="_blank" rel="noopener noreferrer">Gitea</a>
<a href="https://metrics.bstein.dev" target="_blank" rel="noopener noreferrer">Metrics</a>
2025-12-18 01:13:04 -03:00
<a href="mailto:brad@bstein.dev">brad@bstein.dev</a>
</div>
</div>
</div>
<div class="right">
<h1>About Me</h1>
<div class="copy">
2026-06-29 13:23:07 -03:00
<p v-for="paragraph in about.summary.slice(0, 2)" :key="paragraph">{{ paragraph }}</p>
2025-12-18 01:13:04 -03:00
<p>
2026-06-29 13:23:07 -03:00
Public platform work is visible in the
<a href="https://scm.bstein.dev/bstein/titan-iac" target="_blank" rel="noopener noreferrer">Titan IaC repo</a>,
<a href="https://scm.bstein.dev/bstein" target="_blank" rel="noopener noreferrer">scm.bstein.dev</a> and
<a href="https://metrics.bstein.dev" target="_blank" rel="noopener noreferrer">metrics.bstein.dev</a>.
2025-12-18 01:13:04 -03:00
</p>
</div>
2026-06-29 13:23:07 -03:00
<div class="skill-groups" aria-label="Résumé skill summary">
<div v-for="group in about.skillGroups" :key="group.label" class="skill-group">
<h2>{{ group.label }}</h2>
<div class="highlights">
<div v-for="skill in group.items" :key="skill" class="pill mono">{{ skill }}</div>
</div>
</div>
2025-12-18 01:13:04 -03:00
</div>
</div>
</section>
<section class="card">
<div class="section-head">
<h2>Experience</h2>
<span class="pill mono">Summary</span>
</div>
<div class="timeline">
<div v-for="item in timeline" :key="item.id" class="entry">
<div class="dot"></div>
<div>
<div class="entry-title">{{ item.title }}</div>
2026-06-29 13:23:07 -03:00
<div class="entry-sub">
<a v-if="item.companyUrl" :href="item.companyUrl" target="_blank" rel="noopener noreferrer">
{{ item.company }}
</a>
<span v-else>{{ item.company }}</span>
<span> · {{ item.dates }}</span>
</div>
2025-12-18 01:13:04 -03:00
<ul>
<li v-for="point in item.points" :key="point">{{ point }}</li>
</ul>
</div>
</div>
</div>
<div class="divider"></div>
<p class="note">
2026-06-29 13:23:07 -03:00
Web version aligned to <span class="mono">Stein.Brad.Resume.2026.06.pdf</span>. Phone and street address are
intentionally omitted from the public site.
2025-12-18 01:13:04 -03:00
</p>
</section>
<section class="card">
<div class="section-head">
2026-01-13 08:53:13 -03:00
<h2>Titan Lab</h2>
2026-06-29 13:23:07 -03:00
<span class="pill mono">atlas platform</span>
2025-12-18 01:13:04 -03:00
</div>
<div class="copy">
<p>
2026-06-29 13:23:07 -03:00
Titan Lab is the live platform behind bstein.dev. The core is <span class="mono">Atlas</span>, a GitOps-managed
<span class="mono">k3s</span> cluster where services are reconciled by <span class="mono">Flux</span> and operated
with the same habits I use professionally: source of truth, quality gates, observability, identity, storage,
recovery paths, and documented handoff.
</p>
<p>
The platform runs identity, source control, CI/CD, container delivery, observability, storage, member services,
and experimental AI workloads. It is also where I build automation around bootstrap, recovery, service health,
and operator workflows instead of leaving them as manual notes.
2025-12-18 01:13:04 -03:00
</p>
<p>
2026-06-29 13:23:07 -03:00
<span class="mono">Oceanus</span> and <span class="mono">Tethys</span> are now part of Atlas capacity instead of separate public status surfaces.
2026-08-01 03:24:51 -03:00
The dedicated non-cluster hosts are the control-plane database node and the jumphost. <span class="mono">Cassandra</span>,
2026-06-29 13:23:07 -03:00
the MTG AI playtester, is deployed at
2026-08-01 03:24:51 -03:00
<a href="https://cassandra.bstein.dev/" target="_blank" rel="noopener noreferrer">cassandra.bstein.dev</a>.
2026-06-29 13:23:07 -03:00
</p>
</div>
</section>
<section class="card">
<div class="section-head">
<h2>Education</h2>
<span class="pill mono">UT Austin</span>
</div>
<div class="copy">
<p>
Studied Mechanical Engineering and Applied Math at the University of Texas at Austin, including Java, C++,
probability, statistics, complex analysis, numerical methods, number theory, and differential equations.
2026-01-13 08:53:13 -03:00
</p>
<p>
2026-06-29 13:23:07 -03:00
Participated in the Emerging Scholars honors calculus program and later served as an assistant for it.
2025-12-18 01:13:04 -03:00
</p>
</div>
</section>
</div>
</template>
<script setup>
2026-08-01 03:24:51 -03:00
import { computed } from "vue";
import { useRoute } from "vue-router";
import { homepageContentForMode, homepageModeFromRoute } from "../data/homepageContent";
2026-06-29 13:23:07 -03:00
2026-08-01 03:24:51 -03:00
const route = useRoute();
const content = computed(() => homepageContentForMode(homepageModeFromRoute(route)));
const about = computed(() => content.value.about);
2025-12-18 01:13:04 -03:00
const timeline = [
{
id: "titan-lab-architect",
2026-06-29 13:23:07 -03:00
title: "Kubernetes Cluster Development",
company: "Titan Lab",
companyUrl: "https://scm.bstein.dev/bstein/titan-iac",
2025-12-18 01:13:04 -03:00
dates: "Apr 2020 Present",
points: [
2026-06-29 13:23:07 -03:00
"Created and operate a local k3s cluster with metrics for home and self-hosted services.",
"Run personal SCM, CI/CD, password management, mail, cloud storage, movie streaming, video conferencing, AI chatbot, and cluster automation services.",
"Build automation around bootstrap, recovery, service health, operator workflows, identity, storage, and dashboards.",
2025-12-18 01:13:04 -03:00
],
},
{
2026-06-29 13:23:07 -03:00
id: "actalent-boeing-ptes",
2025-12-18 01:13:04 -03:00
title: "Software Development Engineer in Test",
2026-06-29 13:23:07 -03:00
company: "Boeing",
companyUrl: "https://www.boeing.com/",
dates: "Oct 2023 Oct 2025",
2025-12-18 01:13:04 -03:00
points: [
2026-06-29 13:23:07 -03:00
"Consulted through Actalent on a complex communications program at the intersection of test engineering, DevSecOps, and infrastructure automation.",
"Created system and end-to-end tests using Python and Selenium to validate microservice and web UI interactions.",
"Built TaskWatcher tooling for key capture/decryption and Docker Compose drift protection on dedicated hosts.",
"Created Lanterna to visualize a Flux-driven monorepo with Mermaid charts rerun after merged changes.",
"Created promotion-pipeline quality gates for a system test suite and microservice release flow.",
2025-12-18 01:13:04 -03:00
],
},
{
2026-06-29 13:23:07 -03:00
id: "tradehat-frontend",
title: "Frontend Engineer",
company: "TradeHat",
companyUrl: "https://www.tradehat.com/",
dates: "Mar 2020 Mar 2021",
points: [
"Worked as one of four engineers building the startup product from scratch.",
"Selected Vue.js and Quasar as the frontend foundation for multi-architecture support.",
"Helped build the alpha deployment infrastructure using redundant ThinkPads hosted at each engineer's home in Dallas.",
"Built reporting and dashboard pages in Vue with Tailwind CSS and FusionCharts.",
],
},
{
id: "ibm-sdet",
2025-12-18 01:13:04 -03:00
title: "Software Development Engineer in Test",
2026-06-29 13:23:07 -03:00
company: "IBM",
companyUrl: "https://www.ibm.com/cloud",
dates: "Nov 2018 May 2023",
2025-12-18 01:13:04 -03:00
points: [
2026-06-29 13:23:07 -03:00
"Authored and planned automated end-to-end and system tests for IBM Cloud systems in Python, Go, and Terraform.",
"Served as a consultant before accepting a full-time role in 2020; documented contributions and hosted feature demos and knowledge transfers.",
"Automated platform validation for a remote data center, including RHEL and SUSE functionality, licensing, repository availability, and performance.",
"Automated A100 and V100 GPU resource tests for CUDA functionality and data security in accelerated-computing environments.",
"Created a Zabbix health dashboard for Cloud APIs and planned key feature testing in Python.",
"Created Terraform and Go system tests for microservice interactions and platform scalability/autoscaling.",
2025-12-18 01:13:04 -03:00
],
},
{
id: "unifocus-survey-programmer",
2026-06-29 13:23:07 -03:00
title: "Lead Survey Programmer",
2025-12-18 01:13:04 -03:00
company: "UniFocus",
2026-06-29 13:23:07 -03:00
companyUrl: "https://www.unifocus.com/",
2025-12-18 01:13:04 -03:00
dates: "Aug 2014 Nov 2018",
points: [
2026-06-29 13:23:07 -03:00
"Transformed a configuration role into an automation role using Python and SQL for online surveys and reports.",
"Served as team lead, recruiting staff and mentoring junior engineers.",
"Converted Python automation scripts into a CLI tool and built a VBA-driven Excel workbook for business contacts.",
"Automated responsive design updates for web surveys with Python and added JavaScript/CSS mobile support.",
"Created a Python XML parser to restore survey data that could otherwise be lost.",
2025-12-18 01:13:04 -03:00
"Won UniFocus Excellence Award (2015) and Innovation Award (2016).",
],
},
];
</script>
<style scoped>
.page {
2026-06-29 13:23:07 -03:00
max-width: 1260px;
2025-12-18 01:13:04 -03:00
margin: 0 auto;
padding: 32px 22px 72px;
}
.about {
display: grid;
2026-06-29 13:23:07 -03:00
grid-template-columns: minmax(220px, 0.48fr) minmax(0, 2fr);
gap: 30px;
2025-12-18 01:13:04 -03:00
}
.portrait {
width: 120px;
height: 120px;
flex: 0 0 120px;
aspect-ratio: 1 / 1;
2025-12-18 01:13:04 -03:00
border-radius: 50%;
2025-12-19 16:53:29 -03:00
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.12);
2025-12-18 01:13:04 -03:00
display: grid;
place-items: center;
2025-12-19 16:53:29 -03:00
background: linear-gradient(135deg, rgba(0, 229, 197, 0.5), rgba(127, 124, 255, 0.45));
}
.portrait img {
width: 100%;
height: 100%;
object-fit: cover;
2025-12-18 01:13:04 -03:00
}
.left {
display: flex;
2026-06-29 13:23:07 -03:00
flex-direction: column;
align-items: flex-start;
2025-12-18 01:13:04 -03:00
gap: 14px;
2026-06-29 13:23:07 -03:00
padding-top: 8px;
2025-12-18 01:13:04 -03:00
}
.contact .name {
font-weight: 800;
color: var(--text-strong);
}
.contact .role {
color: var(--text-muted);
2026-06-29 13:23:07 -03:00
max-width: 220px;
line-height: 1.35;
2025-12-18 01:13:04 -03:00
}
.contact .meta {
color: var(--text-muted);
font-size: 13px;
margin-top: 2px;
}
.badges {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 10px;
}
.links {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 8px;
}
.links a {
color: var(--accent-cyan);
text-decoration: none;
}
.links a:hover {
color: var(--accent-rose);
}
.right h1 {
margin: 0 0 8px;
}
2026-06-29 13:23:07 -03:00
.skill-groups {
display: grid;
gap: 0;
margin-top: 18px;
}
.skill-group {
display: grid;
grid-template-columns: minmax(130px, 160px) minmax(0, 1fr);
gap: 16px;
align-items: start;
padding: 11px 0;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.skill-group h2 {
margin: 5px 0 0;
color: var(--text-strong);
font-size: 15px;
}
2025-12-18 01:13:04 -03:00
.section-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.copy {
color: var(--text-muted);
}
.copy p {
margin: 0 0 10px;
line-height: 1.55;
}
.copy p:last-child {
margin-bottom: 0;
}
.highlights {
display: flex;
2026-06-29 13:23:07 -03:00
gap: 6px;
2025-12-18 01:13:04 -03:00
flex-wrap: wrap;
2026-06-29 13:23:07 -03:00
margin-top: 0;
}
.highlights .pill {
min-height: 30px;
padding: 5px 9px;
font-size: 12px;
2025-12-18 01:13:04 -03:00
}
.note {
color: var(--text-muted);
margin: 0;
}
.note a {
color: var(--text-muted);
text-decoration: none;
border-bottom: 1px dashed rgba(255, 255, 255, 0.18);
padding-bottom: 1px;
}
.note a:hover {
color: var(--accent-cyan);
border-bottom-color: rgba(0, 229, 197, 0.5);
}
.timeline {
display: grid;
gap: 12px;
margin-top: 8px;
}
.entry {
display: grid;
grid-template-columns: auto 1fr;
gap: 10px;
}
.dot {
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid var(--accent-cyan);
margin-top: 6px;
}
.entry-title {
font-weight: 800;
}
.entry-sub {
color: var(--text-muted);
margin-bottom: 4px;
}
2026-06-29 13:23:07 -03:00
.entry-sub a {
color: var(--accent-cyan);
text-decoration: none;
}
.entry-sub a:hover {
color: var(--accent-rose);
}
2025-12-18 01:13:04 -03:00
ul {
margin: 0;
padding-left: 16px;
color: var(--text-muted);
}
@media (max-width: 820px) {
.about {
grid-template-columns: 1fr;
}
2026-06-29 13:23:07 -03:00
2025-12-18 01:13:04 -03:00
.left {
justify-content: flex-start;
}
2026-06-29 13:23:07 -03:00
.skill-group {
grid-template-columns: 1fr;
gap: 8px;
}
2025-12-18 01:13:04 -03:00
}
</style>