Store landing-page leads without a backend server in Next.js

Amarachi Iheanacho - May 24 '22 - - Dev Community

Lead generation landing pages help facilitate the user acquisition process and are usually created to collect a user’s personal information. With this information, a brand can decide to send resources or figure out their prospective customer’s demographic. Lead generation landing pages establish the initial contact point between our brand and a prospective customer.

What we will be building

This post will discuss creating a landing page to collect and store a user’s contact information in a Next.js application. This application does not require a custom backend server.

GitHub URL

https://github.com/Iheanacho-ai/appwrite-email-leads

Prerequisites

To get the most out of this project, we require the following:

  • A basic understanding of CSS, JavaScript, and React.js
  • Docker Desktop is installed on the computer, run the docker -v command to verify if we have docker desktop installed, if not, install it from here
  • An Appwrite instance running on our computer, check out the this article to create a local Appwrite instance, we will use Appwrite’s powerful database service to handle storing email leads

Setting up our Next.js app

Next.js is an open-source React framework that enables us to build server-side rendered static web applications.

To create our Next.js app, we navigate to our preferred directory and run the terminal command below:

    npx create-next-app@latest
    # or
    yarn create next-app
Enter fullscreen mode Exit fullscreen mode

After creating our app, we change the directory to the project and start a development server with:

    cd <name of our project>
    npm run dev
Enter fullscreen mode Exit fullscreen mode

To see our app, we go to http://localhost:3000.

Installing Appwrite

Appwrite is an open-source, end-to-end, back-end server solution that allows developers to build applications faster.

To use Appwrite in our Next.js application, we install the Appwrite client-side SDK for web applications.

    npm install appwrite
Enter fullscreen mode Exit fullscreen mode

Creating a new Appwrite project

During the creation of the Appwrite instance, we specified what hostname and port we see our console. The default value is localhost:80.

We go to localhost:80 and create a new account to see our console.

On our console, there is a Create Project button. Click on it to start a new project.

Image upload

Our project dashboard appears once we have created the project. At the top of the page, there is a Settings bar. Click the Settings bar to access the Project ID and API Endpoint.

Image upload

We copy the Project ID and API Endpoint, which we need to initialize the Appwrite Web SDK.

Image upload

In our index.js file, we initialize a new Appwrite instance with the following.

    import {Appwrite} from "appwrite";
    import {useEffect, useState } from "react";

    const Home = () => {

        // Init our Web SDK
        const sdk = new Appwrite();
        sdk
        .setEndpoint('http://localhost/v1') // our API Endpoint
        .setProject(projectID) // our project ID
        ;

        return(
          <div>Hello World!</div>
        )
    }

    export default Home;
Enter fullscreen mode Exit fullscreen mode

Creating the collection and attributes

In the Appwrite web Console, we click on Database on the left side of the dashboard.

Image upload

We create a collection in the database tab by clicking on the Add Collection button. This action redirects us to a Permissions page.

At the Collection Level, we want to assign a Read Access and Write Access with a role:all value. We can modify these permissions later to control who has access to read or write to our database.

Image upload

On the right of the Permissions page, we copy the Collection ID, which we need to perform operations on the collection’s documents.

Next, we go to the Attributes tab to create the properties we want a document to have.

Image Upload

We create an email attribute of emailAddress.

Image upload

Creating our Landing page

In our index.js file, we create our landing page. This page consists of an input element that will allow users to input their email addresses to be stored in the database.

    import {Appwrite} from "appwrite";
    import {useEffect, useState } from "react";

    const Home = () => {

        // Init our Web SDK
        const sdk = new Appwrite();
        sdk
        .setEndpoint('http://localhost/v1') // our API Endpoint
        .setProject(projectID) // our project ID
        ;

          return(
            <div className="home">
              <div className="title-container">
                  <h2>Orange Music</h2>
                  <p>Input your email address to get updates when we launch!</p>
                  <input 
                  type="text" 
                  />
                  <button type="button">Add email address</button>
              </div>
            </div>
      )
    }

    export default Home;
Enter fullscreen mode Exit fullscreen mode

NOTE: We use a button with a type= button to override the button’s default submit behavior.

In our global.css file, we add these CSS styles to our landing page.

    body{
        margin: 0;
        padding: 0;
    }

    .home{
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        background-image: url('https://res.cloudinary.com/amarachi-2812/image/upload/v1649445450/music-banner_zveuix.jpg');
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
    }

    .title-container h2{
        color: #fff;
        font-size: 32px;
    }

    .title-container p{
        color: rgba(255, 255, 255, 0.815);
        font-size: 18px;

    }

    .title-container input{
        outline: none;
        height: 30px;
        width: 250px;

    }

    .title-container button{
        height: 35px;
        background-color: #111;
        color: #fff;
        border: 1px solid #111;

    }
Enter fullscreen mode Exit fullscreen mode

We can use any image link for our background image. However, in this tutorial, we use an image stored on Cloudinary because it is easier to apply transformations and optimize delivery.
To understand how to upload images to Cloudinary, check out the Cloudinary documentation.

Here is our landing page:

Image upload

Adding input interaction with the database

Appwrite has a safety policy that insists we sign in to use the Appwrite features like Database and Functions. However, Appwrite allows us to work around that policy for simple projects like this by creating anonymous user sessions.

We create an anonymous user session in our index.js file once our application mounts using Appwrite's createAnonymousSession method.

    import {Appwrite} from "appwrite";
    import {useEffect, useState } from "react";

    const Home = () => {

        // Init our Web SDK
        const sdk = new Appwrite();
        sdk
        .setEndpoint('http://localhost/v1') // our API Endpoint
        .setProject(projectID) // our project ID
        ;

        //creating an anonymous Session

        const createAnonymousSession = async() => {
          try{
            await sdk.account.createAnonymousSession();
          }catch(err){
            console.log(err)
          }

        }
        useEffect(()=> {
          createAnonymousSession()
        }, [])

        return(
          <div className="home">
            <div className="title-container">
              <h2>Orange Music</h2>
              <p>Input your email address to get updates when we launch!</p>
              <input 
              type="text" 
              />
              <button type="button">Add email address</button>
            </div>
          </div>
      )
    }

    export default Home;
Enter fullscreen mode Exit fullscreen mode

Next, in our index.js file, we create a state variable using React useState hook to hold the value of our email address input form.

    // email state 
    const [emailAddress, setEmailAddress] = useState()
Enter fullscreen mode Exit fullscreen mode

We then create a handleEmailAddress function in our index.js file to save the email addresses to the Appwrite database.

    // handle email submission
    const handleEmailAddress = async () => {
      try {
        await sdk.database.createDocument(collectionID, 'unique()',{
          "emailAddress": emailAddress
        } )
        setEmailAddress('');
        alert("Email saved successfully!")
      } catch (error) {
        console.log(error)

      }
    }
Enter fullscreen mode Exit fullscreen mode

In the code block above, the handleEmailAddress function does the following:

  • Creates a new document in the database using Appwrite’s createDocument function, this function receives the collection ID we saved from the Permissions page, a unique() parameter that specifies that we want a dynamically created document ID, and attributes values as parameters
  • Alerts us when we have successfully saved the document and then clears out the information in our emailAddress state variable
  • Logs any error we encountered to our console

Next, we pass our state variable as a value to our input element and our handleEmailAddress function to our button's onClick event listener.

    <div className="home">
      <div className="title-container">
        <h2>Orange Music</h2>
        <p>Input your email address to get updates when we launch!</p>
        <input 
        type="text" 
        value={emailAddress}
        onChange= {(e) => setEmailAddress(e.target.value)}
        />
        <button type="button" onClick={handleEmailAddress}>Add email address</button>
      </div>
    </div>
Enter fullscreen mode Exit fullscreen mode

Here is how our index.js file looks.

https://gist.github.com/Iheanacho-ai/c0b17efee282f5e2b280ac53fb2e8218

Image upload

Please input an email address to see it saved on the database.

Image upload

Conclusion

This article discussed using Appwrite to create data on the database. We created a simple lead generation page in a Next.js application.

Resources

Here are some resources that might be helpful:

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .