Skip to content

Luma — Digital Marketing Agency Landing Page

A Vue 3 practice build: a neon landing page for a growth agency

Luma is a practice project I built to learn front-end work in Vue. It is a landing page for an imagined digital marketing agency, with a loud, high-contrast design: gradient lettering, hollow outline type and wireframe graphics. The aim was to learn Vue’s component model on a real layout, not to ship a finished product.

Type
Practice project · landing page
Role
Design & front-end build
Core stack
Vue 3 · TypeScript · Vite · Tailwind CSS v4 · Swiper
Focus
Vue components, SVG graphics, sliders
Luma — Digital Marketing Agency Landing Page — interface screenshot

The problem

Most of my earlier work was in React. Moving to Vue meant learning a different way to write components: single-file components, <script setup>, props with defaults, and template refs.

A busy agency design was a good test. It has repeated parts like buttons and cards, decorative graphics, and two sliders, so it covers most of what a real Vue front end needs.

What I built

A Vue 3 single-page site in TypeScript, built with Vite, styled with Tailwind CSS v4 and deployed on Vercel.

  • Hero: a “Built for growth” headline in gradient letters cut by thin scan-lines, set against an angled neon panel, with a growth snapshot card showing a sparkline, services and key stats.

  • Brand banner: three rows of hollow “Shine. Grow. Scale.” text scrolling in opposite directions behind a black info band.

  • The Luma Way: a two-column grid of the agency’s service labs and values, with service buttons that link to the contact form.

  • Testimonials and featured work: two Swiper sliders with autoplay, looping, keyboard control and custom arrows and dots.

  • Contact and stats: a contact form with required fields and a thank-you message, a stats section, and a get-in-touch block.

The technical decisions, and why

One button component

Every button comes from a single BaseButton component with typed props for variant, size, icon and shape. It renders a link or a button depending on whether href is set, opens external links in a new tab, and exposes its DOM node so the sliders can use it for navigation.

Graphics drawn in code

The wireframe terrain dividers, the hero sparkline and the flowing testimonial lines are SVG paths built from small formulas in computed values, not image files. A prop like seed or lines gives each divider a different shape at no extra download.

Sliders tied to the component lifecycle

Each slider creates its Swiper instance in onMounted using template refs, and destroys it in onBeforeUnmount, so nothing is left running when the component goes away. The marquee animation also stops for visitors who prefer reduced motion.

Where it landed

The landing page is live and matches the design closely on desktop. It is a practice build: the agency, clients, testimonials and results are placeholder content, and the contact form does not send anywhere.

The main lesson was how close Vue and React are once components are small and typed. The same habits, one shared button and data-driven lists, carried straight across.

Built with

Vue 3TypeScriptViteTailwind CSS v4Swiper

Related work

  • Learn by Build — Online Learning Landing Page

    An early Next.js and Tailwind CSS practice project: a landing page for a hands-on learning platform, with colour-coded course cards and a searchable HTML reference.

  • Evro AI — B2B SaaS Landing Page

    A React 19 and Vite landing page for an AI coaching startup: a header that follows the section colour, a pausable autoplay slider, and copy kept in typed data files.