my contributions
Usability Testing
web development
Interaction design
Woodward Movement is a creative marketing agency based in Ferndale, MI, specializing in brand building and custom apparel design. Their team handles everything in-house, offering services such as branding, retail store design, custom merchandise, and digital marketing.
The requirements
Woodward Movement approached me to develop their website based on their prototype. Their key requirement was to avoid using WordPress and instead opt for a simple HTML-based solution. They wanted a fully customized website that aligned with their unique brand identity and functional needs.
The Challenge
The challenge was to choose the best platform for Woodward Movement's website based on the prototype, ensuring it met their unique requirements while staying away from WordPress.
On top of that, I had to deliver the entire project within a tight deadline, which required careful planning and efficient execution.
12 days
/ Received from client
the Handoff
I have received the initial prototype from the client and am now focused on testing its design and functionality.
/ a complete evaluation
the testing
In this phase, I thoroughly evaluated the website's user experience, design, and functionality.
I identified key heuristics to enhance usability and interaction, compiling my findings into a detailed report, which I shared with the client before moving forward.
/ after analysis
Essential Consideration
After thoroughly testing the prototype and evaluating its design and functionality, I concluded that relying solely on an HTML-based solution wouldn’t meet the project’s needs.
Below are the key findings that led me to choose a more suitable platform for development.
Image-Heavy Pages
With many images on each page, load times will increase, especially if using an HTML-based framework. This can negatively impact user experience and performance.
Challenges of Adding Animations
Hand-coded HTML makes integrating animations complex and time-consuming, requiring manual CSS and JavaScript coding. This can lead to inconsistencies and slow down development.
<html> <head> <title>Woodward Movement</title> </head> <body> <h1>Woodward Movement</h1> </body> </html>
Slower Development Process
Creating a website using only HTML can be a time-consuming task. Each element must be meticulously coded, leading to longer development times.
<div id="itemsWrapperLinks"> <div id="itemsWrapper" class="webgl-fitthumbs fx-three"> <!-- Portfolio Wrap --> <div class="portfolio-wrap flex-grid content-full-width fade-scaleout-effect"> <!-- Portfolio Columns --> <div class="portfolio"> <div class="item wide trigger-item branding design" data-color="#de2606"> <div class="item-parallax"> <div class="item-appear"> <div class="item-content"> <a class="item-wrap ajax-link-project" data-type="page-transition" href="project01.html"></a> <div class="item-wrap-image"> <img src="images/01hero.jpg" class="item-image grid__item-img trigger-item-link" alt="" /> </div> <img class="grid__item-img grid__item-img--large" src="images/01hero.jpg" alt="" /> </div> </div> <div class="item-caption-wrapper"> <div class="item-caption"> <div class="item-title"><span>London Royal Theatre</span></div> <div class="item-cat"><span data-hover="View Case">Brand Identity</span></div> </div> </div> </div> </div> <div class="item trigger-item design photo" data-color="#462883"> <div class="item-parallax"> <div class="item-appear"> <div class="item-content"> <a class="item-wrap ajax-link-project" data-type="page-transition" href="project03.html"></a> <div class="item-wrap-image"> <img src="images/03hero.jpg" class="item-image grid__item-img trigger-item-link" alt="" /> </div> <img class="grid__item-img grid__item-img--large" src="images/03hero.jpg" alt="" /> </div> </div> <div class="item-caption-wrapper"> <div class="item-caption"> <div class="item-title"><span>Moon Purple Dust</span></div> <div class="item-cat"><span data-hover="View Case">Photography</span></div> </div> </div> </div> </div> <div class="item wide trigger-item video" data-color="#000"> <div class="item-parallax"> <div class="item-appear"> <div class="item-content"> <a class="item-wrap ajax-link-project" data-type="page-transition" href="project04.html"></a> <div class="item-wrap-image"> <img src="images/04hero.jpg" class="item-image grid__item-img trigger-item-link" alt="" /> </div> <img class="grid__item-img grid__item-img--large" src="images/04hero.jpg" alt="" /> </div> </div> <div class="item-caption-wrapper"> <div class="item-caption"> <div class="item-title"><span>Hotel Room</span></div> <div class="item-cat"><span data-hover="View Case">Video</span></div> </div> </div> </div> </div> <div class="item wide trigger-item photo" data-color="#70261b"> <div class="item-parallax"> <div class="item-appear"> <div class="item-content"> <a class="item-wrap ajax-link-project" data-type="page-transition" href="project05.html"></a> <div class="item-wrap-image"> <img src="images/05hero.jpg" class="item-image grid__item-img trigger-item-link" alt="" > <div class="hero-video-wrapper"> <video loop muted class="bgvid"> <source src="https://keepgrading.cdn.prismic.io/keepgrading/4cc5e758-b802-4063-9790-dd5dd278f346_G2_MP.mp4" type="video/mp4"> <source src="https://keepgrading.cdn.prismic.io/keepgrading/ba4f9e29-6acc-4993-9ce3-8eb9261f414b_G2_WEBM.webm" type="video/webm"> </video> </div> </div> <img class="grid__item-img grid__item-img--large" src="images/05hero.jpg" alt="" /> </div> </div> <div class="item-caption-wrapper"> <div class="item-caption"> <div class="item-title"><span>Opulence Cosmetics</span></div> <div class="item-cat"><span data-hover="View Case">Photography</span></div> </div> </div> </div> </div> </div> <!--/Portfolio --> </div> <!--/Portfolio Wrap --> </div> </div>
Lack of CMS Flexibility
Without a Content Management System (CMS), updating and managing website content becomes a cumbersome process. Any changes or additions require direct alterations in the HTML code, which can be time-consuming and may lead to potential errors.
/ a perfect solution
The Selection
After carefully evaluating the prototype and testing the functionality, I finalized the platform best suited for the development. It was chosen based on its ability to meet both the client’s needs and the project’s technical requirements, ensuring a seamless and scalable solution for the website.
Below are the key points that influenced my decision to select this platform for development.
convinient framework
When choosing a framework for development, I decided on Next.js for its powerful capabilities and flexibility.
react components
React allows you to create reusable components, meaning you can build a single component for repetitive UI elements like buttons, forms, image galleries, or sliders. Once the component is created, it can be reused throughout the site, ensuring consistency and reducing the amount of code you need to write.
Image Optimization
(Next.js Image Component)
Automatic resizing and serving appropriate image sizes based on the user’s device, screen size, and resolution (e.g., mobile, desktop).
Lazy loading This means images will only load when they come into view, speeding up the initial page load time.
Compression Images are automatically compressed, reducing the file size and improving load times without sacrificing quality.
Incremental Static Regeneration (ISR)
Next.js allows for Incremental Static Regeneration (ISR), which means your client can have the benefits of static site performance but also update individual pages without needing to rebuild the entire site. This is ideal for handling pages with many images, as you can update and optimize them progressively.
Server-Side Rendering (SSR)
In cases where content is dynamic or needs to be frequently updated, Next.js supports Server-Side Rendering (SSR). It will fetch the necessary data and generate the HTML for each request on the server side.
Static Site Generation (SSG)
If a page uses Static Generation, the page HTML is generated at build time. That means in production, the page HTML is generated when you run next build. This HTML will then be reused on each request. It can be cached by a CDN.
/ Crafting From
Handwritten
Here, I showcase the handwritten code snippets that illustrate the custom development approach, emphasizing the unique touch and attention to detail that went into each piece of code.
page structure
<import { Suspense } from "react";>
<import { Brands } from "@features/Brands";>
<import { ButtonDescription } from "@features/ButtonDescription";>
<import { Carousel } from "@features/Carousel";>
<import { LetsChat } from "@features/LetsChat";>
<import { OurWork } from "@features/OurWork";>
<import { SubscribeModal } from "@features/SubscribeModal";>
<import { TitleMarquee } from "@features/TitleMarquee";>
<export default function Home(data)>
return (
<Suspense>
<TitleMarquee
title="WOODWARD MOVEMENT"
topBorder={false}
leftBorder={false}
rightBorder={false}
container={false}
/>
<Carousel />
<ButtonDescription
buttonText="OUR SERVICES"
buttonLink="/"
description="At our office in Ferndale, MI, we specialize in creating design experiences through savvy branding, strategic marketing, custom threads, sweet promotional items and sleek retail design."
/>
<Brands />
<OurWork />
<LetsChat />
<SubscribeModal />
</Suspense>
material ui integration
"use client";
<import { Theme } from "@interfaces/Themes";>
<import { createMaterialUiTheme } from "@interfaces/Themes/muiTheme";>
<import CssBaseline from "@mui/material/CssBaseline";>
<import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles";>
<import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter";>
<import { ThemeProvider } from "styled-components";>
export const Providers = ({ children }) => {
const muiTheme = createMaterialUiTheme(Theme);
return (
<AppRouterCacheProvider options={{ enableCssLayer: true }}>
<ThemeProvider theme={Theme}>
<MuiThemeProvider theme={muiTheme}>
<CssBaseline />
{children}
</MuiThemeProvider>
</ThemeProvider>
</AppRouterCacheProvider>
);
};
manage contents
export const DATA = [
{
type: "BRANDING",
name: "Wildcraft",
image: "/images/portfolio/Wildcraft-Hero.jpg",
projectId: "wildcraft",
},
{
type: "APPAREL",
name: "Rkive",
image: "/images/portfolio/Rkive-hero.jpg",
projectId: "rkive",
},
{
type: "APPAREL",
name: "Blake’s Hard Cider",
image: "/images/portfolio/Blake-hero.jpg",
projectId: "blacks-hard-cider",
},
{
type: "BRANDING",
name: "Odd Duck",
image: "/images/portfolio/oddduck-hero.jpg",
projectId: "oddduck",
},
{
type: "PROMOTIONAL",
name: "Paxahau x Movement",
image: "/images/portfolio/movement-hero.jpg",
projectId: "paxahau-movement",
},
{
type: "BRANDING",
name: "Par",
image: "/images/portfolio/Par-hero.jpg",
projectId: "par",
},
{
type: "PROMOTIONAL",
name: "Olswell",
image: "/images/portfolio/olswell-hero.jpg",
projectId: "olswell",
},
{
type: "BRANDING",
name: "Hytek",
image: "/images/portfolio/Hytek-hero.jpg",
projectId: "hytek",
},
{
type: "APPAREL",
name: "Butter",
image: "/images/portfolio/butter-hero.jpg",
projectId: "butter",
},
{
type: "PROMOTIONAL",
name: "PUFF",
image: "/images/portfolio/puff-hero.jpg",
projectId: "puff",
},
];
components
"use client";
import { useEffect, useRef, useState } from "react";
import { motion } from "framer-motion";
import { Autoplay, Navigation, EffectFade } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
// Import Swiper styles
import "swiper/css";
import "swiper/css/autoplay";
import "swiper/css/effect-fade";
import "swiper/css/navigation";
import { Button, Container, Image } from "./Carousel.styled";
export const Carousel = () => {
const [isVisible, setIsVisible] = useState(false);
const ref = useRef();
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.4 } // Adjust the threshold as needed
);
observer.observe(ref.current);
// Clean up the observer when the component unmounts
return () => observer.disconnect();
}, []);
return (
<motion.div
ref={ref}
initial={{ opacity: 0, y: -40 }}
animate={isVisible ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.8 }} // Adding delay of 0.5 seconds
>
<Swiper
slidesPerView={1}
modules={[Autoplay, Navigation, EffectFade]}
navigation
autoplay
effect="fade" style={{ height: '70vh' }} // Set height to 100vh
>
<SwiperSlide>
<Image src="/images/carousel/slide1.jpg" alt="Slide 1" />
<Container>
{/* <Button size="small">View Project</Button> */}
</Container>
</SwiperSlide>
<SwiperSlide>
<Image src="/images/carousel/slide2.jpg" alt="Slide 2" />
<Container>
{/* <Button size="small">View Project</Button> */}
</Container>
</SwiperSlide>
<SwiperSlide>
<Image src="/images/carousel/slide3.jpg" alt="Slide 3" />
<Container>
{/* <Button size="small">View Project</Button> */}
</Container>
</SwiperSlide>
</Swiper>
</motion.div>
);
};
/ bring life through
Movement
Showcase the dynamic animations and interactions that enhance user engagement across the website. Each element is thoughtfully animated—text elegantly transitions from left to right and vertically, while lines fluidly traverse the page.
These movements create a vibrant, interactive experience, inviting users to explore the content in an engaging way.
Framer Motion
page transition
Framer Motion
custom cursor
Movement
react component
moving text
pure css
moving lines
Responsive
in Action
/ Delivering
Beyond Expectations
It took an additional three days to finalize the project, but in the end, the clients were highly satisfied with both the outcome and the dedication I put into it.
/ In the end
Smooth Deployment
After thorough testing and careful research, I successfully deployed the entire site on the client's testing server. The site is fully functional, and no issues have been encountered since.
Although the site is currently on hold due to pending updated images. The site will be live in the near future.