Introduction
This week, I'm building a full-featured fitness website for a fictional company called Zenith. The purpose of this project is to strengthen my front-end development skills by building and deploying a complete site, adding one key feature each day. My goal is to practice and become deeply proficient in the core web technologies—HTML, CSS, and JavaScript—and to build modular, interactive UIs using React.
To speed up my workflow and maintain a consistent design system, I’m using TailwindCSS. Its mobile-first utility classes make building responsive interfaces faster and more intuitive. To add animations and interactivity, I’m integrating Framer Motion, which pairs nicely with React. Deployment will be handled through Render, which offers a generous free tier for personal projects.
This blog series will serve as a daily log of what I built, the decisions I made, the challenges I faced, and lessons learned. I'm also using this as an opportunity to improve my technical writing and communication—two crucial soft skills in any developer’s toolkit.
Project Setup
Why I Chose Vite Over Create React App
I used Vite as my build tool instead of Create React App. Vite offers faster development times through its instant server start and hot module replacement. It's also lighter and more modular, making it ideal for small-to-medium React projects. The Vite setup process was fast and clean, and it generated the necessary folders (src
, public
, etc.) and config files (vite.config.js
, index.html
).
Dependencies and Configuration
I installed the following packages:
- TailwindCSS for styling
- Framer Motion for animations
- React Icons for vector-based icons
- Google Fonts (Inter) for typography
Tailwind required some setup in tailwind.config.js
and index.css
, but having done this before, I found it fairly straightforward.
Folder Structure
After running npm create vite@latest
, I created a components
folder inside src
to keep my project organized. If I were building a multi-page app, I’d also include folders like pages/
or contexts/
. Since this is a single-page application, I opted not to use React Router to avoid unnecessary bloat.
I also pre-planned the component architecture with help from Claude.ai. The following components will be used across the site:
Header
Hero
Services
Pricing
Trainers
Testimonials
Contact
Footer
Header Component
Today’s focus was building the Header
component. It includes:
- Zenith’s logo
- Desktop and mobile navigation
- A call-to-action (CTA) button
I rendered the Header
as the first element in App.jsx
. The component includes semantic HTML, mobile-first responsive design using Flexbox, and React state management.
Responsive Navigation Strategy
I took a mobile-first approach. In TailwindCSS, you start with base styles and layer on changes at breakpoints (md:
, lg:
, etc.).
For example:
- The desktop nav is hidden by default and becomes visible (
flex
) at thelg
breakpoint (1024px). - The menu toggle button is only visible below
lg
, ensuring a clean layout on larger screens.
This approach keeps things focused and manageable on smaller screens, where space is limited, and then progressively enhances the UI for larger devices.
State Management Approach
I used React's useState
hook for two key pieces of state:
Active Tab: Tracks which nav link is currently active. Initially set to
"home"
. When a link is clicked,setActiveTab()
updates the state, which applies a visual style (e.g., background color) to highlight the active tab.Mobile Menu Toggle: Tracks whether the mobile menu is open. Toggling
mobileToggle
fromfalse
totrue
(and back) determines the visibility of the menu.
const [activeTab, setActiveTab] = useState("home");
const [mobileToggle, setMobileToggle] = useState(false);
{navItems.map((item, index) => (
<a
key={index}
href={item.id}
className={`text-base font-semibold rounded-full px-4 py-2 ${
activeTab === item.id.substring(1) ? "bg-gray-200 flex items-center gap-1" : ""
}`}
onClick={() => setActiveTab(item.id.substring(1))}
>
{item.label}
</a>
))}
Accessibility Considerations
Accessibility is essential. I used semantic HTML where appropriate:
-
<header>
for the main site heading -
<nav>
for navigation areas -
<button>
for all interactive elements
For screen reader compatibility, I added:
-
aria-label
attributes to nav buttons -
aria-expanded
to toggle buttons to indicate menu state
These additions help users with assistive technologies better understand the app structure.
Code Organization
Using Vite helped keep the project structure clean. I used a dedicated components/
folder to separate concerns. For a larger project, I would create additional folders like hooks/
, contexts/
, and utils/
.
I also used the ES7+ React/Redux/React-Native Snippets VS Code extension to scaffold components quickly using rafce
(React Arrow Function Component Export).
Challenges Faced
Here are a few pain points I encountered:
- Z-Index Conflicts: I struggled to keep the mobile menu toggle button visible above the menu overlay due to conflicting stacking contexts.
-
Positioning Confusion: Debated using
fixed
vssticky
headers, and whether to place the mobile menu inside or outside the mainheader
element. - CTA Design on Mobile: I wasn’t satisfied with the look or placement of the CTA in the mobile menu. This is an area I plan to revisit.
I'm learning a lot about layout strategies, relative/absolute positioning, spacing, and responsiveness. These concepts aren’t second nature yet—but they will be with practice.
Refactoring Lessons
One big win was learning to DRY (Don't Repeat Yourself) my navigation links.
Initially, I wrote out each <a>
tag separately, which caused code repetition. Refactoring with a navItems
array and .map()
reduced my nav code from over 40 lines to just 14.
This improved maintainability and keeps the structure clean as the site grows.
Conclusion
Day 1 was a solid start. I set up my development environment with Vite, built a responsive and accessible header, managed React state effectively, and refactored repetitive code.
I’m excited to build on this foundation throughout the week. Tomorrow’s focus: the Hero section.
Repository
Zenith Fitness Website GitHub Repo
Top comments (0)