justin.deal/dist/about/index.html

578 lines
52 KiB
HTML
Raw Normal View History

<!DOCTYPE html><html lang="en"> <head><!-- Theme flash prevention script - must be first in head --><script>
// Immediately apply the saved theme to prevent flash
(function() {
function getThemePreference() {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
const theme = getThemePreference();
// Apply theme immediately to prevent flash
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
// Store the theme in localStorage for future visits
if (typeof localStorage !== 'undefined') {
localStorage.setItem('theme', theme);
}
// Add a class to indicate JS is loaded and theme is applied
document.documentElement.classList.add('theme-loaded');
})();
</script><!-- Service worker registration --><script>
// Register service worker for offline support and caching
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('SW registered: ', registration.scope);
})
.catch(error => {
console.log('SW registration failed: ', error);
});
});
}
</script><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="generator" content="Astro v5.7.5"><!-- Favicons --><link rel="icon" type="image/svg+xml" href="/favicons/favicon.png"><link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><!-- Theme colors --><meta name="theme-color" content="#282828" media="(prefers-color-scheme: dark)"><meta name="theme-color" content="#ebdbb2" media="(prefers-color-scheme: light)"><!-- Preconnect to external resources --><link rel="preconnect" href="https://fonts.bunny.net" crossorigin><link rel="dns-prefetch" href="https://fonts.bunny.net"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="preconnect" href="https://unpkg.com" crossorigin><link rel="dns-prefetch" href="https://unpkg.com"><!-- Preload critical fonts with font-display: swap --><link rel="preload" href="https://fonts.bunny.net/css?family=ibm-plex-mono:400,400i,500,500i,600,600i,700,700i&display=swap" as="style"><link href="https://fonts.bunny.net/css?family=ibm-plex-mono:400,400i,500,500i,600,600i,700,700i&display=swap" rel="stylesheet"><!-- Preload critical font files --><link rel="preload" href="https://cdn.jsdelivr.net/fontsource/fonts/press-start-2p@latest/latin-400-normal.woff2" as="font" type="font/woff2" crossorigin><!-- Preload Alpine.js --><link rel="preload" href="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" as="script"><script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script><!-- Font loading observer --><script>
if ("fonts" in document) {
Promise.all([
document.fonts.load("1em IBM Plex Mono"),
document.fonts.load("1em press-start-2p")
]).then(() => {
document.documentElement.classList.add("fonts-loaded");
});
} else {
document.documentElement.classList.add("fonts-loaded");
}
</script><!-- Time-based theme scheduler --><script>
// Time-based theme switching
(function() {
// Only run if user has selected auto mode
const themeMode = localStorage.getItem('theme-mode');
if (themeMode === 'auto') {
const checkTime = () => {
const hour = new Date().getHours();
const isDayTime = hour >= 7 && hour < 19; // 7 AM to 7 PM
const theme = isDayTime ? 'light' : 'dark';
const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
if (theme !== currentTheme) {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
localStorage.setItem('theme', theme);
// Dispatch theme changed event
window.dispatchEvent(new CustomEvent('theme-changed', {
detail: { theme, automatic: true, mode: 'auto' }
}));
}
};
// Check immediately
checkTime();
// Check every hour
setInterval(checkTime, 60 * 60 * 1000);
// Also check at specific times (7 AM and 7 PM)
const scheduleCheck = () => {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
// Calculate time until next check (either 7 AM or 7 PM)
let nextCheckHour;
if (hours < 7) {
nextCheckHour = 7; // Next check at 7 AM
} else if (hours < 19) {
nextCheckHour = 19; // Next check at 7 PM
} else {
nextCheckHour = 7; // Next check at 7 AM tomorrow
}
// Calculate milliseconds until next check
let msUntilNextCheck;
if (hours >= 19) {
// After 7 PM, next check is 7 AM tomorrow
msUntilNextCheck = ((24 - hours + 7) * 60 - minutes) * 60 * 1000;
} else {
// Before 7 PM, next check is either 7 AM or 7 PM today
msUntilNextCheck = ((nextCheckHour - hours) * 60 - minutes) * 60 * 1000;
}
// Schedule the next check
setTimeout(() => {
checkTime();
scheduleCheck(); // Schedule the next check after this one
}, msUntilNextCheck);
};
// Start the scheduling
scheduleCheck();
2025-04-27 22:15:19 -07:00
}
})();
</script><!-- Theme transition script --><script type="module">document.addEventListener("DOMContentLoaded",()=>{window.addEventListener("theme-changed",t=>{const a=(t instanceof CustomEvent?t:null)?.detail?.theme||(document.documentElement.classList.contains("dark")?"dark":"light");window.matchMedia("(prefers-reduced-motion: reduce)").matches||(document.querySelectorAll("h1, h2, h3").forEach((e,o)=>{e.classList.remove("theme-animate-slide"),e.offsetWidth,setTimeout(()=>{e.classList.add("theme-animate-slide")},50+o*30)}),document.querySelectorAll(".card, article, section:not(section section)").forEach((e,o)=>{e.classList.remove("theme-animate-scale"),e.offsetWidth,setTimeout(()=>{e.classList.add("theme-animate-scale")},100+o*40)}),document.querySelectorAll("img, svg").forEach((e,o)=>{e.classList.remove("theme-animate-fade"),e.offsetWidth,setTimeout(()=>{e.classList.add("theme-animate-fade")},150+o*20)}),a==="dark"?(document.querySelectorAll("code, pre").forEach(e=>{e.classList.add("dark-theme-code")}),document.querySelectorAll(".button-primary, .cta-button").forEach(e=>{e.classList.add("dark-theme-glow")})):(document.querySelectorAll("code, pre").forEach(e=>{e.classList.remove("dark-theme-code")}),document.querySelectorAll(".button-primary, .cta-button").forEach(e=>{e.classList.remove("dark-theme-glow")})))})});const d=()=>{const t=document.createElement("style");t.textContent=`
.dark-theme-code {
box-shadow: 0 0 8px rgba(254, 128, 25, 0.3);
}
.dark-theme-glow {
box-shadow: 0 0 12px rgba(254, 128, 25, 0.4);
}
@media (prefers-reduced-motion: reduce) {
.theme-animate-fade,
.theme-animate-slide,
.theme-animate-scale {
animation: none !important;
transition: none !important;
}
}
`,document.head.appendChild(t)};document.addEventListener("DOMContentLoaded",d);</script><script>
/**
* Initialize search functionality for any content type
* @returns {Object} Alpine.js data object with search functionality
*/
function initializeSearch(contentSelector = '.searchable-item', options = {}) {
const defaults = {
nameAttribute: 'data-name',
tagsAttribute: 'data-tags',
categoryAttribute: 'data-category',
additionalAttributes: [],
noResultsMessage: 'No results found',
allItemsMessage: 'Showing all items',
resultCountMessage: (count) => `Found ${count} items`,
itemLabel: 'items'
};
2025-04-27 22:15:19 -07:00
const config = { ...defaults, ...options };
2025-04-27 22:15:19 -07:00
return {
searchQuery: '',
hasResults: true,
visibleCount: 0,
loading: false, // Start with loading state false - the LoadingManager will control this
init() {
// Initialize the visible count
this.visibleCount = document.querySelectorAll(contentSelector).length;
this.setupWatchers();
this.setupKeyboardShortcuts();
// Handle theme changes
window.addEventListener('theme-changed', () => {
this.filterContent(this.searchQuery);
});
},
setupWatchers() {
this.$watch('searchQuery', (query) => {
// Filter content immediately - no artificial delay
this.filterContent(query);
});
},
setupKeyboardShortcuts() {
// Track the currently focused item index
this.focusedItemIndex = -1;
document.addEventListener('keydown', (e) => {
// '/' key focuses the search input
if (e.key === '/' && document.activeElement.id !== 'app-search') {
e.preventDefault();
document.getElementById('app-search').focus();
}
// Escape key clears the search
if (e.key === 'Escape' && this.searchQuery !== '') {
this.searchQuery = '';
document.getElementById('app-search').focus();
this.focusedItemIndex = -1;
this.clearItemFocus();
}
// Arrow key navigation through results
if (this.searchQuery && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
e.preventDefault();
const visibleItems = this.getVisibleItems();
if (visibleItems.length === 0) return;
// Update focused item index
if (e.key === 'ArrowDown') {
this.focusedItemIndex = Math.min(this.focusedItemIndex + 1, visibleItems.length - 1);
} else {
this.focusedItemIndex = Math.max(this.focusedItemIndex - 1, -1);
}
// Clear previous focus
this.clearItemFocus();
// If we're back at -1, focus the search input
if (this.focusedItemIndex === -1) {
document.getElementById('app-search').focus();
return;
}
// Focus the new item
const itemToFocus = visibleItems[this.focusedItemIndex];
this.focusItem(itemToFocus);
}
// Enter key selects the focused item
if (e.key === 'Enter' && this.focusedItemIndex >= 0) {
const visibleItems = this.getVisibleItems();
if (visibleItems.length === 0) return;
const selectedItem = visibleItems[this.focusedItemIndex];
const link = selectedItem.querySelector('a');
if (link) {
link.click();
}
}
});
},
getVisibleItems() {
return Array.from(document.querySelectorAll(contentSelector))
.filter(item => item.style.display !== 'none');
},
clearItemFocus() {
// Remove focus styling from all items
document.querySelectorAll(`${contentSelector}.keyboard-focus`).forEach(item => {
item.classList.remove('keyboard-focus');
});
},
focusItem(item) {
// Add focus styling
item.classList.add('keyboard-focus');
item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
},
filterContent(query) {
query = query.toLowerCase();
let anyResults = false;
let visibleCount = 0;
// Process all content items
document.querySelectorAll(contentSelector).forEach((item) => {
// Get searchable attributes
const name = (item.getAttribute(config.nameAttribute) || '').toLowerCase();
const tags = (item.getAttribute(config.tagsAttribute) || '').toLowerCase();
const category = (item.getAttribute(config.categoryAttribute) || '').toLowerCase();
// Check additional attributes if specified
const additionalMatches = config.additionalAttributes.some(attr => {
const value = (item.getAttribute(attr) || '').toLowerCase();
return value.includes(query);
});
const isMatch = query === '' ||
name.includes(query) ||
tags.includes(query) ||
category.includes(query) ||
additionalMatches;
if (isMatch) {
item.style.display = '';
anyResults = true;
visibleCount++;
} else {
item.style.display = 'none';
}
});
// Update category visibility for homelab page
this.updateCategoryVisibility(query);
// Update parent containers if needed
this.updateContainerVisibility(query);
this.updateResultsStatus(query, anyResults, visibleCount);
},
updateCategoryVisibility(query) {
// Only proceed if we have category sections (homelab page)
const categorySections = document.querySelectorAll('.category-section');
if (categorySections.length === 0) return;
// For each category section, check if it has any visible app cards
categorySections.forEach((categorySection) => {
const categoryId = categorySection.getAttribute('data-category');
const appCards = categorySection.querySelectorAll('.app-card');
// Count visible app cards in this category
const visibleApps = Array.from(appCards).filter(card =>
card.style.display !== 'none'
).length;
// If no visible apps and we're searching, hide the category
if (query !== '' && visibleApps === 0) {
categorySection.style.display = 'none';
} else {
categorySection.style.display = '';
}
});
},
updateContainerVisibility(query) {
// If there are container elements that should be hidden when empty
const containers = document.querySelectorAll('.content-container');
if (containers.length > 0) {
containers.forEach((container) => {
const hasVisibleItems = Array.from(
container.querySelectorAll(contentSelector)
).some((item) => item.style.display !== 'none');
if (query === '' || hasVisibleItems) {
container.style.display = '';
} else {
container.style.display = 'none';
}
});
}
},
updateResultsStatus(query, anyResults, count) {
// Update results status
this.hasResults = query === '' || anyResults;
this.visibleCount = count;
// Update screen reader status
const statusEl = document.getElementById('search-status');
if (statusEl) {
if (query === '') {
statusEl.textContent = config.allItemsMessage;
this.visibleCount = document.querySelectorAll(contentSelector).length;
} else if (this.hasResults) {
statusEl.textContent = config.resultCountMessage(count);
} else {
statusEl.textContent = config.noResultsMessage;
}
}
}
2025-04-27 22:15:19 -07:00
};
}
2025-04-27 22:15:19 -07:00
// Register Alpine.js data components when Alpine is loaded
document.addEventListener('alpine:init', () => {
// Homelab search
window.Alpine.data('searchServices', () => {
const baseSearch = initializeSearch('.app-card', {
nameAttribute: 'data-app-name',
tagsAttribute: 'data-app-tags',
categoryAttribute: 'data-app-category',
noResultsMessage: 'No services found',
allItemsMessage: 'Showing all services',
resultCountMessage: (count) => `Found ${count} services`,
itemLabel: 'services'
});
// Add icon size slider functionality
return {
...baseSearch,
iconSizeValue: 2, // Slider value: 1=small, 2=medium, 3=large
iconSize: 'medium', // small, medium, large
viewMode: 'grid', // grid or list
displayMode: 'both', // both, image, or name
debounceTimeout: null, // For debouncing slider changes
init() {
baseSearch.init.call(this);
// Apply initial icon size, view mode, and display mode
this.applyIconSize();
this.applyViewMode();
this.applyDisplayMode();
},
// Icon size methods
setIconSize(size) {
if (typeof size === 'string') {
// Handle legacy string values (small, medium, large)
this.iconSize = size;
this.iconSizeValue = size === 'small' ? 1 : size === 'medium' ? 2 : 3;
} else {
// Handle slider numeric values
this.iconSizeValue = parseFloat(size);
// Map slider value to size name
if (this.iconSizeValue <= 1.33) {
this.iconSize = 'small';
} else if (this.iconSizeValue <= 2.33) {
this.iconSize = 'medium';
} else {
this.iconSize = 'large';
}
}
this.applyIconSize();
},
// Handle slider input with debounce
handleSliderChange(event) {
const value = event.target.value;
// Clear any existing timeout
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout);
}
// Set a new timeout
this.debounceTimeout = setTimeout(() => {
this.setIconSize(value);
}, 50); // 50ms debounce
},
applyIconSize() {
const appList = document.getElementById('app-list');
if (!appList) return;
// Remove existing size classes
appList.classList.remove('icon-size-small', 'icon-size-medium', 'icon-size-large');
// Add the new size class
appList.classList.add(`icon-size-${this.iconSize}`);
// Apply custom CSS variable for fine-grained control
appList.style.setProperty('--icon-scale', this.iconSizeValue);
},
// View mode methods
toggleViewMode() {
this.viewMode = this.viewMode === 'grid' ? 'list' : 'grid';
this.applyViewMode();
},
setViewMode(mode) {
this.viewMode = mode;
this.applyViewMode();
},
applyViewMode() {
const appList = document.getElementById('app-list');
if (!appList) return;
// Remove existing view mode classes
appList.classList.remove('view-mode-grid', 'view-mode-list');
// Add the new view mode class
appList.classList.add(`view-mode-${this.viewMode}`);
// Update all category sections
document.querySelectorAll('.category-section').forEach(section => {
const gridContainer = section.querySelector('.grid');
if (gridContainer) {
// Update grid classes based on view mode
if (this.viewMode === 'grid') {
gridContainer.classList.remove('grid-cols-1');
gridContainer.classList.add('grid-cols-2', 'sm:grid-cols-3', 'lg:grid-cols-4');
} else {
gridContainer.classList.remove('grid-cols-2', 'sm:grid-cols-3', 'lg:grid-cols-4');
gridContainer.classList.add('grid-cols-1');
}
}
});
},
// Display mode methods
setDisplayMode(mode) {
this.displayMode = mode;
this.applyDisplayMode();
},
applyDisplayMode() {
const appList = document.getElementById('app-list');
if (!appList) return;
// Remove existing display mode classes
appList.classList.remove('display-both', 'display-image-only', 'display-name-only');
// Add the new display mode class
if (this.displayMode === 'image') {
appList.classList.add('display-image-only');
} else if (this.displayMode === 'name') {
appList.classList.add('display-name-only');
} else {
appList.classList.add('display-both');
}
// Update all category sections
document.querySelectorAll('.category-section').forEach(section => {
const gridContainer = section.querySelector('.grid');
if (gridContainer) {
// Update grid classes based on view mode
if (this.viewMode === 'grid') {
gridContainer.classList.remove('grid-cols-1');
gridContainer.classList.add('grid-cols-2', 'sm:grid-cols-3', 'lg:grid-cols-4');
} else {
gridContainer.classList.remove('grid-cols-2', 'sm:grid-cols-3', 'lg:grid-cols-4');
gridContainer.classList.add('grid-cols-1');
}
}
});
}
};
});
// Blog search
window.Alpine.data('searchArticles', () => {
return initializeSearch('.article-item', {
nameAttribute: 'data-title',
tagsAttribute: 'data-tags',
additionalAttributes: ['data-description'],
noResultsMessage: 'No articles found',
allItemsMessage: 'Showing all articles',
resultCountMessage: (count) => `Found ${count} articles`,
itemLabel: 'articles'
});
});
// Projects search
window.Alpine.data('searchProjects', () => {
return initializeSearch('.project-item', {
nameAttribute: 'data-title',
tagsAttribute: 'data-tags',
additionalAttributes: ['data-description', 'data-github', 'data-live'],
noResultsMessage: 'No projects found',
allItemsMessage: 'Showing all projects',
resultCountMessage: (count) => `Found ${count} projects`,
itemLabel: 'projects'
});
});
});
</script> <title>About Justin Deal • My personal slice of the internet</title> <meta name="description" content="Software engineer with experience in cloud computing, sustainability reporting, and high-performance computing."> <meta property="og:title" content="About Justin Deal • My personal slice of the internet"> <meta property="og:description" content="Software engineer with experience in cloud computing, sustainability reporting, and high-performance computing."> <meta property="og:image" content="https://justin.deal/pixel_avatar.png"> <meta property="og:url" content="https://justin.deal/about"> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="About Justin Deal • My personal slice of the internet"> <meta name="twitter:description" content="Software engineer with experience in cloud computing, sustainability reporting, and high-performance computing."> <meta name="twitter:image" content="https://justin.deal/pixel_avatar.png"> <meta http-equiv="content-language" content="en"> <meta name="language" content="English"> <link rel="canonical" href="https://justin.deal/about"> <link rel="stylesheet" href="/_astro/jellyfin-at-home.z5IOlzDh.css"></head> <body class="zag-bg zag-text zag-transition font-mono"> <!-- Loading overlay for long loading times --> <div class="loading-overlay fixed inset-0 flex flex-col items-center justify-center z-50 bg-opacity-90 zag-bg " role="alert" aria-live="polite" data-astro-cid-veun55td> <div class="loading-content text-center p-8 rounded-lg" data-astro-cid-veun55td> <!-- Enhanced loading indicator --> <div class="mb-6 flex justify-center" data-astro-cid-veun55td> <div class="loading-dots w-12 h-12" style="--dots-color:var(--color-zag-accent-dark)" data-astro-cid-ypbmo55r><div class="dot" data-astro-cid-ypbmo55r></div><div class="dot" data-astro-cid-ypbmo55r></div><div class="dot" data-astro-cid-ypbmo55r></div></div> </div> <!-- Messages with animation --> <div class="messages-container" data-astro-cid-veun55td> <p class="text-xl font-semibold mb-2 zag-text message-animate" data-astro-cid-veun55td>This is taking longer than expected...</p> <p class="text-base zag-text-muted message-animate-delay" data-astro-cid-veun55td>Still working on loading your content</p> </div> </div> </div> <script type="module">class e{overlay=null;timeoutId=null;longLoadingTimeoutId=null;constructor(){this.overlay=document.querySelector(".loading-overlay"),this.setupNavigationListeners()}setupNavigationListeners(){"navigation"in window?(window.navigation.addEventListener("navigate",i=>{new URL(i.destination.url).origin===window.location.origin&&this.showLoading()}),window.navigation.addEventListener("navigatesuccess",()=>{this.hideLoading()}),window.navigation.addEventListener("navigateerror",()=>{this.hideLoading()})):(window.addEventListener("beforeunload",()=>{this.showLoading()}),document.addEventListener("astro:page-load",()=>{this.hideLoading()})),document.addEventListener("astro:before-swap",()=>{this.showLoading()}),document.addEventListener("astro:after-swap",()=>{this.hideLoading()})}showLoading(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this.longLoadingTimeoutId&&(clearTimeout(this.longLoadingTimeoutId),this.longLoadingTimeoutId=null);const i=this.getConnectionBasedDelay();this.timeoutId=setTimeout(()=>{document.querySelectorAll("[x-data]").forEach(t=>{t.__x&&typeof t.__x.$data.loading<"u"&&(t.__x.$data.loading=!0)})},i),this.longLoadingTimeoutId=setTimeout(()=>{this.overlay&&this.overlay.classList.add("visible")},5e3)}hideLoading(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this.longLoadingTimeoutId&&(clearTimeout(this.longLoadingTimeoutId),this.longLoadingTimeoutId=null),this.overlay&&this.overlay.classList.remove("visible"),setTimeout(()=>{document.querySelectorAll("[x-data]").forEach(i=>{i.__x&&typeof i.__x.$data.loading<"u"&&(i.__x.$data.loading=!1)})},100)}getConnectionBasedDelay(){const i=navigator.connection||navigator.mozConnection||navigator.webkitConnection;if(i)switch(i.effectiveType){case"4g"
About Me
</h1> <p class="text-xl zag-text-muted">
Software engineer with a passion for cloud computing, sustainability, and high-performance systems.
</p> </div> <div class="grid grid-cols-1 md:grid-cols-3 gap-8 mb-12"> <div class="md:col-span-1"> <div class="aspect-square w-full max-w-[250px] mx-auto md:mx-0 rounded-lg overflow-hidden -zag-bg"> <img src="/pixel_avatar.png" alt="Justin Deal" class="w-full h-full object-cover"> </div> </div> <div class="md:col-span-2"> <div class="zag-bg-alt p-6 rounded-lg shadow-sm"> <h2 class="text-2xl font-display mb-4">Professional Summary</h2> <p class="mb-4">
I'm a Software Development Engineer at Amazon with expertise in sustainability reporting, ESG systems, and cloud infrastructure. My background spans high-performance computing, data analytics, and full-stack development.
</p> <p>
With a Master's in Computer Science from Georgia Tech (in progress) and a strong foundation in AI and networking, I combine technical expertise with a passion for creating systems that make a positive impact.
</p> </div> </div> </div> <div class="mb-16" x-data="{ activeTab: 'amazon' }"> <h2 class="text-2xl font-display mb-6">Work Experience</h2> <!-- Experience Tabs --> <div class="flex flex-wrap gap-2 mb-6 border-b zag-border-b"> <button @click="activeTab = 'amazon'" :class="activeTab === 'amazon' ? 'zag-text-accent font-semibold border-b-2 zag-border-accent -mb-px' : 'zag-text-muted'" class="px-4 py-2 transition-colors">
Amazon
</button> <button @click="activeTab = 'hpe'" :class="activeTab === 'hpe' ? 'zag-text-accent font-semibold border-b-2 zag-border-accent -mb-px' : 'zag-text-muted'" class="px-4 py-2 transition-colors">
HPE
</button> <button @click="activeTab = 'research'" :class="activeTab === 'research' ? 'zag-text-accent font-semibold border-b-2 zag-border-accent -mb-px' : 'zag-text-muted'" class="px-4 py-2 transition-colors">
Research
</button> </div> <!-- Amazon Experience --> <div x-show="activeTab === 'amazon'" class="zag-bg-alt p-6 rounded-lg shadow-sm"> <div class="flex flex-col sm:flex-row justify-between mb-4"> <h3 class="text-xl font-semibold">Amazon</h3> <span class="zag-text-muted">July 2021 - Present</span> </div> <div class="mb-6"> <div class="flex flex-col sm:flex-row justify-between mb-2"> <h4 class="font-semibold">Software Development Engineer II</h4> <span class="zag-text-muted">August 2024 - Present</span> </div> <ul class="list-disc pl-5 space-y-2"> <li>Certified as an Amazon Guardian, acting as a bridge between development team and security engineers</li> <li>Led away team development of on-demand report generation and egress</li> <li>Designed and implemented capabilities for ESG reporting on precomputed data</li> </ul> </div> <div> <div class="flex flex-col sm:flex-row justify-between mb-2"> <h4 class="font-semibold">Software Development Engineer</h4> <span class="zag-text-muted">July 2021 - August 2024</span> </div> <ul class="list-disc pl-5 space-y-2"> <li>Led sustainability reporting tech team for Amazon's 2024 Carbon Footprint report</li> <li>Automated experimental ESG reports in Amazon's sustainability systems</li> <li>Implemented and maintained critical environmental reporting systems</li> <li>Designed and implemented an ESG metadata store for customer report creation</li> <li>Expanded supply chain simulation capabilities for slow-moving items</li> <li>Implemented monitoring and dashboards across various systems</li> </ul> </div> </div> <!-- HPE Experience --> <div x-show="activeTab === 'hpe'" class="zag-bg-alt p-6 rounded-lg shadow-sm" style="display: none;"> <div class="flex flex-col sm:flex-row justify-between mb-4"> <h3 class="text-xl font-semibold">Hewlett Packard Enterprise</h3> <span class="zag-text-muted">May 2020 - August 2020</span> </div> <div> <h4 class="font-semibold mb-2">Software Engineering Intern - Storage</h4> <ul class="list-disc pl-5 space-y-2"> <li>Redesigned core test scheduling infrastructure for flexible algorithm selection and configuration</li> <li>Refactored test scheduling algorithm to a modular design</li> <li>Created a novel process for developing new scheduling algorithms with maximum code reuse</li> </ul> </div> </div> <!-- Research Experience --> <div x-show="activeTab === 'research'" class="zag-bg-alt p-6 rounded-lg shadow-sm" style="display: none;"> <div class="mb-6"> <div class="flex flex-col sm:flex-row justify-between mb-4"> <h3 class="text-xl font-semibold">Georgia Tech Research Institute (GTRI)</h3> <span class="zag-text-muted">May 2019 - June 2020</span> </div> <h4 class="font-semibold mb-2">High Performance Computing and Data Analytics Researcher</h4> <ul class="list-disc pl-5 space-y-2"> <li>Contributed data annotation and validation tools to an open-source healthcare analytic platform</li> <li>Optimized ray-tracing applications using novel algorithms</li> <li>Designed and implemented an API for the HPC cluster's database with interactive frontend</li> <li>Developed parallelized HPC applications with CUDA C and Open MPI</li> <li>Conducted data analysis on cluster usage data, creating 17 unique visualizations</li> </ul> </div> <div> <div class="flex flex-col sm:flex-row justify-between mb-4"> <h3 class="text-xl font-semibold">Georgia Tech Discrete Math and Molecular Biology</h3> <span class="zag-text-muted">December 2018 - May 2019</span> </div> <h4 class="font-semibold mb-2">Math Department Student Researcher</h4> <ul class="list-disc pl-5 space-y-2"> <li>Developed interactive visualization tools for non-coding RNA secondary structures using D3.js</li> <li>Created a parser to translate HTML to a custom file format</li> <li>Wrote weekly reports and research summaries to guide further development</li> </ul> </div> </div> </div> <div class="mb-16" x-data="{ activeSkillTab: 'languages' }"> <h2 class="text-2xl font-display mb-6">Technical Skills</h2> <!-- Skill Category Tabs --> <div class="flex flex-wrap gap-2 mb-6 border-b zag-border-b"> <button @click="activeSkillTab = 'languages'" :
Languages
</button> <button @click="activeSkillTab = 'aws'" :class="activeSkillTab === 'aws' ? 'zag-text-accent font-semibold border-b-2 zag-border-accent -mb-px' : 'zag-text-muted'" class="px-4 py-2 transition-colors">
AWS Services
</button> <button @click="activeSkillTab = 'frameworks'" :class="activeSkillTab === 'frameworks' ? 'zag-text-accent font-semibold border-b-2 zag-border-accent -mb-px' : 'zag-text-muted'" class="px-4 py-2 transition-colors">
Frameworks & Libraries
</button> </div> <!-- Languages --> <div x-show="activeSkillTab === 'languages'" class="zag-bg-alt p-6 rounded-lg shadow-sm"> <div class="flex flex-wrap gap-3"> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Java</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Scala</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Python</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">TypeScript</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">C/C++</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">JavaScript</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">SQL</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">x86-64 Assembly</span> </div> </div> <!-- AWS Services --> <div x-show="activeSkillTab === 'aws'" class="zag-bg-alt p-6 rounded-lg shadow-sm" style="display: none;"> <div class="flex flex-wrap gap-3"> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">SQS</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">SNS</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Lambda</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">EMR</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">EMR Serverless</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">API Gateway</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">IAM</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">S3</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">DynamoDB</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Athena</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Step Functions</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">CloudWatch</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">CloudFormation</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Glue</span> </div> </div> <!-- Frameworks & Libraries --> <div x-show="activeSkillTab === 'frameworks'" class="zag-bg-alt p-6 rounded-lg shadow-sm" style="display: none;"> <div class="flex flex-wrap gap-3"> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Spark</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">React</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">CUDA</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Open MPI</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Flask</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Java Spring</span> <span class="-zag-text -zag-bg zag-transition px-3 py-2 rounded-md font-semibold">Knockout.js</span> </div> </div> </div> <div class="mb-16"> <h2 class="text-2xl font-display mb-6">Education</h2> <div class="zag-bg-alt p-6 rounded-lg shadow-sm"> <div class="mb-6"> <div class="flex flex-col sm:flex-row justify-between mb-2"> <h3 class="text-xl font-semibold">Georgia Institute of Technology</h3> <span class="zag-text-muted">In Progress</span> </div> <p class="font-medium">Master of Science in Computer Science</p> <p class="zag-text-muted">Concentration: Computer Systems</p> </div> <div> <div class="flex flex-col sm:flex-row justify-between mb-2"> <h3 class="text-xl font-semibold">Georgia Institute of Technology</h3> <span class="zag-text-muted">May 2021</span> </div> <p class="font-medium">Bachelor of Science in Computer Science, Min
2025-04-27 22:15:19 -07:00
&copy; 2025 Justin Deal. All rights reserved.
</p> </footer> </body></html> <script type="module">document.addEventListener("alpine:init",()=>{});</script>