Quick start
Let's get you up and running on Forest Admin in minutes!

Step 1: Create an account and follow the onboarding

Go to https://app.forestadmin.com/signup, create an account and install your project.
For the purpose of this tutorial, we have used this database. Feel free to use it if you don't have one.
At the end of your onboarding, you will out-of-the-box be able to:
  • Access all your data (1)
  • Export your data (2)
  • Add a record (3)
  • View and edit a record (4)
  • Edit your UI (5)
  • Search and filter (6)
However, your business logic likely requires more features. What if you need to...
  • refund an order
  • upload new documents, accept or reject them, or ask customers to update their documents,
  • contact a customer or ask a team member to perform an action,
  • and much more?
It's possible with smart actions
👇

Step 2: Create a Smart Action

Let's say you want to let your customer support team to easily refund orders, you can quickly create a smart action.
SQL
MongoDB
Rails
Django
Laravel
Declare it in your /forest/orders.js file:
/forest/orders.js
1
const { collection } = require('forest-express-sequelize');
2
3
collection('orders', {
4
actions: [{
5
name: 'Refund order'
6
}],
7
});
Copied!
Then implement it according to your business logic:
1
...
2
3
router.post('/actions/refund-order', permissionMiddlewareCreator.smartAction(), (req, res) => {
4
// Add your own logic, like calling a Stripe API for instance
5
res.send({ success: 'Order refunded!' }));
6
});
7
8
...
9
10
module.exports = router;
Copied!
Declare it in your /forest/orders.js file:
/forest/orders.js
1
const { collection } = require('forest-express-mongoose');
2
3
collection('orders', {
4
actions: [{
5
name: 'Refund order'
6
}],
7
});
Copied!
Then implement it according to your business logic:
1
...
2
3
router.post('/actions/refund-order', permissionMiddlewareCreator.smartAction(), (req, res) => {
4
// Add your own logic, like calling a Stripe API for instance
5
res.send({ success: 'Order refunded!' }));
6
});
7
8
...
9
10
module.exports = router;
Copied!
Declare it in your /lib/forest_liana/collections/order.rb file:
/lib/forest_liana/collections/order.rb
1
class Forest::Order
2
include ForestLiana::Collection
3
4
collection :Order
5
6
action 'Refund order'
7
end
Copied!
Then declare the corresponding route:
/app/controllers/forest/orders_controller.rb
1
Rails.application.routes.draw do
2
# MUST be declared before the mount ForestLiana::Engine.
3
namespace :forest do
4
post '/actions/refund-order' => 'orders#refund_order'
5
end
6
7
mount ForestLiana::Engine => '/forest'
8
end
Copied!
Lastly, implement the action according to your business logic:
1
class Forest::OrdersController < ForestLiana::SmartActionsController
2
def refund_order
3
# Add your own logic, like calling a Stripe API for instance
4
render json: { success: 'Order refunded!' }
5
end
6
end
Copied!
Note that Forest Admin takes care of the authentication thanks to the ForestLiana::SmartActionsController parent class controller.
You may have to add CORS headers to enable the domain app.forestadmin.com to trigger API call on your Application URL, which is on a different domain name (e.g. localhost:8000).
Declare it in your app/forest/orders.py file:
app/forest/orders.py
1
from django_forest.utils.collection import Collection
2
from app.models import Order
3
4
class OrderForest(Collection):
5
def load(self):
6
self.actions = [{
7
'name': 'Refund order'
8
}]
9
10
Collection.register(OrderForest, Order)
Copied!
Make sure your project urls.py file include you app urls with the forest prefix.
urls.py
1
from django.contrib import admin
2
from django.urls import path, include
3
4
urlpatterns = [
5
path('forest', include('app.urls')),
6
path('forest', include('django_forest.urls')),
7
path('admin/', admin.site.urls),
8
]
Copied!
Then declare the corresponding route:
app/urls.py
1
from django.urls import path
2
from django.views.decorators.csrf import csrf_exempt
3
4
from . import views
5
6
app_name = 'app'
7
urlpatterns = [
8
path('/actions/refund-order', csrf_exempt(views.RefundOrderView.as_view()), name='refund-order'),
9
]
Copied!
Lastly, implement the action according to your business logic:
app/views.py
1
from django.http import JsonResponse
2
from django_forest.utils.views.action import ActionView
3
4
5
class RefundOrderView(ActionView):
6
7
def post(self, request, *args, **kwargs):
8
# Add your own logic, like calling a Stripe API for instance
9
10
return JsonResponse({'success': 'Order refunded!'})
Copied!
Note that Forest Admin takes care of the authentication thanks to the ActionView parent class view.
You may have to add CORS headers to enable the domain app.forestadmin.com to trigger API call on your Application URL, which is on a different domain name (e.g. localhost:8000).
Declare it in your app/Models/Order.php file:
app/Models/Order.php
1
/**
2
* @return SmartAction
3
*/
4
public function refundOrder(): SmartAction
5
{
6
return $this->smartAction('single', 'refund order');
7
}
Copied!
Then declare the corresponding route:
routes/web.php
1
Route::post('forest/smart-actions/order_refund-order', [OrdersController::class, 'refundOrder']);
Copied!
Lastly, implement the action according to your business logic:
app/Http/Controllers/OrdersController.php
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use ForestAdmin\LaravelForestAdmin\Http\Controllers\ForestController;
6
use Illuminate\Http\JsonResponse;
7
8
/**
9
* Class OrdersController
10
*/
11
class OrdersController extends ForestController
12
{
13
/**
14
* @return JsonResponse
15
*/
16
public function refundOrder(): JsonResponse
17
{
18
return response()->json(
19
['success' => 'Order refunded!']
20
);
21
}
22
}
Copied!
Congrats! Now it's possible to refund an order!

Step 3: Deploy to Production

Now that you have a fully functional admin panel, the next logical step is to make it live, with your live (production) data. Click on Deploy to Production and follow the flow.
That's it! You are now fully operational on Forest Admin.
Next, we recommend reading about our recommended development workflow.