Menu

Menu

Close

Close

Blog

Thoughts & Ideas

My collected thoughts on design, development, and everything in between.

New Posts

view more
Letter Explosion: Killer Text Animation with GSAP & React Tutorial
3 months ago

Letter Explosion: Killer Text Animation with GSAP & React Tutorial

One of my favorite ways to cleanly, and minimally, grab a visitor’s eyeballs is with a killer text animation. Think of it as the secret sauce that turns “nice site” into “holy cow that’s awesome.” Today I’m walking you through the “letter explosion” (aka “letter soup”) effect from my own portfolio. Skip to the bottom for copy-paste code, or read on to understand exactly how, and why, it works. https://medium.com/media/1de4a06490bde3d1e0e16cab5f6c24ba/hrefEnough yap , here it is: Letter Explosion: Crafting a Killer Text Animation with GSAP & React One of my favorite ways to cleanly — and minimally — grab a visitor’s eyeballs is with a killer text animation. Think of it as the secret sauce that turns “nice site” into “holy cow that’s awesome.” Today I’m walking you through the “letter explosion” (aka “letter soup”) effect from my own portfolio. Skip to the bottom for copy-paste code, or read on to understand exactly how — and why — it works. Why Letter Explosion? “If static headers are a handshake, letter explosions are a high-five.” Instant impact. Static text is background noise — dynamic letters stop scroll thumbs cold. Lightweight. All you need is GSAP, ScrollTrigger, React & Tailwind. Customizable. Tweak speeds, rotations, fonts — or add your own color fades. Prerequisites Next.js (App Router, TypeScript) Tailwind CSS GSAP & ScrollTrigger If you’re starting fresh: npx create-next-app@latest my-app --typescriptcd my-appnpm install tailwindcss postcss autoprefixer gsapnpx tailwindcss init -p Add to globals.css: @tailwind base;@tailwind components;@tailwind utilities; Quick GSAP & ScrollTrigger Primer GSAP (GreenSock Animation Platform) is a blazing-fast tweening engine. A tween animates properties (e.g. y: 0 → 500px) over time with perfect frame-timing. ScrollTrigger maps scroll position to those tweens: trigger: element to watch (we use document.documentElement) start / end: scroll bounds (pixels or keywords like "top top") scrub: ties tween progress to scroll (smooth if you pass a number) invalidateOnRefresh: recalculates on resize/layout shift Step 1: Register ScrollTrigger Create components/LetterCollision.tsx and register the plugin: // components/LetterCollision.tsx'use client'; // needed in Next.js App Routerimport { gsap } from 'gsap';import { ScrollTrigger } from 'gsap/ScrollTrigger';// 1️⃣ Hook ScrollTrigger into GSAP's coregsap.registerPlugin(ScrollTrigger); Why? GSAP is modular — registering ScrollTrigger once means you only pay for what you import. Step 2: Split Text with LetterDisplay Each character needs its own DOM node: // components/LetterDisplay.tsximport React from 'react';function getRandomSpeed() { // [0.8, 1.5) - lower = bigger drift return 0.8 + Math.random() * 0.7;}export function LetterDisplay({ word }: { word: string }) { return ( <> {word.split('').map((char, i) => ( <div key={i} className="letter text-6xl font-semibold xs:text-[90px] md:text-[120px]" data-speed={getRandomSpeed()} > {char} </div> ))} </> );} data-speed: randomizes vertical drift per letter. Wrapping each char lets GSAP target them individually. Step 3: Animate on Scroll Add your core animation logic below the registration: // components/LetterCollision.tsximport React, { useEffect, useRef } from 'react';import { LetterDisplay } from './LetterDisplay';const lines = [ 'Creativity ', 'is ', 'my ', 'craft', 'abstract thinking is my passion'];function getRandomRotation() { // ±30° return Math.random() * 60 - 30;}function animateLettersOnScroll(ref: React.RefObject<HTMLDivElement>) { const nodes = ref.current?.querySelectorAll<HTMLElement>('.letter') || []; nodes.forEach(letter => { const speed = parseFloat(letter.dataset.speed || '1'); gsap.to(letter, { // y-offset = fraction of total scroll y: (1 - speed) * ScrollTrigger.maxScroll(window), rotation: getRandomRotation(), ease: 'power2.out', duration: 0.8, // base duration (scrub will sync timing) scrollTrigger: { trigger: document.documentElement, start: 0, end: window.innerHeight, scrub: 0.5, // "momentum" feel invalidateOnRefresh: true } }); });}export function LetterCollision() { const ref = useRef<HTMLDivElement>(null); useEffect(() => { if (!ref.current) return; animateLettersOnScroll(ref); ScrollTrigger.addEventListener('refreshInit', () => ScrollTrigger.refresh()); }, []); return ( <div ref={ref} className="ml-8 scroll-smooth"> {/* layout for two lines + sub-sentence */} <div className="-mt-28 mb-36 flex h-screen flex-col justify-end lg:mb-24"> <div className="flex flex-wrap"> <LetterDisplay word={lines[0]} /> <div className="w-4 sm:w-10" /> <LetterDisplay word={lines[1]} /> </div> <div className="flex flex-wrap"> <LetterDisplay word={lines[2]} /> <div className="w-4 sm:w-10" /> <LetterDisplay word={lines[3]} /> </div> </div> <div className="flex flex-wrap"> <LetterDisplay word={lines[4]} /> </div> </div> );} Why it works y: (1-speed) * maxScroll → random vertical drift (and direction if speed > 1). rotation adds chaotic flair. scrub syncs progress to your scroll for that buttery smooth feel. invalidateOnRefresh keeps everything in sync on resize. Step 4: Integrate into Your Page Drop it into app/page.tsx or pages/index.tsx: // app/page.tsx'use client';import React from 'react';import { LetterCollision } from '@/components/LetterCollision';export default function Home() { return ( <div className="overflow-x-hidden"> <LetterCollision /> {/* …your hero, images, etc. */} </div> );} Heads-up: Without 'use client', ScrollTrigger won’t fire under the App Router. Step 5: Tweak & Optimize Font sizes: adjust the Tailwind text-… breakpoints to suit your design. Spacing: play with -mt-28, mb-36, and padding so letters start fully off-screen. Performance: if dozens of letters cause jank, batch GSAP calls or reduce text length. Next-Level Ideas Fade or blur letters post-collision. Color shifts based on scroll progress. Staggered delays for entry/exit animations. Full Code Listing Copy-paste this into your /components folder to have a pretty cool and eye catching animtion :) import React from 'react';function getRandomSpeed() { return 0.8 + Math.random() * 0.7;}export function LetterDisplay({ word }: { word: string }) { return ( <> {word.split('').map((char, i) => ( <div key={i} className="letter text-6xl font-semibold xs:text-[90px] md:text-[120px]" data-speed={getRandomSpeed()} > {char} </div> ))} </> );} 'use client';import React, { useEffect, useRef } from 'react';import { gsap } from 'gsap';import { ScrollTrigger } from 'gsap/ScrollTrigger';import { LetterDisplay } from './LetterDisplay';gsap.registerPlugin(ScrollTrigger);const lines = [ 'Creativity ', 'is ', 'my ', 'craft', 'abstract thinking is my passion'];function getRandomRotation() { return Math.random() * 60 - 30;}function animateLettersOnScroll(ref: React.RefObject<HTMLDivElement>) { const nodes = ref.current?.querySelectorAll<HTMLElement>('.letter') || []; nodes.forEach(letter => { const speed = parseFloat(letter.dataset.speed || '1'); gsap.to(letter, { y: (1 - speed) * ScrollTrigger.maxScroll(window), rotation: getRandomRotation(), ease: 'power2.out', duration: 0.8, scrollTrigger: { trigger: document.documentElement, start: 0, end: window.innerHeight, scrub: 0.5, invalidateOnRefresh: true } }); });}export function LetterCollision() { const ref = useRef<HTMLDivElement>(null); useEffect(() => { if (!ref.current) return; animateLettersOnScroll(ref); ScrollTrigger.addEventListener('refreshInit', () => ScrollTrigger.refresh()); }, []); return ( <div ref={ref} className="ml-8 scroll-smooth"> <div className="-mt-28 mb-36 flex h-screen flex-col justify-end lg:mb-24"> <div className="flex flex-wrap"> <LetterDisplay word={lines[0]} /> <div className="w-4 sm:w-10" /> <LetterDisplay word={lines[1]} /> </div> <div className="flex flex-wrap"> <LetterDisplay word={lines[2]} /> <div className="w-4 sm:w-10" /> <LetterDisplay word={lines[3]} /> </div> </div> <div className="flex flex-wrap"> <LetterDisplay word={lines[4]} /> </div> </div> );} Copy, tweak, and blast off, your visitors won’t know what hit ’em.

Is Web3 Development Dead? A DevRel Perspective
4 months ago

Is Web3 Development Dead? A DevRel Perspective

What if I told you Web3 isn’t dying, just maturing? Last quarter saw 38.6% fewer weekly contributors, but that slump is only part of a bigger picture, veteran builders are doubling down on ZK, cross-chain, and privacy tech. “Web3 active developers drop nearly 40% in one year.” — Cointelegraph weekly active developers in the blockchain space 24–25 . Source: Artemis terminalThat slump isn’t just a statistic, it’s a wake-up call. Many of those hype-chasers are bowing out, even as a core group of veterans doubles down on real builds. And the community chatter is loud: “The majority of ‘web3’ that got popular was useless or even malicious.” “Too much hype, not enough real-world impact.” https://www.reddit.com/r/webdev/comments/1ehctct/is_web3_blockchain_development_dead/Honestly? I get it. Web3 hasn’t exactly nailed product-market fit because we’ve spent more time chasing flashy funding rounds and speculative tokens rather than building tech that genuinely solves actual problems. Now VCs are pouring into AI, starving blockchain projects of capital. That’s why Developer Relations matters more than ever. Effective DevRel isn’t about hosting pizza meetups or pushing branded hoodies, though let’s be real, everyone loves a good hoodie. Good DevRel start with: Zero-config starter kit: one command to deploy a token contract. 3-minute tutorial: show exactly how to hook that contract into any frontend. Weekly 30-min AMA: fix live integration bugs on stream. Community spotlight: feature your top five GitHub contributors in a newsletter. Those four basics, starter kit, bite-sized tutorial, live debugging, and public recognition, turn curiosity into commitment. Beyond that, great DevRel also means shipping intuitive SDKs with in-browser try-outs, publishing step-by-step docs (video + text), looping developer feedback into your roadmap, and demoing real-world use cases so teams immediately see blockchain’s practical upside. Clearing Up Some Common Misconceptions Myth: DevRel is marketing with a sprinkle of tech jargon. Reality: Effective DevRel professionals are technically deep, contributing directly to product development, defining APIs, and advocating for genuinely useful developer features. Myth: Web3 developers are in it solely for quick cash grabs. Reality: Developers aren’t leaving because they’re fickle, they’re leaving because many projects haven’t demonstrated consistent, meaningful, real-world impact. Myth: Web3 is all speculative hype, no substance. Reality: Admittedly, many Web3 projects have failed to deliver substantial utility. Yet, blockchain technology still holds enormous transformative potential in areas like: Financial automation: Streamlining cross-border payments, cutting remittance costs, and enabling stablecoin-driven economic inclusion, as seen in communities across Latin America beyond El Salvador, such as Colombia and Argentina, which face chronic inflation and financial instability. Healthcare innovation: Secure and interoperable patient records using blockchain can dramatically reduce medical errors, streamline administrative processes, lower costs, and empower patients with greater control over their health data. Secure Digital Ownership and IP protection: Ensuring transparent and immutable verification of digital assets, enhancing trust and reducing fraud in creative industries Myth: AI completely stole Web3’s investment spotlight. Reality: Yes, investors love shiny objects, and AI is currently very shiny, but blockchain complements AI by providing secure, transparent data infrastructure, accountability, and privacy-preserving collaboration frameworks. Skepticism and the Real Path Forward: It’s time for blunt honesty, does Web3 currently solve problems effectively? Clearly not. Decentralization isn’t universally applicable or beneficial. Our job is to rigorously identify and clearly communicate blockchain’s strongest, most compelling use cases: Secure financial infrastructure reducing dependency on inefficient or costly intermediaries. Privacy and collaboration in sensitive sectors like healthcare and finance. Transparent governance and verifiable asset ownership that adds real economic value. Enhanced verification and authenticity in digital ownership and IP protection. Interestingly, younger generations show significantly higher crypto adoption over half (51%) of Gen Z adults own or have owned cryptocurrency, compared to just 35% of the general population [gemini] . Additionally, Gen Z investors are four times more likely to own crypto than to have a traditional retirement account [money.com]. Clearly, there is a future generation poised for digital financial infrastructure, provided we deliver real, tangible value. Gen Z vs. general poulation on owning crypto. Source: gemini.comDeveloper Relations teams must actively engage developers by clearly articulating these genuine value propositions, honestly addressing skepticism, and providing practical pathways for meaningful contributions. Web3’s future hinges on transparency, practicality, and credible technical innovation, not fleeting trends or vague promises. Web3 isn’t dead but without clearer use cases, genuine transparency, and strategically focused innovation, it will continue to struggle to regain developer trust and stay relevant. So, what’s your next DevRel move? Could your docs include a live “first-TX” widget? Or maybe you run a 5-minute ZK tutorial on Twitter Spaces? Pick one and let’s see real traction @bettsosu

profile

Let's work together!

AI/LLM enthusiast | Cutting-edge tech advocate | Web3 builder | Passionate about using technology to make the world a better place.

Version

2024 © Edition

Timezone

5:2 UK (GMT+1)