Developer Guide For Lumber

Getting Started


Lumber is an opensource tool used to generate a fully functional admin interface using Forest. It instantly provides all common admin tasks such as CRUD operations, search, sort, user group management, WYSIWYG interface editor and more. That’s what makes Forest a quick and easy solution to get your admin interface started.

This guide assists developers in having the admin completely tailored to cater to their specific needs. We’ve developed Forest so that your admin is 100% customizable. It means that you have full control over your data, your back-end business logic and the UI.

Forest provides a very simple API-based framework to handle all parts of your admin back-end configuration. You should be good to go in no time, with virtually no investments of time and resources.

This documentation is entirely based on the Forest Live Demo project generated by Lumber and hosted on Github here. A database dump (PostgreSQL) is also available if you want to run the Live Demo on your side. This project tends to illustrate with working examples all the possible features and available options. Please refer to the data model below every time you need it to get a global overview of the collections and relationships used everywhere in our examples.

Live Demo data model



Forest allows to handle even the most complex scenarios. The Smart label enables you to implement your own business logic with code, when necessary. Check this page out for more details on all Smart features

Term Definition
Admin API The API generated by the Forest Liana to manage all your application data and business operations.
Collection A set of records having the same type usually stored in the database.
Data Token A token used to authenticate your requests on your Admin API.
Field An attribute of a collection.
Forest Liana The locally-installed plugin that analyzes your data model and generates the Admin API
Forest UI The web application of Forest Admin, accessible from any browser at
Forest UI Schema A schema of your data model generated by the Forest Liana in order to initialize your Forest UI
FOREST_AUTH_SECRET A private token - chosen by yourself - used to sign the data token.
FOREST_ENV_SECRET A private token - given by Forest Admin - used to identify your project environment in Forest.
DATABASE_URL The path to the database used by your app.
Relationship A connection between two collections.
Segment A subset of a collection gathering filtered records.
Smart Action A button that triggers server-side logic.
Smart Collection A group of records gathered from different sources and implemented following your business logic.
Smart Field A field that displays a computed value in your collection
Smart Relationship A relationship that displays a link to another collection.
Smart Route A route is simply the mapping between an API endpoint and the business logic behind this endpoint.
Smart View A custom view you can code using HTML/CSS/JSS to display data in any way you want.

For the purpose of this guide and our Live Demo, we use third parties librairies that will be present in our coding examples:

How it works

Before you start writing a single line of code, it’s a good idea to get an overview of how Forest works with Lumber. The magic of Forest lies in its architecture. Forest is divided into two main components:

  • The Forest Liana is an open-source plugin that analyzes all your data model and generate the Admin API.
  • The Forest UI (web application), accessible from any browser, that handles communication between the admin user and the database through the Admin API.


When you launch your admin backend, the Forest Liana sends a schema - the Forest UI Schema - to the Forest’s servers to initialize the UI.

Data Privacy

The main advantage of Forest’s architecture is that absolutely no data transits or crosses our servers. The user accesses application data directly from the client and Forest is just deployed as a service to display and interact with the data. Read more about hosting.

With Forest, your data are transferred directly from your application to your browser while remaining invisible to our servers. See how it works.



We use a two-step authentication to connect you to both Forest’s server and your Admin API.

The first step is to retrieve your UI configuration. When logging into your account, your credentials are sent to the Forest’s server which returns the UI token to authenticate your session.

The second step is to authenticate to your admin backend (generated by Lumber) to get access to your data. Your password is sent to your Admin API which returns the Data token signed by the FOREST_AUTH_SECRET you chose. Each of your requests to your Admin API are authenticated with the Data Token.

In a nutshell, your admin uses the UI token to make request about the UI configuration. Then the Data Token is used to make queries on your Admin API to manage your data. All our tokens are generated using the JWT standard.



If you haven’t done it yet, you should have Forest installed on your application. The relevant information is below. You should be set up in no more than a few minutes. If you encounter any issue, feel free to drop us a line at or using the live chat available on our homepage.

Update your models’ definition

The command lumber update will update your models’ definition according to your database schema. It will automatically add your new tables and fields.

⚠️ Please note that the command works for adding tables and fields but not for deleting. In this case, it will have to be done manually.

Deploy to production

After installing and customizing (see all the sections below) your admin, it’s time to deploy it to your production server. Then, you will be ready to onboard all your admin users and start using it in live.

You’re free to deploy your admin backend wherever you want but if you have no clue we recommend to use Heroku. This is where we’ve deployed our Forest Live Demo project.

Deploy to production 1

After clicking on the “Deploy to production” link, you must provide your FOREST_ENV_SECRET, the FOREST_AUTH_SECRET and the DATABASE_URL in the environment variables of your production server.

Then, fill the Application URL field. In our case, the Application URL is

We strongly recommend entering a HTTPS Application URL for security reason. Forest Admin will adapt its protocol based on your Application URL.

Deploy to production 2

Last but not least, it wouldn’t be convenient to configure your UI from scratch again on your Forest Production environment. Forest gives you the possibility to copy the layout from one environment to another. Here, we will copy the Development environment layout to your Production environment.

Deploy to production 3

You’re now ready to use Forest on production and invite all your teammates!

Admin API

What is the Admin API?

The Admin API is a REST API generated automatically by the Forest Liana when you launch your admin backend. This API covers all the common requirements of a fully functional Admin Interface (CRUD operations, search & filters, sort, pagination and more). The API is hosted on your side, so you have virtually no limitation to extend it.

However, to ease the customization of your admin, we’ve introduced the concept of Smart features which helps you to fully extend the API.

Before you start to deep dive into this documentation, it’s a good idea to see how the Admin API is designed.

Retrieving the admin user details

Everytime you interact with your application data from the Forest UI, it triggers an API call to your admin backend. This API call is authenticated using the Data Token. This token is a JWT token signed with your FOREST_AUTH_SECRET (see the Security section for more information) and it is passed to the HTTP request through the Authorization header.

The JWT Data Token contains all the details of the admin user. From a route, you can retrieve them with the variable req.user. On our Live Demo example, we’ve developed a Whoami global Smart Action available that returns the full name of the admin user.

Admin API 1

Configuring the CORS headers

When Lumber generates your admin backend, the CORS headers are automatically configured for you in the app.js file. These headers allow the domain to trigger an API call on your Application URL, which is a different domain name (e.g. localhost:3000).


What is route?

A route is simply the mapping between an API endpoint and the business logic behind this endpoint. In other words, the Admin API automatically generated by the Forest Liana consists of a series of routes.

What is a Smart Route?

Very often, you’ll need to be able to call business logic from your main/customer-facing application to avoid code duplication between your admin and your app. Another typical use case is simply to trigger a verification business logic before executing the logic.

So in summary, the Smart Route feature allows you to extend the default behavior of a Route.

On our Live Demo, we’ve overridden the DELETE /forest/companies/:companyId API call to only allow admin users that are part of the Management team. If you’re in the right team, we call simply next() to trigger the default DELETE implementation.

Admin API 2


What is an action?

An action is a button that triggers server-side logic through an API call. Without a single line of code, Forest supports natively all common actions required on an admin interface such as CRUD (Create, Read, Update, Delete), sort, search, data export, and more.

What is a Smart Action?

Sooner or later, you will need to perform actions on your data that are specific to your business. Moderating comments, logging into a customer’s account (a.k.a impersonate) or banning a user are exactly the kind of important tasks to unlock in order to manage your day-to-day operations.

On our Live Demo example, our companies collection has many examples of Smart Action. The simplest one is Mark as live.

Different types of Smart Action

3 types of Smart Actions are available in Forest:

  • Bulk (default) : The Smart Action will be available on one or several selected records. You can select one or more records directly from the table view to perform your action. Then, this Smart Action will appear on the list of available actions.
  • Single : The Smart Action will only be available for a single record. You will be able to see this action only in the detail (or summary) view of the record.
  • Global : The Smart Action will only be available at a Collection level and does not target any specific record.

To specify the type of a Smart Action, use the option type.

On our Live Demo example, Mark as Live is a Bulk Smart Action, Upload Legal Docs is a Single Smart Action and Import data is a Global Smart Action.

Creating a Smart Action

In the following example, the file forest/companies.js contains the Smart Action declaration. After declaring your Smart Action, your Forest Admin UI will be updated with a new button baring the label of this new action.

If you click on this new button, your browser will make an API call POST /forest/actions/mask-as-live. If you want to customize the call, check the list of available options.

The payload of the HTTP request is based on a JSON API document. The data.attributes.ids key allows you to retrieve easily the selected records from the UI and the data.attributes.values key contains all the values of your input fields (handling input values).

At this time, there’s no Smart Action Implementation because no route in your Admin backend handles the API call yet. In the file /routes/companies.js, we’ve created a new route to implement the business logic behind the “Mark as Live” button.

Forest takes care of the authentication thanks to the Liana.ensureAuthenticated middleware.

The business logic in this Smart Action is extremely simple. We only update here the attribute status of the companies to the value live.

Smart Action 1

Available Smart Action options

Here are the list of available options to customize your Smart Action:

Name Type Description
name string Label of the action displayed in Forest.
type string (optional) Type of the action. Can be bulk, global or single. Default is bulk. Check the different types of Smart Actions section for more details.
fields array of objects (optional) Check the handling input values section.
download boolean (optional) If true, the action triggers a file download in the Browser. Default is false
endpoint string (optional) Set the API route to call when clicking on the Smart Action. Default is 'forest/actions/name-of-the-action-dasherized'
httpMethod string (optional) Set the HTTP method to use when clicking on the Smart Action. Default is POST.

Opening a form to ask input values

Very often, you will need to ask user inputs before triggering the logic behind a Smart Action.

For example, you might want to specify a reason if you want to block a user account. Or set the amount to charge a user’s credit card. On our Live Demo example, we’ve defined 4 input fields on the Smart Action Upload Legal Docs on the collection companies.

Smart Action 2

Handling input values

Here are the complete list of available options to customize your input form.

Name Type Description
field string Label of the input field.
type string Type of the input field. Can be Boolean, Date, Dateonly, Number, String, File or Enum.
enums array of strings (optional) Required only for the Enum type. This is where you list all the possible values for your input field.
description array of fields (optional) Add a description for your admin users to help them fill correctly your form
isRequired boolean (optional) If true, your input field will be set as required in the browser. Default is false.

Prefill a form with default values

Forest Admin allows you to set default values to your form. In this example, we will prefill the form with data coming from the record itself (1), with just a few extra lines of code.

Smart Action Default Value

⚠️ Prefilling a form with default values only works for Single type Smart Actions. See what a Smart Action's type is here.

Customizing response

Default success notification

Returning a 204 status code to the HTTP request of the Smart Action shows the default notification message in the browser.

On our Live Demo example, if our Smart Action Mark as Live route is implemented like this:

We will see a success message in the browser”

Custom success notification

If we return a 200 status code with an object { success: '...' } as the payload like this…

… the success notification will look like this:

Custom error notification

Finally, returning a 400 status code allows you to return errors properly.

Custom HTML response

You can also return a HTML page as a response to give more feedback to the admin user who has triggered your Smart Action. To do this, you just need to return a 200 status code with an object { html: '...' }.

On our Live Demo example, we’ve created a Charge credit card Smart Action on the Collection customers that returns a custom HTML response.

Action 10

Downloading a file

On our Live Demo, the collection customers has a Smart Action Generate invoice. In this use case, we want to download the generated PDF invoice after clicking on the action. To indicate a Smart Action returns something to download, you have to enable the option download.

Smart Action 3

If you want to create an action accessible from the details or the summary view of a record involving related data, this section may interest you.

In the example below, the “Add new transaction” action (1) is accessible from the summary view (2). This action creates a new transaction and automatically refresh the “Emitted transactions” related data section (3) to see the new transaction.

Refresh related data

Below is the sample code. We use faker to generate random data in our example. Remember to install it if you wish to use it (npm install faker or yarn install faker).

Configuring the accessibility of a Smart Action

Enable/Disable a Smart Action according to the state of a record

Sometimes, your Smart Action only makes sense depending on the state of your records. On our Live Demo, it does not make any sense to enable the Mark as Live Smart Action on the companies collection if the company is already live, right?

In the collection settings, you can configure the UI options of your Smart Actions.

Action 11 Action 12

Restrict a smart action to specific users

When using Forest with several teams and when you have clear roles defined it becomes relevant to restrict a smart action only to a few collaborators. This option is accessible through the Edit layout mode (1) in the Smart actions’ section (3) of the collection’s options (2), in a dropdown menu (4).

Restrict Smart Action

Require approval for a Smart action


Critical actions for your business may need approval before being processed.

The option “This smart action requires an approval” (3) is accessible in the Smart action section (1) of your collection’s settings. In our example, the “Approve transaction” action (2) requires approval. You can select approvers among your users(4). Once this option is activated, a warning pop up indicates that the approval workflow is need to perform this action.

Approval workflow 1

Actions requiring approval will be available in the Collaboration menu (5) in the “Approvals” section (6):

  • “Requested” for all incoming requests (yours to approve or not)
  • “To Review” (7) for requests you need to review
  • “History” for all past requests.

In “To Review” you will be able to reject or approve the request (8) with an optional message for more details.

Approval workflow 2

You can access the detail on an action (9) to have more context (10) by clicking on it.

Approval workflow 3


What is a field?

A field is simply an attribute defined in your database. Examples of fields: first name, gender, status, etc.

Customizing a field

Forest allows you to customize how a field appears in your admin interface. You can rename it, choose the right widget to display (e.g. text area, image viewer, Google map), add a description or even set the read/write access.

Field 1

To customize a field, go to Collection Settings -> Fields, then select the field to start configuring it.

What is a Smart Field?

A field that displays a computed value in your collection.

Smart field

A Smart Field is a column that displays processed-on-the-fly data. It can be as simple as concatenating attributes to make them human friendly, or more complex.

Creating a Smart Field

On our Live Demo, the very simple Smart Field fullname is available on the customers collection.

Very often, the business logic behind the Smart Field is more complex and must be asynchronous. To do that, you can simply return a Promise.

In the following example, we illustrate an async logic through our full_address Smart Field also defined in the customers collection.

Smart Field 1

Updating a Smart Field

By default, your Smart Field is considered as read-only. If you want to update a Smart Field, you just need to write the logic to “unzip” the data. Note that the set method should always return the object it’s working on. In the example hereunder, the customer record is returned.

Smart Field 3

Searching on a Smart Field

To perform a search on a Smart Field, you also need to write the logic to “unzip” the data, then the search query which is specific to your zipping. In the example hereunder, the firstname and lastname are searched separately after having been unzipped.

If you are working with Async, you can also return a Promise.

Smart Field 4

⚠️ Note that, sorting on Smart Field is not supported in Forest. Indeed, being able to sort on Smart Field would mean that we have to compute the Smart Field values for all the records of your collection, and then sort the records on this value.

While this is something we could implement, it would not be something scalable. Imagine if your collection has millions of records.

If this sorting is really important for your operations, you should consider the creation of a dedicated column in the database.

Restrict the search on specific fields

Sometimes, searching on all fields is not relevant and may even involve big performance issues. You can restrict the search on specific fields only using the option searchFields, which should be defined in your forest/ folder. In this example, we configure Forest to only search on the fields name and industry of our collection Company.

Available Field Options

Here are the list of available options to customize your Smart Field:

Name Type Description
field string The name of your Smart Field.
type string Type of your field. Can be Boolean, Date, Dateonly, Enum, File, Number or String.
enums array of strings (optional) Required only for the Enum type. This is where you list all the possible values for your input field.
description string (optional) Add a description to your field.
reference string (optional) Configure the Smart Field as a Smart Relationship.
widget string (optional) Configure the widget to display in the browser. Can be color picker, document viewer, file picker, image viewer, JSON editor, link, map, price, rich text editor, text area or text input
isReadOnly boolean (optional) If true, the Smart Field won’t be editable in the browser. Default is true if there’s no set option declared.
isRequired boolean (optional) If true, your Smart Field will be set as required in the browser. Default is false.

Note that if you are choosing the date picker widget for a date field, you will be able to change the format. Please refer to momentjs syntax for formatting options.

Available Widget Options

Widgets fields can be very handy and a great time saver to users with no technical knowledge. Depending on the type of your field, you can choose different widgets (see list below). You can find these options in your collection settings under the fields section.

Depending on the field type in your DB, you have different choices of Widgets available:

Type Widget Description
string link Display clickable link instead of a raw string
  text area Enlarge the text area.
  color picker Change the field to a color picker (hexadecimal code).
  image viewer Display an image instead of a URL link.
  file picker Add a file from your computer.
  rich text editor Write formatted text.
  JSON editor Display a JSON field.
  dropdown Put a drop-down menu of fields among pre-defined options.
  document viewer Display your document in a preview window.
  map Display a location on a map (⚠️ your field must be a “string” respecting the following format “lat, long”).
  address Allow auto-complete on an address field.
date text input Convert your date into a string.
  date picker Use the date picker to select a date.
number/integer belongsTo select Display a dropdown list of related data.
  price Compute your number in the currency of your choice.
array carrousel Display an array of images URLs as a carrousel.

You can see below some of the widgets and how they look:

Widgets list


What is a relationship?

A relationship is a connection between two collections.

Forest supports natively all the relationships defined in your Sequelize models (belongsTo, hasMany, …). Check out the section Adding the relationships for more details.


Adding the relationships

As Lumber generates an admin microservice from the database schema, it only creates belongsTo relationships, based on all your foreign keys. Please note that some ORMs do not create foreign key constraints. This means that in some cases, you will have to add belongsTo relationships manually. Lastly, as databases don’t have the notion of inverse relationships, you will need to add hasMany or hasOne relationships manually.

All Lumber-based admins use the Sequelize ORM to manage data models. Check out their documentation if you need more information.

Adding a BelongsTo relationship

On our Live Demo example, the Address model has a foreignKey customer_id that points to the Customer. In other words, an Address belongsTo a Customer. We’ve declared this relationship in the file models/addresses.js.

Adding Relationship 1

Adding a HasOne relationship

HasOne relationships are the opposite of BelongsTo relationships. Taking the same example as before, the opposite of the Address belongsTo a Customer is simply a Customer hasOne Address.

Adding Relationship 2

Adding a HasMany relationship

The Customer has one Address but can have multiple Orders. In that case, we have to use HasMany instead of HasOne relationships.

Adding Relationship 3

What is a Smart Relationship?

Sometimes, you want to create a virtual relationship between two set of data that does not exist in your database. A concrete example could be creating a relationship between two collections available in two different databases. Creating a Smart Relationship allows you to customize with code how your collections are linked together.

Creating a BelongsTo Smart Relationship

On the Live Demo example, we have an Order belongsTo a Customer belongsTo an Address. We’ve created here a BelongsTo Smart Relationship that acts like a shortcut between the Order and the delivery Address. In this example, ref defines a field in the Orders collection, you could replace with the most appropriate field of your own collection.

A BelongsTo Smart Relationship is created like a Smart Field with the reference option to indicates on which collection the Smart Relationship points to.

Smart Relationship 2

Creating a HasMany Smart Relationship

On the Live Demo example, we have a Product hasMany Orders and an Order belongsTo Customer. We’ve created a Smart Relationship that acts like a shortcut with Product hasMany Customer (buyers).

A HasMany Smart Relationship is created like a Smart Field with the reference option to indicates on which collection the Smart Relationship points to.

Upon browsing, an API call is triggered when accessing the data of the HasMany relationships in order to fetch them asynchronously. In the following example, the API call is a GET on /products/:product_id/relationships/buyers.

We’ve built the right SQL query using Sequelize to count and find all customers who bought the current product.

Then, you should handle pagination in order to avoid performance issue. The API call has a querystring available which gives you all the necessary parameters you need to enable pagination.

Finally, you don’t have to serialize the data yourself. The Forest Liana already knows how to serialize your collection (customers in this example). You can access to the serializer through the Liana.ResourceSerializer object.

Smart Relationship 3


What is a collection?

A collection is a set of data elements physically stored in the database displayed in tabular form (by default), with rows (i.e. records) and columns named (i.e. fields). A collection has a specified number of columns, but can have any number of rows.

Forest automatically analyses your data models and instantly make your collections available in the Forest UI. It covers the majority of use cases. If needed, you can create a Smart Collection to go one step further in the customization of your admin.

What is a Smart Collection?

A Smart Collection is a Forest Collection based on your API implementation. It allows you to reconcile fields of data coming from different or external sources in a single tabular view (by default), without having to physically store them into your database.

Fields of data could be coming from many other sources such as other B2B SaaS (e.g. Zendesk, Salesforce, Stripe), in-memory database, message broker, etc.

Creating a Smart Collection

On our Live Demo, we’ve stored the Legal Documents of a Company on Amazon S3. In the following example, we show you how to create the Smart Collection to see and manipulate them in your Forest admin.

First, we declare the legal_docs collection in the forest/ directory. In this Smart Collection, all fields are related to S3 attributes except the field is_verified that is stored on our database in the collection documents. You can check out the list of available field options here if you need it.

You MUST declare an id field when creating a Smart Collection. The value of this field for each record MUST be unique. On the following example, we simply generate a random UUID.

You can add the option isSearchable: true to your collection to display the search bar.

Implementing the GET (all records)

At this time, there’s no Smart Collection Implementation because no route in your Admin backend handles the API call yet. In the file routes/legal_docs.js, we’ve created a new route to implement the API behind the Smart Collection.

The logic here is to list all the files uploaded on a specific S3 Bucket. We use a custom service services/s3-helper.js for this example. The implementation code of this service is available on Github.

Finally, the last step is to serialize the response data in the expected format which is simply a standard JSON API document. We use the very simple JSON API Serializer library for this task.

Smart Collection 4

Implementing the GET (specific record)

To access the details view of a Smart Collection record, you have to catch the GET API call on a specific record. One more time, we use a custom service services/s3-helper.js that encapsulates the S3 business logic for this example.

The implementation of the reconcileData() and Serializer.serialize() functions are already described in the Implementing the GET (all records) section.

Smart Collection 5

Implementing the PUT

To handle the update of a record we have to catch the PUT API call. In our example, all S3-related fields are set as read-only and only is_verified can be updated.

The implementation of the reconcileData() and Serializer.serialize() functions are already explained in the Implementing the GET (all records) section.

Smart Collection 6

Implementing the DELETE

Now we are able to see all the legal documents on Forest Admin, it’s time to implement the DELETE HTTP method in order to remove the documents on S3 when the admin user needs it.

Smart Collection 7

Implementing the POST

On our Live Demo example, creating a record directly from this Smart Collection does not make any sense because the admin user will upload the legal docs in the company details view. For the documentation purpose, we catch the call and returns an appropriate error message to the admin user.

Smart Collection 8


What is a segment?

A Segment is a subset of a collection gathering filtered records.

Segments are designed for those who want to systematically visualize data according to specific sets of filters. It allows you to save your filters configuration so you don’t have to compute the same actions every day (e.g. signup this week, pending transactions).

Creating a Segment

Simple segment

Forest provides a straightforward UI to configure the segments you want. The only information the UI needs to create a segment within a collection is a name and some filters.

Segment 1

SQL Query segment

Forest gives you a second option to create segment. SQL queries allow you to create advanced filters and connect your data through a few lines of code. In our example, through the Edit layout (1) we access the Transactions collection’s settings (2). Then, in Segments (3), we create a New segment (4) for which we choose a name (5). Pick the Querymode instead of the simple one (6), type in your SQL query (7) and do not forget to save (8).

SQL Segment 1 SQL Segment 2

Creating a Smart Segment

Sometimes, segment filters are complicated and closely tied to your business. Forest allows you to code how the segment is computed.

On our Live Demo example, we’ve implemented a Smart Segment on the collection products to allow admin users to see the bestsellers at a glance.

You’re free to implement the business logic you need. The only requirement is to return a valid Sequelize condition. Most of the time, your Smart Segment should return something like { id: { in: [ 1,2,3,4,5 ] } }.

On our implementation, we use a raw SQL query to filter and sort the product that was sold the most.

Smart Segment 1

Setting up independent columns visibility

By default, Forest applies the same configuration to all segments of the same collection.

However, the “independent columns configuration” option (1) allows you to display different columns on your different segments.

Segment visibility


As an admin user, KPIs are one of the most important things to follow day by day. Your customers’ growth, Monthly Recurring Revenue (MRR), Paid VS Free accounts are some common examples.

Forest can render six types of charts:

  • Single value (Number of customers, MRR, …)
  • Repartition (Number of customers by countries, Paid VS Free, …)
  • Time-based (Number of signups per month, …)
  • Percentage (% of paying customers, …)
  • Leaderboard (Companies who emitted the most transactions, …)
  • Objective (Orders passed per year VS objective, …)

Ensure you’ve enabled the Layout Editor mode to add, edit or delete a chart.

Creating a Chart with the UI

Forest provides a straightforward UI to configure the charts you want.

The only information the UI needs to handle such charts is:

  • 1 collection
  • 1 aggregate function (count, sum, …)
  • 1 group by field
  • 1 time frame (day, week, month, year) option.
  • 1 or multiple filters.

Analytics 8

Creating a Chart on a specific record

Premium feature

Forest’s dashboard is handy when it comes to monitoring the overall KPIs. But you may find the analytics module useful for a more in-depth examination of a specific company, user or any other items.

Analytics 14

“Analytics per record” only supports the Smart and Query mode.

  • For Query charts, use the character ? to inject the current record the user is currently seeing to your query. More details here.
  • For Smart charts, the parameter record_id is automatically passed in the HTTP body to access the record the user is currently seeing.

Creating a Chart with SQL

Premium feature

The Query mode has been designed to provide you with a flexible, easy to use and accessible interface when hard questions need to be answered. Simply type SQL queries using the online editor and visualize your data graphically.

The syntax of the SQL examples below can be different depending on the database type (SQLite, MySQL, Postgres, SQL Server, etc.). Please, refer to your database documentation for more information.

Single value

The returned column must be named value. In the following example, we simply count the number of customers.

Analytics 9

Single value (with growth percentage)

The returned columns must be named value and previous. In the following example, we simply count the number of Appointments booked in January 2018 and compare this value to the number of Appointments booked in the previous month.

Analytics 10


The returned columns must be named key and value. In the following example, we simply count the number of transactions distributed by status.

Analytics 11


The returned columns must be named key and value. In the following example, we simply count the number of appointments per month.

Analytics 12


The returned columns must be named ‘key’ and value and LIMIT must be defined. In the following example, we limited the leaderboard to 12 items.

Leaderboard 1


The returned columns must be named ‘key’ and objective. In the following example, we set manually the objective to 120.

Objective-chart 1

Analytics per account

If you put the character ? in your SQL query, it will automatically be replaced by the current record opened in your Admin. Most of the time, it’s required if you have charts declared in the Analytics per Account section.

Don’t forget this special character with quotes if the type requires it.

In the following example, we compute the number of transactions per month for the company “Deliveroo”. The is an integer here, so there’s no need to quote it.

Analytics 15

Creating a Smart Chart

Sometimes, charts data are complicated and closely tied to your business. Forest allows you to code how the chart is computed. Choose “Smart” as the data source when configuring your chart. Forest will make the HTTP call to Smart Chart URL when retrieving the chart values for the rendering.

Analytics 16

Value Smart Chart

On our Live Demo, we have a MRR value chart which computes our Monthly Recurring Revenue. This chart queries the Stripe API to get all charges made in the current month (in March for this example).

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

Analytics 16

Repartition Smart Chart

On our Live Demo, we have a Charges repartition chart which shows a repartition chart distributed by credit card country. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and check the credit card country.

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

Analytics 17

Time-based Smart Chart

On our Live Demo, we have a Charges time-based chart which shows the number of charges per day. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and group data by day.

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

Analytics 18


What is a view?

A view is simply the way to visualize your data in the Forest UI. By default, Forest renders your data using a table view when you access multiple records and a form view to access, edit and create a specific record.

What is a Smart View?

Premium feature

Smart Views lets you code your view using JS, HTML, and CSS. They are taking data visualization to the next level. Ditch the table view and display your orders on a Map, your events in a Calendar, your movies, pictures and profiles in a Gallery. All of that with the easiness of Forest.

Map View 1

Creating a Smart View

Forest provides an online editor to inject your Smart View code. The editor is available on the collection’s settings, then in the “Smart views” tab.

Smart View 3

The code of a Smart View is an Ember Component and simply consists of a Template and Javascript code.

Don’t panic, you don’t need to know the Ember.js framework to create a Forest Smart View. We will guide you here on all the basic requirements. For more advanced usage, you can still refer to the Ember Component and the Handlebars Template documentations.

Getting your records

The records of your collection are accessible from the records property. Here’s how to iterate over them in the template section:

Accessing a specific record

For each record, you will access its attributes through the forest-attribute property. The forest- preceding the field name is required.

Accessing belongsTo relationships

Accessing a belongsTo relationship works in exactly the same way as accessing a simple field. Forest triggers automatically an API call to retrieve the data from your Admin API only if it’s necessary.

On the Shipping Smart View (in the collection named Order) defined on our Live Demo example, we’ve displayed the full name of the customer related to an order.

Accessing hasMany relationships

Accessing a hasMany relationship works in exactly the same way as accessing a simple field.. Forest triggers automatically an API call to retrieve the data from your Admin API only if it’s necessary.

Refreshing data

Trigger the fetchRecords action in order to refresh the records on the page.

Fetching data

Trigger an API call to your Admin API in order to fetch records from any collection and with any filters you want.

We will use the store service for that purpose. Check out the list of all [available services] from your Smart View.

On our Live Demo example, the collection appointments has a Calendar Smart View. When you click on the previous or next month, the Smart View fetches the new events in the selected month. The result here is set to the property appointments. You can access it directly from your template.

Available parameters

Parameter Type Description
filter Object A list of filters you want to apply. Example filter: { date: '>2018-01-28,<2018-03-11', name: 'Manuela Nolan' }.
filterType String and or or.
timezone String The timezone string. Example: America/Los_Angeles.
page[number] Number The page number you want to fetch.
page[size] Number The number of records per page you want to fetch.

Deleting records

The deleteRecords action lets you delete one or multiple records. A pop-up will automatically ask for a confirmation when a user triggers the delete action.

Triggering a Smart Action

Here’s how to trigger your Smart Actions directly from your Smart Views. You can pass an array or a single record. The first argument is the collection that has the Smart Action. The second argument is the Smart Action name, here Reschedule, and the third argument is an array of records or a single one.

Available properties

Forest automatically injects into your Smart View some properties to help you display your data like you want.

Property Type Description
collection Model The current collection.
currentPage Number The current page.
isLoading Boolean Indicates if the UI is currently loading your records.
numberOfPages Boolean The total number of available pages
records array Your data entries.
searchValue String The current search.

Available actions

Forest automatically injects into your Smart View some actions to trigger the logic you want.

Action Description
deleteRecords(records) Delete one or multiple records.
triggerSmartAction(collection, actionName, record) Trigger a Smart Action defined on the specified collection on a record.


On our Live Demo, we have 4 Smart Views defined:

Example: Map view

Smart View 4

Example: Calendar view

Smart View 5

Example: Shipping view

Smart View 7

Smart View 6


Forest is able to leverage data from third party services by reconciliating it with your application’s data, providing it directly to your admin. All your admin actions can be performed at the same place, bringing additional intelligence to your admin and ensuring consistency.


Premium feature

Configuring the Stripe integration for Forest allows you to have your customer’s payments, invoices and cards (1) alongside the corresponding customer from your application. A Refund Smart Action (2,3) is also implemented out-of-the-box.

Stripe integration 1

On our Live Demo, we’ve configured the Stripe integration on the customers collection. The Stripe Customer ID is already stored on the database under the field stripe_id.

Available options

Here are the complete list of available options to customize your Stripe integration.

Name Type Description
apiKey string The API Secret key of your Stripe account. Should normally starts with sk_.
mapping string Indicates how to reconcile your Customer data from your Stripe account and your collection/field from your database. Format must be model_name.stripe_customer_id_field
stripe library The official Node.js Stripe library NPM package.


Premium feature

The Mixpanel integration allows you to fetch Mixpanel’s events and display them at a record level into Forest.

To benefit from Mixpanel integration, you need to add the package mixpanel-data-export before going further.

Then, add the following code to your app.js file. In our example we will map the with the data coming from Mixpanel. You may replace by your own relevant collection(s).

By default, Mixpanel is sending the following fields: id, event, date, city, region, country, timezone, os, osVersion, browser, browserVersion. If you want to add other fields from Mixpanel, you have to add them in customProperties:

You will then be able to see the Mixpanel events on a record, a Customer in our example.

Mixpanel integration 1


Premium feature

Configuring the Intercom integration for Forest allows you to display your user’s session data (location, browser type, …) and conversations.

You have to add the Intercom integration in your app.js file, as described below. The “mapping” option is the collection on which your integration is pointing.

You will have to restart your server to see Intercom plugged to your project.

Intercom 1

How to’s

Importing data using a CSV file

Forest natively supports data creation but it’s sometimes more efficient to simply import it. This “How-to” shows a way to achieve that in your Forest admin.

In the following example, we’ve created the Smart Action Import data on the collection products which contains two input fields: the CSV file and the Type. The Type input field is completely optional, we use it to import the list of products with the good type set.

When clicking on the Import data Smart Action, an API call to /forest/products/actions/import-data is triggered as indicated in the endpoint parameter of the action. We handle this call in the routes/products.js file.

The CSV file passed into the body of the API call is serialized using a base64 encoding Data URI scheme.

To deserialize the base64 encoded CSV file, we use the NPM package parse-data-uri. We also use the csv parser NPM package to iterate over each line of the CSV file.

You can find a sample CSV file we use here to feed our products table on the Live demo Github repository.

You may find below the coding examples you need to make this Smart action work:

Deploy to production on Heroku

This “How to” is designed to assist people who want to have a step-by-step guide to deploy the Lumber-generated admin to Heroku.

If you don’t have a Heroku account yet, sign up here. Then, create your first Heroku application (1) (2).

Deploy to heroku 1 Deploy to heroku 2

After creating your application, simply follow the Heroku guide “Deploy using Heroku Git” to push the lumber-generated admin code to the Heroku application.

Deploy to heroku 3

After pushing the code using the command git push heroku master, you should have a similar log output:

Your Heroku application is now successfully deployed. The last step to have a complete running application is to deploy a database remotely. In this case, we recommand adding on your Heroku application the free add-on “Heroku Postgres” (1) (2).

Deploy to heroku 4

Once installed, your Heroku application will contain an environment variable DATABASE_URL with the credentials of your freshly created database (1). The “Config Vars” section (2) in the Settings tab is where you will configure the FOREST_ENV_SECRET and FOREST_AUTH_SECRET environment variables later (3).

Deploy to heroku 5

Your new database has no data yet, so you will need to import your local data to this new one. To do that, you first need to create a dump of your local database. Then, you need to import it to the Heroku database.

At this stage, your Heroku application is entirely running with its own database. You can now follow the Forest #deploy-to-production guide to create your production environment on your Forest project.