VisitSPI
South Padre Island
A student tourism website rebuilt to production standards — every animation preserved, every structural flaw fixed.
Overview
A student project done with real care — and what that meant for the rebuild.
VisitSPI is a personal tourism guide to South Padre Island, Texas, built as a semester capstone for an Internet Studio course. The original site had something most student web projects don't: genuine personality. A hand-coded animated wave intro. A bouncing beach ball that was, as the designer's own statement explains, "a complete accident that I chose to then utilize." A sidebar on the dining page labeled "Wyatt's favorite dish." Personal vacation photos with captions like "celebrating my birthday at Coco's — that's a mango smoothie and I was turning 27."
That voice is rare. It's also fragile — the kind of thing that gets accidentally sanded off during a technical revision. The rebuild challenge was to apply production-level standards across HTML semantics, accessibility, SEO, form handling, and CSS correctness while leaving the site's soul completely intact.
"The ball and the bird movement were a complete accident that I chose to then utilize."
The result is a site that passes the same technical audits applied to a professional medical practice website — and still has a beach ball bouncing across the screen.
The Original
What was there — and why it worked despite the bugs.
The original VisitSPI site was a single-stylesheet, seven-page static build. It used five self-hosted fonts (Boldonse, Berkshire Swash, Changa One, Amiko, Biryani) and a 498-line CSS file to create something that looked genuinely distinctive: a teal-and-coral palette inspired by the coastal waters and sunsets of South Padre Island, a logo that dropped in from above on page load, and a fixed animated background of palm tree tiles that scrolled perpetually sideways.
The site had a clear aesthetic point of view. The Boldonse logo text was bold and italic and gold-on-navy. The nav buttons were coral pills with seafoam borders. The page content sat in a centered card with a teal box-shadow that made it feel like it was floating above the animated background. Every design choice had a reason behind it, documented in a dedicated Design Statement page that explained the color palette, typography decisions, and animation philosophy in the designer's own words.
The palette
All nine original colors were retained without modification. The palette was already correct.
What the original did well
What was broken
transform: translate X(0) — a space inside the function name that browsers ignore entirely. Those three elements were never animating. The animations the designer described in the Design Statement weren't running.bottom: -170 and bottom: -190 with no unit. CSS interprets unitless positional values as zero — the waves were starting from the wrong position on every page load.font-weight: strong. The word "strong" is an HTML element, not a CSS keyword. The browser fell back to the default font weight.<label for="">. There was no programmatic connection between the label text and the input. Screen readers couldn't associate them. Clicking the label text didn't focus the field./images/filename.jpg — a path that only resolves when served from a web server root. The site couldn't be previewed by opening HTML files directly in a browser.transform: translateY(-2px) on hover, but no transition property — the movement snapped instantly rather than animating.The Rebuild
Production standards applied without touching the personality.
The rebuild philosophy was simple: fix what's broken, add what's missing, leave everything else alone. Every animation element, every font, every color, every "Wyatt's favorite dish" card is in the final build. The test for every change was whether a visitor looking at the two versions side-by-side could tell the difference. For most of the improvements, they couldn't.
The animation fixes
Three keyframe animations were silently broken by a space inside the CSS function name. The fix was removing the space. The animations now run exactly as the designer intended and described — the bottle spins as it flies across the screen, the plane flies straight, the bird rotates as it moves. The wave positioning was corrected from unitless to -170px and -190px.
@keyframes bottleFly {
from {
transform: translate X(0)
rotate(0deg);
}
}
@keyframes bottleFly {
from {
transform: translateX(0)
rotate(0deg);
}
}
Form labels — the right way
Every form field was given a proper <label for="id"> element paired with a matching id attribute on the input. Phone fields now use type="tel" (which gives mobile users the numeric keyboard) and email fields use type="email" (which enables browser validation and the correct mobile keyboard). The forms were connected to Netlify's form handling with data-netlify="true" and a honeypot spam field, making them actually functional on deployment. A Thank You page was added as the form success destination so users get confirmation rather than a blank page.
<h3>Email Address?</h3>
<p>
<input type="text"
name="guest-email"
placeholder="Enter email">
</p>
<label for="guest-email">
Email Address
</label>
<input type="email"
id="guest-email"
name="guest-email"
autocomplete="email"
required>
Semantic structure
The logo and nav were wrapped in a <header> element. Page content moved into <main id="main-content">. The navigation became a proper <nav aria-label="Main navigation"> with a <ul> of items. Each page marks its own nav link with aria-current="page", which changes the button to ocean blue with gold text — a visible active state that didn't exist in the original. Every decorative animation element received aria-hidden="true" so screen readers don't announce empty divs flying across the page.
What was added without changing the look
Preservation
Everything that makes this site itself.
The hardest part of a rebuild like this is knowing what not to touch. The following elements were preserved exactly as they were in the original:
Takeaways
What this project illustrates about the gap between working and correct.
The original VisitSPI site looked right. In a browser, at a normal zoom level, on a laptop, with no assistive technology, it appeared to work. The animations played — three of the ten were silently not playing, but you'd have to know what to look for to notice. The forms appeared submittable — they posted to #, meaning they did nothing. The wave positioning was slightly off — but only a pixel-precise comparison would reveal it.
This is the most common category of web development problem: things that appear to work but don't. The bottle was supposed to spin as it flew across the screen. It didn't. The form was supposed to send a message. It didn't. The nav hover was supposed to ease smoothly. It snapped. None of these are visible in a screenshot. All of them are visible in experience.
Production standards aren't about making things look different. They're about making things work the way they appear to work.
The accessibility improvements follow the same logic. A form label looks like a heading next to an input. It behaves like a label — but only if the browser knows they're connected. Without the for/id pairing, a screen reader user hears "text input" with no context, and clicking the label text does nothing. The fix is invisible to sighted users and essential to everyone else.
The broader lesson is that personality and correctness aren't in tension. The beach ball can bounce across the screen and still have aria-hidden="true". The "Wyatt's favorite dish" sidebar can stay exactly where it is and still be inside a properly structured content flow. The wave animation can play exactly as designed — in fact, more exactly, now that the keyframe bug is fixed. The charm of this site was never in the broken parts. It was in the choices: the fonts, the colors, the animations, the voice. Those are all still there.