landing page builder

How To Build a Landing Page in Next.js

Posted on May 6th, 2022 by Antonello Zanini

In recent years, marketing campaigns have kept evolving and most of them now rely on landing pages. These pages are designed with conversion in mind and to guide users toward taking a particular action, namely the goal of the campaign. A landing page builder, allows you to create a reusable landing page template is not that difficult, and here you will learn how to build the landing page of your dreams in Next.js.

First, let’s learn what a landing page is. Then, let’s focus on what section it should contain and how to implement it in Next.js. Finally, let’s see what a landing page builder has to offer to you. 
Follow this tutorial to learn how to build the following landing page.

Landing page builder

Want to get started right away?

If you want to try it right away, you can install our landing page template. By clicking on the deploy button, DatoCMS will automatically clone the template to your Github account, create a DatoCMS backend, and publish it to Netlify or Vercel!

Landing page template
Landing page template
Landing page template
Publish this demo online with just three clicks in a matter of minutes.
Deploy the demo project

What Is a Landing Page Builder?

A landing page is a standalone web page where visitors “land” after clicking on a link coming from emails, ads, social posts, or other places on the web. Usually, such pages are specifically created with a goal in mind for a marketing campaign.  

So, while generic web pages generally encourage exploration and might have many goals, landing pages focus on only one marketing goal. This goal is also known as a CTA (Call To Action), a marketing term used to define any design devised to prompt an action from the user.
In other words, users reaching your landing page are encouraged to take an action, such as buying your products, downloading a document, joining your newsletter, or clicking on some business-relevant links. A landing page can be considered successful if many users take the action it was designed for.

It is very common to create different landing pages for different purposes, like optimizing for different SEO keywords, so instead of createing multiple landing page templates, you can only create one template and repeat it, just using with different words and colors.

Now, let’s study the building blocks of a landing page.

What Elements a Landing Page Should Include

The recipe for a good landing page is simple. Let's see the section a landing page should have.

1. Header

The header section of a landing page typically includes a navigation bar (from now on navbar) containing the anchor links to the other sections included in the page. Its goal is to help the visitor traverse the landing page. The links contained in the header must be anchor links because you do not want your users to leave the page. The header section should also include your logo.

Landing page header
Header

2. Hero

The hero section is the first thing users see when landing your landing page. In other terms, it represents the area that goes from the header to the next section, and it is generally designed to take up all the vertical and horizontal space on the screen. Its goal is to impress the visitor with its design and colors and lead them to the next section of the landing page, which is the one containing the CTA.

Landing page hero
Landing page Hero

3. CTA

This is the most important part of a landing page and the only one that is really mandatory. This is where you want to guide your visitor so that they can take the action the landing page was designed for. The CTA section may be a list of products, a form, or a download link.

Landing page CTA
Landing page CTA

4. About

An optional section to add some details and better explain what the landing page is about.

Landing page about
About part

5. Footer

A small section that typically includes links to the privacy policy or any mandatory information for GDPR reasons.

Landing Page Template in Next.js

So, let’s now learn how to build a landing page builder template in Next.js. In the following step-by-step tutorial, you will see how to craft a cool landing page designed entirely with Bootstrap.

Prerequisites

This is the list of all the prerequisites required for the demo application:

Building a Landing Page in Next.js and Bootstrap

You can clone the GitHub repository supporting the article and give a look locally at the landing page you are about to learn how to build by launching the following commands:

Terminal window
git clone https://github.com/Tonel/landing-page-template-nextjs
cd landing-page-template-nextjs
npm i
npm run dev

Then, visit the http://localhost:3000 page in your browser to see the landing page.

Otherwise, keep following this how-to and build the landing page by yourself.

1. Initializing the Next.js Project

The best way to initialize a blank Next.js project is through Create Next App. This is the official and recommended way to generate a Next.js blank application, and you can easily initialize a project called landing-page-template-nextjs by launching the command below:

Terminal window
npx create-next-app landing-page-template-nextjs

The landing-page-template-nextjs folder should now contain the following file structure:

1
multi-language-blog-demo-nextjs
2
├── README.md
3
├── node_modules
4
├── package.json
5
├── .gitignore
6
├── .eslintrc.json
7
├── next.config.js
8
├── public
9
│ ├── favicon.ico
10
│ └── vercel.svg
11
├── styles
12
│ ├── globals.css
13
│ └── Home.module.css
14
└── pages
15
├── _app.js
16
├── index.js
17
└── api
18
└── hello.js

Now, enter the landing-page-template-nextjs folder and launch  the local server by running these two commands:

Terminal window
cd landing-page-template-nextjs
npm run dev

Visit http://localhost:3000/ in your browser, and you should be seeing the default Create Next App page below:

2. Building the Landing Page Components

First, let’s add the required dependencies. You can add bootstrap and react-bootstrap to your project’s dependencies with the following command:

Terminal window
npm install bootstrap react-bootstrap

Your package.json file should now contain the required dependencies.
Let’s now delve deeper into how to implement each of the components the landing page consists of. The components the landing page depends on were inspired by this project.

Header

1
import React from "react"
2
import { Container, Navbar, Nav } from "react-bootstrap"
3
4
export default function Header() {
5
return (
6
<div className={"header"}>
7
<Navbar bf={"light"} expand="md">
8
<Container>
9
<Navbar.Brand href="/">Your Logo</Navbar.Brand>
10
<Navbar.Toggle />
11
<Navbar.Collapse>
12
<Nav className="m-auto">
13
<Nav.Link href="/#">Home</Nav.Link>
14
<Nav.Link href="/#services">Services</Nav.Link>
15
<Nav.Link href="/#about">About</Nav.Link>
16
</Nav>
17
</Navbar.Collapse>
18
</Container>
19
</Navbar>
20
</div>
21
)
22
}


Hero

1
import React from "react"
2
import { Container, Row, Col } from "react-bootstrap"
3
import hero from "../assets/images/hero.png"
4
import Link from "next/link"
5
import Image from "next/image"
6
7
export default function Hero() {
8
return (
9
<section className="section position-relative bg-light hero">
10
<Container>
11
<Row className="align-items-center">
12
<Col lg={6}>
13
<div className="pr-lg-5">
14
<h1 className="mb-4 font-weight-normal line-height-1_4">
15
Your Fantastic <span className="text-warning font-weight-medium">Landing Page</span>
16
</h1>
17
<p className="text-muted mb-4 pb-2">
18
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incidunt ut labore et
19
dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullamco laboriosam, nisi ut
20
aliquid ex ea commodi consequatur.
21
</p>
22
<Link href="#services">
23
<a className="btn btn-warning">
24
Find Out More <span className="ml-2">&darr;</span>
25
</a>
26
</Link>
27
</div>
28
</Col>
29
<Col lg={6}>
30
<div className="mt-5 mt-lg-0">
31
<Image
32
layout={"responsive"}
33
src={hero.src}
34
width={1000}
35
height={710}
36
alt=""
37
className="img-fluid mx-auto d-block"
38
/>
39
</div>
40
</Col>
41
</Row>
42
</Container>
43
</section>
44
)
45
}

Notice that the “Find Out More” button leads to the CTA section below. This is what a hero section should do.

Also, this section might contain large images, and this is why the Next.js <Image/> component was used. Follow this to learn more about how image optimization works in Next.js.

Services

In this example, the CTA section is represented by the following list of services:

1
import React from "react"
2
import { Container, Row, Col } from "react-bootstrap"
3
import Service from "./Service"
4
5
export default function Services({ services }) {
6
return (
7
<section className="section" id="services">
8
<Container>
9
<Row className="justify-content-center">
10
<Col lg={6} md={8}>
11
<div className="title text-center mb-5">
12
<h3 className="font-weight-normal text-dark">
13
<span className="text-warning">Services</span>
14
</h3>
15
<p className="text-muted">
16
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incidunt ut labore et
17
dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullamco laboriosam, nisi ut
18
aliquid ex ea commodi consequatur.
19
</p>
20
</div>
21
</Col>
22
</Row>
23
{services.map((service, i) => {
24
return <Service service={service} key={i} />
25
})}
26
</Container>
27
</section>
28
)
29
}

The list of services is passed as a prop. So, the services to display are not hard-coded into the component, making this component more dynamic. In fact, you can retrieve this list from an API, for example. This way, by changing the service content in your content management platform, your landing page will update accordingly.

Then, this is what the Service component referenced in Services looks like:

1
import React from "react"
2
import { Row, Col } from "react-bootstrap"
3
import serviceImg from "../assets/images/service.png"
4
import Image from "next/image"
5
import Link from "next/link"
6
7
export default function Service({ service }) {
8
return (
9
<>
10
{service.id % 2 !== 0 ? (
11
<Row className={service.id === 1 ? "align-items-center" : "align-items-center mt-5"}>
12
<Col md={5}>
13
<div>
14
<Image
15
layout={"responsive"}
16
src={service.img || serviceImg.src}
17
width={1000}
18
height={667}
19
alt=""
20
className="img-fluid d-block mx-auto"
21
/>
22
</div>
23
</Col>
24
<Col md={{ size: 6, offset: 1 }}>
25
<div className="mt-5 mt-sm-0 mb-4">
26
<h5 className="text-dark font-weight-normal mb-3 pt-3">{service.title}</h5>
27
<p className="text-muted mb-3 f-15">{service.description}</p>
28
<Link href={service.url}>
29
<a className="f-16 text-warning">
30
Try It Now <span className="right-icon ml-2">&#8594;</span>
31
</a>
32
</Link>
33
</div>
34
</Col>
35
</Row>
36
) : (
37
<Row className="align-items-center mt-5">
38
<Col md={6}>
39
<div className="mb-4">
40
<h5 className="text-dark font-weight-normal mb-3 pt-3">{service.title}</h5>
41
<p className="text-muted mb-3 f-15">{service.description}</p>
42
<Link href={service.url}>
43
<a className="f-16 text-warning">
44
Try It Now <span className="right-icon ml-2">&#8594;</span>
45
</a>
46
</Link>
47
</div>
48
</Col>
49
<Col md={{ size: 5, offset: 1 }} className="mt-5 mt-sm-0">
50
<div>
51
<Image
52
layout={"responsive"}
53
src={service.img || serviceImg.src}
54
width={1000}
55
height={667}
56
alt=""
57
className="img-fluid d-block mx-auto"
58
/>
59
</div>
60
</Col>
61
</Row>
62
)}
63
</>
64
)
65
}

In this example, the “Try It Now” buttons are the CTAs and what the users should be prompt to click.

About

1
import React from "react"
2
import { Container, Row, Col } from "react-bootstrap"
3
4
export default function About() {
5
return (
6
<section className="section bg-light" id="about">
7
<Container>
8
<Row className="justify-content-center">
9
<Col lg={6} md={8}>
10
<div className="title text-center mb-5">
11
<h3 className="font-weight-normal text-dark">
12
About <span className="text-warning">Us</span>
13
</h3>
14
<p className="text-muted">
15
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incidunt ut labore et
16
dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullamco laboriosam, nisi ut
17
aliquid ex ea commodi consequatur.
18
</p>
19
</div>
20
</Col>
21
</Row>
22
<Row>
23
<Col md={4}>
24
<h2 className="font-weight-light line-height-1_6 text-dark mb-4">Lorem ipsum dolor sit amet</h2>
25
</Col>
26
<Col md={{ size: 7, offset: 1 }}>
27
<Row>
28
<Col md={6}>
29
<h6 className="text-dark font-weight-light f-20 mb-3">Our Goal</h6>
30
<p className="text-muted font-weight-light">
31
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incidunt ut labore et
32
dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullamco laboriosam, nisi ut
33
aliquid ex ea commodi consequatur.
34
</p>
35
</Col>
36
<Col md={6}>
37
<h6 className="text-dark font-weight-light f-20 mb-3">Our Strategy</h6>
38
<p className="text-muted font-weight-light">
39
Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incidunt ut labore et
40
dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullamco laboriosam, nisi ut
41
aliquid ex ea commodi consequatur.
42
</p>
43
</Col>
44
</Row>
45
</Col>
46
</Row>
47
</Container>
48
</section>
49
)
50
}

This section is totally optional, and you can omit it entirely.

Footer

1
import React from "react"
2
import { Container, Row, Col } from "react-bootstrap"
3
4
export default function Footer({ links }) {
5
return (
6
<section className="footer section">
7
<Container>
8
<Row>
9
<Col lg={4}>
10
<div className="mb-4">
11
<p className="text-muted mt-4 mb-2">your-email@email.com</p>
12
<h6 className="text-muted font-weight-normal">+1 555-2368</h6>
13
</div>
14
</Col>
15
<Col lg={8}>
16
<Row>
17
{links.map((link, key) => (
18
<Col key={key} md={4}>
19
<h6 className="text-dark mb-3">{link.title}</h6>
20
<ul className="list-unstyled company-sub-menu">
21
{link.child.map((fLink, key) => (
22
<li key={key}>
23
<a href={fLink.link}>{fLink.title}</a>
24
</li>
25
))}
26
</ul>
27
</Col>
28
))}
29
30
<Col md={4}>
31
<h6 className="text-dark mb-3">Our Address</h6>
32
<p className="text-muted f-14">1234 Lorem Ipsum, 12345</p>
33
<ul className="list-unstyled footer-social-list mt-4">
34
<li className="list-inline-item">
35
<a href="src/app/components/Footer#">
36
<i className="mdi mdi-facebook"></i>
37
</a>
38
</li>
39
<li className="list-inline-item">
40
<a href="src/app/components/Footer#">
41
<i className="mdi mdi-instagram"></i>
42
</a>
43
</li>
44
<li className="list-inline-item">
45
<a href="src/app/components/Footer#">
46
<i className="mdi mdi-linkedin"></i>
47
</a>
48
</li>
49
</ul>
50
</Col>
51
</Row>
52
</Col>
53
</Row>
54
55
<Row className="mt-5">
56
<Col md={12}>
57
<div className="text-center text-muted">
58
<p className="mb-0 f-15">{${new Date().getFullYear()} - Your Company Name`}</p>
59
</div>
60
</Col>
61
</Row>
62
</Container>
63
</section>
64
)
65
}

Similar to what was explained with the Services component, the Footer component depends on the links prop and can be dynamically updated at will.

3. Putting It All Together

Now, let’s see how to use the components implemented above to build your landing page. Create a index.js file under the pages folder representing your home page and define it as follows:

1
import Layout from "../src/app/components/Layout"
2
import Header from "../src/app/components/Header"
3
import Hero from "../src/app/components/Hero"
4
import Services from "../src/app/components/Services"
5
import About from "../src/app/components/About"
6
import Footer from "../src/app/components/Footer"
7
import serviceSource from "../src/app/assets/services.json"
8
import footerSource from "../src/app/assets/footer.json"
9
10
export default function LandingPage({ services, footerLinks }) {
11
return (
12
<Layout pageTitle="Landing Page Template in Next.js">
13
<Header />
14
<Hero />
15
<Services services={services} />
16
<About />
17
<Footer links={footerLinks} />
18
</Layout>
19
)
20
}
21
22
export function getStaticProps() {
23
// in a real-world scenario retrieve the service list
24
// by calling an API or performing a query
25
const services = serviceSource
26
27
// retrieving the footer link list ...
28
const footerLinks = footerSource
29
30
return {
31
props: {
32
services: services,
33
footerLinks: footerLinks,
34
},
35
revalidate: 60,
36
}
37
}

As you can see, all you have to build your landing page is using the components presented above one below the other.

For the sake of simplicity, the service and footer link lists were retrieved from two JSON files. In a real-world scenario, you should retrieve this them more elegantly with a couple of API calls or by performing two queries in getStaticProps(). In this last case, you should use the revalidate option and take advantage of the Next.js incremental static regeneration approach. This way, your landing page will be static, fast and updated accordingly every 60 seconds.

Et voilà! Your fantastic and exciting landing page is ready to be deployed. 

Why You Need a Landing Page Builder

As learned above, landing pages all share the same recipe. This is why the ideal solution when it comes to building landing pages would be to define a template that works and tweak it accordingly based on your goals. But this is something that only a landing page builder can provide you with. 

Designing a new landing page from scratch for each marketing campaign takes time and money. This is why following the traditional approach to landing pages and ignoring advanced tools feel like reinventing the wheel.

On the other hand, adopting a landing page builder make everything easier and speeds up the implementation of your marketing campaigns. Also, an effective landing page builder allows you to deal with multi-site management and share the same landing page template on different websites by changing colors and text. 

Now, let’s find out more about DatoCMS, the headless CMS landing page builder you were looking for.

DatoCMS: The Landing Page Builder You Dreamt Of

DatoCMS is a headless CMS that comes with advanced features specifically designed for developers and marketers. In detail, it allows you to define reusable components you can then use to create dynamic templates for one-page websites, landing pages, case study pages, and testimonial pages. Learn more about what DatoCMS has to offer when it comes to building dynamic layouts with modular blocks.

So, with DatoCMS your content management team can create a template project, link it to a frontend project, and duplicate it indefinitely. This means that several pages on your website could share the same template. But all pages should be different, and this is why DatoCMS also equips you with the ability to change colors, language, text, and much more.

Also, keep in mind that DatoCMS is much more than just a landing page builder. So, its headless CMS capabilities enable you to use the same template for different projects. This means defining an effective landing page once and then spreading it across all your websites. Also, you could use DatoCMS to manage the content, instead of using JSON files as in the example above. 

Get started right away with our out-of-the-box template.

Landing page template
Landing page template
Landing page template
Publish this demo online with just three clicks in a matter of minutes.
Deploy the demo project

Conclusion

In this article, we learned what is a landing page, what elements should contain, and how to build a landing page template in Next.js. Although achieving this required just a bunch of lines of code and cannot be considered a difficult task, it comes with some pitfalls. So, if you are looking for a more scalable and reliable solution you should consider adopting an advanced, easy-to-use, and complete landing page builder CMS, such as DatoCMS.

Thanks for reading! We hope that you found this article helpful. Feel free to reach out to us on Twitter with any questions, comments, or suggestions.

Start using DatoCMS today
According to Gartner 89% of companies plan to compete primarily on the basis of customer experience this year. Don't get caught unprepared.
  • No credit card
  • Easy setup
Subscribe to our newsletter! 📥
One update per month. All the latest news and sneak peeks directly in your inbox.
support@datocms.com ©2024 Dato srl, all rights reserved P.IVA 06969620480