A highly interactive, visually stunning recreation of the Truus.co website, rebuilt as a Next.js + React application. This project captures the bold aesthetics, playful interactivity, and smooth motion design characteristic of Awwward-winning websites β with every pixel and every frame of animation faithfully recreated.
Header Section![]() |
HorizontalWords Section![]() |
MotionCard Section![]() |
Service Card Section![]() |
Double Marquee Section![]() |
Footer Section![]() |
This project is a high-fidelity clone of the Truus advertising agency website. The codebase was originally built in vanilla HTML/CSS/JS and has been fully transformed to Next.js 15 + React 19, with all animations, interactions, and assets ported 1:1.
The original Truus.co website uses a privately-hosted Vimeo video. Due to Vimeo's Domain-Level Privacy Settings, the video is restricted to the truus.co domain. The hero component uses a standard HTML5 <video> element with the src commented out, rendering a solid dark background. Place your .mp4 in public/ and update the source in VimeoHero.jsx.
- GSAP InertiaPlugin Fling β Motion cards and floating labels track mouse velocity; on
mouseleavethey fling with physics-based inertia and snap back to position. - Page Transition Scribble β Full-screen GSAP-powered scribble mask that draws/undraws on logo click, with random color selection, logo wiggle, and auto-scroll to top.
- Elastic Card Interactions β Service cards spread apart horizontally on hover with elastic bounce physics; hovered card scales up. On mobile, cards stack and reveal via scroll.
- Scroll-Triggered SVG Draws β Hand-drawn underlines and paths animate in via
stroke-dasharrayas the user scrolls past. - Footer Sticker Proximity Push β Stickers react to fast cursor swipes nearby with strength proportional to speed, then spring back elastically.
- Wiggle System β Configurable per-element rotation wiggle on hover, controlled from a single
WIGGLE_CONFIGobject. - Custom Cursor Bubble β GSAP-tracked blob that follows the cursor, pops in elastically over clickable elements with context-aware text.
- Mute Bubble β Separate cursor-following blob on the video hero with mute/unmute states.
- Double Marquee β Infinite scrolling brand logos with smart randomization (no adjacent duplicates for logos or colors, even at the loop seam).
- Credits Pop-out β Footer credits box physically grows/shrinks with staggered text slide animations.
- Lenis Smooth Scroll β Buttery-smooth page scrolling synced with GSAP's ticker.
- Horizontal Scroll & Letter Bounce β Pinned section that scrolls letters horizontally across the screen with random elastic bounces for letters and stickers as they enter the viewport.
- Tab Title Change β Title becomes
"Hey, over here! π"when the tab loses focus.
- React Component Architecture β Every section is a clean, isolated component.
- Modular CSS β 11 partial stylesheets imported via a single
globals.cssentry point. - External SVG Assets β Decorative SVGs extracted to organized folders for clean, readable components.
- Centralized Data β All static data (brands, cards, icons, configs) exported from
lib/data.js. - Self-Hosted Assets β All fonts, brand logos, stickers, and SVGs stored locally β zero CDN dependency.
| Technology | Purpose |
|---|---|
| Next.js 15 | React framework, App Router, file-based routing |
| React 19 | Component-based UI architecture |
| Vanilla CSS | Full design system via CSS Variables β zero Tailwind |
| GSAP + ScrollTrigger + InertiaPlugin | All animations, scroll-driven effects, physics-based fling |
| Lenis | Ultra-smooth inertia scrolling |
truus/
βββ app/
β βββ styles/ # Modular CSS partials
β β βββ base.css # Fonts, CSS variables, reset, body/html
β β βββ navbar.css # Navbar, logos, header hero
β β βββ hero.css # Content section title + underline SVG
β β βββ vimeo-hero.css # Vimeo hero video player + headline
β β βββ motion-cards.css # MotionCard section (heading + cards + labels)
β β βββ showreel.css # Showreel section placeholder
β β βββ cards.css # Service cards, stickers
β β βββ marquee.css # Double marquee section + animations
β β βββ footer.css # Footer layout, credits, stickers
β β βββ cursor.css # Custom cursor bubble + scribble overlay
β β βββ horizontal-words.css # Horizontal scrolling section styles
β β βββ responsive.css # All media queries (tablet + mobile)
β βββ globals.css # Entry point β imports all partials
β βββ layout.jsx # Root layout β <html>, metadata, favicon
β βββ page.jsx # Main page β assembles all components
β
βββ components/
β βββ CursorBubble.jsx # Custom "click" cursor bubble with GSAP tracking
β βββ DoubleMarquee.jsx # Randomised logo marquee + scroll-triggered SVGs
β βββ Footer.jsx # Footer β credits, stickers, socials, wiggles
β βββ HorizontalWords.jsx # Pinned section with elastic letter bounce
β βββ MotionCards.jsx # Motion cards + floating labels + InertiaPlugin fling
β βββ Navbar.jsx # Fixed navbar + scroll color logic + logo wiggle
β βββ ServiceCards.jsx # "Call us if you need" + 5 service cards
β βββ Showreel.jsx # Showreel section placeholder (coming soon)
β βββ SmoothScroll.jsx # Lenis init + GSAP ticker sync (renders null)
β βββ SvgSymbols.jsx # Hidden SVG <symbol> defs (bullet, card divider)
β βββ TransitionScribble.jsx # Full-screen scribble mask on logo click
β βββ VimeoHero.jsx # Video hero β controls, mute bubble, headline
β
βββ lib/
β βββ data.js # All static data as ES module exports
β
βββ public/
β βββ assets/
β β βββ Brand Logos SVG/ # 8 self-hosted marquee brand logos
β β βββ Card-Sticker SVG/ # Stickers overlaying service cards
β β βββ Cursor SVG/ # Custom cursor SVG states
β β βββ Footer-Sticker SVG/ # 6 decorative footer stickers
β β βββ Marquee-blob SVG/ # Blob + hand in marquee section
β β βββ MotionCard SVG/ # Motion card blob + underline
β β βββ Navbar SVG/ # Navbar blob + work icon
β β βββ VimeoHero SVG/ # Smiley, star, oval underline, mute blob
β βββ fonts/
β βββ DMSans-VariableFont_opsz,wght.ttf
β βββ Epilogue-VariableFont_wght.ttf
β
βββ .gitignore
βββ jsconfig.json # @/ import alias configuration
βββ next.config.mjs # Next.js config with webpack @/ alias
βββ package.json
βββ README.md
| Animation | Component | Type |
|---|---|---|
| Inertia fling (cards) | MotionCards | GSAP InertiaPlugin |
| Inertia fling (labels) | MotionCards | GSAP InertiaPlugin |
| Page transition scribble | TransitionScribble | GSAP Timeline |
| Card fan-out on hover | ServiceCards | GSAP Elastic |
| Mobile card scroll stack | ServiceCards | GSAP ScrollTrigger |
| SVG underline draw | ServiceCards | GSAP stroke animation |
| Marquee infinite scroll | DoubleMarquee | CSS Keyframes |
| Marquee SVG reveal | DoubleMarquee | GSAP ScrollTrigger |
| Sticker scroll pop-up | Footer | GSAP ScrollTrigger + back.out |
| Sticker proximity push | Footer | GSAP Elastic |
| Credits pop-out/collapse | Footer | GSAP Timeline |
| Map link draw | Footer | GSAP stroke animation |
| Cursor bubble follow | CursorBubble | GSAP quickTo |
| Mute bubble follow | VimeoHero | GSAP quickTo |
| Wiggle on hover | Navbar, Footer | GSAP steps(1) yoyo |
| Horizontal scroll & pin | HorizontalWords | GSAP ScrollTrigger |
| Letter & sticker bounce | HorizontalWords | GSAP Elastic (Scroll) |
| SVG arrow draw | HorizontalWords | GSAP stroke animation |
| Lenis smooth scroll | SmoothScroll | Lenis + GSAP ticker |
| Tab title change | SmoothScroll | Visibility API |
All static data lives in lib/data.js as named ES module exports:
| Export | Purpose |
|---|---|
brands[] |
8 brand objects { name, src } pointing to /public/assets/ |
colors[] |
Background colour pool for the marquee |
SOCIAL_ICONS[] |
LinkedIn, Instagram, TikTok β href + SVG markup |
CARDS_DATA[] |
5 service card definitions with color, sticker, title, services |
WIGGLE_CONFIG |
Single source of truth for all hover-wiggle intensities |
ANIMATION_CONFIG |
Scribble transition timing and stroke width settings |
export const WIGGLE_CONFIG = {
logoTruus: 4, // The navbar Truus logo
socials: 5, // LinkedIn / Instagram / TikTok icons
jobHeading: 1, // "not hiring right now" heading
googleMap: 1, // Google Maps link text
email: 1, // hello@truus.co
whatsapp: 1, // send us a whatsapp
};Higher number = more rotation (degrees). Set to 0 to disable for any element.
The marquee uses two constraint-aware helpers in components/DoubleMarquee.jsx:
shuffleNoAdjacentSrc(brands)β Fisher-Yates shuffle + post-processing to ensure no two cards with the same logo appear next to each other, including at the loop seam.assignColorsNoAdjacent(count, colors)β Assigns background colours one-by-one, always excluding the previous colour (and the first colour on the last item, to fix the seam).
All SVGs are handled using one of three strategies:
| Strategy | Used For | Why |
|---|---|---|
External .svg + <img> |
Brand logos, stickers, blobs, decorative shapes | Clean components; best for large, non-reused shapes |
Inline <symbol> + <use> |
Repeated icons (bullet-icon, card-divider) |
Defined once in SvgSymbols.jsx, rendered many times; supports currentColor |
Inline <svg> |
Animated paths (map link draw, control icons) | Required for stroke-dasharray animations and React state-driven rendering |
| Folder | Contents |
|---|---|
Brand Logos SVG/ |
8 marquee brand logos |
Card-Sticker SVG/ |
5 stickers for service cards |
Cursor SVG/ |
Custom cursor states |
Footer-Sticker SVG/ |
6 decorative footer stickers |
Marquee-blob SVG/ |
Blob + pointing hand |
MotionCard SVG/ |
Blue blob + wavy underline |
Navbar SVG/ |
Navbar blob + work icon |
VimeoHero SVG/ |
Smiley face, pink star, oval underline, mute blob |
This project uses Next.js, so you need Node.js installed.
-
Clone the repository:
git clone https://github.com/Thakuma07/Truus.co-Awwward-Website.git cd truus -
Install dependencies:
npm install
-
Start the development server:
npm run dev
-
Open in your browser:
http://localhost:3000
Made with β€οΈ by Arkyadeep Pal, Soumyakanta Mitra and Anshu Ram, powered by Antigravity AI.
This project is for educational and portfolio purposes. All original brand assets belong to Truus.co.





