We talk a lot about SmartSuite’s capabilities as a work management platform, but we’ve seen people use it in a variety of ways. One of those that I thought was intriguing is the idea of using SmartSuite as a back end for a Web or mobile application. With SmartSuite’s REST API, this is absolutely possible!
In this blog post, we will create a Web app using Node.js that retrieves its data from the SmartSuite API. To keep things relatively simple we’ll just pull information from SmartSuite and display it in our custom app.
Setting up SmartSuite
Setting up your SmartSuite environment for use as a data back-end can be simple (we’ll create a very simple Solution and App in this demo), but remember that you can use all of SmartSuite’s functionality to create a workflow for your data, calculate values with formulas, or use Automations to streamline workflows or interact with external systems.
For purposes of this project, just create a Solution “from scratch” and name it something like SmartSuite Demo. The single App that is created by default will be enough - the only field that I added to the default fields is a Files & Images field,just to demonstrate how we can use some logic to conditionally display its values. It will also show how the field identifier is a generated value that needs to be looked up in SmartSuite’s API documentation.
Your Solution should look something like this:
Other information you will need from your SmartSuite workspace includes:
- Your Workspace Id (account id), which is the eight characters following app.smartsuite.com in your URL
- Your API Key
- The Application Id for your App. You can get that from the URL as well, it’s the second id listed. Here is the format:
https://app.smartsuite.com/[account id]/solution/[solution id]/[App id]/[Report id]
Setting up the NodeJS project
Open your PowerShell (or Bash if you are using Linux, or terminal on Mac) and type these commands to set up basic files of the project:
mkdir smartsuite-demo
cd smartsuite-demo
touch app.js
npm init
Now back to your terminal again and write these commands to install the required packages to our project. It installs Express, axios, body-parser, and EJS:
npm install express ejs axios body-parser
Now, create the folders and files that we need. As you can see, we have 3 different files in our CSS folder. But you should create only the styles.scss file. After that, you need to install “Live Sass Compiler” to compile our styles.scss file into styles.css file. It handles all the processes (You just need to click the Watch Sass button on the bottom of the VS Code after installation).
Next we'll install a tool called nodemon - it's a package that will automatically restart your node application as you make changes. This isn't essential, but it makes it easier to develop your code. Just type this command in your terminal:
npm install –save-dev nodemon
And open your package.json configuration file and make these changes to start nodemon when the project loads:
{
"name": "smartsuite-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.3.4",
"body-parser": "^1.20.2",
"ejs": "^3.1.8",
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.21"
}
}
Now, go back to your code editor and write some code! We'll have a main "app.js" file that starts up the server and a file called "smart.js" that contains the code to call SmartSuite's API. Then we're using an EJS file (embedded javascript) to render our HTML page and an scss file for a tiny bit of styling. What I have here is just a starting point, you can feel free to play around with the configuration and make it your own.
One other note - in the EJS template I refer to a Files & Images field by it's unique Id, which is specific to my workspace and App. If you want to do something similar, just add a Files & Images field and look up it's Id in the SmartSuite API docs and change the reference in the EJS file.
app.js
const express = require('express')
const app = express()
const port = 3000
app.use(express.static('public'))
app.use('/css', express.static(__dirname + 'public/css'))
app.set('views', './src/views')
app.set('view engine', 'ejs')
const smartRouter = require('./src/routes/smart')
app.use('/', smartRouter)
// Listen on port 3000
app.listen(port, () => console.log(`Listening on port ${port}`))
smart.js
const express = require('express')
const smartRouter = express.Router()
const axios = require("axios");
smartRouter.get('', async(req, res) => {
console.log('Router working')
try {
// fetch data
const headers = {
'Content-Type': 'application/json',
'account-id': 'YOUR_ACCOUNT_ID',
'Authorization': 'Token YOUR_API_KEY'
}
const smartAPI = await axios.post(`https://app.smartsuite.com/api/v1/applications/640a3811c9d3ea77099331e7/records/list/`,{},
{headers: headers})
// transfer response to the smart.ejs
res.render('smart', { records : smartAPI.data })
} catch (error) {
if(error.response) {
console.log(error.response.data)
} else if(error.request) {
console.log(error.request)
} else {
console.log('Error', error.message)
}
}
})
module.exports = smartRouter
smart.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node.js + SmartSuite</title>
<link rel="stylesheet" href="/css/styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?display=swap&family=Roboto:wght@100&display=swap" rel="stylesheet">
</head>
<body>
<header class="header">
<div class="header__logo">Node.js + SmartSuite</div>
</header>
<div class="wrapper">
<div class="smart">
<% if(records.items != null) { %>
<% records.items.forEach(function(record, index) { %>
<a href="https://app.smartsuite.com/snbvtl79/solution/<%- record.solution %>" target="_blank">
<h3>
<%- record.title %></a>
</h3>
<p>
Description:
<% if (record.description != "") { %>
<%- record.description %>
<% } else { %>
<i>No description</i>
<% } %>
</p>
<p>
Priority: <%- record.priority %>
</p>
<p>
Status: <%- record.status.value %>
</p>
<p>
Created: <%- record.first_created.on.toUpperCase() %>
</p>
<p>
Filename:
<% if (record.sc5451fdae[0] != null) { %>
<%- record.sc5451fdae[0].metadata.filename %>
<% } else { %>
<i>No file</i>
<% } %>
</p>
<% }) %>
<% } else { %>
<p>No records found</p>
<% } %>
</div>
</div>
</body>
</html>
styles.scss
.header {
color: #fff;
background-color: #050f6b;
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
margin-bottom: 15px;
}
body {
margin: 0;
font-family: sans-serif;
background-color: #ffffff;
}
.records {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
grid-gap: 2.5rem;
}
img { max-width: 100%; }
h2 { font-size: 1.4rem; }
.wrapper { padding: 0 1rem }
Now we are good to go. Open your terminal and type this command to run the web app:
npm start
Here is the result:
Point your browser to http://localhost:3000 and you will see:
Conclusion
This was just a quick project to see how we can use SmartSuite as a data source to drive an app that displays static content, but with additional work we could absolutely create an interactive app that saves field values, modifies SmartSuite structures and more. While we created a Web app as the sample, SmartSuite's API could equally-well power a mobile app.
I hope this post sparks some ideas - please share them with the SmartSuite developer community. Enjoy building!