<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ryan</title>
    <description>The latest articles on Forem by Ryan (@up_to_nonsense).</description>
    <link>https://forem.com/up_to_nonsense</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F721326%2F2553f0c9-f3fc-4a68-a11f-2dcc22389498.jpg</url>
      <title>Forem: Ryan</title>
      <link>https://forem.com/up_to_nonsense</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/up_to_nonsense"/>
    <language>en</language>
    <item>
      <title>How to add Sign In with Notion to your webapp</title>
      <dc:creator>Ryan</dc:creator>
      <pubDate>Thu, 17 Feb 2022 04:19:29 +0000</pubDate>
      <link>https://forem.com/up_to_nonsense/how-to-add-sign-in-with-notion-to-your-webapp-anc</link>
      <guid>https://forem.com/up_to_nonsense/how-to-add-sign-in-with-notion-to-your-webapp-anc</guid>
      <description>&lt;p&gt;Hey everyone! This is kind of a continuation of &lt;a href="https://commotion.page/blog/how-to-create-a-form-app-with-the-notion-api" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt; where we create a simple React/Express.js app that saves form responses directly to your Notion database. For this part, we’re picking up where we left off. How can we allow users to connect their Notion accounts so we can programmatically do things like fetch their data or saves responses to a Notion page in their workspace? It’s actually pretty easy!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Make your integration into a public integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, go to &lt;a href="https://notion.so/my-integrations" rel="noopener noreferrer"&gt;https://notion.so/my-integrations&lt;/a&gt; and select the integration you created in the last tutorial, Basic Form, or just create a new one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friolfpm8dmnmqbe5fi05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friolfpm8dmnmqbe5fi05.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down a bit and change your integration to a “Public integration.” This means this integration will allow other users to connect their Notion accounts to your integration rather than only your own account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffegpp2egl889aef5hjky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffegpp2egl889aef5hjky.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In order to create a “Public integration”, you’ll need to fill in some info about your company. If you haven’t set up your own website, you can use your Notion page urls for things like your homepage or privacy policy site! Just whip up a Notion page, write some text, and plug it in here. Also, MAKE SURE YOU ADD “&lt;a href="http://localhost:3000%E2%80%9D" rel="noopener noreferrer"&gt;http://localhost:3000”&lt;/a&gt; TO REDIRECT URIs. This is very necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbn10w0rhvi4nyescc7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbn10w0rhvi4nyescc7j.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once you’ve submitted everything, scroll down to hit the save button. Once you do that, if you scroll to the top, you’ll now get an “OAuth client ID” and “OAuth client secret,” which you’ll need to use in your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31m3j5wi2ej60u5oop2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31m3j5wi2ej60u5oop2j.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Add a sign in link to your React app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alright, now that we got these, let’s start building. Let’s go back to the “form-tool” app that we created in the last tutorial (you can also just create a new react app with npx create-react-app form-tool ) and go to the App.js file and paste into it the below code. I’ll explain how this works in a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// form-tool/src/App.js

import { useEffect, useState } from "react";

// The OAuth client ID from the integration page!
const oauth_client_id = "02e1f9d8-...";

function App() {
  const [dbs, setdbs] = useState([]);

  // When you open the app, this doesn't do anything, but after you sign into Notion, you'll be redirected back with a code at which point we call our backend.
  useEffect(() =&amp;gt; {
    const params = new URL(window.document.location).searchParams;
    const code = params.get("code");
    if (!code) return;
    fetch(`http://localhost:3002/login/${code}`).then(async (resp) =&amp;gt; {
      setdbs(await resp.json());
    });
  }, []);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;a
        style={{ display: "block" }}
        href={`https://api.notion.com/v1/oauth/authorize?client_id=${oauth_client_id}&amp;amp;response_type=code&amp;amp;owner=user`}
      &amp;gt;
        Connect to Notion
      &amp;lt;/a&amp;gt;
      {dbs.map((db) =&amp;gt; (
        &amp;lt;div
          style={{
            display: "inline-flex",
            whiteSpace: "pre",
            border: "1px solid black",
            marginBottom: 10,
          }}
        &amp;gt;
          {JSON.stringify(db, null, 2)}
        &amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run npm run start, we get the following plain website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcroeyq04uzped7pu50fr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcroeyq04uzped7pu50fr.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When you click “Connect to Notion”, you should be brought over here to this sign in page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyha9i3xl12qvl0smms4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyha9i3xl12qvl0smms4b.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once you fill everything out, we’re redirected back to our site and… nothing happens. That’s cause we need to update our backend as well. Before that, let’s explain what’s happening.&lt;/p&gt;

&lt;p&gt;Essentially, we created a link to Notion’s site with the OAuth Client ID that allows you to sign into your Notion account. Once you select your workspace and the pages you want to give access to, you’ll be redirected to the url &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, which you should have put into the Redirect URI field in the integrations page. The caveat is now you’re given a secret code in the query parameter so the full URL is &lt;a href="http://localhost:3000?code=SECRET_CODE%E2%80%A6" rel="noopener noreferrer"&gt;http://localhost:3000?code=SECRET_CODE…&lt;/a&gt; . With this secret code, you now can access the Notion user’s workspace.&lt;/p&gt;

&lt;p&gt;So the flow goes: you open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, you click on the click and go to &lt;a href="https://www.notion.so/install-integration?%E2%80%A6" rel="noopener noreferrer"&gt;https://www.notion.so/install-integration?…&lt;/a&gt;, and once you fill everything out, you’ll be sent to &lt;a href="http://localhost:3000?code=CODE_VALUE%E2%80%A6" rel="noopener noreferrer"&gt;http://localhost:3000?code=CODE_VALUE…&lt;/a&gt;, with the code in hand. With this code, we’ll call our backend to start the real magic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Generate an access token and fetch user’s information with the Notion API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Okay, now that we’ve logged in and have the code, now what do we with it? Well, we need to create a new endpoint in our backend. Let’s take the code that we just got from the frontend and convert it into an “access token” that we can actually use. With the token, we’ll return the user’s databases, but theoretically we can do anything we like with the Notion API. Go to your “form-tool-backend” Express.js project (you can also just create a new Express.js project), and go to the file app.js and paste in the code below. Make sure to update the variables with values in the integrations page that we retrieved earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// form-tool-backend/app.js

const express = require("express");
const axios = require("axios");
const cors = require("cors");
const app = express();
const port = 3002;

// The OAuth client ID from the integration page!
const notionClientId = "02e1f9d8-...";

// The OAuth client secret from the integration page!
const notionClientSecret = "secret_...";

app.use(cors());
app.use(express.json());
app.listen(port, () =&amp;gt; {
  console.log(`Example app listening on port ${port}`);
});

app.get("/login/:code", async (req, res) =&amp;gt; {
  const { code } = req.params;

  // Generate an access token with the code we got earlier and the client_id and client_secret we retrived earlier
  const resp = await axios({
    method: "POST",
    url: "https://api.notion.com/v1/oauth/token",
    auth: { username: notionClientId, password: notionClientSecret },
    headers: { "Content-Type": "application/json" },
    data: { code, grant_type: "authorization_code" },
  });

  // You want to save resp.data.workspace_id and resp.data.access_token if you want to make requests later with this Notion account (otherwise they'll need to reauthenticate)

  // Use the access token we just got to search the user's workspace for databases
  const { data } = await axios({
    method: "POST",
    url: "https://api.notion.com/v1/search",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${resp.data.access_token}`,
      "Notion-Version": "2021-08-16",
    },
    data: { filter: { property: "object", value: "database" } },
  });

  res.json(data?.results);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s happening? Well, the code we just got from the frontend, we send it to our backend, and with the code as well as our OAuth client ID and OAuth client secret, we can generate an “access_token” which is the real important thing. So we just used a code to then create our beautiful “access_token” which we can use with the Notion API to interact with the user’s workspace. The “access_token” is very powerful and thus should be hidden away in your backend only and should never be leaked. Save the “access_token” and “workspace_id” from the response we get from our first API call to the userID of the person that just signed in. Whenever you want to call the Notion API for them, retrieve the “access_token” so you don’t need them to sign in again to Notion.&lt;/p&gt;

&lt;p&gt;With the “access_token”, we retrieve the user’s databases in the Notion workspace and return it to the frontend. We can do anything we like using this “access_token” that is outlined in the Notion API docs.&lt;/p&gt;

&lt;p&gt;Once we add this endpoint to our backend, if we go back to our website and Connect to Notion, it will now fetch the database information and display it on your site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9yy2fvp92my3ehcrank.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9yy2fvp92my3ehcrank.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Amazing! So what did we just do? Well, users can connect their Notion accounts, and then we can do things like fetch their data as well as make changes to their Notion workspace. So how could we use this to create a form app like Commotion? A user can connect their Notion account, and we’ll fetch their Notion database. With the database, we’ll generate a form, and when someone submits a response, we’ll take that data and add it to the user’s Notion database, all with the API. All we do is fetch the database here, but with the “access_token”, we can do much more.&lt;/p&gt;

&lt;p&gt;We hope that this was a helpful tutorial! If you want forms for your Notion workspace but don’t have the time, definitely check us out at &lt;a href="https://commotion.page" rel="noopener noreferrer"&gt;Commotion.page&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>How to create a form app with the Notion API </title>
      <dc:creator>Ryan</dc:creator>
      <pubDate>Mon, 24 Jan 2022 14:23:07 +0000</pubDate>
      <link>https://forem.com/up_to_nonsense/how-to-create-a-form-app-with-the-notion-api-1o2</link>
      <guid>https://forem.com/up_to_nonsense/how-to-create-a-form-app-with-the-notion-api-1o2</guid>
      <description>&lt;h2&gt;
  
  
  A tutorial using React.js and Express.js
&lt;/h2&gt;

&lt;p&gt;The Notion API officially came out of beta on May 13, 2021, enabling web developers to create cool apps that integrate with your Notion workspace, an example being ourselves, Commotion. For our form tool, we use the Notion API to save form responses to a connected Notion database. In this tutorial, we’re gonna show you how to create a simple form tool like ours that accepts emails with an html form and saves it to your Notion workspace. Let’s get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Setup the Notion stuff
&lt;/h3&gt;

&lt;p&gt;First, create a Notion account (obviously). Then create a Database table (typing in ‘/database’) and add a column called Email that is of type email, like below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sF_-RxwQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252Fcbef53ff-b0d1-46f7-9136-d906e815b15e%3Falt%3Dmedia%26token%3D5b3588ef-0654-409e-a0af-145d5d03065d" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sF_-RxwQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252Fcbef53ff-b0d1-46f7-9136-d906e815b15e%3Falt%3Dmedia%26token%3D5b3588ef-0654-409e-a0af-145d5d03065d" alt="Sample Notion Database" width="880" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the database object as its own page by clicking the expand icon. We’ll come back to this in a second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k6vwmEKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F950ab2ac-b5d5-429c-920d-d9b1ace3c6a7%3Falt%3Dmedia%26token%3D88cddaa4-5ea7-4a09-9b2b-026c3df9ad77" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6vwmEKY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F950ab2ac-b5d5-429c-920d-d9b1ace3c6a7%3Falt%3Dmedia%26token%3D88cddaa4-5ea7-4a09-9b2b-026c3df9ad77" alt="Expand Notion Database" width="880" height="227"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then go to &lt;a href="https://www.notion.so/my-integrations"&gt;https://www.notion.so/my-integrations&lt;/a&gt; and select “Create new integration” and give it the name “Basic Form” or something.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pyv7ODdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F50d01d00-813f-4152-8653-ec4245af61b8%3Falt%3Dmedia%26token%3De1f8351d-57bf-4174-b1fc-1e5d75ddd48b" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pyv7ODdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F50d01d00-813f-4152-8653-ec4245af61b8%3Falt%3Dmedia%26token%3De1f8351d-57bf-4174-b1fc-1e5d75ddd48b" alt="Notion integrations page" width="880" height="580"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Go back to your database’s Notion page and share the database with the app you just created by hitting Share on the top right, clicking the Invite input in the dropdown, and selecting your app from the popup. This makes sure that the API actually has access to this database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fkuyzPMH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F47fd8cd5-a0d4-4bc2-a4fc-5274032c4dc4%3Falt%3Dmedia%26token%3D61ea072d-e2c8-4e8d-854b-b03cd6701527" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fkuyzPMH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://firebasestorage.googleapis.com/v0/b/reslant.appspot.com/o/forums%252F418b1%252Fposts%252Fc67b7991-d19d-49b9-931e-d5aeb71acbc8%252F47fd8cd5-a0d4-4bc2-a4fc-5274032c4dc4%3Falt%3Dmedia%26token%3D61ea072d-e2c8-4e8d-854b-b03cd6701527" alt="Notion share with API" width="880" height="595"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Setup your backend with Express.js
&lt;/h3&gt;

&lt;p&gt;For this tutorial, we need to setup a backend, so we’re going with Express. You can read how to set it up here, but the gist of it is to go to a new folder and input the following commands in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir form-tool-backend
$ cd form-tool-backend
$ npm install express
$ npm install axios
$ npm install cors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within the form-tool-backend folder, create a file app.js and paste the following into it just to get things going.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// form-tool-backend/app.js

const express = require('express')
const axios = require('axios')
const app = express()
const port = 3002

app.listen(port, () =&amp;gt; {
  console.log(`Example app listening on port ${port}`)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why do we need a backend? Because we need to use secret keys that we don’t want to leak out. If someone were to get your secret key, that would be able to read and and write anything to your Notion workspace! Very scary.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Retrieve Database Information with the Notion API
&lt;/h3&gt;

&lt;p&gt;Finally, let’s actually start building! I’d open up &lt;a href="https://developers.notion.com/reference"&gt;https://developers.notion.com/reference&lt;/a&gt; cause we’ll be referencing this page a lot. First, we need to get our secret key, so let’s go back to &lt;a href="https://www.notion.so/my-integrations"&gt;https://www.notion.so/my-integrations&lt;/a&gt;, select our app, then copy our Internal Integration Token. Make sure to not leak this!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HGjV3fhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sr44ecnf7dkr5z68n5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HGjV3fhX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sr44ecnf7dkr5z68n5a.png" alt="Get secret key" width="880" height="514"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Paste the following code below into your app.js and replace the secretKey variable with the token you just copied. We’ll then create a route that fetches the database data with axios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// form-tool-backend/app.js

const express = require('express')
const axios = require('axios')
const app = express()
const port = 3002

// REPLACE! Retrieved from https://www.notion.so/my-integrations
const secretKey = 'secret_***************'

// What we'll pass into axios
const headers = {
  'Content-Type': 'application/json',
  Authorization: `Bearer ${secretKey}`,
  'Notion-Version': '2021-08-16',
}

// Route to fetch database data
app.get('/:database_id', async (req, res) =&amp;gt; {
  const { database_id } = req.params;
  const resp = await axios({
    method: 'GET',
    url: 'https://api.notion.com/v1/databases/' + database_id,
    headers
  });
  return res.json(resp.data);
})

app.use(cors())
app.use(express.json())
app.listen(port, () =&amp;gt; {
  console.log(`Example app listening on port ${port}`)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have something to test! Within your form-tool-backend folder, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ node app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go back to your Notion database in your browser and copy your database_id from your Notion url, marked as the part here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9mn3aqn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag6c49r4h2o4ytnbavq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9mn3aqn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag6c49r4h2o4ytnbavq1.png" alt="Get Database ID" width="880" height="595"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now if your run the following in a different terminal tab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:3002/REPLACE_THIS_WITH_DATABASE_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get the data from your database!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Setup your frontend with React.js
&lt;/h3&gt;

&lt;p&gt;Next, we need to create our frontend. In this case, we’re using React. Go to your terminal, go to the folder you want to put all your code in, and input the following command to create a sample app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx create-react-app form-tool
$ cd form-tool
$ npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q6f0ctyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9usq1pqcvdzsuoj49d02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q6f0ctyk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9usq1pqcvdzsuoj49d02.png" alt="Empty React app" width="880" height="557"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Let’s make some changes, shall we? Replace the contents of the App.js with the below, and replace the database_id value with the one you copied earlier from the Notion URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// form-tool/src/App.js

import { useEffect, useState } from 'react';

const database_id = REPLACE_WITH_YOUR_DATABASE_ID;

function App() {
  const [db, setDB] = useState({});

  useEffect(() =&amp;gt; {
    // We fetch the data from the local server that we're running
    fetch('http://localhost:3002/' + database_id).then(async (resp) =&amp;gt; {
      setDB(await resp.json())
    });
  }, []);

  return (
    &amp;lt;div&amp;gt;
      {db.title?.[0]?.plain_text}
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just gets the data that our backend retrieves and brings it into our frontend. The schema for a database object is a little unique, so checkout the official documentation here. If we run npm start, we should get the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_h0sPsc3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtnxz5501k8j5hy3nt6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_h0sPsc3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtnxz5501k8j5hy3nt6a.png" alt="Bare bones site" width="880" height="580"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We’ve officially fetched data from our Notion workspace! Hooray!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Save form response to Notion
&lt;/h3&gt;

&lt;p&gt;Finally, what we’ve all been waiting for, let’s actually take some information and save it to our database shall we? We’ll start by adding a simple form in our frontend React project that sends the email + name to our backend to send to Notion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from 'react';

const database_id = REPLACE_WITH_YOUR_DATABASE_ID;

function App() {
  const [db, setDB] = useState({});

  // NEW! This will send the form information to our backend we setup
  const onSubmit = (e) =&amp;gt; {
    e.preventDefault();
    fetch('http://localhost:3002/' + database_id, {
      method: 'POST',
      body: JSON.stringify({ email: e.target.email.value, name: e.target.name.value }),
      headers: { "Content-Type": 'application/json' }
    });
  }

  useEffect(() =&amp;gt; {
    fetch('http://localhost:3002/' + database_id).then(async (resp) =&amp;gt; {
      setDB(await resp.json());
    });
  }, []);

  return (
    &amp;lt;div&amp;gt;
      {db.title?.[0]?.plain_text}
      {/* NEW! This is an extremely simple form to collect the information */}
      &amp;lt;form onSubmit={onSubmit}&amp;gt;
        &amp;lt;input name="name" placeholder="Name" required /&amp;gt;
        &amp;lt;input name="email" placeholder="Email" type="email" required /&amp;gt;
        &amp;lt;button&amp;gt;Submit&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RVq8XgPi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/li39c1t52p8mh4tsk94e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RVq8XgPi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/li39c1t52p8mh4tsk94e.png" alt="Add simple form" width="880" height="557"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We now have an extremely simple form. Right now, nothing actually happens if we submit the form. That’s cause we need to build the backend function! If we switch back to our Express app, we can create a POST route that accepts our data, the name and email, and sends it to our Notion database. Entries in a database are equivalent to a Notion “page”, so we need to create a page where the database_id is the parent. You can reference &lt;a href="https://developers.notion.com/reference/post-page"&gt;https://developers.notion.com/reference/post-page&lt;/a&gt; to get a better sense of what this means.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const axios = require('axios')
const cors = require('cors')
const app = express()
const port = 3002

// REPLACE! Retrieved from https://www.notion.so/my-integrations
const secretKey = 'secret_***************'

// What we'll pass into axios
const headers = {
  'Content-Type': 'application/json',
  Authorization: `Bearer ${secretKey}`,
  'Notion-Version': '2021-08-16',
}

// NEW! This is a new route that will actually send the information to Notion
app.post('/:database_id', async (req, res) =&amp;gt; {
  const { database_id } = req.params
  const { name, email } = req.body
  await axios({
    method: 'POST',
    url: 'https://api.notion.com/v1/pages',
    headers,
    data: {
      parent: { database_id },
      properties: {
        "Name": { "title": [{ text: { content: name } }] },
        "Email": { "email": email }
      }
    }
  })
})

// Route to fetch 
app.get('/:database_id', async (req, res) =&amp;gt; {
  const { database_id } = req.params;
  const resp = await axios({
    method: 'GET',
    url: 'https://api.notion.com/v1/databases/' + database_id,
    headers
  });
  return res.json(resp.data)
})

app.use(cors())
app.use(express.json())
app.listen(port, () =&amp;gt; {
  console.log(`Example app listening on port ${port}`)
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we get this up and running and we restart our backend by quitting and rerunning node app.js , we can input a name and email into our form and it will save to our Notion database! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nDkYC8if--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gn53w7ivnlitpehgy01n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nDkYC8if--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gn53w7ivnlitpehgy01n.png" alt="Saved database" width="880" height="595"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Bonus: For next time
&lt;/h3&gt;

&lt;p&gt;So this has been a tutorial on how to save form responses to YOUR Notion database, but this doesn’t explain how we at Commotion are able to save responses to ANYONE’s Notion database. This requires making your integration a public one and having your user connect their Notion account like how we do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UN7bN2Fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2byeys7a40thc8q6ajy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UN7bN2Fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2byeys7a40thc8q6ajy.png" alt="Connect with Notion" width="880" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bCJrBQky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgvzxaf1ii75z7gwiotj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCJrBQky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgvzxaf1ii75z7gwiotj.png" alt="Notion connector" width="880" height="696"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We’ll save this for another time, but it’s not actually too bad. We’re 75% of the way there already. In the mean time, please check out Commotion if you need to create forms that work with your Notion workspace or want to send emails to contacts in a Notion database, mail merge style. We hope that this was informative!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to add forms to Notion</title>
      <dc:creator>Ryan</dc:creator>
      <pubDate>Thu, 07 Oct 2021 21:22:33 +0000</pubDate>
      <link>https://forem.com/up_to_nonsense/how-to-add-forms-to-notion-38dg</link>
      <guid>https://forem.com/up_to_nonsense/how-to-add-forms-to-notion-38dg</guid>
      <description>&lt;p&gt;Hi Dev.To! This article will explain how to integrate forms with Notion with &lt;a href="https://commotion.page"&gt;Commotion.Page&lt;/a&gt;. With Commotion, you can create forms that you can embed in Notion pages and that save results into a Notion database, so you never need to leave the platform. Here's how you get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a Notion database
&lt;/h3&gt;

&lt;p&gt;This one is fairly straightforward. Go into your Notion workspace and create a Notion database like below.&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NPv0vnXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/createDatabase.59a785ea.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NPv0vnXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/createDatabase.59a785ea.gif" alt="Create a Database" width="600" height="396"&gt;&lt;/a&gt;&lt;br&gt;
  From here, you can add and remove columns to fit what you need. Each column can have a specified type, like a number, text, email, file, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Create a Commotion account
&lt;/h3&gt;

&lt;p&gt;Head over to &lt;a href="https://commotion.page"&gt;&lt;b&gt;Commotion.page&lt;/b&gt;&lt;/a&gt; and sign up for an account. It's a freemium service, so sign up and check it out for free for as long as you like and upgrade to Pro only when you want!&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Connect to your Notion account
&lt;/h3&gt;

&lt;p&gt;You'll need to connect your Notion account in order to create forms with Commotion. Don't worry, Notion has a super easy flow, so just press the connect button, select which pages you want to create forms for, and hit allow access.&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S8yuegTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/connect.da10f557.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S8yuegTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/connect.da10f557.gif" alt="Connect to Notion" width="600" height="392"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Select a Notion database
&lt;/h3&gt;

&lt;p&gt;Now that you've connect your Notion account, let's actually start creating forms. Head to the dashboard and hit the "Create a New Form" button, and we'll get started. Select which workspace and page that contains the database you want to save to. Then, hit "Create Form".&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LUm54R38--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/selectDatabase.68d7fbb9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LUm54R38--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/selectDatabase.68d7fbb9.gif" alt="Select Notion Database" width="600" height="389"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Configure this new form
&lt;/h3&gt;

&lt;p&gt;This is where things get fun. If you're in a rush, you don't need to do anything, just hit "Create Form" and you're set. However, this is where Commotion starts to shine. Firstly, you can update the title of the form and add a description. Additionally, you can drag each question around to the order you want them to appear, and then do things like update the title of a question, the default value, the placeholder text, and any additional info, and even make questions required or just hidden from the form.&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xOWJG2ON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://commotion.page/assets/create.279b7d55.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xOWJG2ON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://commotion.page/assets/create.279b7d55.jpg" alt="Configure form" width="880" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Those are the basics. If you upgrade to our Pro plan, you can do even more with Commotion. For the form, you can add page breaks that paginate the form, changing it from one long list of questions to several screens that users can go between. Very stylish. Also, you can add a password so only some people can see and fill out the form. Finally, our Pro plan supports file uploading, so if you're collecting resumes for example, you can create a simple resume drop form here.&lt;/p&gt;

&lt;p&gt;Another perk of our Pro plan is the functionality once someone does fill out a form. With the Pro plan, once someone completes the form, you can receive an email with that person's response and a confirmation email can be sent to the responder as well. Additionally, if you want to do more with the data, you can send it to a webhook of your choosing. Easy peasy.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Share and embed the new form
&lt;/h3&gt;

&lt;p&gt;Once you hit "Create Form", you'll be moved to a page that has a link you can embed. With this embed link, you can paste it into a Notion page.&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8eVdy2F_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/embed.78f178d9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8eVdy2F_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://commotion.page/assets/embed.78f178d9.gif" alt="Embed Notion form" width="600" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can embed this link anywhere. The most common way to do this is using an &lt;b&gt;iframe&lt;/b&gt; like so...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;iframe height="530" width="490" src="https://commotion.page/embed/..."&amp;gt;&amp;lt;/iframe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... where you adjust the height and width and src link. You can paste this in anywhere you write html.&lt;/p&gt;

&lt;p&gt;If you don't want to go through the hassle, you can also just hit "View Form" and share the link for people to fill out.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Start collecting responses!
&lt;/h3&gt;

&lt;p&gt;You're all done! You can now sit back and just collect responses in your Notion database.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
