If you’ve followed Appsmith for a while, you know that we can do a lot in 30 days!
I am here to give you all the deets; follow along!
We’ve received a lot of positive feedback on our new drag and drop experience. Users dig being able to resize widgets and move them around. This provides them with the ultimate freedom to build applications however they want without barriers that might get in the way :P
We’ve made this even more fun and powerful by adding a multiple widget reflow feature. With this, users should be able to move widgets and resize them even when they are grouped.
This also makes the drag and drop experience more performant in avoiding UI lags while moving widgets.
All of you have been waiting for a much-requested feature, and today, it’s finally here! The application URL now has your app name as a slug, making it easier for you to share and find your Appsmith applications. This is available immediately for all the old applications and, of course, the newly created ones. Here’s a sample app URL.
To upgrade your old app URLs, please navigate the updates section from the bottom bar and hit update. Here’s the recording of how you can do it:
We've added a new response view switcher feature that lets users easily switch between response formats on the fly; you'll be able to view them in different formats (JSON, Table, RAW) based purely on ease of choice. This feature will be available on all action types (APIs/Queries on a datasource).
It’s super easy to set a column type to a button on Appsmith - just navigate to column properties and update the type to Button. To make your table button more extraordinary, we’ve added the variant property taking inspiration from our button widget; with this, you can update table button types to different variants available.
We’ve added a smart substitution feature to Firestore plugin methods (to dynamically perform type conversions on field values in a request body). The smart substitution will work the same way for REST API requests.
Currently, this feature only gets applied to the body section of Create, Set, Add or Update commands, as this is the only input field that expects a JSON input type. This can be toggled by navigating to the settings tab on datasource.
We’ve added MultipartFormDataType variants; with this, users can add an array as a value for multipart requests on REST APIs. It will handle every item in the list as a part of the multipart request. Here’s what an example body will look like:
When the truncating text option is enabled in a text widget, the scroll switch is no longer valid; as we truncate to fix this issue, we made the following changes.
We’ve added an overflow property option with the following configurations:
You can now connect MinIO instances on Appsmith using the S3 plugin. This can be done when:
You can find this connecting in a dropdown from the S3 datasource.
We’ve been listening to a few issues with the select widgets when large datasets are used. Previously, in the case of these large data sets, the Select widget took up to 5 seconds to render. The initial render is down to ~100ms once the options are available from the API call.
Our engineers tested this thoroughly by loading 1000 options from a mock API on a newly upgraded test widget :)
Last month was crazy for us; we’ve published a blog post on how you can connect Stipe on Appsmith to manage your transactions; not just this, we’ve successfully hosted four live sessions.
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 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.
Some things are fantastic together. 🍔🥤
In particular, REST APIs and Low code dovetail nicely.
Although APIs simplify development, they also demand a level of programming skill and technical ability. Low code frameworks like Appsmith can provide a visual layer on top of the API that empowers non-technical audiences and citizen developers to build client applications.
There is much value in simplifying the development process where we can. Low code works best for development projects where the problem domain is well understood and there are very few use cases. REST API clients are well suited to that extent - the API contract itself serves as a kind of blueprint for the client application. Take, for instance, the Brex APIs.
Brex offers several APIs that range from Onboarding and Payments to Teams and Transactions. Brex admins can plug into these APIs to build powerful workflows and custom automations. To demonstrate, we'll build an Appsmith dashboard that will connect to your Brex account.
In this tutorial, we'll create an Appsmith tool that leverages the Brex APIs to perform bulk operations on your Brex account. By uploading a CSV file, you'll be able to create credit cards, users, and vendors. These changes will be reflected in your Brex dashboard immediately. Our tool will also support terminating cards and deleting vendors.
As it is not intended for production use, this application doesn't attempt to be either complete or systematic. It is more like a demo project. Rather than serve as a proper software solution, the final application is meant to demonstrate what is possible using Appsmith and the Brex APIs.
For context, this tutorial depicts the reader as a fictional Brex customer in order to provide a frame of reference and bring meaning to the sample CSV files. Pretend that you are an outer space company that issues Brex credit cards to your colleagues. The cardholders have personal cards as well as other cards designated for expenses such as Equipment Repairs, Launch Services, and Telecom. You will also define fictional Vendors: General Atomics, Orbital Transport Services, Space Food Systems. Let's suppose you are building this application to automate a few back office operations. You have chosen to build it using Appsmith.
First, you'll want to sign into Appsmith and create a new application. Next, sign in to your Brex account and generate a user token with Read/Write permissions for Cards, Referrals, Users, and Vendors. Appsmith will use this token to authorize API calls.
To confirm that your token is working, you can perform a quick sanity check with curl:
COPYcurl --request GET 'https://platform.brexapis.com/v2/users/me' \
--header 'Authorization: Bearer <your-token>'
The response will resemble the following:
COPY{
"id": "cuuser...",
"first_name": "Michael",
"last_name": "Collins",
"email": "mcollins@example.com",
"status": "ACTIVE"
}
Alternatively, you can use Postman to test API calls. In fact, the Brex Developer workspace allows you to experiment with every endpoint documented in the Brex Developer Portal.
Consider using the Appsmith Echo API to spare production API calls.
COPY[POST] https://mock-api.appsmith.com/echo/post
While testing your Appsmith tool, sometimes you will need to invoke non-idempotent API endpoints such as Create card and Invite user. Instead of exercising the live endpoints, you can create an API datasource that relies on the Appsmith Echo API:
COPYfor(let i = 0; i < 5; i++) {
echo_post.run(onSuccess, onError, params);
}
To mock HTTP status codes and errors, you might try httpstat.us.
For testing user invites, I recommend a disposable email system like Mailinator or Temp Mail.
There's a companion repo that contains sample CSV files and supporting JavaScript code for this tutorial. You can also use Appsmith's Import-Export feature to migrate the demo application to your own account.
The base URL for all Brex APIs is https://platform.brexapis.com.
You should now have a datasource that we can use to create Queries.
New query objects will show in the left side panel, under QUERIES/JS. For example, here I've created a query for the Get current user endpoint:
Now, you can create new query objects from the brex-prod datasource. The following search box will appear when you click the + icon next to the QUERIES/JS menu option:
Going forward, we'll create several queries to support our application.
The Onboarding API allows you to refer your customers and personal contacts to Brex. You might use the Create referral endpoint as part of the Brex Referral Program.
Unlike the Get current user endpoint, Create referral is a POST endpoint that requires a JSON body.
Later on, we'll discuss this.params. For now, understand that it is possible to run the create_referral query object and pass parameters into it, like so:
COPYconst params = { referral_code, email, first_name, last_name };
return create_referral.run(params); // always return the promise
The Team API lets you manage users, departments, locations, and cards. For this example, we'll manage users and cards, starting with the Invite user endpoint, which allows you to invite a new team member as an employee. Through the dashboard, Brex admins can assign various role types to the employee, but team members created through this endpoint will bear the Employee role type by default.
Your invite_user query object will POST to /v2/users. The request body should match the following:
COPY{
"first_name": {{this.params.first_name}},
"last_name": {{this.params.last_name}},
"email": {{this.params.email}}
}
Under the Headers tab, be sure to generate a random string value for the Idempotency-Key:
Idempotency is well beyond the scope of this tutorial. But, in short, the idempotency key ensures that the API server will only process a non-idempotent request once.
For a moment, consider network interruptions that may cause downstream services (or even the application itself) to perform a retry. Without an idempotency, the server would attempt to process the same request again. The idempotency key helps the API server keep track of whether the operation was already performed or not.
Notice that the code to generate the Idempotency-Key includes a reference to Lodash: _.random(1000). Lodash, among other libraries, is built into the Appsmith platform, which is super handy.
Create Card
The create_card query object also requires an Idempotency-Key, and will POST to /v2/cards. The request body is:
COPY{
"owner": {
"type": "USER",
"user_id": {{this.params.user_id}}
},
"card_name": {{this.params.card_name}},
"card_type": "VIRTUAL",
"limit_type": "USER"
}
The Create card endpoint also accepts other parameters, card types, and limit types, so check out the developer docs. There's also a spend_controls parameter that allows you to define a spend limit for the card. This limit can be set to refresh each month, quarter, year, or never (for one-time use).
Terminate Card
We can also reference {{this.params...}} in the query object URL. For example, the terminate_card query object will POST to the Terminate card endpoint, which has a URI parameter, {{this.params.card_id}}:
COPY/v2/cards/{{this.params.card_id}}/terminate
The request body for terminate_card:
COPY{
"description": "demo",
"reason": "OTHER"
}
There are also other reason codes such as CARD_LOST, CARD_NOT_RECEIVED and FRAUD, but for this example, we'll stick with OTHER.
Note that the Idempotency-Key is not required, because card termination is idempotent by definition. In other words, terminating a card multiple times has the same effect as terminating a card once.
The Payments API allows you to initiate and manage payments and vendors from your Brex Cash account. We'll use the Create vendor endpoint as an example. In a production application, you would also include vendor payment information to enable ACH, wire, or cheque payments from your Brex Cash account. But, for this example, we'll omit the vendor's payment type. You can also add vendor payment information from the dashboard - How do I manage my vendors on Brex Cash?
Create Vendor
The create_vendor query object will POST to /v1/vendors. This endpoint requires an Idempotency-Key and the request body is:
COPY{
"company_name": {{this.params.company_name}}
}
Delete Vendor
The delete_vendor query object will send DELETE requests to /v1/vendors/{{this.params.vendor_id}}. There is no request body.
The following query objects will enable us to populate tables on page load. To ensure that Appsmith pulls the initial dataset each time, you can configure each query object to run on page load:
QueryEndpointget_cardsList cardsget_usersList usersget_vendorsList vendors
This option is located under the Settings tab inside the query object:
The goal of our app is to provide a user-friendly way to create Brex credit cards, vendors, invites, and referrals. In this section, we'll envision the page layout and breifly touch on a few key points. You'll use a drag/drop interface to build the UI. But, before we get started:
Now that our work is cut out, we'll begin creating each page.
Use the Appsmith widgets to create the following page to your ability. Note that the green Upload widget is a file picker, not a button.
Make sure the Data Format property is set to Text for each file picker:
The Users page has a Tabs widget with two tabs, one for invites and one for referrals. You can drag each Table widget into the appropriate tab.
The Referrals tab:
The Vendors page is almost identical to the Cards page. In fact, you can select every widget on the Cards page and copy/paste them onto the Vendors page. Of course, you'll also need to adjust the widget properties and table data.
Our application is starting to take shape. We now have an end-to-end skeleton system. Next, we'll incrementally add functionality to each page, incorporating the query objects we created earlier. We'll also learn about JS Objects, which allow us to define handler functions that we can bind to the page widgets.
Earlier, we created a few query objects to run on page load. Now, we'll use them to populate our table widgets. As stated in Running APIs on Page Load, "If we connect an API response to a widget, Appsmith automatically runs that API on page load..."
In effect, this means that binding {{get_cards.data.items}} to the Table Data property for tbl_cards will populate the table. However, for this tutorial, we only need the card id and card_name fields from each card. So, we'll write some additional code to remove the unwanted fields:
COPY// bind this to tbl_cards - Table Data property
get_cards.data.items
.filter(card => card.status == "ACTIVE") // only get ACTIVE cards
.map(card => ({ id: card.id, card_name: card.card_name }))
Likewise, we initialize tbl_invites and tbl_vendors:
COPY// bind this to tbl_invites - Table Data property
get_users.data.items
.filter(item => item.status == "INVITED") // only get INVITED users
.map(item => ({ email: item.email, name: `${item.first_name} ${item.last_name}` }))
// bind this to tbl_vendors - Table Data property
get_vendors.data.items.map(vendor => ({ id: vendor.id, company_name: vendor.company_name }))
In earlier versions of Appsmith, there was only support for writing small code snippets to data bind page widgets. But, Appsmith now supports JS Objects, which enable multi-line JavaScript code and reusable functions.
To create a new JS Object, click the + icon next to the QUERIES/JS menu option, and find the New JS Object option.
Create an object for each page: cards_object, users_object, and vendors_object.
Replace the contents of cards_object with the following code:
COPYexport default {
upload: () => {
showAlert('Cards created!', 'success');
}
}
We'll revisit this code shortly. At the moment, let's go back to the page editor and bind {{cards_object.upload()}} to the file picker's onFilesSelected event:
If you are curious, deploy the application and upload a file to the Cards page. You should receive a Cards created! notification.
The cards_object.upload method will leverage the create_card query to issue virtual cards. To follow along here, you'll need your Brex cuuser ID, which you can obtain by running the get_current_user query. Place your ID into a CSV file, formatted like this:
COPYcard_name,user_id
Michael Collins,cuuser...
Later on, we'll upload this file to the Cards page.
The following code will read lines from a CSV file, assuming that your file picker is called fp_cards:
COPY// get the first uploaded file
const csv_file = fp_cards.files[0];
// collect each line from the csv file
const csv_lines = csv_file.data.split("\n");
// omit csv header and blank lines
const rows = csv_lines.slice(1).filter(row => row.length > 0);
Simplified:
COPYconst rows = fp_cards.files[0].data.split("\n")
.slice(1).filter(row => row.length > 0);
To smoothen the discussion around asynchronous code and JavaScript promises, we'll be using a helper function called loop to iterate API calls. For reference, the full loop implementation is here, but we'll strictly focus on understanding its usage:
COPY// visit each row
return cards_object.loop({
collection: rows, // assign rows as the collection
onReadLine: () => {
// do this on every row
},
onEnd: () => {
// do this after the loop ends
}
})
The loop helper calls onReadLine once per row. On each loop iteration, we can pass card_name and user_id into create_card.run():
COPYonReadLine: (card_name, user_id) => {
// be sure to always return the promise,
// otherwise this will not behave as expected
return create_card.run({ card_name, user_id });
}
When the loop ends, we report the number of cards created successfully, and then call get_cards.run so that the new items appear in tbl_cards:
COPYonEnd: () => {
const count = appsmith.store.success_count;
if (count > 0) {
showAlert(`${count} cards created!`, "success");
}
get_cards.run();
}
Once you re-deploy the application and upload a valid CSV file, your card will show in the Brex dashboard, under Card > Manage cards:
Last, but not least, we have cards_object.terminate. Bind this method to btn_terminate_cards - onClick event:
COPYterminate: () => {
// clear variables
cards_object.reset();
// get comma-separated values from the textbox
const rows = txt_card_ids.text.split(",").map((id) => id.trim());
// visit each row, terminate card
return cards_object.loop({
collection: rows,
onReadLine: (card_id) => {
return terminate_card.run({ card_id });
},
onEnd: () => {
const count = appsmith.store.success_count;
if (count > 0) {
showAlert(`${count} cards terminated!`, "success");
}
get_cards.run();
},
});
}
The Users page involves many of the same techniques and concepts discussed earlier. However, there are two tables involved here. We'll need to refresh one of the tables, depending on whether the CSV file is intended for referrals or invites.
I should mention that an invite asks someone to join your Brex account as a team member, whereas a referral prompts someone to sign up for their own Brex account.
Creating an invite sends an email to the recipient:
On the other hand, creating a referral generates a personalized invite link to an onboarding flow. You can find your referral code at dashboard.brex.com/referrals. When the prospect visits their personalized link, they will see a pre-filled form containing data values sent through the Create referral API call:
When the CSV file is uploaded, we can inspect the header row to determine if the file contains referrals or not - referrals have a referral_code column while invites do not:
COPY// invites csv header: "first_name,last_name,email"
// referrals csv header: "referral_code,first_name,last_name,email"
let is_referral = rows[0].indexOf("referral_code,") == 0;
// ...
return is_referral
? users_object.createReferrals(rows)
: users_object.createInvites(rows)
For brevity, the full implementation code is shown here.
Something to note about the Create referral endpoint is that it returns the referral id and the referral_signup_url, but it does not return the applicant details (first name, last name, and email). Instead, the API consumer is expected to store and handle their own Brex referrals securely, as they contain sensitive information about the applicant.
Why do we need a data store?
At first glance, this might seem trivial. Perhaps, we don't need a referral data store. Maybe we could just create the referrals and then use the List referrals endpoint to load the recent items. However, the List referrals endpoint does not return any applicant information either.
So, by design, we need the data store to establish a link between the applicant details (passed into create_referral) and the referral id (returned from create_referral).
Without a data store, it's also not possible to seed tbl_referrals on page load. The List referrals endpoint doesn't return any applicant information, so we need to query the data store instead and then use that response data to populate tbl_referrals.
Implementing the data store
I'm using a serverless database (Fauna) to host the data store for this tutorial, but the type of database you use is unimportant. It is only important that the data store is accessible via a REST API, so that we can easily connect to the data source and create query objects:
QueryEndpointadd_referralgraphql.us.fauna.com/graphqlget_referralsgraphql.us.fauna.com/graphql
Fauna exposes a GraphQL API. Please see the the wiki for more details about this as it relates to add_referral and get_referrals.
Storing the referral data
Now that the data store is in place, we can persist the referral id and referral_signup_url along with the applicant information:
COPY// get response data and csv row
onSuccess: ({ id, referral_signup_url }, row) => {
// get applicant info from the row
const [referral_code, first_name, last_name, email] = row;
// store the referral data
add_referral.run({
id,
name: `${first_name} ${last_name}`,
email,
referral_signup_url,
});
},
Get referrals on page load
Also, remember to configure get_referrals to run on page load:
COPY// bind this to tbl_referrals - Table Data property
get_referrals.data &&
get_referrals.data.data &&
get_referrals.data.data.allReferrals.data
Implementation of the Vendors page is left as an exercise for the reader. Here are some things to keep in mind:
The full vendors_object implementation is here. You can also create multiple vendors by using the bulk upload tool in your Brex dashboard.
Thus far, we've only explored the happy path. If we return to the Cards page and upload cards.invalid-user-id.csv the create_card query will fail. Thankfully, Appsmith will handle this exception and display an error message.
But, imagine if you were to upload the following CSV file:
COPYcard_name,user_id
Space Mountain,invalid-user-id
Cargo Dragon,cuuser...
Planet Express,invalid-user-id
In this case, the API call would fail on Space Mountain and Planet Express, but the default error handling would not be able to detect which rows failed. To correct this, we'll need to implement the error handling ourselves.
During cards_object.loop(), whenever onReadLine fails, the onError function will trigger. We can implement onError to display a message:
COPYonError: ({ row }) => {
const [card_name] = row;
const message = `failed to create card "${card_name}"`;
showAlert(message, "error");
return message; // return message to the loop helper
}
The loop helper also keeps track of errors. There's a has_errors flag, which is a boolean that indicates when any errors have occurred. There is also an errors_arr collection where we store each error message for later display in tbl_errors.
The has_errors flag will determine if the red Icon Button is visible. Set its Visible property to {{appsmith.store.has_errors}}. Also bind its onClick handler to {{showModal("error_modal")}}. This button will launch a Modal that contains a table bound to {{appsmith.store.errors_arr}}:
The beauty of Appsmith is that you can migrate this application to your own workspace and repurpose it for your own needs. Here, we've touched on a few Brex API endpoints. We've also learned how to create an Appsmith dashboard that allows Brex admins to create and terminate Brex cards and refer and invite Brex users.
I encourage Brex admins to build and share custom Appsmith workflows that tap into the Brex APIs. There is much value in simplifying the development process where we can. Low code tools like Appsmith can provide practical advantages to Brex admins who need them, but they can also change the perspectives and attitudes of those who do not.
The views expressed in this post are my own and have not been reviewed or approved by my employer (Brex, Inc.).
A contact application is a database that collects and stores user contact data. The contact app is a widely used application, similar to the contact application on your mobile phone, that stores data such as user contact names, phone numbers, email addresses, etc. Businesses can use this application to manage their customers' information and store personal contact data.
This tutorial primarily focuses on integrating a contact API in Python using the Django Rest Framework. This application will have functionalities that allow users to create, edit, and delete contact data. While this goes on the backend of the application, we will create the interface of our application using Appsmith's pre-built UI widgets.
Appsmith is a powerful open-source low-code framework for creating internal tools with features such as pre-built UI widgets that connect to multiple data sources: APIs, databases, GraphQL, etc., with support for OAuth 2.0 and CURL.
Appsmith allows you to create web application interfaces with little or no code. You don't need to be a developer to create an application dashboard using Appsmith. Using Appsmith's drag-and-drop UI widgets, we will create a dashboard for our application.
We will begin by creating a virtual environment for our project. The essence of a virtual environment is to create a separate environment for all installed packages and dependencies.
The command below shows how to create a virtual environment in your terminal:
COPYpip install virtualenv
virtualenv env
For Windows:
COPYenv\Scripts\activate
For Mac/Linux:
COPYsource env/bin/activate
Virtual environment activated!
Cloning a repository
Next, we will be cloning an already existing repository built with the Django Rest Framework. This repo contains a contact application with functionalities that allow users to create, edit, and delete contact data.
To clone the repo, run these lines of code in your terminal:
COPYgit clone https://github.com/Anitaachu/contactAPI.git
cd contactAPI
Once this is completed, we will be installing a couple of dependencies and packages required for this project using the pip These packages are already contained in your cloned requirements.txt file.
Run this command to create a requirements.txt file and install the packages:
COPYpip install -r requirements.txt
Next, migrate the data to the database and create a superuser. To this by running the following commands:
COPYpython manage.py migrate
python manage.py createsuperuser
Next, let's test this application locally, using the following command: python manage.py runserver
In your browser hit the endpoint http://127.0.0.1:8000/. You can also access the admin page using this URL http://127.0.0.1:8000/admin/
Great! Our application is running!🎉
With our API up and running, the next phase of this project is creating an interface using Appsmith pre-built widgets and connecting these widgets to our data source (API). We will be doing this by writing some queries that will be implemented with the widgets.
Let’s dive in!
It takes a few minutes to connect to a datasource, and you can develop tools on the database of your choosing. You can either connect to a database, an API, or both. For this project, we will connect Appsmith to a deployed API using the API we earlier created. The deployed API can be accessed using this URL: https://contactapp-api.herokuapp.com/
Add the URL of your deployed API and click on ‘run'.
Datasource successfully connected!
Now let’s get to work!
With Appsmith, you can build a fully customized interface with no code. Appsmith has many pre-built UI widgets such as tables, forms, buttons, boxes, images, and more, all available to help you create exciting applications.
Let’s begin! Firstly, let's create a table that will display our contact data.
Follow these steps:
Next, we will create a button widget that will be used to create contacts. When a user clicks this button, it navigates to another page that contains a form widget.
Drag and drop the button widget into the canvas.
In the label section, change the ‘submit’ label to 'create contact'. Next, edit the button widget, in the Events > onClick > Navigate to.
Under "Page Name or URL" type in 'Page 2'. By doing this, when we click on the "Create contact" button, it navigates us to a new page that will take us to the contact form.
Lastly, click on the "+" icon at the top left to add a new page.
This new page will contain a contact form that will be used to add a new contact, using input fields where users can enter the contact data they wish to create.
Let’s create a form using a form widget with these few steps:
COPY{
"first_name": "{{Input1.text}}",
"last_name": "{{Input2.text}}",
"phone_number": "{{Input3.text}}",
"email":"{{Input4.text}}",
"address":"{{Input5.text}}",
"birthday": "{{Input6.text}}"
}
By doing this, a connection will be created between the widget and the datasource.
Now let’s test out our widget to ensure that it's functioning. Firstly, on the contact dashboard, click on the "Create Contact" button. The button would redirect to another page that contains a contact form.
Fill out this form and hit the submit button. You will notice that contact details that are added through the form are displayed on our application dashboard.
So far, we have been able to create a form widget where users can create contacts, and these contacts will be displayed on our dashboard.
Great!
Asides creating contacts, contact applications also have features where users can edit contacts or delete contacts that are no longer needed. Let’s add the edit and delete contact buttons and write queries that will connect these buttons to our datasource.
In our application dashboard, add an edit button. This button will also be connected to our datasource. Let’s work on our edit button.
When you click on the edit button, it spins up a modal. We will edit this modal and add some queries to it to enhance its functionality. To do this:
Now you can edit a contact by clicking on the edit button and adding new data to replace the former contact data.
For the delete function, we simply repeat the same process as that of the edit button. However, the modal of the delete may differ. The Delete modal should appear like this:
Just as we did for the first modal, create a query that will connect the delete button widget to a data source.
Set the body property of your datasource to: {{Table1.selectedRow.id}}
Lastly, execute a query under Events > onClick. This button will query data from the deleted datasource you have created.
Let’s test out the delete method to see if it is working properly.
Nicely done! Our widgets and datasources are well implemented and functioning properly.
So far, we have done a great job. The last phase of this project will deploy our application. On the right section of the dashboard, click on 'Deploy'. You can also deploy this application by connecting to a Git repository.
Our application is deployed! 🎉
Finally, to test the work we have done so far. Try creating a new contact:
We will also test the delete button to ensure it's working as well:
Successful!
In this tutorial, we created an amazing user interface for our contact application with low code. I hope you had fun building!
Happy coding!🙂
If you’ve followed Appsmith for a while, you know that we can do a lot in 30 days!
I am here to give you all the deets; follow along!
We’ve received a lot of positive feedback on our new drag and drop experience. Users dig being able to resize widgets and move them around. This provides them with the ultimate freedom to build applications however they want without barriers that might get in the way :P
We’ve made this even more fun and powerful by adding a multiple widget reflow feature. With this, users should be able to move widgets and resize them even when they are grouped.
This also makes the drag and drop experience more performant in avoiding UI lags while moving widgets.
All of you have been waiting for a much-requested feature, and today, it’s finally here! The application URL now has your app name as a slug, making it easier for you to share and find your Appsmith applications. This is available immediately for all the old applications and, of course, the newly created ones. Here’s a sample app URL.
To upgrade your old app URLs, please navigate the updates section from the bottom bar and hit update. Here’s the recording of how you can do it:
We've added a new response view switcher feature that lets users easily switch between response formats on the fly; you'll be able to view them in different formats (JSON, Table, RAW) based purely on ease of choice. This feature will be available on all action types (APIs/Queries on a datasource).
It’s super easy to set a column type to a button on Appsmith - just navigate to column properties and update the type to Button. To make your table button more extraordinary, we’ve added the variant property taking inspiration from our button widget; with this, you can update table button types to different variants available.
We’ve added a smart substitution feature to Firestore plugin methods (to dynamically perform type conversions on field values in a request body). The smart substitution will work the same way for REST API requests.
Currently, this feature only gets applied to the body section of Create, Set, Add or Update commands, as this is the only input field that expects a JSON input type. This can be toggled by navigating to the settings tab on datasource.
We’ve added MultipartFormDataType variants; with this, users can add an array as a value for multipart requests on REST APIs. It will handle every item in the list as a part of the multipart request. Here’s what an example body will look like:
When the truncating text option is enabled in a text widget, the scroll switch is no longer valid; as we truncate to fix this issue, we made the following changes.
We’ve added an overflow property option with the following configurations:
You can now connect MinIO instances on Appsmith using the S3 plugin. This can be done when:
You can find this connecting in a dropdown from the S3 datasource.
We’ve been listening to a few issues with the select widgets when large datasets are used. Previously, in the case of these large data sets, the Select widget took up to 5 seconds to render. The initial render is down to ~100ms once the options are available from the API call.
Our engineers tested this thoroughly by loading 1000 options from a mock API on a newly upgraded test widget :)
Last month was crazy for us; we’ve published a blog post on how you can connect Stipe on Appsmith to manage your transactions; not just this, we’ve successfully hosted four live sessions.
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 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.
Different organizations rely on admin panels to manage, read and mutate data stored in their database. An admin panel is a console used to control features configurations of an application and manage content in that application. Admins in most organizations use these to help control and manage content and provide security for the application. Anyone looking to handle applications or site functions easily will need to use an admin panel.
In this tutorial, you will learn how to set up a Redshift database and create and deploy an admin panel template built on Appsmith.
To set up your Redshift database: Navigate your browser to Redshift. Click on the 'Get started with Amazon Redshift' button. Sign in if you already have an account; else, create a new user account.
Next, you need to set up a new role for RedshiftDB. Click on Services in the top navigation, then IAM. Choose Roles from the left navigation panel and click on Create role. In the AWS Service group, choose Redshift. Next, choose Redshift - Customizable, then select Next: Permissions. On the Attach permissions policies page, scroll down and select AmazonS3FullAccess. Enter the role name and description, then click on Create role.
On the dashboard, click on ‘Create Cluster’ and enter your cluster name, cluster plan, admin username, and password in the form on the new page that opens up. Ensure to store your admin username and password as you will be using it to connect the database to the Appsmith app. You can finally click on the 'Create Cluster' button when you are done with that.
When the cluster is created, select the cluster and click on Actions; under the 'permissions' section, click on Manage IAM roles. When the management screen appears, select the IAM role you had created earlier, click on Associate IAM role, and click ‘Save Changes.’
With the newly created cluster, you can use a boiler template database. Click on the Query data button.
Select the newly created cluster in the left panel to use a cluster.
By default, Redshift creates a dev database that we will use in this tutorial. You can create your table data using the following command and run it to view your output.
Click on the 'save' button to save this query, enter the name of your query and finally, click save to store it.
To access the database's credentials, click on 'security credentials' in the dropdown menu on your user name at the top navigation bar. Click on 'Create new access key,' then download the key file in the access key.
After setting up the database, the next step is to create the panel on Appsmith.
The endpoint is your hostname, copy and paste it into the required field without the port number at the end. By default, the port number is 5429, but you can find this information in your endpoint.
With the Redshift data source connected, the data from the database can be displayed using a table. Navigate to the page and add a Table Component from the widgets section by dragging and dropping it onto the canvas. Next, open the table's property pane by clicking on the cogwheel icon on the table.
Before that, we need to set up a query for the data with the command:
COPY
COPY
SELECT firstname, lastname, total_quantity
FROM (SELECT buyerid, sum(qtysold) total_quantity
FROM sales
GROUP BY buyerid
ORDER BY total_quantity desc limit 10) Q, users
WHERE Q.buyerid = userid
ORDER BY Q.total_quantity desc;
Then on our page, we can get this data. In Appsmith, we use the mustache syntax {{}} to add Javascript. To get our query, we use {{Query1.data}}
Apart from reading the data to the table, you can use Appsmith to create and update functionalities.
To do this:
Drag the form widget onto the canvas from the widgets section and add the fields for the firstname, lastname, and total_quantity.
You will need to link the form to the database to add the new data with the form setup. You will need to write a query to collate the data from the form when the submit button is clicked and append it to the table. To do this, click on the cogwheel icon on the submit button. Then set the onClick to execute a database query and then click on create a query:
COPY
COPY
INSERT INTO users
('firstname', 'lastname', 'userid')
VALUES
('{{Input1.text}}', '{{Input2.text}}', '1');
INSERT INTO sales
('qtysold', 'salesid', 'listid', 'sellerid', 'buyerid', 'eventid', 'dateid')
VALUES
('{{Input3.text}}', '1', '1', '1', '1', '1', '1')
Here we entered the values of the input fields into the firstname, lastname, and qtysold. Also, I've set the id's to '1' for every entry; usually, you may use default values for this. You can now add new entries through the form to the table.
Apart from reading and creating table entries, we can also update and delete data from our table. You must first target a particular row and set it as the default value in the form's input fields to update the data.
Above, we set the Default Text for the input field to {{Table1.selectedRow.firstname}} to always get the data from the firstname column of the selected row in the input field. We repeat this step for lastname and total_quantity by entering {{Table1.selectedRow.lastname}} and {{Table1.selectedRow.total_quantity}} as their default text respectively. We need to add new functionality via a button to update the table. Add a button from the widgets pane and name the ‘Update’ button.
Next, create a new Javascript query for the on-click handler in the button option pane. For our new query to handle updates, we have the following:
COPY
COPY
update users
set firstname='{{Input1.text}}', lastname='{{Input2.text}}'
where firstname='{{Table1.selectedRow.firstname}}';
The query above checks for the row where the firstname corresponds to the selected row's firstname column value. It then replaces the firstname and lastname columns with the value of the input fields.
We can add another button called Delete to our form to do this.
Create a new query as follows:
COPY
COPY
delete from public.users where firstname = '{{Input1.text}}'
When executed at the click of the Delete button, this query checks the user's table and deletes the corresponding row, which has a firstname with its value corresponding to the selected data.
You can try out the query and observe that the selected row is removed when the 'Delete' button is clicked.
To deploy the Redshift panel template, click on the deploy button at the top right of the navigation bar. You can then make it publicly accessible or share it with specific individuals via email. The admin panel can be further modified with added functionalities such as user authentication for restricted access and email integrations to inform the admin when a change has occurred.
Proper feedback and community management is a significant part of building the organic reach of products, especially open source products. So, marketing teams might decide to build customized apps that contain valuable metrics. Products like Orbit allow us to get live data from our community forums to view them more concisely. In this tutorial, you will learn how to build an internal growth dashboard, where we’ll be able to display key metrics, including monitoring a Slack group and viewing existing members of the channel. The goal is to display specific growth metrics that enable better decision making in the marketing team.
First, we’ll be learning how to connect our Slack directly to Orbit, where we can view our information, activities, and members on their dashboard. Then, we’ll use Orbit’s REST API to view the data on our Appsmith dashboard.
This is useful in cases where we want to view our Slack data in a custom Appsmith app outside something like Orbit, mainly when the dashboard includes other external community data, not data from just the Slack channel.
We’ll [signup to Orbit] (app.orbit.love) and create our Orbit’s workspace:
Once we’ve created the workspace, we can now integrate our Slack community to orbit.
You can now open the Slack workspace you just connected with Orbit.
Go into your channel and open the Channel Details menu by clicking on the top-left channel name. Then, we’ll open the integration panel and click on “add apps.”
We’ll then see a bunch of apps where you’ll select Orbit.
The Orbit integration is now added to our #general channel! This automatically imports all messages and profiles (up to one year). Plus, it will listen for any new activities, including messages, thread replies, etc.
A message will automatically appear in the channel you just added, saying, “Orbit was added to #channel by you.”
To add the Orbit integration to more channels, we need to repeat the same steps or take advantage of the message shown above: Clicking on the name or icon of “Orbit” in that message will open a menu, from which you can add the integration to more channels with a click.
We’ve successfully connected Slack to orbit and can view all activities on our Orbit dashboard.
Setting Up Our Orbit API
Orbit offers RESTful APIs that we’ll use to pull our Slack data into our dashboard. The specific data pulling is the list of members from this Slack channel.
Here’s the endpoint:
app.orbit.love/api/v1{workspace_slug}/members
Note: You can can check the docs for more endpoints and use-cases.
You can find the workspace_slug under the workspace settings. It’s the text in bold below:
Let’s sign up to Appsmith and create our first app. On our first page we’ll add the container and text widgets to act as the header. Then, we’ll also add the list widget.
Now, we’ll go under QUERIES/JS dropdown on the left and create a new Datasource.
Set the API request to GET and add the endpoint. You’ll have to add your {workspace-slug} to the endpoint, as explained earlier. Once that’s done, we’ll click Edit Datasource, and it’ll take us to a page where we’ll add our header token.
Scroll down to the Authentication section of the page, down to the Bearer Token input, and add your Orbit’s API token. You can find that on the settings page. Note that you won’t add Bearer as a prefix, just the token. (that’ll be done automatically)
Let’s go back to our API datasource page and test it again
We now have everything functioning as it should, and the API provides the appropriate response. Look at the left and open a new page:
Once we select the list widget, we go to the left and see all related options. Under items, we’ll get the response preview by adding the name of the API: Orbit_Members.data.data.
{{Orbit_Members.data.data}}
Similarly, you’ll add an image widget inside the List item. On the right, we’ll use currentItem to refer to the current API in question. So it’ll be currentItem.attributes.avatar_url.
In the same vein, we add the name and email to the List item with {{currentItem.attributes.name}} and {{currentItem.attributes.email}}. If we do this correctly, we should have a similar screen to the one we have above.
First, we’ll create a new page called Member Details
We’re now going to add a button to each user that navigates us to a new page (Member Details). While navigating, we’ll save the user’s slug as a store value, and send it as a query param to the next page.
The aim is to use that slug to make another request on the new page. This request displays that particular user’s details. Under Member Details, we’ll name that request Member_Details and get our slug value from Appsmith.value.slug. This allows us pull the data for that single member that was selected on the Dashboard page.
Let’s go back to Member Details and display our data.
First, we add an image component to display the picture and use {{Member_Details.data.data.attributes.avatar_url}} to get our image URL from the Member_Details DataSource we created.
We also use {{Member_Details.data.data.attributes.location}} and {{Member_Details.data.data.attributes.avatar_email}} to display our location and email respectively.
Next, we’ll manually add other data to our dashboard. These include our Daily Active Users (DAU) and New Community Members.
There’s a sales report graph that helps us display our sales data.
In this case, we’re manually adding our data as an array.
Finally, we’ll hardcode other important data like churn rate, conversions, and our MRR.
Now that our Appsmith app is complete, what’s next? Deploying our shiny new app for other team members to use. Here’s the link to our application.
There’s also a tutorial below that shows you how to deploy with digital ocean. youtube.com/watch?v=6fitHGX2G4E&; youtu.be/6fitHGX2G4E
In this article, we’ve covered how to create a growth dashboard with Appsmith and Orbit‘s REST APIs. This shows us how to use low-code tools to optimize time and valuable resources when building internal tools in your company.
Orbit and Appsmith complement each other when it comes to monitoring community platforms like Slack, Discord, Discourse, etc. With Orbit, you get access to direct feedback and necessary information without spending engineering time building infrastructure from scratch. While Appsmith lets you focus on creating a visual dashboard with metrics, using minimal effort to implement and maintain.
Beyond using Orbit as a datasource, we can make use of custom REST APIs, Airtable, Supabase, Backendless, etc. Also, you can add other third-party integrations like intercom, email, or even add Zapier into your application. Appsmith can be customized into any form to fit your technical use-case.
If you have blockers or issues using Appsmith, you can always jump into our community Discord server to ask questions. Plus, you can connect with other Appsmith users.
Also, feel free to check other Appsmith tutorials using similar services like Cube, SnowflakeDB, Hasura, etc.
Stripe is one of the most prominent developer tools for integrating payments into your website or application. The service allows you to start accepting payments from users in 14 countries and 24 currencies, and all this is relatively easy to set up! However, not every business needs a full-fledged website for collecting payments from their customers. In this short tutorial, we'll be building an app on Appsmith that will generate Stripe payment links for you directly from your dashboard. You can create as many payment links as you like and make them available via email. Even if someone doesn't have an Internet connection or uses a computer without a browser installed, they can still take advantage of your services!
Appsmith is an open-source application builder that integrates with custom APIs and databases. It's perfect for building your team's internal tools, admin panels, and dashboards.
Let's dive in!
The first step in building a payment link generator is to set up a Stripe account. You can either create a new account or log in if you're an existing user.
Please note that this application is a built-in test mode, which requires additional information about the business to generate payment links. To make it into a fully-functional application, you will need to add additional details regarding your bank and tax information.
Your dashboard will look like this:
Even in test mode, you will be able to access all the features of Stripe APIs, but this will not be able to make complete transactions from our generated links.
The next step is to make our API requests from Appsmith; we’ll need to copy the secret key that’s available on the main page of the dashboard.
This secret key lets us access our Stripe account via Bearer Token-based authentication.
In the next section, we'll build s simple UI that lets us generate payment links based on the given customer information and payment price.
The first step is to create an account on Appsmith. In this guide, I'll be using the cloud version of Appsmith, but you can always choose to use Appsmith locally or self-host it on your server.
Now, click on the widgets tab and drag and drop a container widget on the canvas; this will allow us to group all the widgets in a container. This can be completely customizable; you could add borders, background colours, shadows, and more by opening the property pane.
Inside the container widget, drag and drop a new form widget and add a few input widgets onto the container that lets us collect information for payment links:
We could also add some additional configuration based on the information that needs to be collected, referring to the Stripe Documentation.
Following is a screenshot of how the UI looks on Appsmith:
Next, let’s create a new datasource, an API endpoint that’ll create a new Stripe payment link.
https://api.stripe.com/v1/checkout/sessions
Authorization - BEARER <token>
To bind the data on the API, we’ll need to use the moustache bindings and the input widgets names. Here’s how we can access the data from the price the amount widget:
Similarly, we add all the required fields on the payload to create a new session. Here’s a screenshot of what the payload looks like:
Our API is now ready; let’s add one more input widget, generating a Stripe Session link (the payment link) for use with the data passed through our input widgets.
Here’s what we’ll need to bind the response from the API endpoint; we can do this by binding the following:
{{stripe_Session.data.url}}
The .data property on an API request will return the response from the API endpoint; here, we’ve accessed the URL field, which is essentially the payment link.
If you open this URL, you’ll see a new Stripe session with the amount and details you’ve entered on the form.
Here’s a recording of how this works:
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.
If you’ve followed Appsmith for a while, you know that we can do a lot in 30 days!
I am here to give you all the deets; follow along!
We’re launching templates! Our ready-made apps are easy to use, forkable, and are bound to give you a little nudge in the right direction. Directly connect your datasource and get customizing!
The Appsmith templates library will be an ever-growing forkable collection of pre-made applications. These apps span across use-cases that will speed up onboarding for new users and makes application development faster.
You can access templates on our website and inside your Appsmith dashboard.
Read the full announcement here.
We’ve just launched the JSON Form Widget, one of our most requested features. It’s live on the cloud app and will be live on the self-hosted app very soon. The JSON form widget is helpful for quickly generating (dynamic or otherwise) forms from JSON fields from queries, APIs, or JS Objects. Check out the documentation for more details.
Here's a short video on how you can generate a form from a table:
Read the full announcement here.
The table widget is one of the most used widgets on Appsmith; it gives the ability to convert column data into different data types, including buttons! With this, developers can add different actions on the onClick property of the button, for example, redirections, showing modals, running queries, etc. Appsmith supports JS throughout the platform using the moustache syntax, but using JS promises to execute actions in the sequence was limited. But now, we got you covered; the Table Button (columns that are set button type) also supports the async-await functions. All triggers are wrapped in a promise, so any missed error will result in an uncaught promise error.
Here’s a simple snippet that can be used in the table button’s onClick property to run a query and then show an alert:
Using JavaScript, we can dynamically add and choose icons in the icon button widget. This will allow developers to customize their applications based on conditions, actions, etc. Here’s a simple example: if you’re adding different links to an icon button widget, it can be super handy. You can update the button icon based on the URL – Google Icon when the icon button redirects to a google page, GitHub icon when the icon button redirects to a GitHub page, etc.
Not just that, you could also replace the close buttons on the modal with the Icon Button widget for more customization.
To create new queries on Appsmith using keyboard shortcuts, you’ll need to use Command/Control + Plus; previously, this was Option + Shift + N. To learn more about all the shortcuts on the platform, you can use Shift + ?.
Smart substitution handling helps users use MongoDB types like ObjectId or ISODate inside the quotes, and the query works correctly with MongoDB. With this, you can focus more on the logic than worrying about the request data. You can toggle this feature on and off on the query settings page:
Following are the MongoDB types that can be handled:
Several developer teams love the commenting feature on Appsmith when building internal applications together. We've added that the comment author's email is set as the comment notification email to make it more fantastic. You can update these details from the settings page.
Last month was crazy for us; we’ve published a couple of new blog posts and have successfully hosted four live events!
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 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.
Forms are a core part of most internal tools since its one of the major ways in which data is created or updated. Today, we're introducing the JSON Form Widget (documentation), which allows for a fantastic form creation experience and has been one of our top requested features.
The JSON form widget is helpful for quickly generating (dynamic or otherwise) forms from JSON fields.
Here are some highlights of this widget:
Once you drag a new JSON form widget, you will see a default form rendered with some details. You can update the source data field to infer data and then generate the form. This can be bound to any query or variable containing JSON data, such as DB queries, APIs, or JS Objects. The JSON Form widget can be bound to any other widget in Appsmith as well.
The form fields are generated according to the source data when you enable an auto-generated form. Fields are generated according to the key-value pairs in the source data. Whenever there is a change in the source data, the form fields get updated automatically.
Field configuration shows all the fields generated automatically in the forms. You can edit the fields to tweak properties like the field type and default value and bind specific actions by using editable properties. Most fields use the underlying data type-specific widget's properties to allow a full level of customization just like the widget would. For example, if the input type is text input, the editable properties are similar to the input widget in Appsmith.
Some of the ways that we've seen our users use the JSON form are:
Note: It’s live on the cloud app and will be live on the self-hosted version very soon.
Want to explore the JSON Form in detail? Head over to the JSON Form documentation page to learn more.