On this article, we’ll stroll by means of the best way to construct an internet site that you should utilize to create new surveys, share your surveys, after which analyze the outcomes. Your web site shall be lightning quick and shall be search engine optimization pleasant, counting on all the newest options in Next.js. It is going to even be versatile and straightforward to construct due to SurveyJS, which makes working with surveys easy.

This text will assume you perceive the fundamentals of React and Next.js, however it can stroll you thru the best way to construct each part and web page of the web site. You may comply with together with the article for all of the code, or you may leap to the tip and use the example repository here. It’s also possible to check out the ultimate model of the web site that I’ve deployed for you here.

Subsequent.js is a React-based framework that helps you construct full-stack web sites solely in React. Subsequent.js handles all of the bundling and offers you highly effective APIs to resolve the best way to render every web page in order that it may be lightning quick. On this article, we’ll be sure that all our pages could be rendered at construct time. Which means that we will simply expose a sitemap that Google can use to index your web site, which is important for ensuring your search engine optimization efficiency is nice.

SurveyJS is an open-source type administration device that offers you the flexibility to create, share and analyze your surveys and types. They supply a React API that we’ll use to create a survey administration system with Subsequent.js.

Setting Up Subsequent.js

First, let’s setup our Subsequent.js software. It’s fast and straightforward to get began with Subsequent.js, as they supply a CLI device that permits you to create a primary app primarily based on the preferences you give.

To make use of the device you should be sure you have npx put in after which run the next command:

npx create-next-app@newest

When you run the create-next-app command it can ask you a sequence of questions concerning the challenge you need to create. A lot of the questions are solely primarily based on private desire, so you may reply them nevertheless you want. For this text, we’ll be utilizing pure JavaScript (moderately than Typescript) and we’ll even be using the new app router in Next.js moderately than the previous file router.

Now that you’ve got your Subsequent.js app arrange, you may run it with:

yarn run dev

It will depart you with a dev server operating that can replace any time you make modifications to your information. For now, let’s maintain this operating so we will add pages with out having to rebuild each time.

Setting Up SurveyJS

To arrange SurveyJS, we’re going to have to put in all of the totally different dependencies. We’re going to make use of all of the totally different elements of SurveyJS together with the shape creator, the shape show and the outcomes bundle, so we want to ensure to put in all of them.

To put in the packages, make certain to run the next set up command:

yarn add survey-analytics survey-core survey-creator-core survey-creator-react survey-react-ui

Setting Up the Type Creator

First, let’s begin of by including the shape creator web page. I’m going to make mine obtainable at /creator, so to do this I create a file at /creator/web page.js.

The creator doesn’t want any server-side information to render, in order that signifies that our web page part could be very easy; it simply renders our Creator part, which I’ll define later. It appears like this:

export const metadata = {
  title: "Survey Creator",
};

export default operate Web page() {
  return Creator />;
}

Within the code above, you may see that I export each the web page and a metadata object. The metadata object will then be used for the search engine optimization meta tags by Subsequent.js. For this web page, we all the time need to use the identical string, so we simply export an object.

The Creator part is the place we really use the SurveyJS API. Let’s check out the part:

"use consumer";

import { useEffect, useState } from "react";
import { SurveyCreatorComponent, SurveyCreator } from "survey-creator-react";

export default operate Creator() {
  let [creator, setCreator] = useState();

  useEffect(() => {
    const newCreator = new SurveyCreator({
      showLogicTab: true,
      showTranslationTab: true,
    });
    setCreator(newCreator);
  }, []);

  return div>{creator && SurveyCreatorComponent creator={creator} />}/div>;
}

The very first thing you’ll discover is we use the use consumer directive on this part. It is because the SurveyJS elements aren’t designed to be run as server elements. To not fear, although; they’ll nonetheless be rendered on the server first earlier than being despatched to the consumer.

The subsequent factor you’ll see is that we run a useEffect with an empty dependency array. Which means that the operate will run as soon as and create the SurveyCreator. You may see at that time we will go in any choices into the creator relying on what options we need to allow.

All we have to do is render the SurveyCreatorComponent and go it the creator object. We optionally render it in order that it doesn’t break earlier than the creator is about up.

Your dev server ought to have been reloading as you go, so when you now go to /creator, you’ll be capable of entry the creator and use all of the options like you may see within the screenshot beneath.

Create a Web page to View the Type

Subsequent we need to create a web page to view the types that we’ve constructed. When you’ve created the shape within the designer, the output shall be a JSON object that can comprise your questions and the preferences you setup as you construct the survey, together with any logic or kinds.

For our type web page, we need to use a dynamic setup in order that we will render any variety of type pages with out having to create a brand new file for each new type. We do that through the use of Subsequent.js dynamic routes. To create a dynamic route, we have to create a brand new file at /app/type/[slug]/web page.js which can give all our types a separate web page at /type/form-slug.

In our new file, we now have to create a number of capabilities to help Subsequent.js to create our pages. First, let’s begin with generateStaticParams, which we will use to inform Subsequent.js which pages we need to generate. Under you may see the contents of the operate:

export async operate generateStaticParams() {
  return surveys.map((x) => ({ slug: x.slug }));
}

For this challenge, we arrange a file that exports an inventory of surveys (which comprise a slug) and a survey (which is the thing offered by the survey designer). If we need to add a brand new survey, we simply want so as to add one other entry to our surveys array. Our generateStaticParams operate must export an inventory of slugs, which Subsequent.js will then use to render our pages at construct time. For us, that is very easy; we simply must map our survey array to suit the format:

export async operate generateMetadata({ params }) {
  const survey = surveys.discover((x) => x.slug === params.slug);

  return {
    title: survey.survey.title,
    description: survey.survey.description,
  };
}

The subsequent operate we are going to have a look at is generateMetadata. This takes within the parameters from the static params operate we simply outlined, after which it returns our title and outline, that are used for the metadata on our net web page. As you may see above, our operate finds the right survey object primarily based on the slug we’re given. Then we will use the identical title and outline that we wrote after we created our survey.

The very last thing we have to outline in our web page.js file is the React web page itself. The web page part for our type web page can also be quite simple. It finds the survey object once more, then passes it by means of to the SurveyComponent:

export default operate Web page({ params: { slug } }) {
  const survey = surveys.discover((x) => x.slug === slug);

  return (
    div>
      SurveyComponent surveyData={survey.survey} />
    /div>
  );
}

The SurveyComponent then must be outlined individually. Check out the part:

"use consumer";

import { useCallback } from "react";
import { Mannequin } from "survey-core";
import { Survey } from "survey-react-ui";

export default operate SurveyComponent({ surveyData }) {
  const mannequin = new Mannequin(surveyData);

  const alertResults = useCallback(async (sender) => {
    fetch("/api/submit", {
      technique: "POST",
      headers: {
        "Content material-Sort": "software/json;charset=UTF-8",
      },
      physique: JSON.stringify({ consequence: sender.information }),
    });
  }, []);

  mannequin.onComplete.add(alertResults);

  return Survey mannequin={mannequin} />;
}

Once more, you’ll discover that we now have the use consumer directive to ensure Subsequent.js is aware of it’s not a server part. We then create a mannequin with SurveyJS and go it into the SurveyJS Survey part. Earlier than we try this, you’ll discover that we arrange an onComplete operate. In our case, the operate simply sends the uncooked information to /api/submit, which might then be dealt with there.

You need to use Subsequent.js to create API endpoints. In our case, we will do it by making a file at /api/submit/route.js and placing a POST operate in it, like so:

export async operate POST(request) {
  const res = await request.json();

  console.log(res);

  return Response.json({ message: "Accomplished" });
}

In our case, the POST operate could be very easy: it grabs the thing that’s despatched after which logs it to the console and responds with a message. That is the place you’d need to save the consequence to your database in case you have one. You may additionally select to validate the consequence additional and return a consequence to show on the frontend. At this level, it’s completely as much as you what you do with the info.

Making a Web page to View the Outcomes

Now that we now have arrange a strategy to create and show types, we have to arrange a method to have a look at the outcomes we’ve collected from our types. Clearly, a method to have a look at the outcomes is simply to look straight on the database, however that gained’t offer you any insights into tendencies which are showing in your surveys. If we need to establish tendencies, we will use the surveyjs-analytics bundle.

For this challenge, I’ve created some pretend consequence information so we will create a outcomes dashboard. I’ve added a outcomes array to every survey object that we used earlier. Every consequence appears one thing like this:

  {
    "nps-score": 9,
    "disappointing-experience": [
      "The service is great, i highly recommend you use it.",
    ],
    "improvements-required": [
      "The service is great, i highly recommend you use it.",
    ],
    "promoter-features": ["ui"],
    rebuy: [true, false],
  }

As you may see, every result’s merely an object that has the query ID as a key and the reply as a price. That is precisely what we get from the onComplete operate when the shape is submitted.

First, we need to create a brand new dynamic web page, as we’ll need to create a brand new net web page for every totally different type so we will present the outcomes for that type particularly. For this web page, we need to create a brand new file at /outcomes/[slug]/web page.js.

Once more, we need to outline a generateMetadata and a generateStaticParams like we did to show the types. In our generateMetadata operate, we make a slight tweak to the title so it’s clear that we’re wanting on the outcomes moderately than the shape itself. The one distinction this time is that, inside our generateStaticParams, we filter a number of the types that don’t have outcomes so we don’t generate a web page for types with none outcomes. Our generateStaticParams operate finally ends up wanting like this:

export async operate generateStaticParams() {
  return surveys
    .filter((x) => x.outcomes.size > 0)
    .map((x) => ({ slug: x.slug }));
}

Once more, we need to additionally export a Web page part. Our web page part is an identical to the web page part from the earlier part, besides as a substitute we render the part Outcomes. However we nonetheless do a discover to seize the appropriate survey information and go that by means of to the part.

Our Outcomes part masses in all the required packages after which renders them to the web page. It requires a number of useEffect hooks to arrange, and the entire part appears like this:

"use consumer";

import { useEffect } from "react";
import { Mannequin } from "survey-core";

export default operate Outcomes({ surveyData }) {
  useEffect(() => {
    (async () => {
      const survey = new Mannequin(surveyData.survey);

      const { VisualizationPanel } = await import("survey-analytics");

      const currentPanel = new VisualizationPanel(
        survey.getAllQuestions(),
        surveyData.outcomes,
        {
          allowHideQuestions: false,
        }
      );

      currentPanel.render("surveyVizPanel");

      return () => {
        const panelElement = doc.getElementById("surveyVizPanel");

        if (panelElement) {
          panelElement.innerHTML = "";
        }
      };
    })();
  }, [surveyData]);

  return (
    div>
      div id="surveyVizPanel" />
    /div>
  );
}

As you may see, we once more begin with the use consumer directive for all the identical causes as earlier than. The part begins with a useEffect that’s used to arrange the panel that reveals all of the charts. It firstly makes use of the surveyData object, which defines the survey itself to create a Mannequin. This lets the outcomes bundle know which graphs to indicate, as it might perceive every query.

The subsequent factor the useEffect does is load the survey-analytics bundle. We do that through a dynamic import, so it isn’t loaded at construct time. This strategy prevents build-time errors brought on by client-side particular code within the bundle.

After getting the required bundle, we arrange the visualization object with all the questions after which we can provide it an inventory of all of the submissions for it to undergo and create graphs from. At this level you may configure your visualizations with the choices offered. After that, all it’s important to do is let the panel object know which ID to make use of to render to within the DOM, which in our case is surveyVizPanel, which we render additional down. Lastly, we now have to ensure to offer a clean-up operate to our hook in order that it clears out the component when it’s executed.

You’ll discover that we solely go within the surveyData to the dependency array in order that we solely re-render all of the graphs if the enter information modifications, which is likely to be the case if we ever hyperlink between totally different outcomes pages.

Additional Work

This text has given you adequate of an concept to get began integrating SurveyJS into your Subsequent.js software. To have a completely functioning system, you’ll need to look into including some form of authentication system with the intention to make certain solely verified customers can entry the totally different elements of the system.

You’ll additionally need to combine with some form of information supply, each for the creator to create new types and to gather the outcomes from the tip person. All of those additions are made very simple in Subsequent.js and SurveyJS.

Conclusion

This information has proven you the best way to construct a complete survey administration system in Subsequent.js with SurveyJS. You get so many advantages out of the field with Subsequent.js, so though you won’t have written that a lot code, you’ll discover that what you’ve got created will scale to as many types as you need with none trouble.

Thanks for taking the time to learn this information. As I beforehand talked about, you may check out the full repo here or you may play with the hosted version of the system here.