Hello and welcome to the new blog
In today’s section, we will be discussing how to build the website templates.
The story begins with working on multiple projects at the same time, which most developers do. I’ven’t found one developer who works on one project at a time.
And I truly believe it’s not a wrong or time-wasting activity unless most of your work is not going into vain, pushing you back to poverty. But on a lighter note, every day hard work pays off, that’s what my uncle told me when I got quite a low rank in a competition exam.
Handling multiple projects is not time-wasting but can help you learn time management effectively, and one good way is to quickly launch the product in the market. To launch any product in the market, one needs frontend websites that most of the …
Hello and welcome to the new blog
In today’s section, we will be discussing how to build the website templates.
The story begins with working on multiple projects at the same time, which most developers do. I’ven’t found one developer who works on one project at a time.
And I truly believe it’s not a wrong or time-wasting activity unless most of your work is not going into vain, pushing you back to poverty. But on a lighter note, every day hard work pays off, that’s what my uncle told me when I got quite a low rank in a competition exam.
Handling multiple projects is not time-wasting but can help you learn time management effectively, and one good way is to quickly launch the product in the market. To launch any product in the market, one needs frontend websites that most of the software developers from a C programming background hate to do, and that is why this blog into picture.
So building frontend websites in 2025 includes a few things
- React or Nextjs as a frontend framework
- JSX or React as a language because HTML and CSS, and JS are no longer the developer’s choice
- Tailwind CSS for styling and for responsiveness, we handle using CSS
- Icons mainly using react-icons and lucide-react
- Deployments go to Vercel for FREE deployment, that is all our templates demo URL ends with .vercel.app 😁, check http://eternal-landing-page.vercel.app/
Moving ahead with frontend, I prefer using Nextjs because of couple of reasons
- Quick server-side API if backend is needed
- Compatibility with Vercel
- Marketplace adoptability
Every template comes with a landing page and a few other pages as follows
- Landing page
- About page
- Blogs page
- Blog page
- Subscribe page or form
- Legal pages (Cookies, Privacy, T&Cs)
- Contact pages
- Services
- Dashboards
- Pricing page
- Subscription form
- Login/Sign up form or pages
etc. It totally depends on the template category and purpose. For example, for building an AI agent template for developers to bring the AI product’s frontend website, then we need all pages, except the dashboards
Dashboards are mainly required for CRM templates. Check our react crm dashboard template for the same.
I was using Nextjs latest version, so my directory looks the same. The first part is to create sections for landing pages, and the simplest chronology for landing pages is explained below
- Navbar
- Hero sections
- About section
- Features/Services
- Testimonials
- Pricing
- FAQs
- Contact Form
- Footer containing social links
Each section has its own data and UI to render, which again depends on the template.
For example, for our Eternal AI landing page, we have more than 5/6 sections, as shown in the image below
Ignore a few files, such as LightEffect, PageLayout, LoginForm, and BackgroundDots rest all our sections for our landing page.
It helps to maintain code. One can definitely edit and add all in one file, inside a section tag.
Since Nextjs give file-based routing, the privacy and cookie and blogs folders are the routes of the template, blogs page, cookie page and privacy page.
For example, the code added below is the Hero section for our landing page, which I’ve split into files to handle decoupling and to reuse.
import { ArrowRight } from "lucide-react";
import { motion } from "framer-motion";
const HeroSection = ({ onOpenLogin }) => {
return (
<motion.section
id="about"
className="my-16 z-50 scroll-mt-20"
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6 }}
>
<div className="text-center cursor-pointer py-2 px-4 mb-4 justify-center rounded-full border border-zinc-800 bg-gradient-to-tr from-black to-zinc-950/90 text-zinc-400 w-fit mx-auto flex gap-1 items-center">
<span className="inline-block w-4 h-4 align-middle mr-1">
<svg
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="32" height="32" rx="7" fill="#FF6600" />
<path
d="M10.645 8.5h2.105l3.25 6.195L19.197 8.5h1.977l-4.346 8.452V23.5h-1.782v-6.537L10.645 8.5Z"
fill="white"
/>
</svg>
</span>
<span className="text-xs font-medium">Backed by YC</span>
</div>
<br />
<div className="max-w-5xl mx-auto text-center">
<h2 className="text-5xl font-extrabold text-zinc-100 mx-auto break-words">
Ecosystem for
<span className="ml-4 py-4 px-8 relative group rounded-full bg-gradient-to-r from-blue-900 to-transparent ring-4 ring-blue-900 shadow-zinc-700 shadow-xl">
AI Agents
</span>
</h2>
<p className="text-zinc-400 my-8 max-w-md mx-auto">
Create intelligent agents to automate, analyze, and make decisions.
</p>
<div className="flex gap-4 justify-center my-10">
<button
onClick={() => onOpenLogin?.()}
className="relative flex gap-1 items-center p-2 rounded-full group bg-white text-black hover:text-white transition-all duration-300 ease-in cursor-pointer"
>
<div className="absolute left-0 bottom-0 w-0 z-0 invisible group-hover:visible transition-all duration-300 ease-in group-hover:w-full bg-blue-800 rounded-full h-full" />
<ArrowRight className="w-5 h-5 p-1 bg-blue-800 z-40 group-hover:bg-transparent rounded-full text-zinc-100 transition-all duration-300 ease-in" />
<span className="z-50 text-sm">Get Started</span>
</button>
<button
className={`w-fit py-2 px-4 rounded-full text-sm font-medium transition-all duration-300 hover:bg-zinc-200 bg-zinc-950 text-white hover:text-black hover:shadow-xl`}
>
Learn more
</button>
</div>
</div>
</motion.section>
);
};
export default HeroSection;
Similarly, the blogs page code looks like the below
"use client";
import { useState } from "react";
import Link from "next/link";
import { ArrowRight, Calendar, Clock } from "lucide-react";
import BackgroundDots from "../LandingPage/components/BackgroundDots";
import Navbar from "../LandingPage/components/Navbar";
import MobileMenu from "../LandingPage/components/MobileMenu";
import Footer from "../LandingPage/components/Footer";
// Helper function to convert title to URL slug
const titleToSlug = (title) => {
return title
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "");
};
// Sample blog data
const blogs = [
{
title: "The Future of Artificial Intelligence in Business",
excerpt:
"Discover how AI is revolutionizing the way businesses operate, from automation to intelligent decision-making processes that drive unprecedented growth.",
date: "March 15, 2024",
readTime: "8 min read",
},
{
title: "Building Scalable Applications with Modern Web Technologies",
excerpt:
"Explore the latest frameworks and tools that enable developers to create robust, scalable applications that can handle millions of users effortlessly.",
date: "March 22, 2024",
readTime: "12 min read",
},
{
title: "Design Thinking: Creating User-Centered Experiences",
excerpt:
"Learn the principles of design thinking and how to apply them to create intuitive, engaging user experiences that truly resonate with your audience.",
date: "March 28, 2024",
readTime: "10 min read",
},
{
title: "Machine Learning: From Theory to Production",
excerpt:
"A comprehensive guide to deploying machine learning models in production environments, covering best practices, monitoring, and maintaining AI systems at scale.",
date: "April 5, 2024",
readTime: "15 min read",
},
{
title: "React Performance Optimization Techniques",
excerpt:
"Discover advanced React optimization strategies including code splitting, memoization, and lazy loading to build faster, more efficient applications.",
date: "April 12, 2024",
readTime: "11 min read",
},
{
title: "The Psychology of User Interface Design",
excerpt:
"Explore how cognitive psychology principles influence interface design and learn to create interfaces that align with human mental models and behavior patterns.",
date: "April 18, 2024",
readTime: "9 min read",
},
];
const BlogsPage = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const scrollToSection = (sectionId) => {
if (typeof window === "undefined") return;
const element = document.getElementById(sectionId);
if (element) {
const offset = 80;
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - offset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
}
};
return (
<div className="relative w-full h-full bg-black min-h-screen">
<BackgroundDots />
<div
className="absolute inset-0 top-0 left-0 right-0 bottom-0 opacity-5 pointer-events-none"
style={{ zIndex: 0 }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="100%"
height="100%"
preserveAspectRatio="none"
viewBox="0 0 1400 1400"
>
<filter id="a">
<feTurbulence
type="fractalNoise"
baseFrequency=".65"
numOctaves="3"
stitchTiles="stitch"
></feTurbulence>
</filter>
<rect width="100%" height="100%" filter="url(#a)"></rect>
</svg>
</div>
<Navbar
isMobileMenuOpen={isMobileMenuOpen}
setIsMobileMenuOpen={setIsMobileMenuOpen}
scrollToSection={scrollToSection}
/>
<MobileMenu
isMobileMenuOpen={isMobileMenuOpen}
setIsMobileMenuOpen={setIsMobileMenuOpen}
scrollToSection={scrollToSection}
/>
<main className="relative z-10 pt-24 pb-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h1 className="text-5xl md:text-6xl font-bold text-white mb-4">
Our Blog
</h1>
<p className="text-xl text-zinc-400 max-w-2xl mx-auto">
Insights, tutorials, and stories about technology, design, and
innovation
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{blogs.map((blog, index) => {
const slug = titleToSlug(blog.title);
return (
<Link key={index} href={`/blogs/${slug}`} className="group">
<article className="bg-gradient-to-r from-black to-zinc-950/60 backdrop-blur-sm hover:shadow-2xl hover:shadow-zinc-800 rounded-2xl p-6 transition-all duration-300 h-full flex flex-col">
<div className="flex-1">
<h2 className="text-2xl font-bold hover:text-white mb-3 text-zinc-200 transition-colors">
{blog.title}
</h2>
<p className="text-zinc-400 mb-4 line-clamp-3">
{blog.excerpt}
</p>
</div>
<div className="flex items-center justify-between text-sm text-zinc-500 mb-4">
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4" />
<span>{blog.date}</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-4 h-4" />
<span>{blog.readTime}</span>
</div>
</div>
<div className="flex items-center gap-2 text-zinc-200 group-hover:gap-4 transition-all">
<span className="text-sm font-medium">Read more</span>
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</div>
</article>
</Link>
);
})}
</div>
</div>
</main>
<Footer />
</div>
);
};
export default BlogsPage;
By the way, how we show each blog page along with content is shown in the image below
Nextjs handle dynamic file routing, so the slug becomes a dynamic URL route, for example, yourdomain.com/blogs/{title of the blog}. For this URL, the slug is equal to “title of the blog”
In this way, one can add all blogs to one different file, for example, a markdown file content and render them using a dynamic file routing. This is quite good for server-side blog SEO in production. check blogs
Once this is completed, we will have mainly all the pages ready. The next and tricky part is to add good CSS that is styling and some proper user experience, like a toast.
Tailwind CSS mainly handle everything from responsive to styling to adding themes and colours. Motion design is handled using framer-motion, an npm package by the framer team or using GSAP core, another JavaScript animating library.
But one can certainly use anime.js or react-spring, or others.
For login/sign up, we prefer the same folder-based routing or mainly add the login/sign form inside overlays like Modals
I am obsessed with Design, and that is why I try to add a better user interface, even if it’s a footer, because if the user has scrolled to the last, make sure you leave him with something to remember
Footer section code as shown below, copy-paste it you will feel good how easy is to get your own footer
import { Heater } from "lucide-react";
import Link from "next/link";
import { navigationItems } from "../constants";
const Footer = () => {
return (
<footer className="relative w-full bg-gradient-to-r from-black to-zinc-950 border-t border-zinc-800 z-10">
<div className="w-full mx-auto p-10 bg-gradient-to-r from-black to-zinc-950 grid md:grid-cols-2 grid-cols-1 items-start justify-center transition-all duration-300 ease-in-out">
<div className="max-w-xl mx-auto ">
<Link href="/" className="flex items-center gap-2 mb-2">
<Heater className="w-5 h-5 text-white" />
<span className="text-white font-semibold text-lg">Eternal</span>
</Link>
<p className="text-zinc-500 text-xs">
© {new Date().getFullYear()} Eternal. All rights reserved.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 justify-center md:justify-start gap-8 mb-8">
<div>
<h5 className="text-white font-semibold mb-4 text-sm uppercase tracking-wider">
Navigation
</h5>
<ul className="space-y-3">
{navigationItems.map((item) => (
<li key={item.label}>
<Link
href={item.href}
className="text-zinc-400 hover:text-white transition-colors text-sm"
>
{item.label}
</Link>
</li>
))}
</ul>
</div>
<div>
<h5 className="text-white font-semibold mb-4 text-sm uppercase tracking-wider">
Legal
</h5>
<ul className="space-y-3">
<li>
<Link
href="/privacy"
className="text-zinc-400 hover:text-white transition-colors text-sm"
>
Privacy Policy
</Link>
</li>
<li>
<a
href="#terms"
className="text-zinc-400 hover:text-white transition-colors text-sm"
>
Terms of Service
</a>
</li>
<li>
<Link
href="/cookie"
className="text-zinc-400 hover:text-white transition-colors text-sm"
>
Cookie Policy
</Link>
</li>
<li>
<a
href="#security"
className="text-zinc-400 hover:text-white transition-colors text-sm"
>
Security
</a>
</li>
</ul>
</div>
<div>
<h5 className="text-white font-semibold mb-4 text-sm uppercase tracking-wider">
Social
</h5>
<ul className="space-y-3">
<li>
<a
href="https://linkedin.com/company/eternal"
target="_blank"
rel="noopener noreferrer"
className="text-zinc-400 hover:text-blue-400 transition-colors text-sm"
>
LinkedIn
</a>
</li>
<li>
<a
href="https://twitter.com/eternal"
target="_blank"
rel="noopener noreferrer"
className="text-zinc-400 hover:text-blue-400 transition-colors text-sm"
>
Twitter
</a>
</li>
<li>
<a
href="https://instagram.com/eternal"
target="_blank"
rel="noopener noreferrer"
className="text-zinc-400 hover:text-pink-400 transition-colors text-sm"
>
Instagram
</a>
</li>
</ul>
</div>
</div>
</div>
<div className="relative h-fit pt-10 text-center rounded-[4em]">
<p className="md:text-[12em] text-7xl shadow-xlfont-bold font-mono uppercase text-transparent bg-clip-text bg-gradient-to-tr from-black to-white">
Eternal
</p>
</div>
</footer>
);
};
export default Footer;
Take care of the navigationItems array on your own.
I prefer to use .map and filter method, then adding hard-coded the same thing twice or thrice, just the production practice of writing performant code
Moving ahead, once that is done, we mainly need to check the responsiveness and handle it using Tailwind CSS classes such as md, lg, xl, xxl, 2xl, sm, xxs, xs, and each can be understood by their name.
Deployment is one click away if using vercel, just push the repository to Github and connect Github to Vercel to import and deploy the repository for a quick demo in production.
Each of the details about pages and sections is in the template and the README file of each template I made to help developers quickly bring up the frontend website.
Feel free to try the same way for building your own template, or else check our templates.
See you at the next one
Shrey