DEV Community

Cover image for Build a Landing Page using Strapi and Vanilla HTML
Mark Munyaka
Mark Munyaka

Posted on

Build a Landing Page using Strapi and Vanilla HTML

This tutorial shows you how to build a professional landing page with HTML, CSS, and JavaScript, connected to a Strapi backend for contact form submissions. You'll deploy the frontend to Cloudflare Pages and the backend to Strapi Cloud.

Prerequisites

  • Node.js (LTS v20 or v22) installed on your local machine.
  • GitHub/GitLab/Google Account to create a Strapi Cloud Account

Create a Strapi project locally

Open your working directory in a terminal and run the following command to create a Strapi project:

npx create-strapi-app@latest backend
Enter fullscreen mode Exit fullscreen mode

Answer the prompts as follows:

- Ok to proceed? y
Enter fullscreen mode Exit fullscreen mode

When prompted, select Login/Sign up, then copy the redirect URL and open it in your browser.

Ensure the confirmation code in your browser matches the one in your terminal, then click Confirm. Complete the login process, then return to your terminal.

Continue with the following responses:

? Do you want to use the default database (sqlite) ? Yes
? Start with an example structure & data? No
? Start with Typescript? No
? Install dependencies with npm? Yes
? Initialize a git repository? No
Enter fullscreen mode Exit fullscreen mode

Change into the new Strapi project directory named backend:

cd backend
Enter fullscreen mode Exit fullscreen mode

Register an Admin User

Start your Strapi server.

npm run develop
Enter fullscreen mode Exit fullscreen mode

Visit localhost:1337/admin in your browser and create an admin user.
Register an admin

After logging in, you’ll see the dashboard.
Strapi Dashboard

Create a Contact collection type

Click Content-Type Builder and create a new collection called Contact.
Create Contacts collection

Click + Add new field and add the following fields to your Contact collection:

  • Name: text field(short)
  • Email: email field
  • Message: text field(long) Contacts collection with fields

Click Save and wait for your Strapi server to restart.

Deploy to Strapi Cloud

Deploy your project for free to Strapi Cloud. First stop your Strapi server by pressing CTRL + C keyboard combo.

Run the following command in your Strapi project folder, backend:

npm run strapi deploy
Enter fullscreen mode Exit fullscreen mode

Give your project a name, choose a NodeJS version and select the region closest to you.

? How would you like to name your project? biz-landing
? Choose your NodeJS version 22 (recommended)
? Choose a region for your project United States (East)
Enter fullscreen mode Exit fullscreen mode

Once your project is deployed you will receive a clickable link that starts with https://cloud.strapi.io/projects. Copy the link and visit it in your browser.

You will see the Strapi Cloud project we have just created, biz-landing in the Strapi Cloud Dashboard.

Strapi Cloud Dashboard

Click the project link to access the Strapi Cloud project page.

Strapi Cloud deployed project

Click the Visit app button in the top right corner to access your deployed Strapi project.

Add API Permissions

Register an admin user then log in to the admin panel of your new Strapi cloud hosted instance. In the new page that opens, complete the form to create the first administrator user of this Strapi Cloud project.

Visit the Settings page then select Roles under Users & Permissions Plugin.

Public Role: Users & Permissions Plugin

Select Public role. Click Permissions tab and select Contact.

Enable the create permission for your Contact collection.
Create permissions for Contact collection

Click Save.

Test the API

In your terminal run the following command to create a new Contact

curl -X POST \
  https://your-strapi-cloud-url.com/api/contacts \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "Name": "John Doe",
      "Email": "john@example.com",
      "Message": "This is a test message"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Replace https://your-strapi-cloud-url.com with your own Strapi Cloud project URL.

You should see a JSON response similar to this:

{
    "data": {
        "id": 1,
        "documentId": "ghn77cyweudup0o1wtpcr8ku",
        "Name": "John Doe",
        "Email": "john@example.com",
        "Message": "This is a test message",
        "createdAt": "2025-07-03T08:42:44.306Z",
        "updatedAt": "2025-07-03T08:42:44.306Z",
        "publishedAt": "2025-07-03T08:42:44.289Z"
    },
    "meta": {}
}
Enter fullscreen mode Exit fullscreen mode

Verify that the contact was saved by checking your Strapi Admin Panel. Visit the Content Manager section and click Collection types then Contacts then view the entries.

Contact entry in Content Manager

Create Contact Form

In your local machine, open your terminal and navigate one directory above your Strapi project folder:

cd ..
Enter fullscreen mode Exit fullscreen mode

Create a new folder called frontend to store your landing page files.

mkdir frontend
Enter fullscreen mode Exit fullscreen mode

Open up the frontend folder in your terminal.

cd frontend
Enter fullscreen mode Exit fullscreen mode

Add an index.html file to your frontend folder.

touch index.html
Enter fullscreen mode Exit fullscreen mode

Add the following code to your index.html file:

<form class="contact-form" id="contactForm">
  <input type="text" id="name" name="name" placeholder="Your Name" required>
  <input type="email" id="email" name="email" placeholder="Your Email" required>
  <textarea id="message" name="message" placeholder="Your Message" rows="5" required></textarea>
  <button type="submit">Send Message</button>
</form>

<script>
document.getElementById('contactForm').addEventListener('submit', async function(e) {
  e.preventDefault();

  const formData = {
    data: {
      Name: document.getElementById('name').value,
      Email: document.getElementById('email').value,
      Message: document.getElementById('message').value
    }
  };

  try {
    const response = await fetch('https://your-strapi-cloud-url.com/api/contacts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(formData)
    });

    if (response.ok) {
      alert('Message sent successfully!');
      document.getElementById('contactForm').reset();
    } else {
      alert('Error sending message. Please try again.');
    }
  } catch (error) {
    alert('Error sending message. Please try again.');
  }
});
</script>
Enter fullscreen mode Exit fullscreen mode

This Contact form will send form data to your Strapi API upon submission. Remember to replace https://your-strapi-cloud-url.com with your actual Strapi Cloud URL.

Open the page in your browser and test the form to see if it submits a contact
Contact form in browser

Deploy Contact Form to Cloudflare Pages

Install Wrangler CLI:

npm install -g wrangler
Enter fullscreen mode Exit fullscreen mode

Authenticate with Cloudflare:

wrangler login
Enter fullscreen mode Exit fullscreen mode

Make sure you are inside the frontend folder and run this to deploy to Cloudflare Pages:

wrangler pages deploy . --project-name=biz-landing
Enter fullscreen mode Exit fullscreen mode

After deployment, you will receive a Cloudflare Pages URL for your project, visit it in your browser.
Cloudflare Pages Contact form in browser

Test the form to see if it submits a contact.
Successful submission of contact form Cloudflare deployment

Of course you can verify the entry in your Strapi Admin as well

Create Full Landing Page

The contact form works, next create the full landing page.

We've built a sample business landing property development website for "Landho" a fictional company that includes:

  • Responsive design with mobile navigation
  • Hero section and 6 key services (Residential, Commercial, Project Management, Investment, Land Acquisition, Consulting)
  • About section, functional contact form with Strapi API integration, and Google Maps

The website is designed as an example to convert visitors into leads through the strategically placed contact form that automatically sends inquiries to your Strapi backend for processing.

Update your index.html file with the following code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Landho - Property Developers</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: Arial, sans-serif;
            background-color: white;
            color: black;
        }

        .navbar {
            background-color: black;
            padding: 0;
            position: fixed;
            top: 0;
            width: 100%;
            z-index: 1000;
        }

        .nav-container {
            max-width: 1200px;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0 20px;
            height: 60px;
        }

        .logo {
            color: white;
            font-size: 24px;
            font-weight: normal;
            text-decoration: none;
        }

        .nav-menu {
            display: flex;
            list-style: none;
            align-items: center;
        }

        .nav-item {
            margin: 0;
        }

        .nav-link {
            color: white;
            text-decoration: none;
            padding: 20px 18px;
            display: block;
            font-size: 16px;
            font-weight: normal;
        }

        .nav-link.active {
            background-color: white;
            color: black;
        }

        .menu-toggle {
            background: none;
            color: white;
            font-size: 16px;
            cursor: pointer;
            padding: 10px;
            font-family: Arial, sans-serif;
        }

        .dropdown-menu {
            position: absolute;
            top: 60px;
            right: 20px;
            background-color: black;
            min-width: 200px;
            display: none;
        }

        .dropdown-menu.active {
            display: block;
        }

        .dropdown-item {
            color: white;
            text-decoration: none;
            padding: 15px 20px;
            display: block;
            font-size: 16px;
            font-weight: normal;
        }

        .dropdown-item.active {
            background-color: white;
            color: black;
        }

        .content {
            margin-top: 60px;
        }

        .hero {
            padding: 60px 20px;
            max-width: 1200px;
            margin: 0 auto;
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
            align-items: center;
        }

        .hero-image {
            width: 100%;
            height: 400px;
            background-color: black;
        }

        .hero-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .hero-text h1 {
            font-size: 48px;
            color: black;
            margin-bottom: 20px;
            font-weight: normal;
        }

        .hero-text p {
            font-size: 18px;
            color: black;
            line-height: 1.6;
            margin-bottom: 30px;
        }

        .hero-cta {
            background-color: black;
            color: white;
            padding: 15px 30px;
            text-decoration: none;
            font-size: 16px;
            display: inline-block;
        }

        .services-section {
            padding: 60px 20px;
            max-width: 1200px;
            margin: 0 auto;
        }

        .services-section h2 {
            font-size: 36px;
            color: black;
            margin-bottom: 40px;
            font-weight: normal;
            text-align: center;
        }

        .services-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 30px;
        }

        .service-card {
            background-color: white;
            text-align: center;
        }

        .service-image {
            width: 100%;
            height: 200px;
            background-color: black;
            margin-bottom: 15px;
        }

        .service-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .service-name {
            font-size: 18px;
            color: black;
            margin-bottom: 10px;
            font-weight: normal;
        }

        .service-description {
            font-size: 14px;
            color: black;
            margin-bottom: 15px;
            font-weight: normal;
            line-height: 1.4;
        }

        .service-cta {
            background-color: black;
            color: white;
            padding: 10px 20px;
            text-decoration: none;
            font-size: 16px;
            display: inline-block;
        }

        @media (max-width: 768px) {
            .nav-menu {
                display: none;
            }

            .hero {
                grid-template-columns: 1fr;
                gap: 30px;
            }

            .hero-text h1 {
                font-size: 36px;
            }

            .services-grid {
                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                gap: 20px;
            }
        }

        @media (min-width: 769px) {
            .dropdown-menu {
                right: 100px;
            }
        }

        .about-section {
            padding: 60px 20px;
            max-width: 1200px;
            margin: 0 auto;
        }

        .about-section h2 {
            font-size: 36px;
            color: black;
            margin-bottom: 40px;
            font-weight: normal;
            text-align: center;
        }

        .about-content {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
            align-items: center;
        }

        .about-text h3 {
            font-size: 24px;
            color: black;
            margin-bottom: 20px;
            font-weight: normal;
        }

        .about-text p {
            font-size: 16px;
            color: black;
            line-height: 1.6;
            margin-bottom: 20px;
        }

        .about-image {
            width: 100%;
            height: 400px;
            background-color: black;
        }

        .about-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .contact-section {
            padding: 60px 20px;
            max-width: 1200px;
            margin: 0 auto;
        }

        .contact-section h2 {
            font-size: 36px;
            color: black;
            margin-bottom: 40px;
            font-weight: normal;
            text-align: center;
        }

        .contact-content {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
        }

        .contact-form {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }

        .contact-form input,
        .contact-form textarea {
            padding: 15px;
            font-size: 16px;
            font-family: Arial, sans-serif;
            background-color: white;
            color: black;
            border: 1px solid black;
        }

        .contact-form button {
            padding: 15px;
            font-size: 16px;
            font-family: Arial, sans-serif;
            background-color: black;
            color: white;
            cursor: pointer;
        }

        .map-container {
            width: 100%;
            height: 200px;
            margin-bottom: 20px;
        }

        .contact-details h3 {
            font-size: 20px;
            color: black;
            margin-bottom: 15px;
            font-weight: normal;
        }

        .contact-details p {
            font-size: 16px;
            color: black;
            margin-bottom: 8px;
        }

        .footer {
            background-color: black;
            padding: 30px 20px;
            text-align: center;
        }

        .footer-content {
            max-width: 1200px;
            margin: 0 auto;
        }

        .footer-content p {
            color: white;
            font-size: 16px;
            font-weight: normal;
        }

        @media (max-width: 768px) {
            .nav-menu {
                display: none;
            }

            .hero {
                grid-template-columns: 1fr;
                gap: 30px;
            }

            .hero-text h1 {
                font-size: 36px;
            }

            .services-grid {
                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
                gap: 20px;
            }

            .about-content {
                grid-template-columns: 1fr;
                gap: 30px;
            }

            .contact-content {
                grid-template-columns: 1fr;
                gap: 30px;
            }
        }
    </style>

</head>

<body>
    <nav class="navbar">
        <div class="nav-container">
            <a href="#" class="logo">Landho</a>

            <ul class="nav-menu">
                <li class="nav-item">
                    <a href="#" class="nav-link active">Home</a>
                </li>
                <li class="nav-item">
                    <a href="#" class="nav-link">Services</a>
                </li>
                <li class="nav-item">
                    <a href="#" class="nav-link">Properties</a>
                </li>
                <li class="nav-item">
                    <a href="#" class="nav-link">Contact</a>
                </li>
            </ul>

            <button class="menu-toggle">Menu</button>

            <div class="dropdown-menu">
                <a href="#" class="dropdown-item active">Home</a>
                <a href="#" class="dropdown-item">Services</a>
                <a href="#" class="dropdown-item">Properties</a>
                <a href="#" class="dropdown-item">Contact</a>
            </div>
        </div>
    </nav>

    <div class="content">
        <section class="hero">
            <div class="hero-image">
                <img src="https://images.unsplash.com/photo-1560518883-ce09059eeffa?w=600&h=400&fit=crop"
                    alt="Modern property development">
            </div>
            <div class="hero-text">
                <h1>Premium Property Development Solutions</h1>
                <p>Landho is your trusted partner for exceptional property development projects. From residential estates to commercial complexes, we deliver innovative solutions that exceed expectations. Whether you're looking to invest or develop, we have the expertise to bring your vision to life.</p>
                <a href="#" class="hero-cta">View Projects</a>
            </div>
        </section>

        <section class="services-section">
            <h2>Our Services</h2>
            <div class="services-grid">
                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1560518883-ce09059eeffa?w=280&h=200&fit=crop"
                            alt="Residential Development">
                    </div>
                    <div class="service-name">Residential Development</div>
                    <div class="service-description">Complete residential development services from planning to completion</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>

                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=280&h=200&fit=crop"
                            alt="Commercial Development">
                    </div>
                    <div class="service-name">Commercial Development</div>
                    <div class="service-description">Modern office buildings and retail spaces designed for success</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>

                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1503387762-592deb58ef4e?w=280&h=200&fit=crop"
                            alt="Project Management">
                    </div>
                    <div class="service-name">Project Management</div>
                    <div class="service-description">End-to-end project management ensuring timely and quality delivery</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>

                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1581091226825-a6a2a5aee158?w=280&h=200&fit=crop"
                            alt="Property Investment">
                    </div>
                    <div class="service-name">Property Investment</div>
                    <div class="service-description">Strategic investment opportunities in prime locations</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>

                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1541888946425-d81bb19240f5?w=280&h=200&fit=crop"
                            alt="Land Acquisition">
                    </div>
                    <div class="service-name">Land Acquisition</div>
                    <div class="service-description">Expert guidance in identifying and acquiring prime development land</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>

                <div class="service-card">
                    <div class="service-image">
                        <img src="https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?w=280&h=200&fit=crop"
                            alt="Consulting Services">
                    </div>
                    <div class="service-name">Consulting Services</div>
                    <div class="service-description">Professional consulting for property development and investment decisions</div>
                    <a href="#" class="service-cta">Learn More</a>
                </div>
            </div>
        </section>

        <section class="about-section">
            <h2>About Us</h2>
            <div class="about-content">
                <div class="about-text">
                    <h3>Over 25 Years of Property Development Excellence</h3>
                    <p>Landho has been transforming landscapes and communities since 1998, delivering exceptional property development projects across the region. Our commitment to innovation, quality, and sustainable development has made us the preferred choice for investors and homeowners alike.</p>
                    <p>We specialize in creating comprehensive property solutions that meet the evolving needs of modern living and business. Our experienced team combines architectural expertise with market insight to deliver projects that stand the test of time.</p>
                    <p>From luxury residential estates to cutting-edge commercial developments, Landho is your trusted partner in creating spaces that inspire and endure. Discover why we are the leading property development company in the region.</p>
                </div>
                <div class="about-image">
                    <img src="https://images.unsplash.com/photo-1554469384-e58fac16e23a?w=600&h=400&fit=crop" alt="Property development team">
                </div>
            </div>
        </section>

        <section class="contact-section">
            <h2>Contact Us</h2>
            <div class="contact-content">
                <div class="contact-form-container">
                    <form class="contact-form" id="contactForm">
                        <input type="text" id="name" name="name" placeholder="Your Name" required>
                        <input type="email" id="email" name="email" placeholder="Your Email" required>
                        <textarea id="message" name="message" placeholder="Your Message" rows="5" required></textarea>
                        <button type="submit">Send Message</button>
                    </form>
                </div>
                <div class="contact-info-container">
                    <div class="map-container">
                        <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3048.4037!2d28.3473!3d-15.3875!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x0!2zMTXCsDIzJzE1LjAiUyAyOMKwMjAnNTAuMyJF!5e0!3m2!1sen!2szm!4v1625000000000!5m2!1sen!2szm" width="100%" height="200" style="border:0;" allowfullscreen="" loading="lazy"></iframe>
                    </div>
                    <div class="contact-details">
                        <h3>Visit Our Office</h3>
                        <p>123 Main Street</p>
                        <p>Lusaka, Zambia</p>
                        <p>Phone: +260 123 456 789</p>
                        <p>Email: info@landho.com</p>
                        <p>Hours: Mon-Fri 8AM-5PM</p>
                    </div>
                </div>
            </div>
        </section>
    </div>

    <footer class="footer">
        <div class="footer-content">
            <p>© 2025 Landho Property Developers. All rights reserved.</p>
        </div>
    </footer>

    <script>
        const menuToggle = document.querySelector('.menu-toggle');
        const dropdownMenu = document.querySelector('.dropdown-menu');

        menuToggle.addEventListener('click', () => {
            dropdownMenu.classList.toggle('active');
        });

        document.addEventListener('click', (e) => {
            if (!menuToggle.contains(e.target) && !dropdownMenu.contains(e.target)) {
                dropdownMenu.classList.remove('active');
            }
        });

        document.querySelectorAll('.nav-link, .dropdown-item').forEach(link => {
            link.addEventListener('click', (e) => {
                e.preventDefault();

                document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active'));
                document.querySelectorAll('.dropdown-item').forEach(l => l.classList.remove('active'));

                const linkText = link.textContent;
                document.querySelectorAll('.nav-link, .dropdown-item').forEach(l => {
                    if (l.textContent === linkText) {
                        l.classList.add('active');
                    }
                });

                dropdownMenu.classList.remove('active');
            });
        });

        // Contact form functionality
        document.getElementById('contactForm').addEventListener('submit', async function(e) {
            e.preventDefault();

            const formData = {
                data: {
                    Name: document.getElementById('name').value,
                    Email: document.getElementById('email').value,
                    Message: document.getElementById('message').value
                }
            };

            try {
                const response = await fetch('https://your-strapi-cloud-url.com/api/contacts', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(formData)
                });

                if (response.ok) {
                    alert('Message sent successfully! We will get back to you soon.');
                    document.getElementById('contactForm').reset();
                } else {
                    alert('Error sending message. Please try again or contact us directly.');
                }
            } catch (error) {
                alert('Error sending message. Please try again or contact us directly.');
            }
        });
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

View it in your browser and test the contact form again if you wish.
Updated local landing page

Deploy Full Landing Page

Deploy it to Cloudflare Pages

wrangler pages deploy . --project-name=biz-landing
Enter fullscreen mode Exit fullscreen mode

Visit the your Cloudflare Pages URL to view your updated landing page and confirm that the contact form still works.
Cloudflare Deploy Update

Conclusion

You've built a complete landing page with Strapi backend and deployed it to Cloudflare Pages. The contact form automatically saves submissions to your Strapi Cloud database, giving you a professional lead capture system ready for production use.

GitHub Repo for Article Source Code

Top comments (0)