DEV Community

Cover image for How I Built a Modern Agency Landing Page with Next.js 15 and Tailwind CSS
Anas Sheikh
Anas Sheikh

Posted on

How I Built a Modern Agency Landing Page with Next.js 15 and Tailwind CSS

Most agency websites lose clients before they even read a word.

Bad first impression. Generic design. Slow load time.

I built AgencyX to fix thatβ€”a modern, conversion-focused agency landing page that helps visitors trust your brand from the very first screen.

Live Demo: https://agencyx-template.vercel.app/


πŸš€ What's Inside

  • Bold hero section designed to capture attention immediately
  • Services showcase with premium card layouts
  • Portfolio grid for case studies and client work
  • Testimonials section with social proof
  • Pricing tables for service packages
  • Team section, FAQ, Contact form, and Footer
  • Fully responsive and SEO optimized

πŸ›  Tech Stack

  • Next.js 15
  • React
  • Tailwind CSS
  • Lucide React
  • App Router

🎯 The Hero Section

The hero section is the most important part of any agency website. You have just a few seconds to convince visitors to stay.

export function Hero() {
  return (
    <section className="min-h-screen flex items-center bg-gradient-to-br from-black via-surface-900 to-black">
      <div className="max-w-6xl mx-auto px-6 grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">

        <div>
          <div className="inline-flex items-center gap-2 px-4 py-2 bg-brand-500/10 border border-brand-500/20 rounded-full mb-6">
            <span className="w-2 h-2 bg-brand-400 rounded-full animate-pulse" />
            <span className="text-brand-400 text-sm">
              Now booking Q3
            </span>
          </div>

          <h1 className="text-5xl lg:text-7xl font-black text-white leading-none mb-6">
            Stories that earn{" "}
            <span className="text-brand-400">
              second looks.
            </span>
          </h1>

          <p className="text-slate-400 text-lg mb-8 max-w-md">
            Positioning, content and campaigns that compound long after launch.
          </p>

          <div className="flex gap-4">
            <a
              href="/contact"
              className="px-8 py-4 bg-brand-500 text-black rounded-xl"
            >
              Start a Project
            </a>

            <a
              href="/portfolio"
              className="px-8 py-4 border border-white/20 rounded-xl text-white"
            >
              Selected Work
            </a>
          </div>
        </div>

        <div className="grid grid-cols-2 gap-4">
          {stats.map((stat) => (
            <div
              key={stat.label}
              className="p-6 bg-white/5 border border-white/10 rounded-2xl"
            >
              <div className="text-3xl font-bold text-white">
                {stat.value}
              </div>

              <div className="text-slate-400">
                {stat.label}
              </div>
            </div>
          ))}
        </div>

      </div>
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

πŸ’Ό Services Cards

Each service card includes a subtle hover animation.

export function ServiceCard({
  icon: Icon,
  title,
  description,
  features,
}) {
  return (
    <div className="group p-8 bg-surface-800/60 border border-white/10 rounded-2xl">

      <div className="w-14 h-14 rounded-2xl bg-brand-500/10 border border-brand-500/20 flex items-center justify-center mb-6">
        <Icon size={24} className="text-brand-400" />
      </div>

      <h3 className="text-xl font-bold text-white mb-3">
        {title}
      </h3>

      <p className="text-slate-400 mb-6">
        {description}
      </p>

      <ul className="space-y-2">
        {features.map((feature) => (
          <li
            key={feature}
            className="flex items-center gap-2 text-slate-300"
          >
            <span className="w-1.5 h-1.5 rounded-full bg-brand-400" />
            {feature}
          </li>
        ))}
      </ul>

    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

⭐ Testimonials

Specific testimonials build more trust than generic praise.

const testimonials = [
  {
    quote:
      "AgencyX helped us close three new clients in the first month.",
    author: "Sarah M.",
    role: "Founder, Northwind Studio",
    avatar: "/avatars/sarah.jpg",
  },
];

export function TestimonialCard({
  quote,
  author,
  role,
  avatar,
}) {
  return (
    <div className="p-8 bg-surface-800/60 border border-white/10 rounded-2xl">

      <div className="flex gap-1 mb-4">
        {[...Array(5)].map((_, i) => (
          <span key={i}>β˜…</span>
        ))}
      </div>

      <p className="mb-6">
        "{quote}"
      </p>

      <div className="flex items-center gap-3">
        <img
          src={avatar}
          alt={author}
          className="w-10 h-10 rounded-full"
        />

        <div>
          <div>{author}</div>
          <div>{role}</div>
        </div>
      </div>

    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ What I Learned

  • A "Now Booking" badge creates urgency.
  • Stats in the hero build trust quickly.
  • Specific testimonials outperform generic ones.
  • Keep one primary CTA above the fold.

πŸŽ‰ The Result

Live Demo

https://agencyx-template.vercel.app/

Get the complete template with all components and documentation:

AgencyX

https://pixelanas.gumroad.com/l/AgencyX

Questions? Drop them in the comments below.

Built by Anas β€” Full-stack developer specializing in Next.js, premium UI, and conversion-focused web experiences.

Top comments (0)