Debugging your apps in Appsmith with the Appsmith Debugger, part 2

Debugging your apps in Appsmith with the Appsmith Debugger, part 2
Ayush Pahwa
 minutes ↗
Meet the sidekicks, Logs and Inspect Entity

The first part of this teardown helped you see how the Error pane can save you hours in debugging and build better internal apps. In this one, let’s meet two seemingly innocuous features that can give you debugging super-powers when used right.


The Logs pane shows you everything logged by Appsmith and, like Errors, in lockstep with the sequence of code execution in your build. Borrowing from the experience of showing logs in general—in the browser console, from a shell, or on your favorite IDE—the Logs pane has four views for specific debugging use cases.

Post_5.jpg (1920×1080)

All Logs

This view shows you all logs timestamped by when we saw them in your Appsmith session. Updated a widget’s property? Wrote a new action to your GraphQL datasource? Ran a JS Object to concat two queries? It all gets logged, including the errors you see in the Errors pane, in a separate view called Error Logs. You will see how that can be useful in a GIF, pun intended.

The All Logs view can be a little overwhelming, though, and a bit of work when you have been at your build for a while. For easier tracking of relevant logs, use one of the three options below.

Post_6.gif (1440×810)

Errors Logs

Everything you learned about the Errors pane applies to this view, too, but there’s more to this view. Here's a likely scenario to show that.

State #1

You have a button to reload a table, presumably to refresh the data from your datasource.

Condition #1

You use the Button property, onClick, which runs the query to fetch the latest data into the table.

Scenario #1

Your query fails.

- On just the Error pane

  • You see just the error for the failing query. Although helpful, it doesn’t offer context for the before and after of the error.

- On the Error Logs pane under Logs

  1. You see logs for the Button click and the executed onClick event .
  2. Because the onClick property is binded to queries and JS Objects, you see the ones that are successfully executed and those that fail.
Error_Logs__Appsmith.gif (1440×810)

The triaging in our example above is especially useful when you have nested queries, several dependent bindings, and a more complex workflow overall.

Console Logs

console.log_in_the_Editor__Appsmith.jpg (1920×1080)

Just introduced in the Debugger, console methods in Appsmith help you see statements for just JS Objects and JavaScript bindings so much better than in the browser sub-window.

Set points in your code that you want to log statements at, view tabular data, or see groups for repeated errors.

System Logs

Post_7.jpg (1920×1080)

Automatically tracking all your interactions with Appsmith during build, System Logs show a helpful trail of activity by descending order of timestamp, especially useful when you want to go back in time or pivot from a point of failure to everything that led to it.

They show up for different situations and interactions for the type of entity you are working with.

With widgets, you see a log when you

  • Drag-and-drop a new widget on the canvas.
  • Update the widget’s properties
    Updating a property also updates all its dependent properties which then show up in System Logs.
Dependent_properties_updates_in_system_logs__Appsmith.gif (1280×720)
For example, when you update the tableData property, you also see its dependent properties like selectedRowIndex, filters, triggeredRowIndex, and so on.
  • Trigger events with an end-user action.
Trigger_events_with_an_end-user_action__Appsmith.gif (1280×720)
For example, when you are using an end-user action to store a value with storeValue or when you want a click-action to trigger an operation like an update or delete and are using onClick, you see them show up in System Logs.
  • Delete a widget from the canvas

With actions, you see them when you

  • Create a new datasource or a query
  • Update query properties like queryName, queryBody, queryConfiguration, and queryProperties.
  • Execute a query
Execute_a_query.gif (1440×810)
This can be either from query pane, running a plain REST API query, a JS Object, or via a widget’s bindings.
  • Delete a query

With JS Objects, you’ll see system logs when you

  • Create and update code inside JS Objects
  • Execute JS Objects
Execute_JS_Objects.gif (1440×810)

Just like errors, system logs are native to entities and have four parts to them.

Parts_of_a_system_log_line__Appsmith.jpg (1920×1080)

The timestamp

Logged as your entities are created, updated and deleted, these little breadcrumbs help you track back from when the error occurred to when it was last A-Okay.

Timestamped_logs_in_System_Logs.gif (1440×810)

The message

Useful during build, the message of the log answers two questions— what were you doing with an entity—creating it, updating it, deleting it—and what happened with your action—success or failure.

  • With widgets, outside of CRUD information, you also see event-specific info like onClick and showAlert linked to those widgets.
  • Queries and JS Objects are straightforward with start and end points that indicate if they were updated, ran, and failed.

The source

Like errors, a system log has two parts to its source—the entity’s name.the type of entity, e.g., SELECT1.TABLE1.WIDGET.

Redirect_from_an_Inspect_Entity_sub-window.gif (1440×810)
👌🏽 Appsmith Experience plug

Clicking the source from the logs takes you to the associated entity anywhere in Appsmith, be it a widget, a query, or a JS Object. Noice!

The response

This doesn’t always show, but when it does, it can be useful confirmation of a binding working, a query running successfully, or a JS Object executing completely.

  • For widgets, you see which properties are updated when you are configuring them and how.
    Say you’re updating the text widget’s background property and you don’t see it change on the canvas. Track the log to the response for a quick confirmation of that and troubleshoot the canvas next.
  • For queries, you’ll see two different logs—the start of a query run and the status of its execution.
    The first type of log will show you configuration details of the query—helpful to verify if the config matches the request.        

    "body":"SELECT * FROM public."users" LIMIT 10;"

  • The second type will throw an error if the run fails. When the query runs successfully, it shows all the parameters that the query ran with and the time taken for the response.

	"response" : [...],
	"request" : {
		"actionId" "6321c1193668£71e£7caala2"
		"requestedAt" : 1663912830.640344
		"requestParams": {...}

  • With JS Objects, you see the response from the function as a JSON after an object is successfully run. This shows you how Appsmith handles the function while evaluating and running it and can be useful for spotting conflicts, undefined references, or troublesome variables.

Inspect Entity

Borrowing from a modern browser’s Inspect Element feature, Inspect Entity lets you see incoming and outgoing entities for any widget. These entities can be queries, JS Objects, or even other widgets.

Group_8480.png (1920×1080)
  • Incoming entities are those that fetch data from the datasource into the widget.
    For example, if the data on a table is populated by a Postgres query, you’ll see the query name under the Incoming entities column.
  • Outgoing entities are those that can specify the data that’s to be sent to the datasource in a typical CUD operation and then send it to your datasource.
    Say, a text widget is binded to a table's selectedRow property, you will see the text widget’s name under the Outgoing entities column.

The Inspect Entity pane lets you see dependencies for all your widgets on the canvas, especially useful if you have a medium-complex app with several widgets working off of each other. For example, when you have a parent widget or query that controls bindings on other dependent widgets---call them children widgets---, Inspect Entity can show you all those children when you click the parent and quickly take you to any one of them directly.

In combination with Errors, Logs and Inspect Entity round out the Debugger for several scenarios during build and save you hours in building an app end-users love. Try out the Debugger and let us know how you like it, what it's missing, and what we can improve. Our Discord is the best place for that feedback.

Appsmith hits 20000 Stars. How did we get here?

Appsmith hits 20000 Stars. How did we get here?

Appsmith hits 20000 Stars. How did we get here?
Rishabh Kaul
 minutes ↗

Day before yesterday we reached 20,000 Stars on Github. 

We’re excited by this number because of what it represents. 20,000 Stars is a milestone that puts us in the company of other exciting open source projects that we all use and love. 

It’s been a steady rise. Since our launching on Github in mid 2020, it’s taken us a little over 2 years to reach this milestone. In June last year, we wrote about our learnings while hitting 4500 Stars. Since then, we’ve gotten a 4.4x jump since. 

How did we get here?

There’s a big debate in the open source community around the value of Github Stars. One Stack Overflow question laments "GitHub Stars" is a very useful metric. But for *what*?

We look at Github Stars as an informal measure of popularity of an open source project. And so while there might exist popular projects with low Stars, projects with high Stars more often than not command some mindshare. 

So while we keep an eye on this metric, it’s definitely not something we lose sleep over. 

Our philosophy has been to focus on things that add value to developers worldwide and focus methodically initiatives that further that cause. And so here are the things we’ve been doing (with pride)

Committing (Code)

We’ve been shipping. A LOT. And it's getting noticed. The folks at OSSInsight have been tracking and ranking various open source projects. We've submitted the highest number of pull requests among all low code development platforms. What makes this more interesting (and exciting) is that the definition of a low code platform according to OSSInsight is quite broad, including companies like Hasura, Supabase, Strapi.

And Appsmith continues to lead this chart month over month. 

Our users are noticing this too.

In addition to new users discovering us from word of mouth, we’re also seeing a lot of existing users returning back to Appsmith citing how much better the platform has gotten since they last tried it.

Even though our primary aim has been to educate our users about new features releases, bug fixes and helping users create bettet software, we started noticing that a lot of developer media began picking up our updates. This was very exciting to observe. Devops.com covered our version control, New Stack highlighted our OSS approach, JAXenter covered our JS Editor launch, and SD Times featured us not once, but twice as their Project of the Week (the second time was probably due to our fundraise). 

Retention over Acquisition

We made a conscious call in 2020 to focus on retention and user education over user acquisition. The good folks at Threado covered our early community-building efforts some time back

We believed as long as we served users via solving bugs, prioritizing features they asked for, and making ample content to help people get the most out of the platform, word of mouth would take care of acquisition. 

We launched our discourse community to create a Q&A type knowledgebase. In addition to helping our existing users and reducing load on our support team, it’s also becoming a growing source of organic traffic and bringing in new users (plausible data only from Apr 22) 

To increase retention, we also created Sample Apps, and Templates to help users understand product features better. While Templates enable a user to see a fully functional application that’s ready to be forked (like a dashboard or admin panel), Sample Apps have a narrower scope to help users perform a specific functions like How to implement a Search / Filter functionality in a Table with MongoDB as a datasource. This is in addition to the videos and blogs we’ve been regularly publishing around use-cases and investing in robust documentation. We’re slowly seeing the fruits of this from a new user acquisition perspective kick in because this type of content is also great for SEO. 

Highlighting Self Hosting

One of the early calls we made was to ensure that we made it easy for people to self-host Appsmith because that's how a lot of our users preferred using the platform. This is also reflected in our outreach efforts; you might see us plugging in links to our Github repo often (more so than website). The self host option is also prominently featured on our website's “hero section”.

Communicating across channels: Feature Updates, Opinions and Engaging Developers

We've been actively answering questions and sharing our feature releases on Reddit, Twitter, HackerNews and community forums of our integration partners. None of these channels individually bring a massive spike to traffic, but instead send a steady stream of consistent traffic to us every month and brings in a lot of new users to our Github repo. Like our July updates which is being received well from the Reddit community.

Word of Mouth 

While our team continues to actively monitor and post our opinions on these platforms, increasingly we’ve started noticing that our users have started talking about us. For example, user comments on HackerNews like these make our day. All in, across Github and our website, 3rd party forums are increasingly contributing anywhere from 4-6K unique hits a month across our websites and Github. 

A lot of our users are also writers, empowered by platforms like Medium or Dev.to or Hashnode and many of them have started featuring us in tutorials or listicles. This has lead to a massive spike in traffic, and my hunch is increasingly becoming a big contributor to our star growth. 


For awareness, we had to be surgical. Instead of spending effort on SEO or ads, we decided to go after podcasts. Why? Laser focused target audience that resonates with the problem. Check. Organic backlinks. Check. Ample time to go deep into product, technology and how/why we’re building. Check. People who know what they’re talking about (our founders basically). Check. Till date we’ve recorded 15 podcasts (with 11 of them live) with an estimated cumulative 100K listens. All this in less than a 6 months. Check out Nikhil on JAMStack Radio or Arpit on Hanselminutes.  

Github Juice

Github is possibly the last true organic platform. We’ve benefitted immensely from Github’s organic traffic. We’re not quite sure how Github’s “trending” algorithm works, but we’ve been consistently been “trending” in a bunch of sub-topics like JavaScript, TypeScript, Projects from India. But this often ends up becoming a domino effect, where because we’ve been doing a lot of the things above, there are people who discover us and star us, which in turn makes us trend, bringing in further Stars.  

As a parting note, this is just the start. And we can’t wait to see what the future holds and we’ve got so many exciting features we’re working on (and yes bug fixes too). We’ll keep executing and serving our users. Do try out Appsmith incase you haven’t already or share it with developers in your team. Want to get more involved? Maybe contribute to the project or better still, join us if you want to be a part of an organization that is building something meaningful for developers worldwide.

Inline editing in the table widget, integration with Airtable, and more

Inline editing in the table widget, integration with Airtable, and more

Inline editing in the table widget, integration with Airtable, and more
Vihar Kurama
 minutes ↗

In July, we squashed 102 of the peskiest bugs and shipped 34 top requested features over and above under-the-hood performance and usability improvements. There’s a new table widget that’s so much more powerful, an Airtable integration, and cleaner Google Sheets queries with 178 commits in 22 days just for that enhancement alone! You can tell we have got our ears close to you. Keep it coming, guys. We love it all, and we are always listening.


The swanky new table widget

Fact: Just 25% of you tell us who you are and how you use Appsmith. We are okay with that. We respect your privacy.
Assertion: Our usage numbers should be 4X more.
Inference: When we say the Table widget, ever since we launched it, has been used a crazy 820,000 times by 6,840 users, we actually mean it's been used a lot more and is second only to the Button.
Takeaway: Give it more love.

Introducing the new Table widget

Everything you asked for from the table and more is packed into this massive update. Here’s three that should make you sit up.

  • With inline editing, you can now forget about writing queries to edit data by cell, row, or column. You just get your data into the table and edit on the screen. We heavylift the queries, updating the database, and making sure it sticks–all behind the scenes. Clicksaver? Lifesaver? Timesaver? All three and more? We think so, too.
  • You know how you have always wanted to refer to custom column names more naturally than typing customColumn1, customColumn2, and so on in your queries? Yep. Done. No matter what the name of your column, reference away just as naturally as you name them.
  • Themes have been making apps pretty for a while, but Tables stayed rebelliously aloof from that prettiness. We have now made them fall in line with Themes, so if you want shades of blue and Roboto, you got it in Tables, too.

There’s a whole lot more that you are going to have to see for yourself.

Airtable integration, out in the sun

Our Airtable integration gave UI facelifts to the low-code datasource. It is now out of beta, ready for its moment in the sun.

Connect with a Airtable base in two minutes, and start building your apps without worrying about complex data workflows.

Auto-indent here to make a dent

On our latest version? Tried the JavaScript editor yet? No? Do that now and you don’t have to read on anymore. 

Oh, okay. You are still here. Fine. We will show you.

Automatically pretty code is pretty cool, huh? More about it here.


“Hide Error Messages, Hide”

Infuriating little things, error messages, that bring up existential questions, right? And when they showed up all the time, they got us to, “Frustrating!”. They don’t anymore, only showing up when a widget is visible and clicked.

“How much to upgrade?”

Got your Appsmithing going, but a paid feature’s in your way? Fret not, self-hoster. We got your back with a command-line feature that estimates your usage in thirty seconds. Click this and all shall be revealed.

Run any Appsmith branch locally

With something like ./scripts/local_testing.sh chore/local-testing, running any branch as a FAT container is a breeze. Make sure Docker’s installed and running, port 80 is open, and you add arguments if you don’t want to run the release branch.

Errors, alerts, and logs

Two new modules, logger.js and mailer.js now store backup errors and alert you to them—helpful to get you on top of the error and aid find-and-fix.

While logger.js is on by default, mailer.js needs appsmithctl backup --error-mail to get humming.

Just two of the many, many ways we got your back(up).

Moving Google Sheets to UQI 

Google Sheets is a popular data source. We didn’t dig up numbers, but you can take out word for it. UQI stands for Unified Query Interface and affords standardization for queries. Made sense to get queries to Sheets working better and looking neater, too.


If wishes were fishes, round-ups would be essays. Wishes aren’t fishes. So, head over to v1.7.9 if you closed our Release Notes in-app pop-up one of four different ways—yeah, we are fixing it—and see What Happened In July Appsmith style.

Need a new datasource connected?   ||    Discord    ||    YouTube    ||    Twitter

Track and manage bugs effectively using Appsmith and Airtable

Track and manage bugs effectively using Appsmith and Airtable

Track and manage bugs effectively using Appsmith and Airtable
Vidushi Gupta
 minutes ↗

Airtable is a popular choice for developers who want to manage tabular data easily. While it's easy to use Airtable as a backend, it can be challenging to build a custom UI from scratch. This is where Appsmith comes in. With Appsmith's native Airtable integration, you can create dashboards, CRUD apps, and internal tools in minutes.

In this tutorial, we'll use an Airtable base to build an issue tracker. We'll start by creating a database in Airtable and then importing our data into Appsmith and building on top of it using JavaScript. 

With this application, users can:

  • Connect to their Airtable base.
  • Add a new bug/issue
  • Update the existing issue
  • View the current bugs in the management tool.

Let's jump in!

Step 1:  Getting started

Create a new Appsmith App 

First, we need to create a new application in Appsmith so we can build it out.

  • Visit https://www.appsmith.com to create a new account or login in to an existing one.
  • Create a new application in your preferred organization and edit it.

Connect to Airtable

Now, we need to add your Airtable datasource to the app. In this case, we will clone an existing Airtable sample to provide our data. 

  • Create a new datasource by clicking ‘+’ on the Datasources tab from the entity explorer and then select Airtable.
  • Rename the datasource. Select API Key as the Authentication Type and enter your API Key in the input field. Hit Save.
  • Choose a workspace and a base in the dialog box and hit 'Create Table.'
  • Go to https://airtable.com/api and select the base titled 'All bugs and issues'
  • In the 'Introduction' section of the documentation, copy the Base ID (highlighted in green in the picture below)
  • Select the "Bugs and issues Table" on the left pane. Copy the table name highlighted in green in the image below.

Step 2 : Set up UI for the App


Here is the wireframe for what we are trying to create.

Including the modal that is used to add new bugs.

Create your widgets

Using the wireframe as a guide, create the UI for the application using the drag and drop editor. Here is a suggested process.

  • Choose a preferred theme from the Theme properties option in the property pane on the right.
  • Add a container widget with a text widget for your app's header.
  • Three (or as many as you like) stats boxes on the canvas to display essential statistics at a glance.
  • A container with a text, icon button, and list widget for showing a list of all the issues.
  • A container with text, button, select and list widgets for showing details of the selected issues.
  • A modal with a text, icon button, and JSON form widgets for adding a new bug entry.

Step 3 : Binding data on widgets

Listing records on the List widget

The list of bugs/issues should look something like this. In order to populate the data, create a new query and bind the results to the text.

  • Create a new query from the left pane which uses the Airtable datasource you created in the first step. Rename the query to getBase and choose the Commands to be List records. We chose this command because we would like to list all the bugs and issues in our app. Enter the Base ID and Table Name you copied in the steps above. 
  • Hit Run and you should see a JSON response generated which lists the records. 
  • To bind this response to the list widget, we would first create a JSObject that maps the fields from the records. Create a new JSObject and paste in the following snippet.

getAirTableFields: () => {
  return getBase.data.records.map((record) => {
    let row = record.fields;
    row["id"] = record.id;
    return row;

  • In this JSObject, we get the response from the GetBase query, map the fields, and get the id for every row in the table. 
  • Bind the list with this data using  {{JSObject1.getAirTableFields()}}
  • For getting the bug name and the source, bind the text widgets within the list with {{currentItem.Name}} and {{currentItem.Bug_source}} respectively.

Getting details of the selected bug

When we click on an item from the list, we should populate the view container with details of the selected issue

  • In order to get details about the selected bug on the container placed on the right, we would just use the {{List.selectedItem.attribute}} for all the details you wish to display. For example, The bug title can be displayed using {{List1.selectedItem.Name}}, for Associated features write {{List1.selectedItem.Associated_features}}, For priority write {{List1.selectedItem.Priority}}. So on and so forth. 
  • For a closed/open bug field, use the ternary format to display the status. {{List1.selectedItem.Closed == '1'? "Closed": "Open"}}
  • To bind the attachments for the selected bug, write {{List1.selectedItem['Attachments']}} to bind data on the list widget in the right container. 
  • Just like binding the bug details, in the image widget enter {{currentItem.url}} in the property pane to display the image attached
  • Use {{currentItem.filename}} and {{currentItem.type}} to display the file name and type on the text widget.

Displaying statistics on the statsboxes

These statsboxes should help display important information at a glance from this database. As the number of issues grows, this will give us a quick understanding of the status.

  • In order to populate the statsboxes with statistics, we would create a JSObject function that maps to fields and then to Priority within the same JSON response and check if the value is High, meaning the priority is set to high. What we get in the response is our desired statistic. 

highPriority: () => {
  const high = getBase.data.records.map((record) => record.fields.Priority);
  return high.filter((currentItem) => currentItem == "High").length;

  • Bind this output in the text widget using {{JSObject1.highPriority()}}
  • In the very same manner, write a function and bind the output for the number of bugs labeled open and critical

Adding a new Bug/Issue

When clicking the button to add an issue, a modal appears with a form that creates a new entry. It looks like this:

  • Set the Modal to open on onClick of the icon button on the top right corner of the container on the left. 

  • Populate the JSON Form with source data by pasting the following.

"fields": { 
    "Bug Title": "",
    "Priority": "",
    "Assigned To":"",
    "Status": "",
    "Screenshots": [
        "URL": ""
    "Bug Description": "",
    "Bug Source": "",
    "Features Associated": "",
    "Created by": ""

You can customize the field configuration as per your requirement. Here’s what the JSON Form looks like https://www.loom.com/share/1087b1e8932846feaf3dd03e8b3bb780

  • To insert a new record, we’ll write a new query. 
    Create a new query and name it as InsertQuery. Choose the command to be Create Records. Add in your Base ID and Table Name. For the Records, bind the form data from the JSON form for every field. 

    "fields": {
      "Name": "{{JSONForm1.formData.fields['Bug Title']}}",
      "Priority": "{{JSONForm1.formData.fields['Priority']}}",
      "Status": "{{JSONForm1.formData.fields['Status']}}",
      "Attachments": [
          "url": "{{JSONForm1.formData.fields.Screenshots[0].URL}}"
      "Assigned_to": "{{JSONForm1.formData.fields['Assigned To']}}",
      "Description": "{{JSONForm1.formData.fields['Bug Description']}}",
      "Bug_source": "{{JSONForm1.formData.fields['Bug Source']}}",
      "Associated_features": "{{JSONForm1.formData.fields['Features Associated']}}",
      "Created_by": "{{JSONForm1.formData.fields['Created by']}}"

  • We’ll make a new JSObject function to run multiple queries when the Add Bug button is clicked in the form

addBug: async () => {
  • Now bind this function on onClick of the Add Bug button in the JSON Form.

Update fields of a bug

This query/button can help update the details of the bug. In this case, we update the priority and statuses. 

To update the priority and status of a selected bug, an Update Records query would be used. 

  • Create a new query and rename it as updateQuery. Choose the command to be Update Records and enter your BaseID and Table Name. In the records field, paste the following to get the selectedOptionValue of the select widgets

      "id": {{List2.selectedItem.id}},
      "fields": {  
        "Priority": {{Select1.selectedOptionValue}},

  • Now, bind this query to run on onClick of the update button.

Final thoughts

And that’s it! You have your bug tracker application ready using Appsmith’s native Airtable integration 🎉

First, you created a new Appsmith application and connected it to Airtable. Then you created the UI for your app using the drag and drop tools in Appsmith. Finally, you tied the data from Airtable to the UI widgets. Your final app should look similar to this:

Please use this form to contact us if you have any template requests for internal tools that you need, and we will get to work! 

If you have any questions, contact us on Discord. You can also keep up with us on Twitter and YouTube.

Build Custom UI on top of Airtable data

Build Custom UI on top of Airtable data

Build Custom UI on top of Airtable data
Rishabh Kaul
 minutes ↗

Today, our integration with Airtable comes out of beta and is available for everyone 🎉! You can now build custom UIs and interact with applications built on Airtable, with minimal configuration.

While it is possible to use the default API interface to connect to Airtable, we wanted to make it easier for you to directly connect your Airtable account and create applications faster than ever. This new data connector introduces a number of features:

  • Integration located in the “Datasources” section
  • Connect to your Airtable account with either an API Key or a Bearer Token (OAuth 2.0)
  • Create queries to fetch, create, retrieve, update and delete data from a datasource using the Appsmith query editor. 
  • List command lets you display all the data from Airtable, and can also present data that has been filtered and sorted based on fields, records, time zones, etc. 

For details and information on how to use this new integration (with videos!), check out our Airtable documentation here. See it in action on our full tutorial here, where we build an issue tracker with Airtable as backend. As always, let us know what you think!

June Round-up: Fuzzy Search, Backup and Restore, More Product Updates
Monthly Round-up

June Round-up: Fuzzy Search, Backup and Restore, More Product Updates

June Round-up: Fuzzy Search, Backup and Restore, More Product Updates
Vihar Kurama
 minutes ↗
Monthly Round-up

It's been an eventful month here at Appsmith! We raised a Series B led by Insight Partners with participation from Accel and Cannan Partners. The round will help us improve our open source project and make it easier for large companies to adopt Appsmith. We're excited to have such strong partners on board as we continue our mission to make it easy for anyone to build and deploy internal applications. Stay tuned for more updates in the coming months!

Not just that, we've shipped a lot of features over the past month, so let's go through them.

New Features

Fuzzy Search for Widgets!

With so many options, it can be tricky to find the right widget for your needs can be tricky. We've got you covered! Fuzzy Search is an easy way navigation through all of our widgets by typing in keywords or phrases that match what exactly need to be done.

For example, say you have a typo while searching a specific widget. We'll make your search experience enjoyable by showing you the right results without hassle. Or say, if you're looking to find different input widgets that can help in your data collection process, just type an idea related to data input, and we'll show you all of the widgets that are likely to be needed on this project!

Easy Backup and Restore

Are you self-hosting Appsmith? Want to back up your data? Or are you recovering from an old backup? No worries! We just added two new commands that you can use from CLI that make it easy as pie.

For backup use:

appsmithctl backup

To restore use:

appsmithctl restore

Spellcheck for Rich Text Editor

The rich text editor's new superpowers will help you type quicker, with fewer errors. Yes! We've added a spell checker that enables you to catch any typos on your way no matter where you are or how busy things get. Just hit the CTRL and right-click on the typo; you should see the corrections.

Spell Check Image.png

Connection Pooling for MS SQL

We now introduce a connection pool for the Microsoft SQL Server (MS SQL), where we allow multiple connections per datasource (up to 5). So if five queries need to run on page load, they can all pick their connection and get executed simultaneously.

Previously, if multiple queries were to run together, they would be sequentially queued. And if the first query took a lot of time to execute, the second query would time out even before it got sent because it starved for a connection.

Generate New Page now Uses JSON Forms

The new Generate New Page feature makes it easier to customize your app! JSON forms now power the CRUD Apps, so you can change just one setting without editing individual form elements.

Product Updates

Better App Editing Experience

We know sometimes it’s hard for you to select a widget you need. We improved the experience by introducing a couple of changes:

  • Focus on the first property whenever we click on the widget.
  • When we add or paste a new widget, focus on the widget name. (it should be editable only if we press Space or Enter; otherwise, it will be hard to other operations like delete, copy, paste, etc.,)
Added more styles to Checkbox and Switch Widget

Checkbox and Switch Widget support more styles out of the box. The new options include text position, alignment label, and color size font style!

Added Deprecation warning to old widgets

With this update, we're adding a warning to all the widgets going out of date. If you want you're running on a self-hosted version, you can show these Deprecation messages on their widgets; just add "deprecated: true" in the config file.

Theming for CRUD Templates and JSON Form Templates

Theming is now supported for CRUD apps and JSON Forms. This will allow developers to create and customize forms more efficiently in a few clicks.

Fixed Cyclic Dependency Errors

We fixed cycles in dependency error messages when changing or updating widgets' names and other bugs that made them behave incorrectly.

Update Organization URL Slug

When the organization name is updated, the slug is not updated. This generates an outdated URL when the user clicks on an organization name from the left panel. This PR changes the following behaviors.

  • The Organization slug will no longer be unique.
  • Link to organization applications will be based on the organization id instead of the slug.
  • The organization slug will be updated whenever there is a change in the organization name.
  • All the existing organization slugs will be updated.

Collaborations, Technical Content, Videos & Tutorials

June was an excellent month for the community, with many folks collaborating on exciting new projects and maintaining their current work. We documented many user queries on our forum that will help guide future development decisions.

  • These questions can be found on our Community website (community.appsmith.com) under the appsmith-support tag.
  • We've done an awesome How Do I Do X Session with our engineers Trisha and Nidhi on JS Promises, onPageLoad Actions, and Prepared Statements. Watch the stream here.
  • The engineers behind the scenes are constantly working on something new and exciting. They just shipped an excellent feature - Version Control with Git! Watch as they describe its function, explain how it was built with examples in no time, and most importantly, show you some cool tricks using this powerful tool yourself!"
  • We've partnered with a few friends from MariaDB to build an easy-to-use reservations tool. You have to input your desired date and time, then let the system take care of everything else. Watch the stream here.

If you're curious about what we were up to, look no further and follow this link.

If you’re interested in using a database not listed on our website as an integration, please let us know by raising a PR on Github, and we will do our best to include it at the earliest opportunity.

Join our growing community on Discord, and follow us on Youtube and Twitter to stay up to date.

Build a Product Review Tool For Telegram Bot with Appsmith

Build a Product Review Tool For Telegram Bot with Appsmith

Build a Product Review Tool For Telegram Bot with Appsmith
Paul Asalu
 minutes ↗

Telegram-Business" is a Telegram bot that connects customers to small-scale businesses. Users can either sign up to use the bot as business owners and create a catalog for their products or use it as customers looking to purchase something from businesses on the bot. It works a lot like the popular 'Whatsapp Business' platform.

In this article, I will teach you how to use Appsmith to build a product review tool for a Telegram bot. Think of this as a proof of concept of how Appsmith can help small businesses by automating some aspects of their businesses. More specifically, with this app, users can add reviews on products they've used to help others make wise decisions when purchasing, and business owners can take the feedback given to make their products more consumer-friendly.

If you want to see how I built the Telegram bot you can check this article I wrote about it here.


To follow along with the article steps, you should have the following setup:

  • Appsmith Account: You can create an account with Appsmith for free via this link.
  • Also, be sure to read the tutorial on how to create a telegram bot via this link.

Overview of the Tool

The process starts by creating a new application on Appsmith, and designing the interface for the product review tool using the available widgets in the design area, as shown below:


This utilizes the rating widget for the star rating, the text widget to display the product description, image widget to show an image of the product, and input widget for the comment that the user may want to leave on the product as part of their review, and of course, a button widget to submit the review.

We also want users to see comments made by other people on the product, so we'll design a second portion of the interface right beneath this one, as shown below:


This portion consists of a text widget which describes the section "what others are saying", followed by the list widget, which has been emptied and contains only a text widget to display the comments by other users. It's empty at the moment so it seems bare, however, once the data kicks in it'll come to life. You can choose to add an outline to the input field to make it more visible as shown below:


Adding Datasources

We'll start by creating an API to fetch data to display on the list widget from the bot's database; which is hosted by Fauna which is a serverless database provider, that also provides us with a graphql API through which we can send queries directly to the database.

We will be querying the database via this GraphQL API from our Appsmith application. Head over to the "Queries/JS" section and choose to create a new "Blank API", and add the following details to this new API:

Once you're done your API should look like this:

{{    JSON.stringify(        {            variables: null,            query: `                query {                    findProductByID(id: "${appsmith.URL.queryParams.product_id}")                    {                        name                        image                        description                    }                }            `        }    )}}

You will observe that in the body of this API we make use of the "findProductByID" graphql query made available to us via FaunaDB.

Inside of this query we must specify a product id, namely the product id of the product that is to be reviewed, that way we can fetch the information about the product including the product image and description, which we can then display on our interface via the image widget and text widget.

id: "${appsmith.URL.queryParams.product_id}"

That is what this line does in the query, we fetch the product id from the Context object that Appsmith provides us with.

The Context object contains a number of properties of any Appsmith application that help us store and reference information about our application, for example, the famous "store" object is a part of the context object and we can use it to store information in our application's local store. Here's a list of items available in the Appsmith context object:


You can find out more about the context object here.

Meanwhile, the item of interest for us here is the "URL" object from the context object, which holds information about our application's URL, including the hostname, and query parameters amongst other things, as shown below:


This is important to us because we will be passing in information about the product to be reviewed and the user issuing a review as query parameters to our application url, namely the "product id" and the "user id" from the bot. This will make more sense when we integrate the application with the telegram bot.

getReviews API

Next, let's add another API that will fetch all the reviews on the given product. So head to the "Queries/JS" section again and choose to create a new API this time with the following details:

{{    JSON.stringify(        {            variables: null,            query: `                query {                    findReviewByProductID(product_id: "${appsmith.URL.queryParams.product_id}")                    {                        data {comment}                    }                }            `        }    )}}

Here we send a query to the bot's database to fetch all reviews from the "Reviews" table that are associated with the given product's id, which is also gotten from the URL query parameter as with the previous API.

send_review API

This API is what will handle the creation of new reviews which plays a vital role in our application since that's the main purpose of the application. This API unlike the rest utilizes a graphql mutation (also provided by the FaunaDB graphql API for the bot's database). Below are the details of this API:

{{    JSON.stringify(        {            variables: null,            query: `                mutation {                    createReview (data: {                        chat_id: "${appsmith.URL.queryParams.chat_id}"                        stars: "${Number(Rating1.value)}"                        comment: "${Input1.text}"                        product_id: "${appsmith.URL.queryParams.product_id}"                    })                    {                        _id                    }                }            `        }    )}}

As you can see in this mutation query, we reference the data from some of the widgets, including the rating widget, for the value of the ratings that are given. And the "input" widget, which holds the comment given by the user on the product. Also, observe that we fetch the user's telegram id (chat_id) from the URL to associate the new review with that particular user.

Connect Datasources To Widgets

Next, we must connect the APIs we've created to the interface via some of the widgets. First, off we want the user to be able to send in a review to the database once they click on the "submit review" button, so to do that, we will open up the properties of the button by clicking on the settings icon next to it, and choose an OnClick action for the button.

Head over to the submit button widget and bring up the settings pane, and under the Actions section, choose the option to Execute a query and then select thesend_review` API from the list of options shown, as shown below:


Not only do we specify an "onClick" action, but we also specify an onSuccess action, which simply brings up a modal that displays a success message, like the one shown below:


This is a simple modal with just two Text widgets, so you can create one like that and link it to the onSuccess action as I have done.

Next, we must feed data to the list under the "What others are saying" section; click on the widget to bring up the settings for the list. Under the " items" option, add the following to load the data from our getReviews API:


This will load data from the query onto the list widget as a list of JSON objects. However, we must still specify what data goes where for each list item. In our case, we must specify what data from the "current object" goes to each list item's Text widget. Recall that each list item has a "text" widget in it, so for that text widget, we will specify its "Text" property to be the following:


Lastly, we must add data to the Image widget and the Text widget that holds the product's description. For the image, we'll set the "image" property to the following:


Here, I am calling the "getProduct" API, which we created earlier on, and fetching the data from the response of the API call. For the description text widget, we'll set the "text" property to something similar:


Now that we are done with this, we can deploy the application and fetch the URL. So I'll click on the Deploy button to deploy the application, wait for it to load up completely, then copy the URL from the browser.


As observed, the application currently has no data in it because necessary arguments for the APIs getProduct and getReviews are not yet present, namely:

  • user_id
  • product_id

If you recall, these two parameters were taken from Appsmith's URL context object, which holds information about the current URL of our application - including any query parameters that may be present.

This is important because I will be passing these two arguments as query parameters to our Appsmith application.

Integrate With The Telegram Bot

This brings me to my next stop, which is to implement some logic from the bot to help users who want to leave reviews access my application.

For this, I will send a message containing the link to our Appsmith application, along with the query parameters, which would contain the "ID" of the product they want to review and their user id on telegram (chat_id) to whoever is interacting with the bot.

Note: The code snippets shown below do not show the full implementation of my telegram bot; if you want to see how I built it, kindly refer to this article.

Typically, when users come to the bot, they get multiple options when viewing products in a catalog, as shown below:


As observed I have added a last option which allows them to Add Product Review, in order to handle that I wrote a handler function that will send back a message containing the Appsmith URL with the product id and their chat_id in the URL as query parameters. Observe:

appsmith_url = "https://app.appsmith.com/app/review-     product/review-6179715eb2db5a27f21af7e5"    product_id = data.split(';')[1]    # generate link to appsmith UI    bot.send_message(       chat_id=chat_id,       text="Kindly click on the following link to head over to        the review page "       f"{appsmith_url}?chat_id={chat_id}&product_id={product_id}"     )

The appsmith_url variable holds the URL for our deployed Appsmith application, and contains no parameters, so opening that would just display a "bare" version of the interface we designed. However, notice how i append the ?chat_id={chat_id} option along with the product_id={product_id} option to the URL before sending it.

That way the user gets a response that's customized to include their personal id and the id of the product they wish to review. As such, when they click on the URL our Appsmith APIs will be able to fetch the data they need from the context object and react accordingly. Here's what a typical response from the bot looks like:


Now when they click the link, it'll take them to the Appsmith tool we created but this time with data loaded in, as shown below:


This way, my users can also leave comments on the products, and see reviews on the product, further increasing the trust that they have in the platform and in small-scale business ventures.

I hope you enjoyed reading that!, this article has shown you how to use the Appsmith context tool as well as how to send GraphQL queries on Appsmith, via the API editor, and ultimately how to build a simple product review tool for any use case you might have.

I invite you to use what you've learned from this article to build more interesting versions of what I have built or even different tools if you wish, rest assured everything you need to fast-track your development is available to you on Appsmith.com. If you wish to see the code base for my bot you can find it on GitHub here.

$41mn Series B Funding Raised: Good, Better, and onto Becoming the Best 

$41mn Series B Funding Raised: Good, Better, and onto Becoming the Best 

$41mn Series B Funding Raised: Good, Better, and onto Becoming the Best 
Abhishek Nayak
 minutes ↗
No items found.

TL;DR: We just raised $41m in our Series B, led by new investor Insight Partners, alongside Canaan Partners, Accel, and angel investors.

Frontend and backend development for simple applications have become incredibly complicated. It feels like we are building the same things repeatedly but just using different programming languages. The world has about 20 million software developers; most have spent hours building admin panels, forms-based workflows, dashboards, or some version of a CRUD app. That's billions of hours spent building internal apps and doing a lot of repetitive and mundane work. 

My co-founders, Arpit and Nikhil, had spent many years building CRUD apps and were tired of dealing with the same problem at every company. There had to be a better way to build these apps. We decided to release an MVP to a small community that embraced Appsmith with wide-open arms. 

We started Appsmith with a simple goal: To help engineers build the best apps they can to help their teams while avoiding repetition and monotony.

I am happy to announce that we've raised our Series B to deepen our commitment to that goal. 

First, the lowdown

The lead investor for Appsmith's Series B is Insight Partners, joined by existing investors Canaan Partners, Accel India, and angel investors like Abhinav Asthana (Co-founder, Postman) and Jeff Hammerbacher (Co-founder, Cloudera). Our goal was to bring investors that understood the technology landscape well and were impressed with Insight's track record of backing companies like Docker, Postman, and JFrog, many of which are also open source. As we spent more time with the Insight team, we realized they would be the right partners for us as we scale to the next level. 

And of course, a big mention to our users and community. We're only here because you decided to take your valuable time in using, giving feedback, and contributing to the core product.

What have we done so far? 

Today, Appsmith is a robust open-source, low-code platform for building, shipping, and maintaining internal tools. Users can connect to any datasource, create UI with pre-built widgets, and deploy business-critical applications. 

You can see it in action: 

Our focus last year was on improving the quality and complexity of the frontend that can be built using Appsmith, a couple of examples of which is our latest theming feature or our in-built JS editor is an excellent way to code.  These are a few among the 150+ features and enhancements we shipped in 2021. 

Where do we go from here?

Over 100,000s developers have used Appsmith for personal and professional projects so far. We see over 7,000 active teams daily relying on apps built quickly on Appsmith. We developed a 3000-member strong Discord community and helped our users build over 100,000 apps. From providing rich support to writing detailed tutorials to contribute valuable integrations, our community and team are the heart and soul of Appsmith. We have loudly and proudly built Appsmith in public and honestly believe transparency and community involvement help us in the short and long term. 

Now, it's time we make it happen for dynamic apps starting with internal apps as our focus.

With this round of funding, Appsmith will build on the progress from 2021. 

Here's a five-point plan for the coming year: 

  • Add more UI widgets and Data Integrations
  • Simplify the coding and debugging experience
  • Investing more in nurturing the community
  • Build out a robust set of offerings for advanced or mid and large-sized teams 
  • Improve performance of Appsmith apps

Final words

As I mentioned before, this accomplishment wouldn't have been possible without the love, care and support from our team, community, families, and friends.

I want to thank you all again for your continuous support and assure you we don't take it for granted. 

How To Display and Manage Documents on Appsmith

How To Display and Manage Documents on Appsmith

How To Display and Manage Documents on Appsmith
Uma Chukwudinma Victor
 minutes ↗

Today, modern websites that use document-based data have provisions to view, manage and download these documents. Such documents can range from simple files showing budgets, tutorials, or even notes. With these features, application users can upload and manage files. While such features are nice to have, building an ideal solution to handle them are not feasible and can be time-consuming. Often developers find it hard to code PDF-viewers on their web apps because of dependency issues (libraries and frameworks), and when working with frontend frameworks — React, Vue.JS, etc. — configuration can get complicated. 

When building apps on Appsmith, the in-built document widget takes care of some important functionalities related to managing documents. This widget supports multiple file extensions, such as .txt, .pdf, .docx and .xlsx among others. Documents can also be populated via APIs and URLs. 

In this tutorial, we will learn what the document viewer widget is, and its applications. At the end, you will be able to fetch and display documents in Appsmith, and also learn to configure different properties that come with the widget.

Set-up the  Document Viewer Widget

The document viewer widget on Appsmith can be used to display a wide range of documents. This document widget has support for numerous file extensions of documents. Documents to be displayed can be of type: .pdf, .docx, .xlsx, .pptx, .ppt and .txt.

To get started using this widget:

  • You will first need to have an Appsmith account. You can log in if you have a pre-existing Appsmith account, otherwise, you can create a new Appsmith account.
  • Once logged in, you are navigated to a dashboard. Here, create a new application. On the left sidebar, you will see a number of widgets offering different functionalities.
  • Find the document viewer widget and drag it into the workspace.

Adding the widget will give a result similar to the image below:

Within the widget, you will notice there is a document being displayed. This document is being generated with the link in the Document Link property of the widget. 

To display documents, you can either add links/URLs or connect a data source that can be connected to display documents. The document widget provides the option to download or print the displayed document.

Alternatively, a data source can be used to provide the documents. 

The data source could be a database or an API pointing to the file you want to display. 

The Connect Data button will take you to a page to add a data source.

Here you will see options for APIs and different databases. 

In this tutorial, we will use the MongoDB database to supply our documents. 

First, you will need to create a database on MongoDB (I will show you how to do this in the next section) and then link it to our application. 

Select MongoDB from the datasource link

Here, I’ve renamed my data source to “Book Datasource.” Take note of the IP addresses; you will need to allowlist this when creating your MongoDB cluster to allow external access via Appsmith.

Creating a MongoDB Database

To get started with MongoDB, navigate your browser to MongoDB and click on Try free to create a user account.

After logging in, select your database plan and click on Create Cluster.

Next, set up security credentials to authorize access to the database.

Finally, allowlist the domains from Appsmith, click on the Finish and Close button, and click 'Go to Database' on the popup dialogue that appears.

On the new page that opens up, you will have your database and a cluster created for you. 

On the cluster, click on the Browse Collections button.

You will get a page to manage the data stored in your database.

Select Add My Own Data to define our own database’s content. On the new page, select Insert document to add new documents to the database.

Our 'Collections' will contain two fields, namely: Name and Url, along with their corresponding values. Above I have a URL for a Javascript tutorial document. Click on the Insert button when done to add the new document.

Below, I have three documents in my database collection.

On the side pane, click on Database to navigate to the cluster. Click on the Connect button and select Connect with Mongodb Shell

Copy the selected area in the image below

Add the Newly-Created Mongodb as a Datasource

Now that we are done setting up our database, we need to add it as a datasource to Appsmith. For this, you will need to navigate back to Appsmith and fill in the required fields.

Select Replica set for the connection type, paste the copied connection string into the host address field, and enter your database name. Under authentication, enter the username and password you defined when creating the cluster.

Click on test to check the validity of the datasource, then finally, click on Save. Click on the new query to create a query for the datasource.

Enter the name of the collection in the field provided and click on the Run button. You will get a response showing the database content. Click on Add new Widget and select Table on the left window pane. This will create a table widget with the database as its data source.

You can link this new widget to your document viewer widget. 

To do this, open the document viewer widget option pane. Within the Document Link field, add the following moustache syntax


This will set the document to be displayed in the document viewer widget, to be the URL of any row you select from the table.

The document viewer widget has 3 properties: the Document Field, visible and Animate Loading properties. The visible field determines if the widget will be visible upon production while the latter controls the loading of the widget.

Approving and Rejecting Documents

In the Filepicker widget, criteria can be set, which the document to be uploaded has to satisfy, else it would be rejected. Select and drag the file picker widget onto the workspace to add it.

Above is the file picker option pane. The label property is the text to be displayed on the widget. With this, you can also set the number of files to be uploaded, max size of the files, and allowed file types. Documents not meeting the predefined criteria will be rejected. Documents uploaded with the file picker widget can also be linked and displayed using the document viewer widget.

Click on the widget to upload a file.

You can either drag and drop files unto the widget to upload them, or you can browse your system directories for the files to be uploaded.

Here is a file I’ve added using the widget. Note that the file picker widget stores uploaded documents in the form of an array. To view your uploaded document, add the following mustache syntax to the document viewer widget document link property: {{FilePicker1.files[0].data}}. Here, the document at position zero is the first document which I added.

Above is an image showing the document uploaded using the file picker widget.

Sending Documents as Mails

Documents can be sent to specific email addresses using the Appsmith SMTP email service. To do this, you will first need to do is to add SMTP integration. Navigate to datasources and select SMTP.

To be able to use this service, you will need to create an account with an SMTP provider. On the configuration page, add the host address, port and authentication credentials of your SMTP provider.

With SMTP setup, you can build a form to send the documents to an email address. To do this, add the form widget to your work environment.

Here is a form which will take the values of the name of the email and the file name of the document to be sent.

To send emails, create a new query using the configured SMTP service.

Here is the query screen. The from email property would take the email address you used to create your SMTP service, the To email(s) property can be bound to the input field of the form using the following moustache syntax: {{Input1.text}}. The subject would be: {{Input2.text}} and finally the attachment would be the file uploaded to the file picker widget. So use the moustache syntax: {{FilePicker1.files[0]}}.

Finally, you will need to bind this query to the submit button on the form to run it.

Here, I’ve added the query to the onClick event handler, and added a message to be displayed once the document has been sent. Clicking on the button will run the query and send the attached document to the email specified in the form.

We also covered using the file picker widget to upload files and send documents to specified email addresses. You can take a look at the tutorial here. 

Building an Inventory Management Tool Using HarperDB

Building an Inventory Management Tool Using HarperDB

Building an Inventory Management Tool Using HarperDB
Dancia Jos
 minutes ↗

This guide explains how to quickly build an Inventory Management tool to manage movie rentals by connecting a HarperDB backend to an Appsmith frontend. It also implements authentication using HarperDB’s role-based access control feature.

HarperDB is a distributed database that supports key-value, document store, and traditional SQL. As a flexible platform for distributed applications and data, HarperDB is read/write optimized and globally replicates data in under 100ms.

You will need a HarperDB account, which can be created by signing in here.

Appsmith is an open-source framework for building internal tools. It lets you drag-and-drop UI components to build pages, connect to any API, database, or GraphQL source and write logic with JavaScript objects

If you don't have an Appsmith account, create one here.

Let’s get started!

Step 1: Set up your Backend on HarperDB

We’ll be using the HarperDB cloud instance free - tier. Click on Create New HarperDB Cloud Instance → Create AWS or Verizon Wavelength Instance


Select Choose HarperDB Cloud on AWS and then click on Instance Info


Fill in the details about your instance and click on Instance Details button


Keep the default settings in the Instance Specs modal and click on Confirm Instance Details


Click on the Add Instance button


This will begin creating your database cloud instance on HarperDB. Your instance will be up and running in no time.


Step 2: Create the Database (Schema)

  • Create a schema called Movies
  • Next, create tables for Customer, Film and Rentals with id as the hash attr. The hash attr in HarperDB is equivalent to a primary key.

Use the Upload CSV feature of HarperDB to populate data into the three tables. You can find sample data here.


Step 3: Create Roles and Users on HarperDB

Click on the roles tab and create two users named admin_user and rental_user under Standard Roles. admin_user will have all privileges on the three tables so update all the permissions to true


rental_user will have all permissions on the Rental table and only the read permission on the Customer and Film tables


Under the users tab, create a user named assistant with the role of rental_user.


Similarly, create a user named manager with the role of admin_user

And just like that, the backend setup is complete.

Step 4: Build UI on Appsmith

  • On Appsmith, on the Entity Explorer pane, go to PAGES→ Page1 . Rename the page to Login. Drag and drop a Form widget onto the canvas. Add input widgets for Username and Password as shown below. For the Password input widget, choose Password as the Data Type so that the characters entered are masked.
  • Create a second page called Rental Inventory which will be the page that the user will be redirected to after login.
  • Drag and drop a Tab widget onto the canvas and add three tabs called Rental, Film, and Customer
  • On the Rental tab, add a Table widget and a Form widget to its right which will populate the details of the selected rental record that can be updated. On the Update Rental form, Customer and Movie are Text widgets, Status is a Select Widget, and Returned is a Datepicker Widget.
  • Add a modal widget onto the canvas to create a form for adding new rentals. Customer (rentalCustEmail) and Film (filmTitle) are select widgets
  • Set this modal to open on the onClick event of the New button
  • Create the same layout for the Film Tab. The title is Text widget, Rental Duration, Rental Rate, and Replacement Cost are all Input widgets of Number Datatype.
  • Drop a Modal widget on the canvas and create a form to add new movies to the collection. Title and Description are Input widgets of Data Type property set to Text and and the remaining are input widgets of Data Type property set to Number. Set this modal to open on the onClick event of the New button on the Film tab
  • Lastly, add widgets to the Customer tab as follows. Search is an input widget (Use the search icon under Icon Options and add “Type to search” under Placeholder in the property pane) and customerList is a List widget with two input widgets for Name and Email.
  • Drop a Modal widget on the canvas and create a form to add new customers to the database. All are input widgets. Set this modal to open on the onClick event of the New button on the Customer tab

Step 5: Configure the Login page

  • The next step is to create a query to retrieve the JWT tokens when the correct credentials are entered in the login form.
  • On the Login page, click on the + icon next to Queries/JS. Select New Blank API
  • On the API pane, rename Api1 to get_token and select the POST method. For the URL endpoint, enter the url of the HarperDB instance. You can copy paste this from your instance card on the HarperDB dashboard.

Under Headers, ensure that the content-type is application/json

  • Under Body tab of the API pane, enter the following in Raw format. Notice here you are passing the username and password entered in the two input widgets on the form.

    "operation": "create_authentication_tokens",
    "username": "{{Input1.text}}",
    "password": "{{Input2.text}}"

You can enter the username and password on the Login form and then test run the query to view the response. This query returns two tokens - The operation_token which is used to authenticate all HarperDB operations in the Bearer Token Authorization Header and the refresh_token which is used to generate a new operation_token upon expiry.

  • Next, we are going to create a JavaScript function that will redirect the user to the main page (Rental Inventory) of the app based on credentials and their roles.
  • Click on the + icon next to Queries/JS. Select New JS Object. Rename JSObject1 to utils and paste the code snippet below in the JavaScript Editor.

export default {
    login: async () => {
        return get_token.run()
        .then(res => storeValue('user', {username: Input1.text, token: res.operation_token}))
        .then(() => navigateTo('App'))
        .catch(e => showAlert(e.message, 'error'))

Note: storeValue is an Appsmith function that is used to store data in key-value pairs that can be accessed later anywhere in the application.

  • Bind the JS Object to the onClick event of the Submit button on the login form.

Step 6: Write queries and bind data to widgets

  • Create query to fetch data from Rental table in HarperDB and display it in the Table widget on Appsmith (rentalTable)
  • On the Rental Inventory page, click on the + icon next to Queries/JS. Select New Blank API
  • On the API pane, rename Api1 to get_rental and select the POST method. For the URL endpoint, enter the url of the HarperDB instance as shown in Step 5.
  • Under Headers, add the following key-value pairs. We have to pass the Bearer token generated on successful login under Authorization.
  • Under the Body tab of the API pane, enter the following in Raw format. This is an SQL query to fetch the data from the rental table and we are using server-side pagination to display data in the table widget (rentalTable), hence the limit and offset are set in the query.

    "operation": "sql",
    "sql": "SELECT * FROM movies.Rental LIMIT {{rentalTable.pageSize}} OFFSET {{(rentalTable.pageNo - 1) * rentalTable.pageSize}}"

  • Bind the data from this query under Table Data property of the rentalTable table using the following snippet


  • You will notice the table widget populates with results from the query.
  • Next, we will bind data to the widgets on the Update form to the right of the table. When a user click on the table row, the corresponding details should be displayed on the form.
  • For the Rental Update form, set the widgets in the following manner. Notice that we are manually adding the values in the Status select widget so that the status of the rental can be updated on the form.
CleanShot 2022-06-07 at 13.21.52@2x.png
  • Create a query to update the Rental status and Returned date on this form.
  • On the Rental Inventory page, click on the + icon next to Queries/JS. Select New Blank API
  • On the API pane, rename Api1 to update_rental and select the POST method. Repeat the same steps as above for the URL endpoint and the Headers
  • In the Body tab of the API pane, enter the following under Raw tab

    "operation": "update",
    "schema": "movies",
    "table": "Rental",
    "records": [
            "id": {{rentalTable.selectedRow.id}},
            "status": {{status.selectedOptionValue}},
                        "return_date": {{returnedDate.selectedDate}}

  • Hook this query on the onClick event of the Submit button on the Update Rental form. On success of this query also run the get_rental query to repopulate the table widget with updated data.
  • Create API query named search_customer with headers same as before with the following code snippet under Body tab of the API pane in Raw format

      "operation": "search_by_value",
      "schema": "movies",
      "table": "Customer",
      "search_attribute": "email",
          "limit": 10,
      "search_value": {{`*${rentalCustEmail.filterText}*`}},
      "get_attributes": [
          "id", "email"

  • Create another API query named search_film with the following code snippet under Body tab of the API pane in Raw format.

      "operation": "search_by_value",
      "schema": "movies",
      "table": "Film",
      "search_attribute": "title",
          "limit": 10,
      "search_value": {{`*${filmTitle.filterText}*`}},
      "get_attributes": [
          "id", "title"

  • Create a third query name new_rental to add new rental information with the following code snippet under Body tab of the API pane in Raw format.

      "operation": "upsert",
      "schema": "movies",
      "table": "Rental",
      "records": [
                          "film_title": {{filmTitle.selectedOptionValue}},
                          "rental_date": {{moment().utc()}},
                          "staff_id": {{appsmith.store.user.username == 'assistant'? 2: 1}},
                          "customer_email": {{rentalCustEmail.selectedOptionValue}},
                          "status": "borrowed"

  • Open the modal by clicking the New button on the Rental tab. On Customer select widget write the following code snippet to populate the customer email ids from the search_customer query.
  •  {{search_customer.data.map(c => ({label: c.email, value: c.email}))}}
  • Similarly, populate the Film select widget from the search_film with below code snippet.

{{search_film.data.map(m => ({label: m.title, value: m.title}))}}

  • Set the new_rental query to run on the onClick event of the Confirm button on the modal.
  • Repeat the above steps for the Film Tab.
  • The Update Form on the Film tab has the following data bindings
CleanShot 2022-06-07 at 13.26.37@2x.png
  • Create an API query named update_film with the following code snippet under Body tab of the API pane in Raw format. Bind this query to run on the onClick action of the onClick event of the Submit button on the Update Film form.

    "operation": "update",
    "schema": "movies",
    "table": "Film",
    "records": [
                    "id": {{filmTable.selectedRow.id}},
                    "rental_duration": {{ufDuration.text}},
                    "rental_rate": {{ufRate.text}},
                    "replacement_cost": {{ufCost.text}}

  • Let’s configure the queries to run to add new film data. Create API query named create_film with headers same as before. Add the following code snippet under Body tab of the API pane, enter the following in Raw

  • Open the modal by clicking the New button on the Film tab. Set the create_film query to run on the onClick event of the Confirm button on the modal. Close the modal and rerun the get_film query to refresh the Film table widget on success of the query.
  • Finally on the Customer page, write queries for the search input widget (customerSearchInput) and for displaying data in the list(customerList) below.
  • Create query called get_customers with the following under Body tab of the API pane.

    "operation": "search_by_value",
    "schema": "movies",
    "table": "Customer",
    "search_attribute": "email",
        "limit": 10,
    "search_value": "{{`*${customerSearchInput.text}*`}}",
    "get_attributes": [
        "id", "email", "first_name", "last_name"

Bind this query to the onTextChanged action of the customerSearchInput box


  • Bind the results of this query {{get_customers.data}} to the Items property of the customerList box
  • Let’s configure the queries to run to add new Customer data. Create API query named new_customer with headers same as before. Add the following code snippet under Body tab of the API pane, and enter the following in Raw

      "operation": "upsert",
      "schema": "movie",
      "table": "customer",
      "records": [
                          "first_name": {{ncFNameInput.text}},
                          "last_name": {{ncLNameInput.text}},
                          "email": {{ncEmailInput.text}}

  • Open the modal by clicking the New button on the Film tab. Set the new_customer query to run on the onClick event of the Confirm button on the modal. Close the modal on success.

Step 7: Control access to information based on user roles

  • On the Rental Inventory page, set the Visibility of the Tab widget to show only if the login process returns tokens on success. Toggle the JS button next to the Visible property to enter the following code snippet


  • The Rental tab is visible to both the Manager and Assistant roles so we leave its visibility as is
  • The Film and Customer tab should only be visible to the Manager
  • The Visible property of the individual tabs can be accessed by clicking on the gear icon next to the tab name
  • Add the following snippet of code in the Visible property of both the tabs

{{appsmith.store.user.username !== 'assistant'}}

Step 8: Configure the Logout button

When the user clicks on the Logout button, we will clear the username and token information in the store variable and redirect the user to the Login page. Add the following snippet of code on the onClick event of the Logout button.

{{storeValue('user', {}); navigateTo('Login')}}


So far, we've done a great job. The last part of this project will deploy our application. On the dashboard's top right section, click on the 'Deploy' button. You can also deploy this application by connecting to a Git repository. Our application is now deployed!

If you're interested in using a database not listed on our website as an integration, please let us know about it by raising a PR on Github, and we will do our best to include it at the earliest.

Join our growing community on Discord, and follow us on Youtube and Twitter to stay up to date.