<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://blog.lukefrauhiger.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1648830050332/I6SmEdDD5.png</url><title>Untitled Publication</title><link>https://blog.lukefrauhiger.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 18 May 2026 11:20:19 GMT</lastBuildDate><atom:link href="https://blog.lukefrauhiger.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Form Builder for Developers]]></title><description><![CDATA[Table of Contents

The form building gap
Fetch Forms intro
The form building process
Code examples
Javascript & html
React example
React w/custom components



The problem with current developer form tools
There are lots of form builders and form too...]]></description><link>https://blog.lukefrauhiger.com/the-form-builder-for-developers</link><guid isPermaLink="true">https://blog.lukefrauhiger.com/the-form-builder-for-developers</guid><category><![CDATA[forms]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Luke Frauhiger]]></dc:creator><pubDate>Fri, 01 Apr 2022 16:33:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648830610179/qCzW3n6Nb.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#the-problem-with-current developer-form-tools">The form building gap</a></li>
<li><a class="post-section-overview" href="#fetch-forms">Fetch Forms intro</a></li>
<li><a class="post-section-overview" href="#get-started-with-fetch-forms">The form building process</a></li>
<li><a class="post-section-overview" href="#how-about-we-look-at-some-code">Code examples</a><ul>
<li><a class="post-section-overview" href="#simple-javascript-amp-html-example">Javascript &amp; html</a></li>
<li><a class="post-section-overview" href="#simple-react-example">React example</a></li>
<li><a class="post-section-overview" href="#with-custom-components-example">React w/custom components</a></li>
</ul>
</li>
</ol>
<h3 id="heading-the-problem-with-current-developer-form-tools">The problem with current developer form tools</h3>
<p>There are lots of form builders and form tools available today. Whether you need to share a simple form with family members, build a complex registration form, or gather payment information, there is a form builder or tool for you. Or is there...I see a gap.</p>
<p><strong>Form backend services</strong> help JAMstack websites collect form submissions without a server and connect data to 3rd party systems. But you still have to hand build the HTML form and its supporting functions like client-side validation. On top of that, if you want to use the form submissions locally in your code, as well as use a backend service, you can’t!</p>
<p><strong>Code libraries</strong> like Formik and Angular Forms are incredibly helpful for managing form state and validation. You can use your own components and build a high-quality form much quicker than with standard HTML. Unfortunately, you still have to spend time hand-building every single form and its validation rules. You also have to spend time creating a backend to handle form submissions and integrate the data.</p>
<blockquote>
<p>Forms are too repetitive and time-consuming for developers to constantly be hand-building them.</p>
</blockquote>
<h3 id="heading-fetch-forms">Fetch Forms</h3>
<p>That’s why I built Fetch Forms. I wanted the benefits of a form backend service and to be able to build the forms in a form builder that would remove the repetitive aspects.</p>
<p>The Fetch form builder’s defaults and templates will help you build and collaborate on forms in record time.</p>
<p>The Fetch API will help you integrate high-quality forms with client-side validation into your application in a matter of minutes.</p>
<p>Updates are just as easy. Complete your changes and publish them with a single click. All applications using the updated Fetch form will begin to pull the new form.</p>
<h2 id="heading-get-started-with-fetch-forms">Get started with Fetch Forms</h2>
<p>Get the speed of a form builder with the control of code. Here’s how:</p>
<h3 id="heading-1-build">1. Build</h3>
<p>Use the Fetch form builder to create and build your form. It’s packed with templates and defaults to make building forms painless.</p>
<ul>
<li>Select validation rules and input masking</li>
<li>Choose whether to save submissions to Fetch Forms</li>
<li>Use form and field templates to build forms in record time
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xq8ohm2ualvd9gwxrz2e.png" alt="Fetch form builder" /></li>
</ul>
<h3 id="heading-2-deploy">2. Deploy</h3>
<p>Deploy your form using any of our NPM modules, the embed script, or by simply using the native fetch API. The possibilities are endless!</p>
<ul>
<li>Install and use the Javascript or React library</li>
<li>Use the embed script to drop a form into any web-based tool</li>
<li>Extend your own component library
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56a8pwjganm83gedb11f.png" alt="A fetch form in code" /></li>
</ul>
<h3 id="heading-3-submissions">3. Submissions</h3>
<p>You don’t have to send submissions to Fetch Forms — all data submitted is available to your local code no matter what.</p>
<p>If you configured the form to save submissions to the Fetch Forms library, they will be <strong>validated on the server</strong> and sent through <strong>spam filtering</strong>. Submissions will then activate any connections you have set up.</p>
<hr />

<h2 id="heading-how-about-we-look-at-some-code">How about we look at some code?</h2>
<p>Using Fetch Forms can be as simple or as complex as you need. The first two examples are using a styled component provided by Fetch Forms. You can also implement a Fetch form with your own component library - see example 3.</p>
<p>You watch me talk through building and deploying a form in <a target="_blank" href="https://www.fetchforms.io/video-walkthrough">the walkthrough here</a>.</p>
<h3 id="heading-simple-javascript-andamp-html-example">Simple Javascript &amp; HTML example</h3>
<p>See more at <a target="_blank" href="https://www.fetchforms.io/docs/fetch-forms-javascript">www.fetchforms.io/docs/fetch-forms-javascript</a></p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"max-width: 600px; margin: auto"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Fetch Forms Javascript<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"form_name"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"margin-bottom: 25px"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"fetch_form"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">pre</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"result"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">import</span> { renderForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"@fetchforms/core"</span>;

    <span class="hljs-comment">// Called when data is submitted</span>
    <span class="hljs-keyword">const</span> onComplete = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
      <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"result"</span>).innerHTML = <span class="hljs-built_in">JSON</span>.stringify(data, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>);
    };

    <span class="hljs-comment">// Called when the Fetch form is loaded from the API</span>
    <span class="hljs-keyword">const</span> onLoad = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
      <span class="hljs-comment">// Set the form name on the HTML </span>
      <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"form_name"</span>).innerHTML = data.name;
    };

    <span class="hljs-comment">// Pass in the form slug, element Id to attach the form to, and optional utility functions</span>
    renderForm(
      <span class="hljs-string">"__form_slug__"</span>,
      <span class="hljs-string">"fetch_form"</span>,
      onComplete,
      onLoad
    );

  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="heading-simple-react-example">Simple React example</h3>
<p>See more at <a target="_blank" href="https://www.fetchforms.io/docs/fetch-forms-react">www.fetchforms.io/docs/fetch-forms-react</a></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { FetchForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"@fetchforms/react"</span>;

<span class="hljs-keyword">const</span> ManagedForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [formSubmission, setFormSubmission] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [formName, setFormName] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-keyword">async</span> (values) =&gt; {
    <span class="hljs-comment">/* To show an error on the form, uncomment the line below */</span>
    <span class="hljs-comment">// return 'There was an error submitting the form.';</span>
    setFormSubmission(values);
  };

  <span class="hljs-keyword">const</span> onLoad = <span class="hljs-keyword">async</span> (values) =&gt; {
    setFormName(values.name);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl mb-2"</span>&gt;</span>Component Form<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-600"</span>&gt;</span>
        The easiest way to use Fetch Forms. Pass in a form slug and we'll handle
        client-side validation, input formatting, submissions, and styling.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>{formName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">FetchForm</span> <span class="hljs-attr">slug</span>=<span class="hljs-string">{__form_slug__}</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span> <span class="hljs-attr">onLoad</span>=<span class="hljs-string">{onLoad}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        {formSubmission &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span>{JSON.stringify(formSubmission, null, 2)}<span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span>}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<h3 id="heading-with-custom-components-example">With custom components example</h3>
<p>This example is using Ant Design as the component library.</p>
<p>See a full working example at <a target="_blank" href="https://www.fetchforms.io/docs/fetch-forms-react">www.fetchforms.io/docs/fetch-forms-react</a></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"antd/dist/antd.css"</span>;
<span class="hljs-keyword">import</span> { useFetchForms } <span class="hljs-keyword">from</span> <span class="hljs-string">"@fetchforms/react"</span>;
<span class="hljs-keyword">import</span> { Form, Input, Button, Checkbox, Select, Radio, InputNumber, Alert } <span class="hljs-keyword">from</span> <span class="hljs-string">"antd"</span>;

<span class="hljs-keyword">const</span> CustomFetchForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [fetchForm, loading, error, doCloudSubmit] = useFetchForms(<span class="hljs-string">"__form_slug__"</span>);

  <span class="hljs-comment">// Called when submission passes client-side validation</span>
  <span class="hljs-keyword">const</span> onFinish = <span class="hljs-keyword">async</span> (values) =&gt; {
    <span class="hljs-keyword">if</span> (fetchForm.cloudSave) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Saving to the Fetch Form's cloud"</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> isSaved = <span class="hljs-keyword">await</span> doCloudSubmit(fetchForm.id, values);
        <span class="hljs-keyword">if</span> (!isSaved) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"There was an error submitting your form."</span>);
        }
      } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(err);
      }
    }
  };

  <span class="hljs-keyword">const</span> onFinishFailed = <span class="hljs-function">(<span class="hljs-params">errorInfo</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Failed:"</span>, errorInfo);
  };

  <span class="hljs-comment">// This takes the validation rules from the Fetch form and formats them for </span>
  <span class="hljs-comment">// the Ant Design form component.</span>
  <span class="hljs-keyword">const</span> createValidationRules = <span class="hljs-function">(<span class="hljs-params">fieldType, validations</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> rules = validations.map(<span class="hljs-function">(<span class="hljs-params">validation</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (validation.rule === <span class="hljs-string">"required"</span>) {
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">message</span>: validation.message };
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (validation.rule === <span class="hljs-string">"regex"</span>) {
        <span class="hljs-keyword">return</span> {
          <span class="hljs-attr">pattern</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(validation.limit),
          <span class="hljs-attr">message</span>: validation.message
        };
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> {
          [validation.rule]: validation.limit,
          <span class="hljs-attr">message</span>: validation.message,
          <span class="hljs-attr">type</span>: fieldType === <span class="hljs-string">"number"</span> ? <span class="hljs-string">"number"</span> : <span class="hljs-string">"string"</span>
        };
      }
    });
    <span class="hljs-keyword">return</span> rules;
  };

  <span class="hljs-comment">// Builds out the field based on it's configuration</span>
  <span class="hljs-keyword">const</span> dynamicField = <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
    <span class="hljs-keyword">switch</span> (item.fieldType) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">"select"</span>:
        <span class="hljs-keyword">const</span> { Option } = Select;
        <span class="hljs-keyword">return</span> (
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Select</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.name}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Option</span>&gt;</span>
            {item.options.map((option) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">Option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{option.value}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{option.value}</span>&gt;</span>
                {option.label}
              <span class="hljs-tag">&lt;/<span class="hljs-name">Option</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Select</span>&gt;</span></span>
        );
      <span class="hljs-keyword">case</span> <span class="hljs-string">"checkbox"</span>:
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Checkbox</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.name}</span> /&gt;</span></span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">"textarea"</span>:
        <span class="hljs-keyword">const</span> { TextArea } = Input;
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TextArea</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.name}</span> /&gt;</span></span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">"number"</span>:
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">InputNumber</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.name}</span> /&gt;</span></span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">"radio"</span>:
        <span class="hljs-keyword">return</span> (
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Radio.Group</span>&gt;</span>
            {item.options.map((opt) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">Radio</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{opt.value}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{opt.value}</span>&gt;</span>
                {opt.label}
              <span class="hljs-tag">&lt;/<span class="hljs-name">Radio</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Radio.Group</span>&gt;</span></span>
        );
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Input</span> {<span class="hljs-attr">...item.fieldHtml</span>} <span class="hljs-attr">key</span>=<span class="hljs-string">{item.name}</span> /&gt;</span></span>;
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">""</span>&gt;</span>
      {loading ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ) : (
        fetchForm &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Form</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"HookForm"</span>
            <span class="hljs-attr">labelCol</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">span:</span> <span class="hljs-attr">6</span> }}
            <span class="hljs-attr">wrapperCol</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">span:</span> <span class="hljs-attr">18</span> }}
            <span class="hljs-attr">onFinish</span>=<span class="hljs-string">{onFinish}</span>
            <span class="hljs-attr">onFinishFailed</span>=<span class="hljs-string">{onFinishFailed}</span>
            <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"off"</span>
            <span class="hljs-attr">noValidate</span>
          &gt;</span>
            {fetchForm.formItems.map((item, i) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">Form.Item</span>
                <span class="hljs-attr">key</span>=<span class="hljs-string">{i}</span>
                <span class="hljs-attr">label</span>=<span class="hljs-string">{item.label}</span>
                <span class="hljs-attr">name</span>=<span class="hljs-string">{item.name}</span>
                <span class="hljs-attr">valuePropName</span>=<span class="hljs-string">{</span>
                  <span class="hljs-attr">item.fieldType</span> === <span class="hljs-string">"checkbox"</span> ? "<span class="hljs-attr">checked</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">value</span>"
                }
                <span class="hljs-attr">rules</span>=<span class="hljs-string">{createValidationRules(item.fieldType,</span> <span class="hljs-attr">item.validation</span>)}
                <span class="hljs-attr">validateTrigger</span>=<span class="hljs-string">"onBlur"</span>
              &gt;</span>
                {dynamicField(item)}
              <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Item</span>&gt;</span>
            ))}
            <span class="hljs-tag">&lt;<span class="hljs-name">Form.Item</span>
              <span class="hljs-attr">wrapperCol</span>=<span class="hljs-string">{{</span>
                <span class="hljs-attr">span:</span> <span class="hljs-attr">8</span>,
                <span class="hljs-attr">offset:</span> <span class="hljs-attr">6</span>
              }}
            &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">htmlType</span>=<span class="hljs-string">"submit"</span>&gt;</span>
                {fetchForm.submitText}
              <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Form.Item</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Form</span>&gt;</span>
        )
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p></p><hr />
Fetch Forms is a headless form builder that exists to help developers build and manage forms easily so they can focus on more important things. It’s perfect for headless websites, JAMstack websites, and web apps.<p></p>
<ul>
<li>Website: <a target="_blank" href="https://fetchforms.io?ref=hashnode">www.fetchforms.io</a></li>
<li>Docs: <a target="_blank" href="https://fetchforms.io/docs/overview?ref=hashnode">www.fetchforms.io/docs</a></li>
<li>Twitter: <a target="_blank" href="https://twitter.com/FetchForms">www.twitter.com/FetchForms</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Full Stack Starter - Svelte and Express]]></title><description><![CDATA[Svelte and Node.js
Knowing how to build either a frontend or backend is a valuable skill. I started my career in technology as a UI/UX designer, but I hated that I couldn't help turn my designs into a functional webapp. That's when I jumped into fron...]]></description><link>https://blog.lukefrauhiger.com/full-stack-starter-svelte-and-express</link><guid isPermaLink="true">https://blog.lukefrauhiger.com/full-stack-starter-svelte-and-express</guid><category><![CDATA[Svelte]]></category><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[full stack]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Luke Frauhiger]]></dc:creator><pubDate>Fri, 01 Apr 2022 16:27:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648830242935/NNbm0lDD8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h4 id="heading-svelte-and-nodejs">Svelte and Node.js</h4>
<p>Knowing how to build either a frontend or backend is a valuable skill. I started my career in technology as a UI/UX designer, but I hated that I couldn't help turn my designs into a functional webapp. That's when I jumped into frontend development! I desperately wanted to do more than designing the interactions - I wanted to be able to build them!</p>
<p>Learning frontend design was a great challenge and it was amazing how much it affected my designs. Knowing more about data structures, data manipulation, and the capabilities of various frameworks forced me to think critically about the designs I was doing. It especially helped with the hand-off between myself and developers. Terms like, "I don't know how to do it, just do it", left my vocabulary and I was much more helpful in the implementation. Something my fellow developers are thankful for to this day.</p>
<p>However, for most people learning just frontend or just backend isn't enough. To put a website or web app on the internet for all to see, you have to know more than just one discipline. That's why I'm writing this! I hope this article helps you with your journey of building and deploying a Svelte app. There are other ways to deploy Svelte and the other SPA frameworks, but using an application server is one of my favorites if you need to do backend &amp; API work. </p>
<h2 id="heading-before-we-begin">Before we begin</h2>
<p>Before we jump in let's go over some details.</p>
<p>You'll need Node.js installed - you can <a target="_blank" href="https://nodejs.org/en/download/">download it here</a> if you haven't already. </p>
<p>You can access my <a target="_blank" href="https://github.com/lukefrogger/full-stack-starter-svelte-express-app">template repo with the completed files here</a>.</p>
<h4 id="heading-the-plan">The plan</h4>
<p>The plan is to create a Svelte frontend, a Node &amp; Express backend, and wire them together so that our frontend can search for gifs from the GIPHY API. This will be a great example of why using an application server can be so great for your full-stack development. It keeps all the files in one place and sensitive data, like API keys, are hidden in the server and not your frontend. </p>
<h4 id="heading-sosvelte-is-awesome-right">So...Svelte is awesome, right?</h4>
<p>As a full-stack developer of 7 years, I honestly say that Svelte is pretty amazing...but not for everything. Here is a saying that I've said far too often in my career</p>
<blockquote>
<p>"Anything can be used as a hammer"</p>
</blockquote>
<p>I'm a huge advocate for using the right tool for the job. Sometimes that means it's going to be Svelte, sometimes it won't. You could choose to use Svelte for all your projects and that might be a great call for you. It might not be a good call for someone else.</p>
<p>My personal opinion - I wouldn't use Svelte for bigger applications. It's not because Svelte can't handle bigger projects! It's because I think tools like React or Angular provide much better tooling and organizational potential than Svelte does. For our small example today, I think Svelte is perfect! </p>
<h2 id="heading-lets-jump-in">Let’s jump in</h2>
<p>The first thing we’ll do is create our Svelte app. To do that, we’ll follow the <a target="_blank" href="https://svelte.dev/blog/the-easiest-way-to-get-started">instructions on this page</a> and run the following:</p>
<pre><code class="lang-bash">$ npx degit sveltejs/template svelte-express-app
</code></pre>
<p>If you haven’t used <code>npx</code> before, it’s an executable package, baked into NPM, that enables one-time use of an npm package. In this case, <code>npx</code> is executing the tool degit to pull down and clone the Svelte template repo. You can read more info about the <a target="_blank" href="https://www.npmjs.com/package/degit">degit project here.</a></p>
<p>This command clones the Svelte template repo and names it “svelte-express-app”. Once the command completes, install the project, and you’re ready to begin developing with Svelte! Let’s run the following commands to get our Svelte app 100% ready.</p>
<pre><code class="lang-bash">$ <span class="hljs-built_in">cd</span> svelte-express-app
$ yarn
$ yarn dev
</code></pre>
<p>We can now begin to develop our Svelte app! Let's move to the Node.js backend. </p>
<p>We’ll use Express on top of Node.js to make building the API super easy. To get this started, we'll first install Express and CORS.</p>
<pre><code class="lang-bash">$ yarn add express --save
$ yarn add cors --save
</code></pre>
<p>Now that we have Express added to our project, let's create the server file and get it set up so that it can serve the Svelte app. It's important that the server file is outside of the "src" folder. Since the Svelte app is within the "src" folder, everything within it gets compiled and bundled through Rollup - the bundler that Svelte uses. Since we want our server to be separate and serve the frontend to the browser, we need to make sure that the server file is outside of any directory that's being compiled.</p>
<p><strong>NOTE</strong>: You could write Node.js and Express with Typescript and need it to be compiled. But that's a slightly different process and one we're not going over in this article. If that's something you'd like to see, let me know!</p>
<p>Let's create our file at the root of our project. I'm going to name my file "server" - I'm really creative, I know! You can create the file with the following command or however you're favorite editor allows you to.</p>
<pre><code class="lang-bash">$ touch server.js
</code></pre>
<p>Open that file up and add the boilerplate code for Express</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">5000</span>;
<span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cors'</span>);
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);

app.use(cors());
</code></pre>
<p>These lines of boilerplate do several things. They set up the express app, assign a port if the application doesn't have one, import the CORS and Path libraries from npm, and finally, it assigns the Express app to use CORS instead of the baked in security. Cors is really helpful in fine-tuning the security of your application in regards to what domains, outside of your hosting domain, can be used to access the server.</p>
<p>Just a few more lines before we're ready to use the server!</p>
<pre><code class="lang-js">app.use(express.static(<span class="hljs-string">'public'</span>));
app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.sendFile(path.resolve(__dirname, <span class="hljs-string">'public'</span>, <span class="hljs-string">'index.html'</span>));
});
app.listen(port, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server is up at port <span class="hljs-subst">${port}</span>`</span>);
});
</code></pre>
<p>The first two functions are used to serve the index.html in the public directory to the browser. If you'd like to read more on how the Path library works <a target="_blank" href="https://nodejs.org/api/path.html">take a look here</a>, but It's essentially a baked in library that allows Node.js to read and write files!</p>
<p>The last function is a listener that prints out a statement about the port number of the server! This is a really quick way to know if the server is up when developing locally.</p>
<h4 id="heading-lets-test">Let's Test</h4>
<p>Let's test each app separately to make sure they're working. Make sure you kill the process before you run another one.</p>
<p><code>yarn dev</code> to start the Svelte app. Go to your browser and check it out!</p>
<p><code>node server.js</code> to start the express app. The console should read <code>Server is up at port 5000</code></p>
<h2 id="heading-starting-both-with-one-command">Starting Both With One Command</h2>
<p>Now that we have our frontend and backend configured, we need to spin them up! There are differences in the build process between development and production. To serve this in a production environment, it's a pretty straightforward process.</p>
<ol>
<li><p>Build the Svelte app <code>yarn build</code></p>
</li>
<li><p>Start the server.  <code>yarn start</code></p>
</li>
</ol>
<p>It's so simple because we don't want the Svelte app to be hot reloading. For production, we want a super-performant, minified bundle that will load in the browser quickly.</p>
<p>But for development, hot reloading is a must for the Svelte side of things! We'll have to adjust the package.json scripts so we can re-compile the Svelte every time we make changes. And we need to serve the Svelte app from our Express server instead of Svelte's default serve library.</p>
<p>Svelte uses the library "sirv" to deliver the compiled bundle of Javascript to your browser. Let's open the package.json file and take a look at the "scripts" part of the file. You'll find a "start" command that uses the sirv library to serve the public folder. Let's change that <strong>FROM</strong> "sirv public" <strong>TO</strong> "node server.js". This creates a single command that will hot-reload the Svelte app and use our Express app as the server. Let's give it a go!</p>
<pre><code class="lang-bash">yarn dev
</code></pre>
<p>Go to your browser at localhost:5000 and see it work! You should also see the console print out the port number. </p>
<h4 id="heading-youre-done-but-theres-more">You're done! But there's more</h4>
<p>Congratulations, you've built a full-stack web app that is incredibly easy to develop! But we're not going to stop there. Let's add an API endpoint to our Express app and use the GIPHY API to search for gifs. </p>
<h2 id="heading-adding-a-route">Adding a route</h2>
<p>The first thing we're going to do is add a new route to our Express.</p>
<pre><code class="lang-js">app.get(<span class="hljs-string">'/giphy'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Searching for a gif with the term: <span class="hljs-subst">${req.query.term}</span>`</span>);
    res.send({
        <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">data</span>: []
    })
});
</code></pre>
<p>It's incredibly important to note that this function MUST BE BEFORE the app.use() function that sends the index.html to the frontend. If you place this function after that app.use() function, nothing will happen on your request.</p>
<p>The first line is the Express function that declares the URL path of the endpoint and which HTTP verbs can be used for it. This endpoint can be accessed through localhost:5000/giphy and it's a "GET" function only. You can also use other HTTP verbs like POST, PUT, and DELETE. If you'd like to use an endpoint for everything, the "USE" function is the perfect choice.</p>
<p>The next line is a console log to print out the search term and then we have the <code>res.send()</code> function that sends our data back to the frontend. There's no special sauce here - you can return whatever you'd like from your endpoint. In my experience creating an object that has a success flag and then a property with the data makes it easy to do success/fail conditionals in the front end.</p>
<h4 id="heading-making-the-request-from-svelte">Making the request from Svelte</h4>
<p>Now to Svelte! Open up App.svelte and replace the paragraph after "Hello World" with the following:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-block"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search for gif"</span> <span class="hljs-attr">bind:value</span>=<span class="hljs-string">{searchTerm}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{searchForGif}</span>&gt;</span>Search<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"gifs"</span>&gt;</span>
    {#if gifs.length &gt; 0}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"gifs-grid"</span>&gt;</span>
            {#each gifs as gif}
                <span class="hljs-tag">&lt;<span class="hljs-name">iframe</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{gif.embed_url}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{gif.title}</span> /&gt;</span>
            {/each}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
     {:else}
         No gifs to show yet
     {/if}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Now, add this javascript in the script tag.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> gifs = [];
<span class="hljs-keyword">let</span> searchTerm = <span class="hljs-string">""</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">searchForGif</span>(<span class="hljs-params">e</span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> returnValue = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/giphy?term=<span class="hljs-subst">${searchTerm}</span>`</span>);
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> returnValue.json();
        gifs = response.data;
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error);
    }
}
</code></pre>
<p>At this point, I'm assuming you know Svelte and it's flavor of syntax, so I'm not going to talk in detail about how this works. From a high level, the button calls a function that uses the value bound to the input field and calls to our Express endpoint. On return, the code is formatted and assigned to a variable. Once all that code is added, you should be able to type something in the input field, click the button and see the Express server log out the search term. Since we're not returning any data from our endpoint, the Svelte won't change or display anything. </p>
<h4 id="heading-using-the-giphy-api">Using the GIPHY API</h4>
<p>Let's change that - let's add the GIPHY API. To make API calls from Express, we'll need to add a library. I like axios, but node-fetch is another popular one. Run <code>$ yarn add axios</code> to install axios and then add the require() to the server <code>const axios = require('axios');</code></p>
<p>Now we're ready to add the API call. In the <code>/giphy</code> endpoint replace the contents with this:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Searching for a gif with the term: <span class="hljs-subst">${req.query.term}</span>`</span>);

<span class="hljs-keyword">let</span> params = req.query.term.replace(<span class="hljs-regexp">/ /g</span>, <span class="hljs-string">'+'</span>);
params += <span class="hljs-string">'&amp;api_key=YOUR_API_KEY'</span>;
params += <span class="hljs-string">'&amp;limit=10'</span>;

axios.get(<span class="hljs-string">`https://api.giphy.com/v1/gifs/search?q=<span class="hljs-subst">${params}</span>`</span>)
    .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{
        res.send({
            <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">data</span>: response.data.data
        })
    })
    .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
        res.send({
            <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
            <span class="hljs-attr">data</span>: []
        })
    });
</code></pre>
<p>The first part of this code takes the <code>term</code> variable and replaces any spaces with a plus sign. The next two lines add the API key and a query limiter. These are all well documented in <a target="_blank" href="https://developers.giphy.com/docs/resource/#code-examples">GIPHY's doc here</a>.</p>
<p>The axios function will make a GET request to the endpoint and then resolve or reject, sending the appropriate response back to the client.</p>
<p>Before you can query the GIPHY API, you'll need to get your own API key. Head over to their <a target="_blank" href="https://developers.giphy.com/docs/sdk">developer page and create an account</a> and an app. Make sure you select API when you are generating a key. Then copy and paste that bad boy after the <code>YOUR_API_KEY</code> param in the code above!</p>
<h2 id="heading-search-for-gifs">Search for Gifs!</h2>
<p>Once you've added your API key to the endpoint you're ready to use the search functionality! 
Restart your server with <code>yarn dev</code> and type something in the search box and hit the button! A grid of 10 gifs should popup! This project is super extensible, so feel free to hack around and explore it on your own.</p>
<p>You can access my template repo with the <a target="_blank" href="(https://github.com/lukefrogger/full-stack-starter-svelte-express-app">completed files here.</a></p>
]]></content:encoded></item><item><title><![CDATA[Full Stack Development Starter - React and Nodejs]]></title><description><![CDATA[When I went from being a UI & UX designer to a programmer I had literally no idea what I was doing. What made it worse was that I didn’t have any mentorship or guidance on how to move forward. All of my coworkers were Salesforce developers and hadn’t...]]></description><link>https://blog.lukefrauhiger.com/full-stack-development-starter-react-and-nodejs</link><guid isPermaLink="true">https://blog.lukefrauhiger.com/full-stack-development-starter-react-and-nodejs</guid><category><![CDATA[React]]></category><category><![CDATA[Express]]></category><category><![CDATA[full stack]]></category><dc:creator><![CDATA[Luke Frauhiger]]></dc:creator><pubDate>Fri, 01 Apr 2022 16:11:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648829340207/quXVvE2Fs.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I went from being a UI &amp; UX designer to a programmer I had literally no idea what I was doing. What made it worse was that I didn’t have any mentorship or guidance on how to move forward. All of my coworkers were Salesforce developers and hadn’t built any full-stack web apps with industry standard technology. It was up to me to pave the way forward with a new technology stack and deployment strategy.</p>
<p>With no idea of what to even Google and almost no concept of what it takes to build a full-stack application, I headed into the technological wilderness to find my path. After several weeks of research about coding languages and hosting platforms I finally had a full-stack application completed and running on Node.js and Angular 2+. </p>
<p>I often wonder what this project, or even the next couple of years of development, would have looked like if I had mentorship while figuring all of this out. That’s my goal with this article - to act as a simple mentor and get you started down the full stack trail. </p>
<h4 id="heading-react-and-nodejs">React and Node.js</h4>
<p>We’re gonna start with a full javascript stack. This can make developing and deploying full-stack applications a breeze since you only need to know one language. </p>
<p>There are several ways you can structure the client and server folders, but for today’s example, we’re going to keep it as simple as possible! That way you can expand it on your own in the future!</p>
<p><strong>Prerequisites</strong>
Node.js installed - <a target="_blank" href="https://nodejs.org/en/download/">You can download it here</a>.</p>
<h4 id="heading-get-started">Get Started</h4>
<p>First things first - let’s create our React app:</p>
<pre><code class="lang-bash">$ npx create-react-app react-node
$ <span class="hljs-built_in">cd</span> react-node
$ yarn build
</code></pre>
<p>If you’ve never used npx before - it’s basically an execution library. Instead of having to install create-react-app globally and then use the global command to create the app, you can use npx!</p>
<p>At this point our React app is ready to go! We’re not going to do anything else with it right now since all we’re trying to do is serve it from a server.</p>
<p>We’ll need to add Express to our project and then create a file. I’ll name mine server.js.</p>
<pre><code class="lang-bash">$ yarn add express
$ touch server.js
</code></pre>
<p>Now, open the file and paste these lines:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-comment">// instantiates express so we can use the middleware functions</span>
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Node’s native tool for working with files. </span>
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);

<span class="hljs-comment">// set a default port in case the host isn’t configured with one</span>
<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">3000</span>;

app.use(express.static(path.join(__dirname, <span class="hljs-string">'build'</span>)));

app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req,res</span>) =&gt;</span> {
   res.sendFile(path.join(__dirname+<span class="hljs-string">'build/index.html'</span>));
});

app.listen(port, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${port}</span>`</span>));
</code></pre>
<p>Since the file is a javascript file and we’ll  the <code>node</code> command to start it up, the runtime is established as Node.js. </p>
<p>On 2 two we’ve instantiated “app” as our Express application. Just like REST requests, Express has <code>get</code>, <code>post</code>, <code>put</code>, and <code>delete</code> functions. But if you’d like to use a single middleware function for all of the HTTP verbs, the <code>use</code> function is your jam. </p>
<p>On line 6 the Express app loads the build folder. Without this line the code would fail since Express wouldn’t be able to send the index.html file to the browser. </p>
<p>The <code>app.use(...)</code> function is what actually serves the root of our React app to the browser. Notice that it’s only being served when on a GET request, but it is serving the file at all routes. This way when our React app begins routing, the server is returning the index.html file and making sure the React app is running. </p>
<p>To serve your app, make sure you’re in the root of the project and type:</p>
<pre><code class="lang-bash">$ node server.js
</code></pre>
<p>Whala! Full-stack app - done. You’re serving your pre-built React app with Express.
But let’s add one more route to make sure you’re well on your way to becoming a full-stack developer. </p>
<p>First, let’s add the body-parser library.</p>
<pre><code class="lang-bash">$ yarn add body-parser
</code></pre>
<p>Now let’s import it and setup our new route:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
+ <span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>)
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);
<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">3000</span>;

app.use(express.static(path.join(__dirname, <span class="hljs-string">'build'</span>)));
+ app.use(bodyParser.json());

+ app.post(<span class="hljs-string">'/new-route'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
+   <span class="hljs-keyword">let</span> name = req.body.name;
+   res.send(
+        {<span class="hljs-attr">greeting</span>: <span class="hljs-string">`Hello <span class="hljs-subst">${name}</span>`</span>}
+   );
+ })

app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req,res</span>) =&gt;</span> {
   res.sendFile(path.join(__dirname+<span class="hljs-string">'build/index.html'</span>));
});

app.listen(port, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${port}</span>`</span>));
</code></pre>
<p>This new route will take a POST request at a route matching “/new-route” and return an object with a greeting. Notice that we’ve also added another <code>app.use(...)</code> function that will parse the value of the body in the req object. </p>
<p>Now onto the React!</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">'./logo.svg'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">const</span> [greeting, setGreeting] = useState(<span class="hljs-string">''</span>);

+ fetch(<span class="hljs-string">"/new-route"</span>, {
+   method: <span class="hljs-string">'POST'</span>,
+   headers: {
+     <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
+   },
+   body: <span class="hljs-built_in">JSON</span>.stringify({<span class="hljs-attr">name</span>: <span class="hljs-string">'Luke Duke'</span>})
+ })
+   .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json())
+   .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
+       setGreeting(result.greeting);
+   })
+   .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(error))
 <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
         Edit <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>src/App.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> and save to reload.
       <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
       + {greeting &amp;&amp;
       +  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{greeting}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
       + }
       <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
         <span class="hljs-attr">className</span>=<span class="hljs-string">"App-link"</span>
         <span class="hljs-attr">href</span>=<span class="hljs-string">"https://reactjs.org"</span>
         <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
         <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>
       &gt;</span>
         Learn React
       <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
 );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We added the “useState” import and added a hook for the response from the server. We also added a <code>fetch()</code> function that POSTs into our server with a name. The JSX renders the greeting when it’s set. </p>
<p><em>Note: You do not have to return an object from the Express app. Typically real world applications return a non-string variable, but you can return any type from Express.</em></p>
<p>Finally, rebuild the React and start up the server to see your app work!</p>
<pre><code class="lang-bash">$ yarn build
$ node server.js
</code></pre>
<p>And that is our Javascript all-the-way example! There is a ton of great documentation on the Express.js Framework page to help you along on your way.</p>
]]></content:encoded></item></channel></rss>