AI-assisted coding is changing the way developers create software, streamlining traditional workflows and reducing manual effort. Previously, we explored how to build a CRM using Replit Agent.
Today, we’ll dive into setting up a Gmail integration using Cursor Agent, a powerful AI coding assistant, in combination with the Nylas APIs. By the end of this guide, you’ll have a functioning email integration system up and running in no time. Let’s get started!
To kick off our project, let’s jump into our development environment. Follow these steps to get started:
1. Set Up Cursor: Download Cursor to access the Cursor Agent (shortcut ⌘I).
2. Create a new folder in terminal: Open your terminal and, if starting from scratch, create a new project directory named gmail-integration
, then launch Cursor and open the project folder:
We will circle back to entering a prompt shortly and start with the Nylas starter prompts.
3. Configure Nylas API Credentials: Register for a free Nylas Developer account (if you haven’t already) and retrieve your API Key and Client ID from the Nylas Dashboard. These credentials will be used throughout the integration:
Important: never commit secrets to source control.
4. Create Cursor Rules: Create a directory at /.cursor/rules
and store the relevant Nylas starter prompts as .mdc
files (for authentication and email):
5. (Optional) Consider adding a PRD: If you’d like a structured plan, use Cursor Chat (shortcut ⌘L) to generate a Product Requirements Document (PRD), outlining the CRM’s core features. View the post, How to Build a CRM with Replit AI Agent: A Step-by-Step Guide, for a example PRD.
In this post, we will be building using Node.js and React. Now that the environment is ready, let’s move on to implementing Gmail authentication.
Now we’ll develop the main features. For each feature, we’ll explain the approach along with links to any useful resources. You can literally instruct the AI with these requirements, and it will produce similar code. We’ll focus on:
To enable users to connect their email accounts, we’ll use Nylas Hosted OAuth, a simple and secure authentication flow. This method allows users to log in via a redirected Nylas login page, where Nylas manages authentication, provider detection, and token exchange seamlessly.
In practice, you’ll create an OAuth URL and have the user authorize your application. Nylas will return a grant ID (in Nylas API v3) for the connected account, which we’ll use in subsequent API calls. Cursor Agent can help generate the auth route. Let’s get started with our first prompt to the Cursor Agent:
View attached starter prompts:
1) A starter prompt to build with Nylas APIs: @nylas-starter.mdc
2) A PRD for a CRM that I like to build using the Nylas API: @crm-mvp-prd.mdc
3) A prompt to explain how to build hosted authentication: @nylas-hosted-auth.mdc
Since the CRM requires a lot of API integrations, I want to start step by step and build and test things out as I go. So build features and I will manually test them sequentially via available UI. Let's start with adding Nylas Hosted Authentication to connect to user's accounts.
Before installing packages, please request my review of the package version as I like to understand the rationale for selecting a specific package version.
And before building a feature, ensure it can be tested through UI by the user.
Here is a screen shot of the initial prompt:
I pasted the following prompts:
Here are a few notes on the starter prompt:
It should produce code to generate the auth URL and a callback endpoint to capture the authorization code and exchange it for credentials. During this step, you may be requested to enter specific environment variables:
After this step, you will have the ability to authenticate a user and retrieve a Nylas grantId
associated with the user. Now the app can use Nylas APIs on behalf of that user. Here is a short code snippet of the code generated:
// src/routes/auth.ts
import { Router } from 'express';
import Nylas from 'nylas';
const router = Router();
// Store connected accounts in memory
export const connectedAccounts = new Map<string, {
grantId: string;
emailAddress: string;
}>();
// Initialize Nylas client
const nylas = new Nylas({
apiKey: process.env.NYLAS_API_KEY!,
apiUri: 'https://api.us.nylas.com'
});
// Initiate OAuth2 flow
router.get('/nylas', (req, res) => {
const authUrl = nylas.auth.urlForOAuth2({
clientId: process.env.NYLAS_CLIENT_ID!,
redirectUri: `${process.env.BASE_URL}/auth/callback`,
scope: [
'openid',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/calendar'
],
});
res.redirect(authUrl);
});
// Handle OAuth2 callback
router.get('/callback', async (req, res) => {
try {
const { code } = req.query;
const tokenData = await nylas.auth.exchangeCodeForToken({
clientId: process.env.NYLAS_CLIENT_ID!,
clientSecret: process.env.NYLAS_API_KEY!,
code: code as string,
redirectUri: `${process.env.BASE_URL}/auth/callback`,
});
connectedAccounts.set(tokenData.email, {
grantId: tokenData.grantId,
emailAddress: tokenData.email
});
res.redirect('/?connected=true');
} catch (error) {
res.redirect('/?error=auth_failed');
}
});
The below example application was generated by Cursor (UI results may vary):
Now that authentication is complete, we can move on to email integration. Our objective is to enable users to send and receive emails directly within the app, leveraging the Nylas Email API.
With Cursor Agent, we can generate an email module by providing a prompt:
I like to consider adding the next steps, so I have received a prompt from Nylas to use. I like to add Email functionality using the Nylas APIs. View attached prompt: @nylas-email-api.mdc
I want to review what is functionality, UI and proposed before writing any code.
This will allow the Cursor Agent to have the sufficient context to build the Nylas Email API integration and build out a UI to read and send emails. You now have email sending and reading integrated with minimal coding.
Here is a short code snippet of the code Cursor Agent generated:
// src/routes/emails.ts
import { Router } from 'express';
import Nylas from 'nylas';
const router = Router();
// GET /api/nylas/emails - List emails
router.get('/', async (req, res) => {
try {
const account = Array.from(connectedAccounts.values())[0];
if (!account) {
return res.status(401).json({ error: 'No connected account found' });
}
const { limit = '10', cursor } = req.query;
const messages = await nylas.messages.list({
identifier: account.grantId,
queryParams: {
limit: parseInt(limit as string, 10),
cursor: cursor as string
}
});
res.json(messages);
} catch (error) {
console.error('Error fetching emails:', error);
res.status(500).json({
error: 'Failed to fetch emails',
details: error instanceof Error ? error.message : 'Unknown error'
});
}
});
The below example application was generated by Cursor (UI may vary):
For more advanced email features, check out the Nylas Email API docs – you can list threads, search emails, download attachments, etc., all through SDK calls. And continuing the same approach using Contact and Calendar specific prompts, we can build out the Nylas API integrations.
At this point, we’ve successfully implemented user authentication and email management. With Cursor Agent, most of the heavy lifting—writing boilerplate code—was handled automatically, allowing us to focus on refining the integration with Nylas APIs.
You can sign up for Nylas for free and start building! Continue building with Nylas by exploring different quickstart guides or by visiting our developer documentation.
Ram loves teaching, building and exploring technologies. He is passionate about empowering developers to ship amazing products to market as fast as possible ????. Ram is excited to share knowledge and help others. He’s a Relaxed Tomato ????.