Add contact form with Cloudflare Functions

This commit is contained in:
Daniel LaForce 2025-04-02 02:26:14 -06:00
parent 6436562a66
commit 11adc676f6
8 changed files with 2215 additions and 72 deletions

49
functions/contact.js Normal file
View File

@ -0,0 +1,49 @@
export async function onRequestPost(context) {
try {
const { name, email, subject, message } = await context.request.json();
// Validate inputs
if (!name || !email || !subject || !message) {
return new Response(
JSON.stringify({ error: 'All fields are required' }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
// Send email using Resend
const response = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${context.env.RESEND_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: 'contact@argobox.com',
to: 'daniel.laforce@gmail.com',
subject: `Contact Form: ${subject}`,
html: `
<h3>New Contact Form Submission</h3>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Subject:</strong> ${subject}</p>
<h4>Message:</h4>
<p>${message}</p>
`
})
});
if (!response.ok) {
throw new Error('Failed to send email');
}
return new Response(
JSON.stringify({ message: 'Message sent successfully!' }),
{ status: 200, headers: { 'Content-Type': 'application/json' } }
);
} catch (error) {
return new Response(
JSON.stringify({ error: 'Failed to send message' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
}

View File

@ -69,27 +69,27 @@
<div class="hero-buttons">
<a href="#contact" class="btn btn-primary">Hire Me</a>
<a href="#lab" class="btn btn-outline">Explore My Lab</a>
<a href="resume.pdf" class="btn btn-outline" target="_blank">View Resume</a>
<a href="resume.html" class="btn btn-outline" target="_blank">View Resume</a>
</div>
</div>
<div class="hero-visual">
<div class="data-stream">
<div class="data-line" style="left: 10%; width: 80%; animation-duration: 3s;"></div>
<div class="data-line" style="left: 15%; width: 60%; animation-duration: 4s;"></div>
<div class="data-line" style="left: 25%; width: 30%; animation-duration: 2.5s;"></div>
<div class="data-line" style="left: 40%; width: 50%; animation-duration: 3.5s;"></div>
<div class="data-line" style="left: 55%; width: 35%; animation-duration: 4.5s;"></div>
<div class="data-line" style="left: 70%; width: 25%; animation-duration: 2s;"></div>
<div class="data-line" style="left: 85%; width: 10%; animation-duration: 3.8s;"></div>
</div>
<div class="terminal">
<div class="terminal-line"> > Monitoring infrastructure... </div>
<div class="terminal-line success"> > CPU load: Normal </div>
<div class="terminal-line success"> > RAM usage: 42% </div>
<div class="terminal-line success"> > Network: Stable </div>
<div class="terminal-line info"> > Containers: 16 running </div>
<div class="terminal-line warning"> > Backing up critical data... </div>
<div class="terminal-line"> > Status: All systems operational </div>
<div class="tech-dashboard">
<div class="data-stream">
<div class="data-line" style="left: 10%; width: 80%; animation-duration: 3s;"></div>
<div class="data-line" style="left: 25%; width: 60%; animation-duration: 4s;"></div>
<div class="data-line" style="left: 40%; width: 40%; animation-duration: 2.5s;"></div>
<div class="data-line" style="left: 55%; width: 30%; animation-duration: 3.5s;"></div>
<div class="data-line" style="left: 70%; width: 20%; animation-duration: 4.5s;"></div>
</div>
<div class="terminal">
<div class="terminal-line">> Monitoring infrastructure...</div>
<div class="terminal-line success">> CPU load: Normal</div>
<div class="terminal-line success">> RAM usage: 42%</div>
<div class="terminal-line success">> Network: Stable</div>
<div class="terminal-line info">> Containers: 16 running</div>
<div class="terminal-line warning">> Backing up critical data...</div>
<div class="terminal-line">> Status: All systems operational</div>
</div>
</div>
</div>
</div>
@ -461,24 +461,24 @@
<div class="contact-icon">
<i class="fas fa-envelope"></i>
</div>
<h3 class="contact-item-title">Email</h3>
<p><a href="mailto:contact@argobox.com">contact@argobox.com</a></p>
<h3 class="contact-title">Email</h3>
<p><a href="mailto:daniel.laforce@argobox.com">daniel.laforce@argobox.com</a></p>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fab fa-linkedin"></i>
</div>
<h3 class="contact-item-title">LinkedIn</h3>
<p><a href="https://linkedin.com/in/yourprofile" target="_blank">Connect on LinkedIn</a></p>
<h3 class="contact-title">LinkedIn</h3>
<p><a href="https://www.linkedin.com/in/danlaforce" target="_blank">linkedin.com/in/danlaforce</a></p>
</div>
<div class="contact-item">
<div class="contact-icon">
<i class="fab fa-github"></i>
</div>
<h3 class="contact-item-title">GitHub</h3>
<p><a href="https://github.com/yourusername" target="_blank">View My Projects</a></p>
<h3 class="contact-title">GitHub</h3>
<p><a href="https://github.com/keyargo" target="_blank">github.com/keyargo</a></p>
</div>
</div>
@ -504,7 +504,10 @@
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Send Message</button>
<button type="submit" class="btn btn-primary">
<i class="fas fa-paper-plane btn-icon"></i>
Send Message
</button>
</form>
</div>
</div>
@ -525,18 +528,18 @@
<a href="#services">Services</a>
<a href="#lab">Live Lab</a>
<a href="#projects">Projects</a>
<a href="#experience">Experience</a>
<a href="#contact">Contact</a>
</div>
<div class="footer-social">
<a href="https://linkedin.com/in/yourprofile" target="_blank"><i class="fab fa-linkedin"></i></a>
<a href="https://github.com/yourusername" target="_blank"><i class="fab fa-github"></i></a>
<a href="https://github.com/keyargo" target="_blank"><i class="fab fa-github"></i></a>
<a href="https://www.linkedin.com/in/danllaforce" target="_blank"><i class="fab fa-linkedin"></i></a>
<a href="mailto:daniel.laforce@argobox.com"><i class="fas fa-envelope"></i></a>
</div>
</div>
<div class="footer-bottom">
<p>&copy; <span id="current-year">2025</span> Argobox.com. All rights reserved.</p>
<p>&copy; <span id="current-year"></span> All rights reserved. Inovin LLC</p>
</div>
</div>
</footer>

1254
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "argobox-portfolio",
"version": "1.0.0",
"description": "Portfolio website with contact form functionality",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"nodemailer": "^6.9.7"
},
"devDependencies": {
"nodemon": "^3.0.2"
}
}

710
resume.html Normal file
View File

@ -0,0 +1,710 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daniel LaForce | Resume</title>
<!-- SEO Meta Tags -->
<meta name="description" content="Professional resume of Daniel LaForce - Systems & Infrastructure Engineer specializing in virtualization, containerization, and secure network architecture.">
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22256%22 height=%22256%22 viewBox=%220 0 100 100%22><rect width=%22100%22 height=%22100%22 rx=%2220%22 fill=%22%230f172a%22></rect><path fill=%22%233b82f6%22 d=%22M30 40L50 20L70 40L50 60L30 40Z%22></path><path fill=%22%233b82f6%22 d=%22M50 60L70 40L70 70L50 90L30 70L30 40L50 60Z%22 fill-opacity=%220.6%22></path></svg>">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- FontAwesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- CSS -->
<link rel="stylesheet" href="styles.css">
<style>
/* Resume-specific styles */
.resume-container {
max-width: 1000px;
margin: 6rem auto 4rem;
padding: 0 1.5rem;
}
.resume-header {
text-align: center;
margin-bottom: 3rem;
}
.resume-name {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.resume-title {
font-size: 1.5rem;
color: var(--accent);
margin-bottom: 1.5rem;
}
.resume-contact {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 1.5rem;
margin-bottom: 2rem;
}
.resume-contact-item {
display: flex;
align-items: center;
color: var(--text-secondary);
}
.resume-contact-item i {
margin-right: 0.5rem;
color: var(--accent);
}
.resume-section {
margin-bottom: 2.5rem;
background-color: var(--card-bg);
border-radius: 1rem;
padding: 2rem;
border: 1px solid var(--border);
}
.resume-section-title {
font-size: 1.5rem;
margin-bottom: 1.5rem;
color: var(--accent);
position: relative;
padding-bottom: 0.75rem;
}
.resume-section-title::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 3px;
background: var(--accent-gradient);
border-radius: 3px;
}
.resume-job {
margin-bottom: 2rem;
}
.resume-job:last-child {
margin-bottom: 0;
}
.resume-job-header {
margin-bottom: 1rem;
}
.resume-job-title {
font-size: 1.25rem;
margin-bottom: 0.25rem;
}
.resume-job-company {
font-weight: 600;
color: var(--accent);
margin-bottom: 0.25rem;
}
.resume-job-period {
color: var(--text-secondary);
font-size: 0.9rem;
}
.resume-job-description {
color: var(--text-secondary);
margin-bottom: 1rem;
}
.resume-job-achievements {
list-style: none;
}
.resume-job-achievement {
display: flex;
margin-bottom: 0.75rem;
align-items: flex-start;
}
.resume-job-achievement i {
color: var(--accent);
margin-right: 0.75rem;
margin-top: 0.25rem;
flex-shrink: 0;
}
.resume-skills {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.resume-skill-category {
margin-bottom: 1.5rem;
}
.resume-skill-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: var(--accent);
}
.resume-skill-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.resume-skill {
background-color: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.3);
color: var(--accent);
font-size: 0.85rem;
font-weight: 500;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
}
.resume-education {
margin-bottom: 1.5rem;
}
.resume-education-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.25rem;
}
.resume-education-institution {
color: var(--accent);
margin-bottom: 0.25rem;
}
.resume-education-period {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.resume-projects {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.resume-project {
background-color: rgba(59, 130, 246, 0.1);
border-radius: 0.75rem;
padding: 1.5rem;
border: 1px solid rgba(59, 130, 246, 0.3);
}
.resume-project-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: var(--accent);
}
.resume-project-tech {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 0.75rem;
}
.resume-project-tech-item {
font-size: 0.8rem;
color: var(--text-secondary);
background-color: rgba(255, 255, 255, 0.1);
padding: 0.15rem 0.5rem;
border-radius: 0.25rem;
}
.resume-awards {
list-style: none;
}
.resume-award {
display: flex;
margin-bottom: 0.75rem;
}
.resume-award i {
color: var(--accent);
margin-right: 0.75rem;
}
.resume-download {
text-align: center;
margin-top: 3rem;
}
@media (max-width: 768px) {
.resume-skills, .resume-projects {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar">
<div class="container nav-container">
<div class="logo">
<a href="index.html">
<span class="logo-text">Argobox</span>
<span class="logo-dot">.com</span>
</a>
</div>
<div class="nav-links">
<a href="index.html#home" class="nav-link">Home</a>
<a href="index.html#services" class="nav-link">Services</a>
<a href="index.html#lab" class="nav-link">Live Lab</a>
<a href="index.html#projects" class="nav-link">Projects</a>
<a href="index.html#experience" class="nav-link">Experience</a>
<a href="index.html#contact" class="nav-link">Contact</a>
</div>
<div class="nav-actions">
<a href="https://dashboard.argobox.com" class="dashboard-btn" target="_blank">
<span class="live-dot"></span>
<span>Live Dashboard</span>
</a>
<button class="mobile-menu-btn">
<i class="fas fa-bars"></i>
</button>
</div>
</div>
</nav>
<!-- Resume Content -->
<div class="resume-container">
<div class="resume-header">
<h1 class="resume-name">Daniel LaForce</h1>
<h2 class="resume-title">Infrastructure & Systems Engineer</h2>
<div class="resume-contact">
<div class="resume-contact-item">
<i class="fas fa-envelope"></i>
<a href="mailto:daniel.laforce@argobox.com">daniel.laforce@argobox.com</a>
</div>
<div class="resume-contact-item">
<i class="fab fa-linkedin"></i>
<a href="https://www.linkedin.com/in/danllaforce" target="_blank">linkedin.com/in/danllaforce</a>
</div>
<div class="resume-contact-item">
<i class="fab fa-github"></i>
<a href="https://github.com/keyargo" target="_blank">github.com/keyargo</a>
</div>
</div>
</div>
<!-- Experience Section -->
<div class="resume-section">
<h2 class="resume-section-title">Professional Experience</h2>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Freelance Consultant GIS, Infrastructure & Security Solutions</h3>
<div class="resume-job-company">Inovin LLC</div>
<div class="resume-job-period">April 2023 Present | Colorado Springs, CO</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed TerraTracer, a GIS mapping platform used by independent mining claim prospectors to automate boundary plotting, terrain-informed site selection, and BLM/state compliance, reducing manual research by 85%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Consulted on virtualization and DevOps projects for SMB clients, implementing Proxmox/VMware solutions, containerizing legacy apps with Docker, and orchestrating microservices with Kubernetes.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Built secure cloud environments integrating Azure AD, SSO, and VPN/firewall solutions, increasing operational resilience while aligning with HIPAA and zero-trust principles.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Automated infrastructure tasks via PowerShell, Python, and Bash, optimizing system deployment, backup routines, and monitoring pipelines.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Project Engineer</h3>
<div class="resume-job-company">Anchor Point IT Solutions</div>
<div class="resume-job-period">December 2023 - June 2024</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Executed 5 Microsoft 365 and SharePoint migrations with downtime reduced by 60%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Implemented comprehensive security stack including BlueMira & DUO (Identity), SentinelOne (Endpoint), ConnectSecure (Network), and Email Mesh Security.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Reduced security incidents by 83% through security implementations and improved system updates by 60%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed approximately 235 clients with environment sizes ranging from 30 to 1000 people.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Interim Virtual Chief Security Officer</h3>
<div class="resume-job-company">Technology Response Team, LLC</div>
<div class="resume-job-period">August 2023 - September 2023</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Served as temporary VCSO for ~120 clients, conducting penetration testing using BURP Professional.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed enterprise security stack deployment including Blackpoint & Webroot (Endpoint), DNSFilter (Network), and ThreatLocker (Application Control).</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Administered Azure AD security policies and MFA enforcement, reducing monthly vulnerabilities by at least 20%.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Network Engineer II</h3>
<div class="resume-job-company">NOVUS Professional Services, Inc.</div>
<div class="resume-job-period">August 2022 - March 2023</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Designed and implemented a WiFi testing cage for remote firmware testing of router models (Wave2, WiFi6).</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed Python automation for Plume device registration and Ansible scripts for network tasks.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed RF testing and signal verification across 9 headends and maintained network connectivity for ~100 routers across two sites.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Field Engineer</h3>
<div class="resume-job-company">COMPUTEK Dental Systems</div>
<div class="resume-job-period">December 2021 - August 2022</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed IT infrastructure for 300+ dental practices (3700+ workstations, ~300 Windows Servers).</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed VSA Deployer application (Kaseya VSA RMM) for agent installation, reducing deployment time by 80%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Maintained server, Hyper-V VM, and MySQL/MSSQL backups using N-Able Backups, Windows Server Backups and AIS.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">End-to-End Systems Engineer</h3>
<div class="resume-job-company">Lockheed Martin</div>
<div class="resume-job-period">June 2018 - December 2019</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Maintained 2 IRON databases (AIMS and RAPID) with ~1800 configurations each, ensuring 100% database accuracy.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Collaborated with engineering team to implement Remote Tracking Station (RTS) configurations.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Identified and documented an average of 27 critical defects every month.</span>
</div>
</div>
</div>
</div>
<!-- Skills Section -->
<div class="resume-section">
<h2 class="resume-section-title">Technical Skills</h2>
<div class="resume-skills">
<div class="resume-skill-category">
<h3 class="resume-skill-title">Cloud & Infrastructure</h3>
<div class="resume-skill-list">
<span class="resume-skill">Microsoft Azure</span>
<span class="resume-skill">AWS</span>
<span class="resume-skill">GCP</span>
<span class="resume-skill">VMware ESXi/vSphere</span>
<span class="resume-skill">Hyper-V</span>
<span class="resume-skill">Docker</span>
<span class="resume-skill">Kubernetes (K3s)</span>
<span class="resume-skill">ProxMox</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Networking</h3>
<div class="resume-skill-list">
<span class="resume-skill">LAN/WAN</span>
<span class="resume-skill">VPN</span>
<span class="resume-skill">OSPF</span>
<span class="resume-skill">EIGRP</span>
<span class="resume-skill">STP</span>
<span class="resume-skill">IPv4/IPv6</span>
<span class="resume-skill">DNS/DHCP</span>
<span class="resume-skill">VLANs</span>
<span class="resume-skill">QoS</span>
<span class="resume-skill">Cisco Routers</span>
<span class="resume-skill">Catalyst Switches</span>
<span class="resume-skill">ASA Firewalls</span>
<span class="resume-skill">UniFi Systems</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Programming/Scripting</h3>
<div class="resume-skill-list">
<span class="resume-skill">Python</span>
<span class="resume-skill">JavaScript (Node.js)</span>
<span class="resume-skill">PowerShell</span>
<span class="resume-skill">Bash</span>
<span class="resume-skill">C/C++</span>
<span class="resume-skill">SQL</span>
<span class="resume-skill">AutoHotkey</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Security</h3>
<div class="resume-skill-list">
<span class="resume-skill">Penetration Testing</span>
<span class="resume-skill">BURP Professional</span>
<span class="resume-skill">SentinelOne</span>
<span class="resume-skill">Blackpoint</span>
<span class="resume-skill">Webroot</span>
<span class="resume-skill">ThreatLocker</span>
<span class="resume-skill">Zero-Trust Architecture</span>
<span class="resume-skill">HIPAA Compliance</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Operating Systems</h3>
<div class="resume-skill-list">
<span class="resume-skill">Windows Server</span>
<span class="resume-skill">Active Directory</span>
<span class="resume-skill">Group Policy</span>
<span class="resume-skill">Linux (Ubuntu, CentOS)</span>
<span class="resume-skill">Cisco IOS</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">GIS & Data</h3>
<div class="resume-skill-list">
<span class="resume-skill">Geospatial Mapping</span>
<span class="resume-skill">GeoPandas</span>
<span class="resume-skill">GDAL/OGR</span>
<span class="resume-skill">KML Generation</span>
<span class="resume-skill">Data Visualization</span>
<span class="resume-skill">Machine Learning</span>
<span class="resume-skill">Pandas</span>
<span class="resume-skill">NumPy</span>
<span class="resume-skill">Scikit-learn</span>
</div>
</div>
</div>
</div>
<!-- Education Section -->
<div class="resume-section">
<h2 class="resume-section-title">Education</h2>
<div class="resume-education">
<h3 class="resume-education-title">Bachelor of Science, Computer Science</h3>
<div class="resume-education-institution">Western Governors University</div>
<div class="resume-education-period">June 2019 - April 2023</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Sigma Alpha Phi (NSLS)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Academic Excellence Award</span>
</div>
</div>
</div>
<div class="resume-education">
<h3 class="resume-education-title">Associate's Degree, General Studies</h3>
<div class="resume-education-institution">Front Range Community College</div>
<div class="resume-education-period">January 2016 - May 2018</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Magna Cum Laude</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Phi Theta Kappa</span>
</div>
</div>
</div>
</div>
<!-- Certifications Section -->
<div class="resume-section">
<h2 class="resume-section-title">Certifications</h2>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Project+ (CompTIA)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Network+ (FRCC)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>A+ (FRCC)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>CCNA Cyber Ops (2021)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>CCNA Routing & Switching (2021)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Virtual Cyber Security Officer Training (vCSO Advanced)</span>
</div>
</div>
</div>
<!-- Projects Section -->
<div class="resume-section">
<h2 class="resume-section-title">Notable Projects</h2>
<div class="resume-projects">
<div class="resume-project">
<h3 class="resume-project-title">TerraTracer</h3>
<p>A GIS mapping platform used by mining claim prospectors to automate boundary plotting and compliance verification, reducing manual research by 85%.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Python</span>
<span class="resume-project-tech-item">Node.js</span>
<span class="resume-project-tech-item">GeoPandas</span>
<span class="resume-project-tech-item">KML</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">Wi-Fi Testing Cage</h3>
<p>Designed and implemented a full-access Wi-Fi testing facility for remote firmware testing of router models, supporting Wave2 and WiFi6 capabilities.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">RF Engineering</span>
<span class="resume-project-tech-item">Network Testing</span>
<span class="resume-project-tech-item">CAD Prototyping</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">VSA Deployer</h3>
<p>Custom application for streamlining Kaseya VSA RMM agent installation, reducing deployment time by 80% across dental practice environments.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">PowerShell</span>
<span class="resume-project-tech-item">AutoHotkey</span>
<span class="resume-project-tech-item">RMM</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">Argo Cloudflare DDNS</h3>
<p>Bash script for automating DNS updates with Cloudflare, featuring user input validation, API integration, and cron scheduling.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Bash</span>
<span class="resume-project-tech-item">API Integration</span>
<span class="resume-project-tech-item">DNS</span>
</div>
</div>
</div>
</div>
<div class="resume-download">
<a href="resume/daniel-laforce-resume.pdf" class="btn btn-primary" download>
<i class="fas fa-download btn-icon"></i>
Download Full Resume (PDF)
</a>
</div>
</div>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-logo">
<span class="logo-text">Argobox</span>
<span class="logo-dot">.com</span>
</div>
<div class="footer-links">
<a href="index.html#home">Home</a>
<a href="index.html#services">Services</a>
<a href="index.html#lab">Live Lab</a>
<a href="index.html#projects">Projects</a>
<a href="index.html#experience">Experience</a>
<a href="index.html#contact">Contact</a>
</div>
<div class="footer-social">
<a href="https://www.linkedin.com/in/danllaforce" target="_blank"><i class="fab fa-linkedin"></i></a>
<a href="https://github.com/keyargo" target="_blank"><i class="fab fa-github"></i></a>
</div>
</div>
<div class="footer-bottom">
<p>&copy; <span id="current-year"></span> All rights reserved. Inovin LLC</p>
</div>
</div>
</footer>
<!-- JavaScript -->
<script src="script.js"></script>
</body>
</html>

View File

@ -65,22 +65,41 @@ document.addEventListener('DOMContentLoaded', function() {
const contactForm = document.getElementById('contact-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
contactForm.addEventListener('submit', async function(e) {
e.preventDefault();
// In a real implementation, you would send the form data to a backend service
// For now, we'll just simulate a successful submission
const submitButton = contactForm.querySelector('button[type="submit"]');
const originalButtonText = submitButton.innerHTML;
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
submitButton.disabled = true;
const formData = new FormData(contactForm);
const formValues = Object.fromEntries(formData.entries());
console.log('Form submission:', formValues);
// Show success message
alert('Thank you for your message! I will get back to you soon.');
// Reset form
contactForm.reset();
try {
const formData = new FormData(contactForm);
const formValues = Object.fromEntries(formData.entries());
const response = await fetch('/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formValues)
});
const result = await response.json();
if (response.ok) {
alert('Thank you for your message! I will get back to you soon.');
contactForm.reset();
} else {
throw new Error(result.error || 'Failed to send message');
}
} catch (error) {
console.error('Error:', error);
alert('Failed to send message. Please try again or contact me directly via email.');
} finally {
submitButton.innerHTML = originalButtonText;
submitButton.disabled = false;
}
});
}
@ -93,17 +112,15 @@ document.addEventListener('DOMContentLoaded', function() {
// Create animated data streams in the dashboard
function createDataStreamAnimation() {
// Look for either class name that might be in the HTML
const dataStreamContainer = document.querySelector('.data-stream') ||
document.querySelector('.hero-visual .tech-dashboard .data-stream');
console.log('Data stream container found:', !!dataStreamContainer);
if (!dataStreamContainer) return;
const dataStreamContainer = document.querySelector('.data-stream');
if (!dataStreamContainer) {
console.log('Data stream container not found');
return;
}
// Clear existing lines
const existingLines = dataStreamContainer.querySelectorAll('.data-line');
existingLines.forEach(line => line.remove());
dataStreamContainer.innerHTML = '';
// Create new random lines
for (let i = 0; i < 10; i++) {
@ -113,21 +130,25 @@ document.addEventListener('DOMContentLoaded', function() {
// Random positioning and animation
const left = Math.random() * 90 + 5; // 5-95%
const width = Math.random() * 40 + 10; // 10-50%
const duration = Math.random() * 3 + 2; // 2-5s
const duration = Math.random() * 3 + 2; // 2-5s duration
const delay = Math.random() * 2; // 0-2s delay
line.style.left = `${left}%`;
line.style.width = `${width}%`;
line.style.animationDuration = `${duration}s`;
line.style.cssText = `
left: ${left}%;
width: ${width}%;
animation: datastream ${duration}s linear infinite;
animation-delay: -${delay}s;
opacity: ${Math.random() * 0.3 + 0.2};
`;
dataStreamContainer.appendChild(line);
console.log('Added data line:', i);
}
}
// Try to initialize the data stream animation (with retry for race conditions)
setTimeout(createDataStreamAnimation, 100);
// Initialize the data stream animation immediately
createDataStreamAnimation();
// Refresh data streams periodically
// Refresh data streams every 8 seconds
setInterval(createDataStreamAnimation, 8000);
// Update terminal output with random status messages

63
server.js Normal file
View File

@ -0,0 +1,63 @@
const express = require('express');
const nodemailer = require('nodemailer');
const cors = require('cors');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.static('public'));
// Email transporter
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS
}
});
// Contact form endpoint
app.post('/api/contact', async (req, res) => {
try {
const { name, email, subject, message } = req.body;
// Email options
const mailOptions = {
from: process.env.EMAIL_USER,
to: 'daniel.laforce@argobox.com',
subject: `Contact Form: ${subject}`,
text: `
Name: ${name}
Email: ${email}
Subject: ${subject}
Message:
${message}
`,
html: `
<h3>New Contact Form Submission</h3>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Subject:</strong> ${subject}</p>
<h4>Message:</h4>
<p>${message}</p>
`
};
// Send email
await transporter.sendMail(mailOptions);
res.status(200).json({ message: 'Message sent successfully!' });
} catch (error) {
console.error('Error sending email:', error);
res.status(500).json({ message: 'Failed to send message. Please try again.' });
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});

View File

@ -297,45 +297,69 @@ ul {
.hero-visual {
flex: 1;
min-width: 300px;
max-width: 600px;
}
.tech-dashboard {
background-color: var(--secondary);
border-radius: 1rem;
overflow: hidden;
border: 1px solid var(--border);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
transform: perspective(1000px) rotateY(-5deg) rotateX(5deg);
transition: all 0.3s ease;
}
.tech-dashboard:hover {
transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
}
/* Data Stream Animation */
.data-stream {
height: 200px;
background-color: var(--secondary);
border-radius: 0.5rem;
background-color: rgba(15, 23, 42, 0.95);
border-radius: 0.5rem 0.5rem 0 0;
position: relative;
overflow: hidden;
margin-bottom: 0.5rem;
background-image:
linear-gradient(rgba(59, 130, 246, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(59, 130, 246, 0.05) 1px, transparent 1px);
background-size: 20px 20px;
}
.data-line {
position: absolute;
height: 1px;
background-color: var(--accent);
height: 2px;
background: linear-gradient(90deg, var(--accent), transparent);
opacity: 0.5;
animation-name: datastream;
animation-timing-function: linear;
animation-iteration-count: infinite;
transform: translateY(-100%);
will-change: transform;
animation: datastream 3s linear infinite;
}
@keyframes datastream {
0% { transform: translateY(-100%); }
100% { transform: translateY(500%); }
from { transform: translateY(-100%); }
to { transform: translateY(1000%); }
}
.terminal {
background-color: var(--primary);
border-radius: 0.5rem;
background-color: rgba(15, 23, 42, 0.98);
border-radius: 0 0 0.5rem 0.5rem;
padding: 1rem;
font-family: monospace;
font-family: 'JetBrains Mono', monospace;
font-size: 0.9rem;
}
.terminal-line {
margin-bottom: 0.5rem;
color: var(--text-muted);
}
.terminal-line.success { color: var(--success); }
.terminal-line.warning { color: var(--warning); }
.terminal-line.info { color: var(--info); }
.success {
color: var(--success);
}