How to Quickly Build and Add Landing Pages to a React Native App Using ButterCMS
Posted by Eze Nnaemeka on January 4, 2023
GSD
A landing page is a single web page designed to achieve a single goal: conversion. It's an excellent form of marketing that may also be utilized for advertising purposes. This page may result from clicking on a search engine-optimized result, an email marketing campaign, a social media campaign, or an online advertisement. The landing page can help you generate leads, reach your ideal customers, and guide your marketing strategy's general path.
Table of contents
Why use React Native?
React Native is a robust and well-known JavaScript-based framework for mobile development that allows you to build native mobile applications for Android and iOS. In addition, it lets you build applications for different platforms using a single code base.
Facebook originally published React Native as an open-source project in 2015, and it quickly grew in popularity as one of the major frameworks for mobile development. Some of the world's most popular mobile apps, such as Instagram, Facebook, and Skype, are built with React Native.
Features of React Native include:
Live reload: React Native has an intriguing extra feature not present in other native frameworks—the live reload function, which allows you to immediately see the effect of the most recent adjustment you have made to the code.
Third-party library support: Node Package Manager (NPM) is used to install React Native, and it is pretty simple to use. Most JavaScript programmers are familiar with NPM, and it's easy for beginners to understand NPM commands. The third-party library provides native app functionality that is not accessible in React Native. According to the React Native documentation, there are several functionalities that are not accessible (such as maps). As a result, we must incorporate third-party libraries into our project.
Code reusability: React Native uses JavaScript, which is commonly known as one of the most well-known and high-level interpreted programming languages. It is simpler to read and debug in comparison with other languages like Java or Swift. In addition, JavaScript enables code reuse, which speeds up app development. React Native's modular nature makes the code easier to comprehend and maintain. Developers can now share similar code across platforms with little effort and expense, saving time and money on mobile app development.
User interface improvements: React Native's JSX lets you create user interfaces with JavaScript. It allows you to develop a highly interactive UI for your app while avoiding platform requirements. It's important because user interfaces in React are built using declarative programming, which reduces coding errors and makes it very easy to discover where things go wrong when they do.
Why use ButterCMS?
ButterCMS is a headless content management system (CMS) that enables rapid development and offers a variety of features, such as custom page types, a built-in blog engine, relational content modeling webhooks, and built-in SEO. It lets marketers quickly generate SEO landing pages, client case studies, and other material.
A few more notable features of ButterCMS include:
- SEO built-in: ButterCMS has built-in search engine optimization that assists in optimizing web pages for search engines.
- Collections: ButterCMS has a collection feature that lets users add pieces of information stored in one instance to multiple pages. Collections enable the use of reusable content that can be updated from a single source of truth.
- Content types: ButterCMS manages all content types (collections, components, pages) from a single dashboard. From this dashboard, you can configure whatever content your application needs. It also helps solve CMS problems faster with the help of its intuitive content modeling and simple-to-integrate content API.
- Scheduled content releases: ButterCMS also offers a feature that allows you to schedule when your content will be live.
Tutorial prerequisites
To follow this tutorial, ensure you have the following:
- Basic knowledge of React Native.
- React Native set up on your device.
- An Android and iOS simulator to test the application. You can learn more about setting up a simulator for React Native here.
- A code editor for writing and editing our code, I recommend VS Code.
The code for this tutorial can be found in this GitHub repo.
Tutorial: Build & Add Landing Pages to a React Native Application
In this tutorial, we'll build a landing page that contains several different sections with React Native. Here's a GIF showing what we'll build in this tutorial:
npx create-expo-app buttercms-landing-page
cd buttercms-landing-page
After this, we can start the development server with the npm command.
npm start
React Native follows a component-based design similar to React, whereby the user interface is separated into multiple sections called components. For our landing page, we will create multiple components, such as a Navbar.jsx
and Footer.jsx
.
In the root folder of our app, let's create a folder called Components and create the following files: Announcement.jsx
, Contact.jsx
, CTA.jsx
, Footer.jsx
, Navbar.jsx
, Terms.jsx
, and Wishlist.jsx
:
Setting up our React Native application
Let's also create a fundamental React Native functional component in all the files we created, return a View component imported from the React Native library, and render them by modifying our App.js
:
import { View, Text } from "react-native";
const Navbar = () => {
return (
<View>
<Text> Navbar </Text>
</View>
);
};
export default Navbar;
More modifying of our App.js
file:
import { StatusBar } from "expo-status-bar";
import { StyleSheet, View, SafeAreaView, ScrollView } from "react-native";
import CTA from "./Components/CTA";
import Navbar from "./Components/Navbar";
import Terms from "./Components/Terms";
import Wishlist from "./Components/Wishlist";
import Announcement from "./Components/Announcement";
import Contact from "./Components/Contact";
import Footer from "./Components/Footer";
export default function App() {
return (
<View >
<StatusBar style="auto" />
<SafeAreaView>
<ScrollView>
<Navbar />
<CTA />
<Terms/>
<Wishlist/>
<Announcement/>
<Contact/>
<Footer/>
</ScrollView>
</SafeAreaView>
</View>
)}
Creating the navigation bar
To create the navigation bar, let's add the following code to our Navbar.jsx
. In this tutorial, we will be styling our React Native application using the StyleSheet component, which we'll import from the React Native library.
import React from "react";
import { View, StyleSheet, Image } from "react-native";
import logo from "../assets/logo.png";
const Navbar = () => {
return (
<View style={styles.nav_container}>
<Image source={logo} />
</View>
);
};
export default Navbar;
const styles = StyleSheet.create({
nav_container: {
width: "100%",
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 20,
},
});
Navbar.jsx
Adding the CTA section
A call to action (CTA) is a marketing word that refers to the next step a marketer wishes their audience or reader to take. Our landing page's CTA section is a statement to the visitor to persuade them to take action by downloading our application.
To create the CTA section, let's add the following code to our CTA.jsx
file:
import React from "react";
import { View, StyleSheet, Text, Image } from "react-native";
import Apple from "../assets/apple.png";
import google from "../assets/google.png";
const CTA = () => {
return (
<View style={styles.container}>
<View style={{ alignItems: "center" }}>
<Text style={styles.buyText}>Buy from independent,</Text>
<Text style={styles.smallText}>small businesses</Text>
<Text style={styles.terms}>Shop on your terms </Text>
</View>
<View
style={{
marginTop: 20,
width: "80%",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<View style={styles.button_container}>
<Image source={Apple} />
<View style={{ marginLeft: 5 }}>
<Text style={styles.download}>Download on the</Text>
<Text style={styles.appStore}>AppStore</Text>
</View>
</View>
<View style={styles.button_container}>
<Image source={google} style={styles.googleImage} />
<View style={{ marginLeft: 5 }}>
<Text style={styles.download}>Get it on</Text>
<Text style={styles.appStore}>Google Play</Text>
</View>
</View>
</View>
</View>
);
};
export default CTA;
const styles = StyleSheet.create({
container: {
backgroundColor: "black",
width: "100%",
height: 300,
marginTop: 40,
alignItems: "center",
justifyContent: "center",
},
buyText: {
color: "#fff",
fontSize: 25,
letterSpacing: "1",
},
smallText: {
color: "#ED4A66",
fontSize: 25,
letterSpacing: "1rem",
marginTop: 8,
},
terms: {
color: "#fff",
marginTop: 8,
fontSize: 18,
},
button_container: {
borderWidth: "1",
borderColor: "#fff",
flexDirection: "row",
borderRadius: 5,
padding: 5,
alignItems: "center",
},
download: {
color: "#fff",
},
appStore: {
color: "#fff",
fontSize: 20,
fontWeight: "600",
},
googleImage: {
width: 20,
height: 20,
},
});
CTA.jsx
In our CTA section, the above code will yield the following result:
Adding an image
Landing page images significantly boost the efficacy of your landing page. The eye is drawn to images. These are the elements that your visitors initially notice when they visit your landing page and scan the website. Images can quickly answer your prospects' initial question: "Am I at the correct spot to find what I'm searching for?" Images always support, complement, and improve a landing page.
To add an image in React Native, we usually import the Image component from the React Native library. We will be rendering the Image component directly from our App.js
file:
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, SafeAreaView, Image, ScrollView } from "react-native";
import CTA from "./Components/CTA";
import Navbar from "./Components/Navbar";
import shop from "./assets/shop.png"
export default function App() {
return (
<View style={styles.container}>
<StatusBar style="auto" />
<SafeAreaView>
<ScrollView>
<Navbar />
<CTA />
<Image source={shop} style={{width:"100%"}}/>
</ScrollView>
</SafeAreaView>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
});
App.js
Notice that the Image components have a prop called source, which is the image source. It can either be a local file resource or a remote URL, but in our case, we imported our image from our Assets folder (a local file resource).
Here's a preview of what our landing page looks like now:
Adding the Terms section
The Terms section aims to provide a brief description of how the system works. It includes View and Text components imported from the React Native library.
Here’s a preview of what our Terms section will look like:
To achieve the following, let's add the following code to our Terms.jsx
file:
import React from "react";
import { Text, View, StyleSheet } from "react-native";
const Terms = () => {
return (
<View style={styles.container}>
<Text style={styles.terms}>SHOP ON YOUR TERMS</Text>
<View style={styles.text_container}>
<Text style={styles.text_content}>
Shop on your own terms by choosing how much you are willing to pay for
your item and if the seller agrees, voila! we have a sale.
</Text>
</View>
</View>
);
};
export default Terms;
const styles = StyleSheet.create({
container: {
width: "100%",
alignItems: "center",
marginTop: 20,
marginBottom: 20,
},
terms: {
color: "rgba(255, 0, 104, 1)",
fontSize: 20,
fontWeight: "600",
},
text_container: {
width: "70%",
marginTop: 10,
},
text_content: {
textAlign: "center",
fontSize: 15,
letterSpacing: "0.03rem",
},
});
Terms.jsx
Adding the wishlist section.
The wishlist feature on our landing page captures visitors' email addresses and sends them information about the application.
Our wishlist section contains the View, Text, and Input components imported from the React Native library. So, let's add the following code to our Wishlist.jsx
file to achieve that.
import React from "react";
import { Text, View, StyleSheet, TextInput, Button } from "react-native";
const Wishlist = () => {
return (
<View style={styles.container}>
<View style={styles.header_container}>
<Text style={styles.header_text}>Buy from Haggle</Text>
<Text style={styles.header_text}>Merchants and</Text>
<Text style={styles.header_text_last}>pay small small</Text>
</View>
<View style={styles.content_container}>
<Text style={styles.content}>
Buying is a pleasure. Be in control of your happiness; choose how much
you're willing to pay and when you will pay back.
</Text>
</View>
<View style={styles.input_container}>
<TextInput
placeholder="Input your email address"
style={styles.input}
/>
<View>
<Button title="JOIN WAITLIST" color="rgba(255, 0, 104, 1)" />
</View>
</View>
</View>
);
};
export default Wishlist;
const styles = StyleSheet.create({
container: {
width: "100%",
height: 300,
backgroundColor: "black",
alignItems: "center",
justifyContent: "center",
},
header_container: {
width: "100%",
alignItems: "center",
},
header_text: {
color: "#fff",
fontSize: 20,
fontWeight: "600",
},
header_text_last: {
color: "rgba(255, 0, 104, 1)",
fontSize: 20,
fontWeight: "600",
},
content_container: {
width: " 70%",
marginVertical: 20,
},
content: {
color: "#fff",
textAlign: "center",
},
input_container: {
width: "80%",
flexDirection: "row",
},
input: {
backgroundColor: "#fff",
width: "50%",
padding: 8,
borderRadius: 5,
},
});
Wishlist.jsx
After adding the following code to Wishlist.jsx
, here's a view of how our landing page looks:
Adding the announcement section
The announcement section gives brief news about the application.
Let's add the following code to the Announcement.jsx
file:
import React from "react";
import { Text, View, StyleSheet, Image } from "react-native";
import logo from "../assets/logo.png";
import whatsapp from "../assets/whatsapp.png";
import insta from "../assets/Insta.png";
import twitter from "../assets/twitter.png";
const Announcement = () => {
return (
<View style={styles.container}>
<View>
<Image source={logo} />
</View>
<View style={styles.content_container}>
<Text style={styles.content}>
Haggle is an omnichannel solution geared at MSMEs that addresses
issues of liquidity, operations inefficiency and purchase funnel leaks
through Buy Now, Pay Later loans to shoppers, and inventory financing
to merchants.
</Text>
</View>
<View>
<View style={styles.icon_box}>
<View style={styles.icon_container}>
<Image source={whatsapp} />
</View>
<View style={styles.icon_container}>
<Image source={insta} />
</View>
<View style={styles.icon_container}>
<Image source={twitter} />
</View>
</View>
</View>
</View>
);
};
export default Announcement;
const styles = StyleSheet.create({
container: {
paddingVertical: 20,
paddingHorizontal: 20,
},
content_container: {
marginTop: 20,
},
content: {
letterSpacing: "0.03rem",
fontSize: 15,
},
icon_container: {
backgroundColor: "#000",
width: 35,
height: 35,
alignItems: "center",
justifyContent: "center",
borderRadius: 50,
marginRight: 10,
},
icon_box: {
flexDirection: "row",
marginVertical: 15,
},
});
Announcement.jsx
Adding the contact section
Contact pages are commonly used on landing pages to allow users to contact the organization or individual providing the website. One or more of the following things can be found on this page: an email address, a phone number, or the office address.
Let's add the following code to the Contact.jsx
file:
import React, { Component } from "react";
import { Text, View, StyleSheet } from "react-native";
const Contact = () => {
return (
<View style={styles.container}>
<View>
<Text style={styles.header}>Contact Us</Text>
<View>
<Text>Primewater view Gardens 2 Off Freedom Way, Lekki Phase 1.</Text>
</View>
</View>
</View>
);
};
export default Contact;
const styles = StyleSheet.create({
container: {
paddingHorizontal: 20,
},
header: {
color: "#000",
fontWeight: "700",
fontSize: 20,
},
});
Contact.jsx
Adding the footer section
The footer contains information that helps the overall usability of our landing page. For example, it usually has a copyright notice or a privacy policy link. Finally, let's add the footer section.
import React from "react";
import { Text, View, StyleSheet } from "react-native";
const Footer = () => {
return (
<View style={styles.container}>
<Text style={styles.text_content}>
Haggle is a Registered Trademark of Souq Technologies Ltd. Copyright
2022..
</Text>
</View>
);
};
export default Footer;
const styles = StyleSheet.create({
container: {
width: "100%",
backgroundColor: "#000",
padding: 15,
marginTop: 20,
},
text_content: {
color: "#fff",
textAlign: "center",
letterSpacing: "0.03rem",
lineHeight: 20,
},
});
Footer.jsx
Creating our landing page in ButterCMS
To start building our landing page with ButterCMS, we need to head over to the ButterCMS website. Then, we need to sign up and create an account. If you already have an existing account, log in with your credentials and you will be directed to your dashboard.
Building the CTA component
Let's head to the sidebar of our dashboard, hover over Content Types, and then click on Components.
On this page, we'll find the default components, which we will delete. We will create our own custom component by following the steps below.
We'll be adding our texts as short text fields and our App Store and Google Play logos as media fields.
- Short text ⇢ independent_title
- Short text ⇢ business_text
- Short text ⇢ terms_text
- Media ⇢ appstore_logo
- Media ⇢ googleplay_logo
Then, click the Create Component button and name the component “CTA Section”.
The Image component
Now, we're done creating the CTA Section component in ButterCMS. Let's now create the Image component:
But first, let's add the fields. Our Image component is made up of just an Image, so we will add the picture as a media field in ButterCMS and save the component.
- Media ⇢ clothes_image
Then, save it as “Image Section”.
The Terms component
Just as we created other components, our Terms section has a heading which will be a short text field and other text content which will be a long text field.
- Short text ⇢ terms_heading
- Long text ⇢terms_content
The Wishlist component.
The Wishlist component contains text fields, such as:
- Short text ⇢ buy_text
- Short text ⇢ merchant_text
- Short text ⇢ small_text
- Long text ⇢ wishlist_subtitle
The Announcement component
The announcement components contain the following fields:
- Media ⇢ logo
- Long text ⇢ subtitle_text
- Media ⇢ whatsapp_logo
- Media ⇢ instagram_logo
- Media ⇢ twitter_logo
The Contact component
The Contact component contains the following fields:
- Short text ⇢ contact_header_text
- Long text ⇢ contact_text
The Footer component
The Footer component contains the following fields:
- Long text ⇢ footer_text
Building our landing page
Now, we're done creating our components in ButterCMS. Next, head to Pages and create one in our ButterCMS dashboard.
We'll create a new page by clicking on the New Page button and then clicking on Create New Page.
Here's a view of what you'll get when you create a new page:
Let's get started by adding our components:
Next, we click on Add from Library to import our components.
Next, we select the CTA Section component.
Let's repeat the previous steps and add each of the ButterCMS components we created. After we've included them all, our page should look like this:
Let's click the Save button and save the page as Home Page:
After saving the new page, we can begin adding its content.
Adding CTA section content:
Adding Image section content:
Adding Terms section content:
Adding Wishlist section content:
Adding Announcement section content:
Adding Contact section content:
Adding Footer section content:
After we're done adding the content, click on the Publish button.
Connecting our React Native App to ButterCMS
After adding the content in ButterCMS, let's head back to our code. To connect our app to ButterCMS, we require an access_Token, which can be found on the Settings page of the ButterCMS website.
We will also use Axios, a well-known library for sending asynchronous HTTP requests to REST APIs. This library comes in handy when conducting CRUD operations. You may communicate with the backend using this library. We will utilize Axios in our application to link our CMS to our application via a fetch request, which will return the content saved in our CMS.
We will use the following command to install Axios:
npm i axios
We will create a GET request in App.js to retrieve data from the CMS:
//...
import { useState, useEffect } from "react";
import axios from "axios";
export default function App() {
const [data, setData] = useState();
const access_Token = "API KEY";
useEffect(() => {
const fetchData = async () => {
await axios
.get(
`https://api.buttercms.com/v2/pages/*/home-page/?auth_token=${access_Token}`
)
.then((response) => {
setData(response.data.data.fields);
})
.catch((err) => console.error(err));
};
fetchData();
}, []);
return (
<View style={styles.container}>
<StatusBar style="auto" />
<SafeAreaView>
<ScrollView>
<Navbar />
<CTA data={data?.cta_section} />
<Image
source={{ uri: data?.image_section?.clothe_image }}
style={{ width: "100%", height: 200 }}
/>
<Terms data={data?.terms_section} />
<Wishlist data={data?.wishlist_section} />
<Announcement data={data?.announcement_section} />
<Contact data={data?.contact_section} />
<Footer data={data?.footer_section} />
</ScrollView>
</SafeAreaView>
</View>
);
}
We set up a retrieve request in the above code block that returns data from the CMS. When we perform the request, we set the value of the state data to the received result. The necessary data pieces were also supplied as props for each component. For example, we may configure the CTA component to use CMS content as follows:
//…
const CTA = ({ data }) => {
return (
<View style={styles.container}>
<View style={{ alignItems: "center" }}>
<Text style={styles.buyText}>{data?.independent_title}</Text>
<Text style={styles.smallText}>{data?.business_text}</Text>
<Text style={styles.terms}>{data?.terms_text}</Text>
</View>
<View
style={{
marginTop: 20,
width: "80%",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<View style={styles.button_container}>
<Image
source={{ uri: data?.appstore_logo }}
style={{ width: 25, height: 25 }}
/>
<View style={{ marginLeft: 5 }}>
<Text style={styles.download}>Download on the</Text>
<Text style={styles.appStore}>AppStore</Text>
</View>
</View>
<View style={styles.button_container}>
<Image
source={{ uri: data?.googleplay_logo }}
style={{ width: 25, height: 25 }}
/>
<View style={{ marginLeft: 5 }}>
<Text style={styles.download}>Get it on</Text>
<Text style={styles.appStore}>Google Play</Text>
</View>
</View>
</View>
</View>
);
};
In Terms.jsx
:
//...
const Terms = ({ data }) => {
return (
<View style={styles.container}>
<Text style={styles.terms}>{data?.terms_heading}</Text>
<View style={styles.text_container}>
<Text style={styles.text_content}>{data?.terms_content}</Text>
</View>
</View>
);
};
In Wishlist.jsx
:
//...
const Wishlist = ({ data }) => {
return (
<View style={styles.container}>
<View style={styles.header_container}>
<Text style={styles.header_text}>{data?.buy_text}</Text>
<Text style={styles.header_text}>{data?.merchant_text}</Text>
<Text style={styles.header_text_last}>{data?.small_text}</Text>
</View>
<View style={styles.content_container}>
<Text style={styles.content}>{data?.wishlist_subtitle}</Text>
</View>
<View style={styles.input_container}>
<TextInput
placeholder="Input your email address"
style={styles.input}
/>
<View>
<Button title="JOIN WAITLIST" color="rgba(255, 0, 104, 1)" />
</View>
</View>
</View>
);
};
In Announcement.jsx
:
//...
const Announcement = ({ data }) => {
return (
<View style={styles.container}>
<View>
<Image
source={{ uri: data?.logo }}
style={{ width: 200, height: 90 }}
/>
</View>
<View style={styles.content_container}>
<Text style={styles.content}>{data?.subtitle_text}</Text>
</View>
<View>
<View style={styles.icon_box}>
<View style={styles.icon_container}>
<Image
source={{ uri: data?.whatsapp_logo }}
style={styles.image_socials}
/>
</View>
<View style={styles.icon_container}>
<Image
source={{ uri: data?.instagram_logo }}
style={styles.image_socials}
/>
</View>
<View style={styles.icon_container}>
<Image
source={{ uri: data?.twitter_logo }}
style={styles.image_socials}
/>
</View>
</View>
</View>
</View>
);
};
In Contact.jsx
:
//...
const Contact = ({ data }) => {
return (
<View style={styles.container}>
<View>
<Text style={styles.header}>{data?.contact_header_text}</Text>
<View>
<Text>{data?.contact_text}</Text>
</View>
</View>
</View>
);
};
And, finally, in Footer.jsx
:
//...
const Footer = ({data}) => {
return (
<View style={styles.container}>
<Text style={styles.text_content}>
{data?.footer_text}
</Text>
</View>
);
};
Now, when we run our program in the simulator, we get the following result:
Closing thoughts
That's all there is to it! React Native has become a popular choice in the mobile app development field for a good reason, thanks to its ability to build cross-platform apps and its other intriguing features. In addition, it is a valuable framework for developers and a promising technology for enterprises. So, if you want to create a cross-platform mobile app, l strongly encourage you to consider React Native.
In this lesson, we created a landing page, organized its content in the ButterCMS dashboard, and linked it to our React Native application. Using a CMS to handle site content simplifies updating, viewing, and managing application data.
ButterCMS is the #1 rated Headless CMS
Related articles
Don’t miss a single post
Get our latest articles, stay updated!
Self-driven engineer with over 3 years of experience that places figuratively cutting-edge collaborative and team efforts. Who's currently focused on developing advanced software development and leadership skills.