The DevXP engineering team hosts office hours every Thursday at 11 a.m. Pacific Time where we answer your questions live and help you get up and running with Flatfile. Join us!

Flatfile Spaces are micro-applications, each having their own database, filestore, and auth. A Space is comprised of Workbooks, Files and Users. It can also include Documents, Themes and Metadata.

In this example, we’ll create a simple Space with a Workbook and a Document. We’ll also theme the Space to be red.

Dynamically build your Space

When the “Create New Space” button is clicked from within your App in the dashboard, it triggers a job event within the space domain that initiates a configure operation.

This operation is analogous to performing a POST request to the endpoint /api/v1/spaces with the parameter autoconfigure set to true.

Usage

In the following code, we will:

  1. Filter on the red namespace. (Or replace this with your namespace.)
  2. Filter for a job by the domain (space) and the operation (configure) it was created.
  3. Listen for a job:ready event.
  4. Acknowledge the Job and mark the progress.
  5. Add the contents of the Space, including one Workbook and a simple Document.
  6. Update the space theme to be the color red.
  7. Complete (or fail) the job.
import api from "@flatfile/api";

export default function flatfileEventListener(listener) {
  // Part 1: Setup a listener (https://flatfile.com/docs/apps/custom/meet-the-listener)
  listener.on("**", (event) => {
    // Log all events
    console.log(`Received event: ${event.topic}`);
  });

  listener.namespace(["space:red"], (red) => {
    // Part 2: Configure a Space (https://flatfile.com/docs/apps/custom)
    red.on(
      "job:ready",
      { job: "space:configure" },
      async ({ context: { spaceId, environmentId, jobId } }) => {
        try {
          await api.jobs.ack(jobId, {
            info: "Gettin started.",
            progress: 10,
          });

          await api.workbooks.create({
            spaceId,
            environmentId,
            name: "All Data",
            labels: ["pinned"],
            sheets: [
              {
                name: "Contacts",
                slug: "contacts",
                fields: [
                  {
                    key: "firstName",
                    type: "string",
                    label: "First Name",
                  },
                  {
                    key: "lastName",
                    type: "string",
                    label: "Last Name",
                  },
                  {
                    key: "email",
                    type: "string",
                    label: "Email",
                  },
                ],
              },
            ],
            actions: [
              {
                operation: "submitAction",
                mode: "foreground",
                label: "Submit foreground",
                description: "Submit data to webhook.site",
                primary: true,
              },
            ],
          });

          await api.documents.create(spaceId, {
            title: "Getting Started",
            body:
              "# Welcome\n" +
              "### Say hello to your first customer Space in the new Flatfile!\n" +
              "Let's begin by first getting acquainted with what you're seeing in your Space initially.\n" +
              "---\n",
          });

          await api.spaces.update(spaceId, {
            environmentId,
            metadata: {
              theme: {
                root: {
                  primaryColor: "red",
                },
                sidebar: {
                  backgroundColor: "red",
                  textColor: "white",
                  activeTextColor: "midnightblue",
                },
                // See reference for all possible variables
              },
            },
          });

          await api.jobs.complete(jobId, {
            outcome: {
              message: "Your Space was created.",
              acknowledge: true,
            },
          });
        } catch (error) {
          console.error("Error:", error.stack);

          await api.jobs.fail(jobId, {
            outcome: {
              message: "Creating a Space encountered an error. See Event Logs.",
              acknowledge: true,
            },
          });
        }
      }
    );
  });
}

Run your listener locally and create a new Space

To allow this listener to run, you’ll want to run it locally using the same “develop” command you used when initially setting up the listener.

As a reminder, that command is:

npx flatfile@latest develop typescript/index.ts

Once this is running, click the “Create New Space” button in your dashboard.

Meet your Space

So what did that just do?

In your Flatfile account you should now be able to see your Space.

As you can see, this Space has a Workbook with a sheet and fields. A is like a template, its definition includes a profile of the data it expects to hold. We call that profile a Blueprint.

Blueprint is Flatfile’s robust data definition language (DDL) that emphasizes validation and data preparation. Flatfile APIs leverage Blueprint for their create, update, and read operations.

Watch your Events

Because your listener was running, it logged your activity as the Space was being built. You should see several events that took place.

Now, to watch your listener receive another event, make a few changes in the Workbook. For example, try typing text into a cell.

Typing in a cell (editing a Record) triggers an Event!

console
 ▶ commit:created  10:13:05.159 AM us_evt_1234
 ↳ on(**, {})
 ↳ on(commit:created, {"sheetSlug":"contacts"})

---

## Next steps

Now that you have a Workbook in a Space, which acts both as a schema and destination for your data, you're ready to [Add data transformations](../custom/add-data-transformation.mdx).