Skip to content

Connecting to the Notion API

Leo Heng edited this page May 1, 2024 · 3 revisions

Creating a Notion Database

All databases are stored within the HackMelbourne Website Workspace within Notion. Ask your website director if you do not have permission to access this. Within the workspace, all accessible databases are stored within "website dynamic content" page.

Creating a new database

  1. Navigate into "website dynamic content"
  2. Create a new page by typing /page
  3. Click into the page and type /database to create a new database

Customising the database

  • You can create new entries with the tables and add in attributes that are able to be accessed.
  • The view of the database can be anything but "table" and "board" are the most useful. Select whatever makes the most sense for your task
  • IMPORTANT: Only fields within the database can be queried within this guide. This means that whatever you write in the content part of the page will be unavailable. (Though it is possible to get, but requires a bit more work)

image

Fetching from the Notion DB

We will use Firebase cloud functions to perform this action and return the information through firebase to our front-end.

Setting up environment files

.env files are sensitive data that will not be available on github as it contains the notion API key. To create this file open the HackMelbourne.github.io folder

  1. Navigate INTO the functions folder
  2. Create a new .env file WITHIN the functions folder

Your folder structure should look like this:

HACKMELBOURNE.GITHUB.IO
    > functions
        .env
  1. Paste the API key your website director gave you

Getting the Notion DB key

  1. Make sure you open your database as a full page (if your page is an inline db) image
  2. Select the first part of the link in the url image That is your database id (this is not confidential)

Coding the serverless function with firebase

  1. Here is a template code:
    const { Client } = require("@notionhq/client");
    const notion = new Client({ auth: process.env.NOTION_KEY });
    
    exports.getEventCalendar = onCall(
      {
        cors: CORSLIST,
        region: SERVERLOCATION,
      },
      async () => {
    	  // This is your database ID see step 2
        const databaseId = "f619a35d55c54430960cc6252308fd74";
    
        try {
          // Fetching Notion Data
          const response = await notion.databases.query({
            database_id: databaseId
          });
    
          // Parse Notion Data to the required format
    
          return result;
        } catch (e) {
          return e;
        }
      },
    );
  1. Change the databaseId to the Id you copied above
  2. Update the logic within the try-catch statement with relevant filters and sorting see below for more info
    1. API doc https://developers.notion.com/reference/post-database-query
    2. Filter doc https://developers.notion.com/reference/post-database-query-filter
    3. Sort doc https://developers.notion.com/reference/post-database-query-sort
    4. Example
const response = await notion.databases.query({
  database_id: databaseId,
  // Filter is an object
  filter: {
    property: "Status",
    select: {
      equals: "Live",
    },
  },
  // Sorts is a list
  sorts: [
    {
      property: "Date",
      direction: "ascending",
    },
  ],
});
  1. Transform the data into whatever the front end requires
    • Note: Notion will return an object with a lot more information than you need
    • It is highly recommended you return an object that removes all the unnecessary bits and pieces
    • To test the output you can just console.log the response on the front end

Retrieving the data in the front-end

  1. Create a new file within src/services/..
  2. Import functions and httpsCallable
import { functions } from "../firebase"; // Note this route will change as it is a relative route
import { httpsCallable } from "firebase/functions";
  1. Import the typescript interface for the data output ( VERY IMPORTANT FOR CODE QUALITY). See other services files for reference
  2. Create async function
export async function getEventCalendar(): Promise<CalendarItemProps[]> {
  try {
    console.log("testing");
    let result = await httpsCallable(functions, "getEventCalendar")();
    return result.data as CalendarItemProps[];
  } catch (e) {
    console.log(e);
    return [];
  }
}
  1. Call your function where you need it
    • You’ll likely use useEffectand useState from react
    • You should implement a loading animation aswell
const Hackiethon = () => {
  const [brackets, setBrackets] = useState<TournamentBracketProps[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  useEffect(() => {
    setIsLoading(true);
    getHackiethonBrackets().then((result) => {
      setBrackets(result);
      setIsLoading(false);
    });
  }, []);

  return (
    <>
      <TitleHero
        pageTitle="Hackiethon"
        pageDescription="The hackiethon tournament bracket. Best of luck to every participant"></TitleHero>
      <div className="max-w-screen-lg mx-auto mt-24 flex flex-col items-center gap-12">
        {isLoading ? (
          <CircularProgress />
        ) : (
          brackets.map((value, key) => {
            return <TournamentBracket title={value.title} link={value.link} key={key}></TournamentBracket>;
          })
        )}
      </div>
    </>
  );
};

FAQ

I am getting CORs issue

  1. Check if the function you are exporting in the backend (functions folder) is the same name as the function you are calling in the front end
  2. Check if your local backend server is running ( something like http://127.0.0.1:4000/functions )
  3. Reinstall your node dependencies for the backend
    1. Delete functions/package-lock.json
    2. Delete functions/node_modules
    3. Run npm install WITHIN functions folder