In this article, we’ll walk through a build for a multi-tenant real-estate platform, and you’ll learn how to create and add content to models along the way. You’ll also explore more advanced concepts like setting roles and permissions for a project team member and how to set Permanent Auth Tokens (PATs) to protect your content endpoint.
#What is Hygraph and how is it used?
Hygraph is a headless CMS that focuses on content federation. Its native support for GraphQL enables you to easily deliver ambitious applications at scale.
Hygraph’s API-first approach lends itself to a variety of use cases, including:
Knowledge management. Hygraph provides you with a schema builder for structuring data in a reusable and centralized manner. You can deliver that data to consumers programmatically via an API or through the Hygraph Content Studio.
Content federation. All your end users can access content from a single location instead of having several fragmented data sources. That way, your users always have access to updated information, and you can avoid tedious data migration.
Websites and SEO. With features like structured content, SEO, and asset management, you can optimize your site’s content for multiple devices. Edit your website’s metadata to fit your specific needs, leading to a better SEO score.
Multi-tenancy. Run a single instance of the software on a server and serve multiple clients. Multi-tenant applications allow you to configure them to serve your specific needs without changing their core code structure. That translates into easy configuration, lower costs, and no maintenance fees.
This tutorial focuses on that last use case, multi-tenancy.
#Building a multi-tenant real-estate platform with Hygraph
Before you move on with the tutorial, make sure you’re prepared with the following prerequisites:
A Hygraph account that’s subscribed to the Enterprise plan.
Node.js and npm installed.
A web browser.
Three email accounts: one account to create the project, and two more to act as project invitees.
Project overview
Here’s a high-level view of what you’ll create:
My Real Estate is the name of the project.
agentOne Listing and agentTwo Listing are the different models that belong to the My Real Estate project.
- agentOne and agentTwo are the custom roles you’ll create for the project.
The arrows indicate the permissions assigned to each role.
Each role will have access to a specific model and cannot access any other model.
Creating a project and models
Log into your Hygraph account and click Add project.
On the New project pop-up, enter My Real Estate as the project name, provide a project description, and select a region where you want your content to be stored.
Click Add project to navigate to your dashboard. On the sidebar, click Schema to open the schema editor.
Click + Add to create a new agentOne Listing
. This model will store the real estate listings for one agent. Leave the API ID
and Plural API ID
with their default values. You can add an optional description for this model.
Click Add Model to create the model.
To add a field to the model, select one of the field types from the schema editor. The agentOne Listing
model has the following fields:
Name
. Stores the name of the listing.Location
. Stores the location of the listing.Price
. Stores the listing’s price.Image
. Stores the listing’s image.Description
. Stores the listing’s description.
To create the Name
field, select the Single line text field type. Set Display name to Name
. On the Validations tab, make the field required.
Repeat the process to create other fields. The following table shows the types and validations for other fields:
Field | Field Type | Validation |
---|---|---|
Location | Single line text | Make field required |
Price | Float | Make field required |
Image | Asset picker | Make field required |
Description | Multi line text | Make field required |
After completing this process, your UI should look like this:
Repeat the process for creating the model and create a new model called agentTwo Listing
with the same fields as the agentOne Listing
model.
Please note that you’re creating two different models, as each agent will only have access to its corresponding model.
Adding content to the models
Now that you have two models set up, go ahead and add content to them. Select Content from the project dashboard sidebar to open the content editor.
First, let’s add content for the agentOne Listing
model. Make sure that you have it selected and click + Add entry.
Once you’ve filled out all the required details, click Save & publish. When prompted, confirm whether you want to also publish the referenced documents. Select the image checkbox to confirm and select Save and publish.
Repeat the process above to add content for the agentTwo Listing
model. You can add as many content entries as you want, but this tutorial only covers the use of one content entry per model.
To test whether the content was successfully published, select API playground from the project dashboard and test the query below:
{agentOneListings {namepricelocationimage {url}description}agentTwoListings{namepricelocationimage {url}description}}
Your output should be similar to this:
Setting up roles and permissions for users
Within the Hygraph CMS, roles help to ensure data safety by dictating the data a user can view and the actions they are allowed to perform on that data. Hygraph offers default system roles but also gives you the freedom to implement your own custom roles.
Note that custom roles are only available in enterprise plans.
To configure custom roles so that each agent can only access its own content models, select Project settings > Roles & Permissions from the project dashboard sidebar.
Select + Add custom role.
Set agentOne Role
as the name of the custom role and provide an optional description of the role. Then click Add to create the custom role.
Open the custom role details page by clicking on the name of the role. On the "agentOne Role" details page, select "+ Add permission".
On the Add permission page, select agentOne Listing
as the model that this role applies to. Select all the checkboxes to give this role the permission to create, update, delete, read, publish, unpublish, and view versions of the agentOne Listing
model. Click Add to save the permissions.
On the details page for agentOne Role
, select Edit permissions to open the Update role page. On this page, under Management API Permissions, select the following checkboxes:
Create new entries
Update existing non published entries
Update published entries
Publish non published entries
Delete existing entries
Users assigned the agentOne Role
can now perform the actions described by these permissions. Do not deselect the already-selected options! These options allow users assigned to this role to read the existing environments, models, enumerations, fields, and entries.
The next step is to assign members to this role. On the "agentOne Role" details page, click the "Assign members" button and select "Add team members" on the page that opens.
Here, enter the email address of the team member you want to invite and click the "Add" button. Confirm that you want to add the member to the role by clicking the "Assign 1 member" button on the confirmation page. An invitation email will be sent to the provided email address.
Repeat this process to create a custom role called agentTwo Role
for the agentTwo Listing
model.
To confirm that the set roles and permissions are working as expected, accept the agentOne Role
invite and confirm that you can only access the agentOne Listing
model. You can also confirm that you are only able to perform actions permitted by the permissions you set earlier.
Enabling API access
Hygraph allows you to either enable full public access to your API endpoint or protect it with a permanent auth token. Let’s walk through setting up permanent auth tokens as each agent will have its own unique token for querying its respective content models.
To implement permanent auth tokens, navigate to Project settings > API Access > Permanent Auth Tokens. Click + Add token to set up the first token.
Name your token agentOne Token
and click Add & configure permissions.
This takes you to the agentOne Token
details page. Select + Add permission.
Choose the agentOne Listing
model, select all the permissions, and click Add.
Finally, click + Add permission again, this time selecting the Asset
model. Select all the permissions and click Add. This permission on the assets model allows the agent to query assets, such as the real-estate listing image.
Repeat this process to create a permanent auth token for the agentTwo Listing
model as well.
Take note of these two tokens for agentOne
and agentTwo
; you’ll use them in the frontend to query the Hygraph GraphQL endpoint.
Setting up the frontend project
Implement the frontend using React, a JavaScript library for building user interfaces. Navigate to a directory of your choice and run the following commands in the terminal to create a React app using Vite:
npm create vite@latest my-real-estate -- --template reactcd my-real-estatenpm install
To install the dependencies you’ll use in this project, run the following command:
npm install @apollo/client graphql bootstrap react-bootstrap
The dependencies include the following:
@apollo/client
. Queries the Hygraph GraphQL endpoint.graphql
. Parses GraphQL queries.bootstrap
andreact-bootstrap
. Style the webpage.
Once you’ve successfully installed the dependencies, open the src/main.jsx
file and replace the existing code with the following:
import 'bootstrap/dist/css/bootstrap.min.css'import React from 'react'import ReactDOM from 'react-dom/client'import App from './App'import { HttpLink, ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';import { setContext } from '@apollo/client/link/context';const httpLink = new HttpLink({uri: '<your-hygraph-content-api-endpoint>',});const authLink = setContext((_, { headers }) => {// set the auth tokenconst token = '<your-agentOne-token>'// return the headers to the context so httpLink can read themreturn {headers: {...headers,authorization: token ? `Bearer ${token}` : "",}}});const client = new ApolloClient({link: authLink.concat(httpLink),cache: new InMemoryCache(),});ReactDOM.createRoot(document.getElementById('root')).render(<ApolloProvider client={client}><React.StrictMode><App /></React.StrictMode></ApolloProvider>,)
In the code above, you initialized an ApolloClient
instance, attached the Bearer token, and connected the client to the React app.
Remember to replace
<your-agentOne-token>
with your actualagentOne
token from the Hygraph dashboard. You should also replace<your-hygraph-content-api-endpoint>
with the value for your Hygraph Content API endpoint. You can get this value from Project settings > API Access > Endpoints.
Next, open the src/App.jsx
file and replace the existing code with the following:
import { gql, useQuery } from '@apollo/client';import { Container, Card } from 'react-bootstrap';const GET_LISTINGS = gql`query GetListings {agentOneListings {idnamepriceimage {url}descriptionlocationcreatedAt}}`;function App() {const { loading, error, data } = useQuery(GET_LISTINGS);if (loading) return 'Loading...';if (error) return `Error! ${error.message}`;return (<Container className='d-flex flex-column align-items-center'><h2>My Real Estate Listings</h2>{data.agentOneListings.map(listing => (<Card style={{maxWidth: '50rem'}} key={listing.id}><Card.Img variant='top' src={listing.image.url} /><Card.Body><Card.Title className='h2'>{listing.name}</Card.Title><Card.Text className='h6'>{listing.location}</Card.Text><Card.Text className='h5'>Price: ${listing.price}</Card.Text><Card.Text>{listing.description}</Card.Text></Card.Body><Card.Footer>{`Created on: ${new Date(listing.createdAt).toLocaleString()}`}</Card.Footer></Card>))}</Container>)}export default App
In the code above, you created a GraphQL query to get agentOne
's listings and used the useQuery
hook to request the data from the Hygraph Content API endpoint. You then looped the data using the map()
function and displayed it using the Bootstrap Card
component.
To confirm that the application is working as expected, start the development server with the command npm run dev
and open your browser on http://localhost:5173/
. You should get output similar to the following image:
To view agentTwo
's listings, open the src/main.jsx
file and replace the token
's value with agentTwo
's permanent auth token. Then open the src/App.jsx
file and replace the existing code with the following:
import { gql, useQuery } from '@apollo/client';import { Container, Card } from 'react-bootstrap';const GET_LISTINGS = gql`query GetListings {agentTwoListings {idnamepriceimage {url}descriptionlocationcreatedAt}}`;function App() {const { loading, error, data } = useQuery(GET_LISTINGS);if (loading) return 'Loading...';if (error) return `Error! ${error.message}`;return (<Container className='d-flex flex-column align-items-center'><h2>My Real Estate Listings</h2>{data.agentTwoListings.map(listing => (<Card style={{maxWidth: '50rem'}} key={listing.id}><Card.Img variant='top' src={listing.image.url} /><Card.Body><Card.Title className='h2'>{listing.name}</Card.Title><Card.Text className='h6'>{listing.location}</Card.Text><Card.Text className='h5'>Price: ${listing.price}</Card.Text><Card.Text>{listing.description}</Card.Text></Card.Body><Card.Footer>{`Created on: ${new Date(listing.createdAt).toLocaleString()}`}</Card.Footer></Card>))}</Container>)}export default App
In the code above, note that you only changed the query to fetch agentTwo
's listings and the map function to loop through agentTwo
's listings. Open your browser, and you should get a result similar to the following image:
To confirm that agentOne
cannot query agentTwo
's real estate listings, change the value of token
in the src/main.jsx
file to agentOne
's permanent auth token. Do not modify the src/App.jsx
file, so that it will attempt to query for agentTwo
's real estate listings with agentOne
's token. You should get an Error! not allowed
message in the browser.
#Conclusion
In this article, you learned about Hygraph’s use cases as well as some of its basic concepts, such as creating a model and populating the model with data. You also learned about Hygraph's more advanced concepts, such as setting up custom roles and permissions to limit what data your project team members can view and what actions they can perform. Finally, you explored how to project your project endpoint so that only authorized personnel can query data and perform other actions through the endpoint.
To learn more about what you can achieve with Hygraph, check out the official documentation.
The Complete Guide on CMS Multi-Tenancy
Learn how to unlock the full potential of multi-tenant CMS solutions.
Download the guide