Telecom
German eSim Provider
2023 – 2025
Overview
Content-rich marketing and product website for a digital-first mobile carrier (Telekom sub-brand). The project prioritised sophisticated scroll-driven animations and third-party content integration, targeting a digitally native audience expecting a premium, app-like web experience.
Architecture
Nuxt 3 (SSG — static generation) │ ├── GSAP + DrawSVGPlugin + ScrollTrigger │ └── Card icon animations — stroke-draw on mount/hover │ ├── Content integrations (build-time) │ └── App Store + Google Play ratings (app-store-scraper) │ ├── Fuse.js — fuzzy FAQ search (zero-latency, client-side) ├── Swiper — product carousel + feature gallery ├── focus-trap-vue — WCAG modal & drawer focus management └── Tealium · UTM redirect tracking · Salesforce live chat Histoire — component library docs for the distributed team
Key Contributions
- GSAP-powered animations using DrawSVGPlugin and ScrollTrigger — card icon stroke-draw sequences on hover, and scroll-triggered section transitions across the page
- focus-trap-vue integration for WCAG-compliant modal and navigation-drawer focus management, ensuring keyboard users never lose context
- Live App Store and Google Play rating integration via build-time scraping (app-store-scraper, google-play-scraper), keeping social proof data fresh without a backend dependency
- Fuse.js fuzzy search powering the FAQ section — zero-latency client-side search with ranked results and hit highlighting
- Tealium analytics, UTM redirect composable, and Salesforce Embedded Service live chat — all abstracted into reusable composables following Vue 3 Composition API conventions
- Component library documented in Histoire, maintaining visual consistency across a distributed team
Code Examples
GSAP DrawSVG Card Animation Timeline
Each feature card SVG starts fully undrawn. On hover or focus the GSAP timeline plays forward — stroking every path via DrawSVGPlugin, sliding clip masks, and scaling icon elements with staggered easing.
composables/useCardAnimation.ts
import gsap from "gsap";
import DrawSVGPlugin from "@/app/DrawSVGPlugin";
export const useCardAnimation = (cardlet: HTMLElement): gsap.core.Timeline | undefined => {
gsap.registerPlugin(DrawSVGPlugin);
if (!cardlet) return;
const icon1Clip = cardlet.querySelector(".card__icon-clip-mask--euro");
const iconEyeDot = cardlet.querySelectorAll(".card-icon__eye-dot");
const iconAppLogo1 = cardlet.querySelector(".app-logo__clip-path");
const iconAppLogo2 = cardlet.querySelector(".app-logo__clip-path--2");
const tl = gsap.timeline({ paused: true });
// Start with all paths undrawn
tl.set(cardlet.querySelectorAll("rect, path, line, circle, polygon, polyline"), {
drawSVG: "0% 0%",
});
if (icon1Clip) tl.set(icon1Clip, { x: -105 });
if (iconEyeDot.length) tl.set(iconEyeDot, { scaleY: 0.5, y: 3 });
if (iconAppLogo1) tl.set(iconAppLogo1, { x: -80 });
if (iconAppLogo2) tl.set(iconAppLogo2, { x: -60 });
// Animate all strokes into view
tl.to(cardlet.querySelectorAll("rect, path, line, circle, polygon, polyline"), {
duration: 1, drawSVG: "0% 100%", ease: "power1.out", delay: 0.1,
}, 0);
if (icon1Clip)
tl.to(icon1Clip, { duration: 1, x: -35, ease: "power1.out" }, 0);
if (iconEyeDot.length)
tl.to(iconEyeDot, { duration: 0.2, scale: 1, y: 0, ease: "power1.out" }, 0);
if (iconAppLogo1)
tl.to(iconAppLogo1, { duration: 0.6, x: 0, ease: "power1.out" }, 0.4);
if (iconAppLogo2)
tl.to(iconAppLogo2, { duration: 0.8, x: 0, ease: "power1.out" }, 0.2);
return tl;
};Icon Gallery
Each card icon starts fully undrawn. GSAP's DrawSVGPlugin strokes every path into view on hover — the CSS animation below replicates the same effect.
Tech Stack
Framework
- Nuxt 3
- Vue 3
- TypeScript
Animation
- GSAP
- DrawSVGPlugin
Styling
- Sass / SCSS
UI Libraries
- Swiper
- focus-trap-vue
Utilities
- Fuse.js
- VueUse
Dev Tooling
- Histoire
- Vitest