Learn how to use WeWeb + Xano's CRM template

WARNING

The build guide below was created using an older version of WeWeb.

We are currently working on a new CRM build guide that will use our latest UI.

Getting Started

Hey 👋

Welcome on our WeWeb CRM template documentation.

The idea behind this template was to create a rather simple, yet customizable CRM using WeWeb (as the frontend) and Xanoopen in new window (as the backend).

Here’s a quick summary video on how this app works 👇

Please know that all the data used in the CRM is fake, except company names that are copyrighted. The person names, emails, and company data are all invented and doesn’t exist.

Also, when you sign up, some data is generated for you so that you can “play” with the template.

⚠️ This data is deleted every Sunday at 01:01:01 PM GMT+2.

Before to continue, please follow this video to setup your own CRM template:

To get up to speed quickly, here's a Xano snippetopen in new window to copy the CRM's backend.

Data Structure

The CRM data structure revolves around 5 models:

  • user
  • company
  • contact
  • deal
  • note

Each of them having their own table and API endpoints.

Here’s a quick video showcasing the data structure and the Xano backend:

ℹ️ We used the REST API in WeWeb instead of the Xano plugin most of the time to make the template more pedagogical. Of course, you could use it in your app to go even faster.

Again, here's a Xano snippetopen in new window to copy the CRM's backend.

User

The user table is responsible for storing the end users of the app, that means you and me.

It’s composed of these fields:

  • id: integer the primary keyopen in new window
  • created_at: timestamp storing the record’s creation date and time
  • name: text the name of the user
  • email: text the email of the user
  • password: password the password hashopen in new window of the user’s password
  • picture: image the user’s profile picture
  • role: text the user’s role that grants him/her rights

Here’s what it looks like in Xano 👇

Company

The company table stores… companies 😆 (like Airbnb, Google or WeWeb 😉)

Every CRM revolves around deals that are tied to a contact and a company. That’s why we have to store companies in a separate table, as some deals can be linked to the same company.

Here are the table fields:

  • id: integer the primary key
  • created_at: timestamp storing the record’s creation date and time
  • name: text the name of the company
  • domain: text the web domain of the company’s website
  • logo: text the URL of the company’s logo
  • location: text the location of the company’s headquarters
  • industry: text the company’s industry type
  • number_of_employees: text the company’s headcount range
  • user_id: integer the foreign-keyopen in new window linking the company to the user’s table

Here’s what it looks like in Xano 👇

As you can see, this table is linked to the user one through a foreign-key so that we’re able to restrict the display of companies (both in WeWeb and Xano) to the current user (meaning a user can only see and edit the companies he’s attached to).

Contact

A contact is the person attached to a deal, that’s also part of a company. In the case of a CRM, that’s the person you’re “trying to close” on a deal.

It’s composed of those fields:

  • id: integer the primary key
  • created_at: timestamp storing the record’s creation date and time
  • name: text the name of the contact
  • picture: image the profile picture of the contact
  • email: text the contact’s email address
  • job_title: text the contact’s job title in his/her company
  • company_id: integer the foreign key linking the contact to his/her company
  • user_id: integer the foreign key linking the contact to the user’s table

Here’s what it looks like in Xano 👇

You can see that the contacts are linked to companies, by storing the API key here, as a contact only have one company, but a company can be linked to multiple contacts.

Deal

Maybe the most important table in the CRM, the deals are all the commercial opportunities that a CRM stores. They’re linked to contacts and companies.

A deal is composed of those fields:

  • id: integer the primary key
  • created_at: timestamp storing the record’s creation date and time
  • name: text the name of the deal
  • contact_id: integer the foreign key linking the deal to his/her contact
  • company_id: integer the foreign key linking the deal to his/her company
  • status: text the current status of the deal that we’ll use to filter deals in the right column in the WeWeb kanban (eg: qualified, closing, lost, etc)
  • description: text the deal description
  • order: integer the order deals are displayed in their column in the WeWeb kanban
  • user_id: integer the foreign key linking the deal to the user’s table

Here’s what it looks like in Xano 👇

As you can see, a deal is linking both to a contact (and can theoretically have multiple contacts, even if it’s not the case in our data) and a company. That’s why it has 2 foreign keys linking to these tables.

Screens

Signup, Login, Reset and Forgot Password

Signup, login and reset password pages are basically pages containing one form, which on submit sends back the data to Xano to either signup, login or reset the user password:

⚠️ Make sure to send a profile picture. Otherwise, the signup won’t work.

A note on Reset and Forgot Password flow

When a user forgot his/her password, he’ll basically land on the Forgot Password page, where he’ll type his email.

When doing so, it’ll trigger an API call to Xano which will send an email (in this example, through customer.ioopen in new window) to the user which a URL.

When clicking on the email’s URL, the user will land on the Reset Password page concatenated with a querystring variable magic_link, which will be used inside the Reset Password workflow to sign-in the user without his password (both in WeWeb and Xano), then reset his email on Xano-side.

Deals

Here’s a summary of the main elements on this screen 👇

Sidebar

Let’s begin with the first element, which is common to all screens (reusable section), the Sidebar.

It’s a simple vertical flexbox made of links to other pages and a div which contains the logged-in user’s details:

Kanban

Then, the most important element is the Kanban. This element is bound the the Deal collection but also using data from the Contacts and Companies collections, as shown here:

The Kanban is made of Stacks that are determined by the status column inside each Deal.

When moving an item, the Kanban will trigger a workflow which will:

  • Update the moved deal status and order by using the Event to and newIndex parameters
  • Updating each other deal’s order in the current stack by sending the updated list to Xano

Dropdowns

Then are dropdowns and search bar that are used to filter and search the Deal collection:

Finally, there is the Add new deal button which, on click, triggers a workflow that opens a modal (by settings its display variable to true), enabling you to create a deal:

When submitting the form, it’ll POST a new deal to Xano and close the modal by setting the modal’s display variable to false.

Contacts and Companies screens

Datagrid

The only difference with the deals screen is that we replaced the Kanban with a Datagrid element:

Also, this element and the dropdown/search are now bound to the Contacts collection.

When updating or deleting a contact inside the datagrid, it’ll POST or DELETE the contact in Xano and refetch the contacts collection.

For companies, it’s the same, but everything is bound to the Company collection:

User Management

Workflows

API

💡 It’s actually considered a best practice inside WeWeb to store all your API requests inside global workflows that you call from your app’s elements. So that you only have to maintain/edit them once.

First is a folder called API, which is this app API management center:

It references all the Xano’s API endpoints that you can also find here: https://xc0b-vcze-d4we.n7.xano.io/api:QvNUhc0Vopen in new window

Every time we’ll need to update or delete a contact, company, deal, etc from the WeWeb app, the element triggering the workflow will actually call these global workflows.

Components

Next is a folder called Components that contains all the workflows to trigger the display of elements such as the sidebar or the alerts:

Variables

Deals, Contacts and Companies

In these folders, you’ll find the variables that are used to display specific data from deals, contacts or companies when the UI needs it.

As an example, the selectedDeal variable is used to store the currently clicked on deal that should appear in the modal:

API

API contains the API’s base URL, which is used to construct collections or global workflows URLs without having to always retype the URL in full.

Here’s an example on how it’s used in a collection:

Components

Components variables are used to store the component current state, that you shouldn’t modify directly but use their attached workflows:

Querystring

Querystring variables are used to pass data after the ? sign in a URL. There’s only one in this project, magic_link, which is used for the reset password:

Last Updated:
Contributors: Joyce Kettering