Building a code editor within NextJS

This page summarizes the projects mentioned and recommended in the original post on dev.to

Our great sponsors
  • SurveyJS - Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • Next.js

    The React Framework

  • import Editor from "./editor"; import * as style from "./editor.module.css"; import cn from "classnames"; const EditorApp = () => { return ( <> ) }; export default EditorApp;

    Enter fullscreen mode Exit fullscreen mode

    And then we can rip out all the boiler code in index.js and import our editorApp

    import CodeEditor from "../components/editorApp";
    
    export default function Home() {
      return (
        
      )
    }
    
    Enter fullscreen mode Exit fullscreen mode

    You should see Editor 3 times on your screen. Cool.

    Editor.js

    We need to install codemirror, so run npm install react-codemirror2-react-17 codemirror --save
    Let's import the styles for codeMirror and our theme. You can test different themes here, and we will also import the codemirror editor.

    import "codemirror/lib/codemirror.css";
    import "codemirror/theme/tomorrow-night-bright.css";
    import { Controlled as ControlledEditor } from "react-codemirror2-react-17";
    
    Enter fullscreen mode Exit fullscreen mode

    We have to import the languages differently as to not throw a ReferenceError of navigator is not defined.

    let languageLoaded = false;
    if (typeof window !== "undefined" && typeof window.navigator !== "undefined") {
        require("codemirror/mode/xml/xml");
        require("codemirror/mode/css/css");
        require("codemirror/mode/javascript/javascript");
        languageLoaded = true;
    }
    
    Enter fullscreen mode Exit fullscreen mode

    We are going to add create our editor now, with a title and body. This includes our props and handleChange function.

    import "codemirror/lib/codemirror.css";
    import "codemirror/theme/tomorrow-night-bright.css";
    import { Controlled as ControlledEditor } from "react-codemirror2-react-17";
    
    let languageLoaded = false;
    if (typeof window !== "undefined" && typeof window.navigator !== "undefined") {
        require("codemirror/mode/xml/xml");
        require("codemirror/mode/css/css");
        require("codemirror/mode/javascript/javascript");
        languageLoaded = true;
    }
    
    const Editor = (props) => {
        const { language, editorTitle, value, onChange, className } = props;
    
        function handleChange(editor, data, value) {
            onChange(value);
        }
    
        return(
            
    {editorTitle}
    ) } export default Editor;
    Enter fullscreen mode Exit fullscreen mode

    editorApp.js

    We need to fill out our now. Add a
    const [html, setHtml] = useState(''); (import useState)
    and for the first editor

      
    
    Enter fullscreen mode Exit fullscreen mode

    Copy this pattern for css and javascript.
    Then we are going to add a useEffect to set the iframe srcDoc.

    const [srcDoc, setSrcDoc] = useState("");
    
    useEffect(() => {
        const timeout = setTimeout(() => {
          setSrcDoc(`
            
              ${html}
              ${css}
              ${js}
            
          `);
        }, 200);
    
        return () => clearTimeout(timeout);
      }, [html, css, js]);
    
    Enter fullscreen mode Exit fullscreen mode

    and add the srcDoc prop as srcDoc to the iframe. You should have

    import { useState, useEffect } from "react";
    import Editor from "./editor";
    import * as style from "./editor.module.css";
    import cn from "classnames";
    
    const EditorApp = () => {
      const [html, setHtml] = useState("");
      const [css, setCss] = useState("");
      const [js, setJs] = useState("");
      const [srcDoc, setSrcDoc] = useState("");
    
      useEffect(() => {
        const timeout = setTimeout(() => {
          setSrcDoc(`
            
              ${html}
              ${css}
              ${js}
            
          `);
        }, 200);
    
        return () => clearTimeout(timeout);
      }, [html, css, js]);
    
      return (
        <>
          
    </div> </> ); }; export default EditorApp; </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p>You should now be able to type in the the editors and see your results displayed.</p> <h2> <a name="uselocalstoragejs" href="#uselocalstoragejs"> </a> useLocalStorage.js </h2> <p>Last step.<br> In this component, we use <code>localStorage</code>, which will either throw a <code>localStorage is not defined</code> or <code>window is not defined</code> in NextJS.<a href="https://nextjs.org/docs/basic-features/pages">NextJS pre-renders</a> every page which results in Static or Server Side rendering. localStorage is a property of the window object which is available on the client side / browser.<br> To get around this, we first have to check if the window is defined.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>import { useEffect, useState } from "react"; function getStorageValue(key, initialValue) { if (typeof window !== "undefined") { const savedValue = localStorage.getItem(key); return savedValue !== null ? JSON.parse(savedValue) : initialValue; } } export const useLocalStorage = (key, initialValue) => { const [value, setValue] = useState(() => { return getStorageValue(key, initialValue); }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }; </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p>Import and replace useState in <code>editorApp.js</code> for your html, css, and js with useLocalStorage<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code> const [html, setHtml] = useLocalStorage("html", ""); const [css, setCss] = useLocalStorage("css", ""); const [js, setJs] = useLocalStorage("js", ""); </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <h2> <a name="boom" href="#boom"> </a> Boom </h2> <p>You should now have a working codeEditor. If you want to prefill any section with code, just put your code in the empty "" ex. <code>const [html, setHtml] = useLocalStorage("html", "<div>foo</div>");</code>. Keep in mind that localStorage is being saved so you may need to clear your browsing data once or many times.<br> </p> <div class="ltag-github-readme-tag"> <div class="readme-overview"> <h2> <img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo" loading="lazy"> <a href="https://github.com/ayseboogie"> ayseboogie </a> / <a style="font-weight: 600;" href="https://github.com/ayseboogie/next-code-editor"> next-code-editor </a> </h2> <h3> </h3> </div> <div class="ltag-github-body"> <div id="readme" class="md" data-path="README.md"><article class="markdown-body entry-content container-lg" itemprop="text"><p dir="auto">This is a <a href="https://nextjs.org/" rel="nofollow">Next.js</a> project bootstrapped with <a href="https://github.com/vercel/next.js/tree/canary/packages/create-next-app"><code>create-next-app</code></a>.</p> <h2 dir="auto"> Getting Started</h2> <p dir="auto">First, run the development server:</p> <div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight" data-snippet-clipboard-copy-content="npm run dev # or yarn dev"> <pre>npm run dev <span class="pl-c"><span class="pl-c">#</span> or</span> yarn dev</pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p dir="auto">Open <a href="http://localhost:3000" rel="nofollow">http://localhost:3000</a> with your browser to see the result.</p> <p dir="auto">You can start editing the page by modifying <code>pages/index.js</code>. The page auto-updates as you edit the file.</p> <p dir="auto"><a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow">API routes</a> can be accessed on <a href="http://localhost:3000/api/hello" rel="nofollow">http://localhost:3000/api/hello</a>. This endpoint can be edited in <code>pages/api/hello.js</code>.</p> <p dir="auto">The <code>pages/api</code> directory is mapped to <code>/api/*</code>. Files in this directory are treated as <a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow">API routes</a> instead of React pages.</p> <h2 dir="auto"> Learn More</h2> <p dir="auto">To learn more about Next.js, take a look at the following resources:</p> <ul dir="auto"> <li> <a href="https://nextjs.org/docs" rel="nofollow">Next.js Documentation</a> - learn about Next.js features and API.</li> <li> <a href="https://nextjs.org/learn" rel="nofollow">Learn Next.js</a> - an interactive Next.js tutorial.</li> </ul> <p dir="auto">You can check out <a href="https://github.com/vercel/next.js/">the Next.js GitHub repository</a> - your feedback and contributions are welcome!</p> <h2 dir="auto"> Deploy on Vercel</h2> <p dir="auto">The easiest way to deploy your Next.js app is to use the <a href="https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme" rel="nofollow">Vercel Platform</a> from…</p></article></div> </div> <div class="gh-btn-container"><a class="gh-btn" href="https://github.com/ayseboogie/next-code-editor">View on GitHub</a></div> </div> <p>This is my first post, I hope it was easy to follow and helps someone out :-)</p>

  • next-code-editor

  • import Editor from "./editor"; import * as style from "./editor.module.css"; import cn from "classnames"; const EditorApp = () => { return ( <> ) }; export default EditorApp;

    Enter fullscreen mode Exit fullscreen mode

    And then we can rip out all the boiler code in index.js and import our editorApp

    import CodeEditor from "../components/editorApp";
    
    export default function Home() {
      return (
        
      )
    }
    
    Enter fullscreen mode Exit fullscreen mode

    You should see Editor 3 times on your screen. Cool.

    Editor.js

    We need to install codemirror, so run npm install react-codemirror2-react-17 codemirror --save
    Let's import the styles for codeMirror and our theme. You can test different themes here, and we will also import the codemirror editor.

    import "codemirror/lib/codemirror.css";
    import "codemirror/theme/tomorrow-night-bright.css";
    import { Controlled as ControlledEditor } from "react-codemirror2-react-17";
    
    Enter fullscreen mode Exit fullscreen mode

    We have to import the languages differently as to not throw a ReferenceError of navigator is not defined.

    let languageLoaded = false;
    if (typeof window !== "undefined" && typeof window.navigator !== "undefined") {
        require("codemirror/mode/xml/xml");
        require("codemirror/mode/css/css");
        require("codemirror/mode/javascript/javascript");
        languageLoaded = true;
    }
    
    Enter fullscreen mode Exit fullscreen mode

    We are going to add create our editor now, with a title and body. This includes our props and handleChange function.

    import "codemirror/lib/codemirror.css";
    import "codemirror/theme/tomorrow-night-bright.css";
    import { Controlled as ControlledEditor } from "react-codemirror2-react-17";
    
    let languageLoaded = false;
    if (typeof window !== "undefined" && typeof window.navigator !== "undefined") {
        require("codemirror/mode/xml/xml");
        require("codemirror/mode/css/css");
        require("codemirror/mode/javascript/javascript");
        languageLoaded = true;
    }
    
    const Editor = (props) => {
        const { language, editorTitle, value, onChange, className } = props;
    
        function handleChange(editor, data, value) {
            onChange(value);
        }
    
        return(
            
    {editorTitle}
    ) } export default Editor;
    Enter fullscreen mode Exit fullscreen mode

    editorApp.js

    We need to fill out our now. Add a
    const [html, setHtml] = useState(''); (import useState)
    and for the first editor

      
    
    Enter fullscreen mode Exit fullscreen mode

    Copy this pattern for css and javascript.
    Then we are going to add a useEffect to set the iframe srcDoc.

    const [srcDoc, setSrcDoc] = useState("");
    
    useEffect(() => {
        const timeout = setTimeout(() => {
          setSrcDoc(`
            
              ${html}
              ${css}
              ${js}
            
          `);
        }, 200);
    
        return () => clearTimeout(timeout);
      }, [html, css, js]);
    
    Enter fullscreen mode Exit fullscreen mode

    and add the srcDoc prop as srcDoc to the iframe. You should have

    import { useState, useEffect } from "react";
    import Editor from "./editor";
    import * as style from "./editor.module.css";
    import cn from "classnames";
    
    const EditorApp = () => {
      const [html, setHtml] = useState("");
      const [css, setCss] = useState("");
      const [js, setJs] = useState("");
      const [srcDoc, setSrcDoc] = useState("");
    
      useEffect(() => {
        const timeout = setTimeout(() => {
          setSrcDoc(`
            
              ${html}
              ${css}
              ${js}
            
          `);
        }, 200);
    
        return () => clearTimeout(timeout);
      }, [html, css, js]);
    
      return (
        <>
          
    </div> </> ); }; export default EditorApp; </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p>You should now be able to type in the the editors and see your results displayed.</p> <h2> <a name="uselocalstoragejs" href="#uselocalstoragejs"> </a> useLocalStorage.js </h2> <p>Last step.<br> In this component, we use <code>localStorage</code>, which will either throw a <code>localStorage is not defined</code> or <code>window is not defined</code> in NextJS.<a href="https://nextjs.org/docs/basic-features/pages">NextJS pre-renders</a> every page which results in Static or Server Side rendering. localStorage is a property of the window object which is available on the client side / browser.<br> To get around this, we first have to check if the window is defined.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>import { useEffect, useState } from "react"; function getStorageValue(key, initialValue) { if (typeof window !== "undefined") { const savedValue = localStorage.getItem(key); return savedValue !== null ? JSON.parse(savedValue) : initialValue; } } export const useLocalStorage = (key, initialValue) => { const [value, setValue] = useState(() => { return getStorageValue(key, initialValue); }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }; </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p>Import and replace useState in <code>editorApp.js</code> for your html, css, and js with useLocalStorage<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code> const [html, setHtml] = useLocalStorage("html", ""); const [css, setCss] = useLocalStorage("css", ""); const [js, setJs] = useLocalStorage("js", ""); </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <h2> <a name="boom" href="#boom"> </a> Boom </h2> <p>You should now have a working codeEditor. If you want to prefill any section with code, just put your code in the empty "" ex. <code>const [html, setHtml] = useLocalStorage("html", "<div>foo</div>");</code>. Keep in mind that localStorage is being saved so you may need to clear your browsing data once or many times.<br> </p> <div class="ltag-github-readme-tag"> <div class="readme-overview"> <h2> <img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo" loading="lazy"> <a href="https://github.com/ayseboogie"> ayseboogie </a> / <a style="font-weight: 600;" href="https://github.com/ayseboogie/next-code-editor"> next-code-editor </a> </h2> <h3> </h3> </div> <div class="ltag-github-body"> <div id="readme" class="md" data-path="README.md"><article class="markdown-body entry-content container-lg" itemprop="text"><p dir="auto">This is a <a href="https://nextjs.org/" rel="nofollow">Next.js</a> project bootstrapped with <a href="https://github.com/vercel/next.js/tree/canary/packages/create-next-app"><code>create-next-app</code></a>.</p> <h2 dir="auto"> Getting Started</h2> <p dir="auto">First, run the development server:</p> <div class="highlight highlight-source-shell position-relative overflow-auto js-code-highlight" data-snippet-clipboard-copy-content="npm run dev # or yarn dev"> <pre>npm run dev <span class="pl-c"><span class="pl-c">#</span> or</span> yarn dev</pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p dir="auto">Open <a href="http://localhost:3000" rel="nofollow">http://localhost:3000</a> with your browser to see the result.</p> <p dir="auto">You can start editing the page by modifying <code>pages/index.js</code>. The page auto-updates as you edit the file.</p> <p dir="auto"><a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow">API routes</a> can be accessed on <a href="http://localhost:3000/api/hello" rel="nofollow">http://localhost:3000/api/hello</a>. This endpoint can be edited in <code>pages/api/hello.js</code>.</p> <p dir="auto">The <code>pages/api</code> directory is mapped to <code>/api/*</code>. Files in this directory are treated as <a href="https://nextjs.org/docs/api-routes/introduction" rel="nofollow">API routes</a> instead of React pages.</p> <h2 dir="auto"> Learn More</h2> <p dir="auto">To learn more about Next.js, take a look at the following resources:</p> <ul dir="auto"> <li> <a href="https://nextjs.org/docs" rel="nofollow">Next.js Documentation</a> - learn about Next.js features and API.</li> <li> <a href="https://nextjs.org/learn" rel="nofollow">Learn Next.js</a> - an interactive Next.js tutorial.</li> </ul> <p dir="auto">You can check out <a href="https://github.com/vercel/next.js/">the Next.js GitHub repository</a> - your feedback and contributions are welcome!</p> <h2 dir="auto"> Deploy on Vercel</h2> <p dir="auto">The easiest way to deploy your Next.js app is to use the <a href="https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme" rel="nofollow">Vercel Platform</a> from…</p></article></div> </div> <div class="gh-btn-container"><a class="gh-btn" href="https://github.com/ayseboogie/next-code-editor">View on GitHub</a></div> </div> <p>This is my first post, I hope it was easy to follow and helps someone out :-)</p>

  • SurveyJS

    Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App. With SurveyJS form UI libraries, you can build and style forms in a fully-integrated drag & drop form builder, render them in your JS app, and store form submission data in any backend, inc. PHP, ASP.NET Core, and Node.js.

    SurveyJS logo
NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts