Migrate to thin Eleventy build + a11y/SEO/perf/CI hardening (#20)
* chore(build): add Eleventy scaffold
Thin Eleventy build (v3.1.6, pinned) — passthrough-copies assets/,
robots.txt, sitemap.xml; outputs flat HTML to _site/. _data/site.json
holds site-wide constants; _data/images.json maps image keys to
src+width+height for the {% image %} shortcode (CLS fix). Output stays
flat HTML served from the same S3 bucket + CloudFront.
* refactor(templates): base layout, partials, shared JS, CSS extraction
- _includes/base.njk + nav/mobile-menu/footer partials reproduce the
shared chrome once (was hand-duplicated across 13 pages). Adds a
skip-link and <main> landmark (WCAG 2.4.1), aria-expanded/role=dialog
hooks on the menu, and a {% year %} shortcode replacing document.write.
- assets/js/nav.js: extracted sticky-nav + accessible mobile-menu dialog
(focus trap, Escape, focus return) + rAF-throttled hero parallax.
- assets/js/form.js: Basin AJAX submit with an accessible status region.
- assets/css/*.css: per-page inline <style> extracted into page CSS files
(home/about/services/careers/jobs/contact/social/legal/404); skip-link
+ :focus-visible added to main.css.
- index.njk: homepage converted as the reference page.
* fix(css): make hero-bg url root-relative after extraction
Inline CSS used a document-relative url('assets/...') that resolves
correctly from / but breaks once moved into /assets/css/home.css.
Rewrite to /assets/images/.
* refactor(pages): convert 12 pages to Eleventy templates
Convert about, services, careers (listing + 3 jobs), contact, social-
accountability, privacy-policy, terms-of-service, eula, and 404 from
standalone HTML to .njk against base.njk. Each page now carries only
front-matter (title/description/SEO) + its <main> content; shared head/
nav/footer/scripts come from the layout. JobPosting + LocalBusiness
JSON-LD preserved. Images use the {% image %} shortcode (width/height).
Contact gets an accessible #form-status region. form.js generalized to
wire BOTH the contact form and the .apply-form job application forms
(was contact-only), preserving each submit button's own label.
* fix(a11y): footer contrast to WCAG AA + scope services .form-group
Raise footer text colors (footer-bottom/col/brand/social/contact) and
darken --text-muted so muted text clears 4.5:1 on the dark footer and
warm-gray surfaces. Scope services' flex .form-group override to
.contact-form .form-group so it can't leak to the global rule.
* perf(seo): og-cover image, webp logos, hero preload
Add a real 1200x630 og-cover.jpg (was a 153x49 favicon) wired site-wide
via base.njk og:image/twitter:image. Convert nav/footer logos to webp
(nav 58KB->22KB); PNGs kept as passthrough so old URLs still resolve.
Preload the LCP hero image on the homepage (fetchpriority=high). All
<img> carry width/height via the image shortcode (CLS).
* ci(deploy): build-then-sync, cache headers, safe concurrency
Rename main.yml -> deploy.yaml (org convention). Build with Eleventy
(npm ci && npm run build) and sync _site/ instead of the repo root, so
only built output ships (no source/templates/node_modules). Split
Cache-Control (1-day assets, no-cache HTML) and keep /* invalidation
since filenames are not yet fingerprinted. concurrency cancel-in-progress
false so a deploy is never cut mid sync. ci.yaml validates _site/ via
ci-static build mode.
* docs: README for the Eleventy build and structure
* fix(security): wire services form, guard build, harden deploy
Fable build-review findings:
- BLOCK: services puts .contact-form on the <form> itself (contact uses a
wrapper div), so form.js selector '.contact-form form' never matched it
— the services lead form submitted natively with an empty reCAPTCHA
token. Selector now also matches form.contact-form.
- Guard the build before the --delete S3 sync: require index/contact/404
and >=40 files, so a silently-empty build can never wipe the live bucket.
- npm ci --ignore-scripts on deploy (build verified to pass) to shrink the
supply-chain window on the OIDC-credentialed runner.
- Escape quotes in the image shortcode alt text.
2026-06-12 17:02:06 -04:00
---
layout: base.njk
title: "Traveling Maintenance/Electrical Assistant — Sea Haven Industries"
description: "Apply for the Traveling Maintenance/Electrical Assistant position at Sea Haven Industries. View job details and submit your application today."
pageCss: jobs
recaptcha: true
2026-06-12 17:23:11 -04:00
breadcrumbName: "Traveling Maintenance / Electrical Assistant"
breadcrumbParent: { name: "Careers", url: "/careers/" }
Migrate to thin Eleventy build + a11y/SEO/perf/CI hardening (#20)
* chore(build): add Eleventy scaffold
Thin Eleventy build (v3.1.6, pinned) — passthrough-copies assets/,
robots.txt, sitemap.xml; outputs flat HTML to _site/. _data/site.json
holds site-wide constants; _data/images.json maps image keys to
src+width+height for the {% image %} shortcode (CLS fix). Output stays
flat HTML served from the same S3 bucket + CloudFront.
* refactor(templates): base layout, partials, shared JS, CSS extraction
- _includes/base.njk + nav/mobile-menu/footer partials reproduce the
shared chrome once (was hand-duplicated across 13 pages). Adds a
skip-link and <main> landmark (WCAG 2.4.1), aria-expanded/role=dialog
hooks on the menu, and a {% year %} shortcode replacing document.write.
- assets/js/nav.js: extracted sticky-nav + accessible mobile-menu dialog
(focus trap, Escape, focus return) + rAF-throttled hero parallax.
- assets/js/form.js: Basin AJAX submit with an accessible status region.
- assets/css/*.css: per-page inline <style> extracted into page CSS files
(home/about/services/careers/jobs/contact/social/legal/404); skip-link
+ :focus-visible added to main.css.
- index.njk: homepage converted as the reference page.
* fix(css): make hero-bg url root-relative after extraction
Inline CSS used a document-relative url('assets/...') that resolves
correctly from / but breaks once moved into /assets/css/home.css.
Rewrite to /assets/images/.
* refactor(pages): convert 12 pages to Eleventy templates
Convert about, services, careers (listing + 3 jobs), contact, social-
accountability, privacy-policy, terms-of-service, eula, and 404 from
standalone HTML to .njk against base.njk. Each page now carries only
front-matter (title/description/SEO) + its <main> content; shared head/
nav/footer/scripts come from the layout. JobPosting + LocalBusiness
JSON-LD preserved. Images use the {% image %} shortcode (width/height).
Contact gets an accessible #form-status region. form.js generalized to
wire BOTH the contact form and the .apply-form job application forms
(was contact-only), preserving each submit button's own label.
* fix(a11y): footer contrast to WCAG AA + scope services .form-group
Raise footer text colors (footer-bottom/col/brand/social/contact) and
darken --text-muted so muted text clears 4.5:1 on the dark footer and
warm-gray surfaces. Scope services' flex .form-group override to
.contact-form .form-group so it can't leak to the global rule.
* perf(seo): og-cover image, webp logos, hero preload
Add a real 1200x630 og-cover.jpg (was a 153x49 favicon) wired site-wide
via base.njk og:image/twitter:image. Convert nav/footer logos to webp
(nav 58KB->22KB); PNGs kept as passthrough so old URLs still resolve.
Preload the LCP hero image on the homepage (fetchpriority=high). All
<img> carry width/height via the image shortcode (CLS).
* ci(deploy): build-then-sync, cache headers, safe concurrency
Rename main.yml -> deploy.yaml (org convention). Build with Eleventy
(npm ci && npm run build) and sync _site/ instead of the repo root, so
only built output ships (no source/templates/node_modules). Split
Cache-Control (1-day assets, no-cache HTML) and keep /* invalidation
since filenames are not yet fingerprinted. concurrency cancel-in-progress
false so a deploy is never cut mid sync. ci.yaml validates _site/ via
ci-static build mode.
* docs: README for the Eleventy build and structure
* fix(security): wire services form, guard build, harden deploy
Fable build-review findings:
- BLOCK: services puts .contact-form on the <form> itself (contact uses a
wrapper div), so form.js selector '.contact-form form' never matched it
— the services lead form submitted natively with an empty reCAPTCHA
token. Selector now also matches form.contact-form.
- Guard the build before the --delete S3 sync: require index/contact/404
and >=40 files, so a silently-empty build can never wipe the live bucket.
- npm ci --ignore-scripts on deploy (build verified to pass) to shrink the
supply-chain window on the OIDC-credentialed runner.
- Escape quotes in the image shortcode alt text.
2026-06-12 17:02:06 -04:00
---
<!-- ── Page Hero ── -->
<section class="page-hero">
<div class="container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href="/">Home</a>
<span aria-hidden="true">/</span>
<a href="/careers/">Careers</a>
<span aria-hidden="true">/</span>
Traveling Maintenance/Electrical Assistant
</nav>
<h1>Traveling Maintenance/Electrical Assistant</h1>
<a href="/careers/" class="back-link">← Back to All Positions</a>
</div>
</section>
<!-- ── Job Details ── -->
<section class="job-details section">
<div class="container">
<div class="job-layout">
<!-- Main Content -->
<div class="job-content">
<p class="job-summary">Learn real trade skills fast—work side-by-side with a veteran technician across commercial facilities, earn above-market pay with per diem, and travel the Gulf South.</p>
<h2>Overview</h2>
<p>This is not a typical “helper” role. You’ll work directly alongside a highly experienced technician, supporting maintenance and electrical work across large-scale commercial and industrial facilities. This is a hands-on, travel-heavy role designed for someone who wants to learn real trade skills fast, earn above-market pay, and be part of a small, no-nonsense team.</p>
<h2>What You’ll Be Doing</h2>
<p>You’ll assist in a wide range of field tasks, including:</p>
<ul>
<li>Electrical support (running conduit, pulling wire, changing breakers)</li>
<li>General maintenance and repair work</li>
<li>Light plumbing assistance (valves, basic systems)</li>
<li>Painting and facility upkeep</li>
<li>Loading/unloading materials and tools</li>
<li>Working on lifts and at heights (up to ~35 ft)</li>
</ul>
<p>You’ll be working side-by-side with the lead technician at all times—this is a true apprentice-style role.</p>
<h2>Work Environment & Schedule</h2>
<p>Work takes place at commercial facilities across Louisiana, South Arkansas, and Mississippi.</p>
<ul>
<li>Start: ~9:00–10:30 AM</li>
<li>End: ~3:30–4:30 PM</li>
<li>Mostly weekday work, with occasional project-based weekends</li>
</ul>
<h2>Travel Requirements</h2>
<ul>
<li>Travel required almost every week</li>
<li>Up to 5 days on the road</li>
<li>Overnight stays ~75% of the time</li>
<li>Hotels arranged and covered</li>
<li>Daily per diem provided</li>
</ul>
<p>If you’re not comfortable being on the road regularly, this role won’t be a fit.</p>
<h2>Why This Role Stands Out</h2>
<ul>
<li>Direct mentorship from a veteran industry professional</li>
<li>Exposure to electrical, maintenance, and facility work</li>
<li>Fast, hands-on skill development—no classroom training</li>
<li>Work inside major commercial environments</li>
<li>Stable, consistent workload</li>
<li>No corporate bureaucracy—field-focused, straightforward work</li>
</ul>
<h2>Required</h2>
<ul>
<li>Minimum 6 months experience in construction, electrical, HVAC, or similar hands-on work</li>
<li>Comfortable with physical labor, lifting, and working at heights</li>
<li>Able to follow strict safety standards</li>
<li>Ability to take direction and work under supervision</li>
<li>Reliable, punctual, and consistent</li>
</ul>
<h2>Preferred</h2>
<ul>
<li>Valid driver’s license</li>
<li>Clean background</li>
<li>Basic electrical or maintenance experience</li>
</ul>
<div class="job-note">
People with a criminal record are encouraged to apply.
</div>
</div>
<!-- Sidebar -->
<aside class="job-sidebar">
<h3>Job Overview</h3>
<div class="sidebar-item">
<div class="sidebar-item-label">Job Type</div>
<div class="sidebar-item-value">Full-time</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Base Salary</div>
<div class="sidebar-item-value">$63,000/year</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Per Diem</div>
<div class="sidebar-item-value">$50/day while traveling</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Total Compensation</div>
<div class="sidebar-item-value">~$75K–$83K+ annually</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Schedule</div>
<div class="sidebar-item-value">Monday to Friday<br>~9:00 AM–4:30 PM</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Benefits</div>
<div class="sidebar-item-value">PTO + 401(k) matching</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Probationary Period</div>
<div class="sidebar-item-value">90 days</div>
</div>
<div class="sidebar-item">
<div class="sidebar-item-label">Work Location</div>
<div class="sidebar-item-value">Travel—LA, AR, MS</div>
</div>
<a href="#apply-section" class="btn btn-primary sidebar-cta">Apply Now</a>
</aside>
</div>
</div>
</section>
<!-- ── Application Form ── -->
<section class="apply-section section" id="apply-section">
<div class="container">
<h2 class="display-md">Apply For This Position</h2>
<div class="form-success" id="form-success" style="display:none; background: var(--rose-tint); border-left: 3px solid var(--rose); padding: 1.25rem 1.5rem; margin-bottom: 2rem; border-radius: 2px;">
<strong style="color: var(--text);">Application received!</strong>
<p style="color: var(--text-muted); margin-top: 0.25rem; font-size: 0.875rem;">Thank you for applying. We'll review your submission and get back to you soon.</p>
</div>
<form class="apply-form" action="https://usebasin.com/f/1d3141e6918e" method="POST" enctype="multipart/form-data">
<input type="hidden" name="_gotcha" style="display:none">
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response">
<input type="hidden" name="g-recaptcha-version" value="v3">
<input type="hidden" name="_next" value="https://seahaven.com/careers/traveling-maintenance-assistant/?submitted=true">
<div class="form-group">
<label for="apply-name">Name *</label>
<input type="text" id="apply-name" name="name" required placeholder="Your full name">
</div>
<div class="form-group">
<label for="apply-email">Email *</label>
<input type="email" id="apply-email" name="email" required placeholder="you@example.com">
</div>
<div class="form-group">
<label for="apply-phone">Phone *</label>
<input type="tel" id="apply-phone" name="phone" required placeholder="(555) 123-4567">
</div>
<div class="form-group">
<label for="apply-cover">Cover Letter</label>
<textarea id="apply-cover" name="cover_letter" placeholder="Tell us why you'd be a great fit..."></textarea>
</div>
<div class="form-group">
<label for="apply-resume">Resume *</label>
<input type="file" id="apply-resume" name="resume" required accept=".pdf,.doc,.docx">
</div>
<div class="form-submit">
<button type="submit" class="btn btn-primary">Submit Application</button>
</div>
</form>
</div>
</section>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "JobPosting",
"title": "Traveling Maintenance / Electrical Assistant",
"description": "A hands-on, travel-heavy role working directly alongside an experienced technician, supporting maintenance and electrical work across large-scale commercial and industrial facilities. Learn real trade skills fast, earn above-market pay, and be part of a small, no-nonsense team.",
"datePosted": "2025-04-01",
"validThrough": "2026-12-31",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Sea Haven Industries",
"sameAs": "https://seahaven.com",
"logo": "https://seahaven.com/assets/images/seahaven-logo-nav-new.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Lafayette",
"addressRegion": "LA",
"postalCode": "70508",
"addressCountry": "US"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": 63000,
"maxValue": 80000,
"unitText": "YEAR"
}
},
"jobBenefits": "PTO, 401(k) matching, daily per diem while traveling, hotels covered",
"applicantLocationRequirements": {
"@type": "Country",
"name": "US"
},
"directApply": true
}
</script>