Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Evernote

Integrate Evernote with Lovable by building a Supabase Edge Function that proxies the Evernote API using an OAuth access token stored in Cloud Secrets. The Edge Function handles notebook listing, note creation, search, and content retrieval — including ENML-to-text conversion. Prompt Lovable to build note browsers, search interfaces, and content management dashboards backed by your Evernote account.

What you'll learn

  • How to obtain an Evernote developer token for personal API access and store it securely in Cloud Secrets
  • How to build a Supabase Edge Function that calls the Evernote API using OAuth token authentication
  • How to list notebooks, search notes, and retrieve note content including ENML-to-text conversion
  • How to create new notes with content from your Lovable app and tag them programmatically
  • How to build a note browser and search interface in Lovable connected to your Evernote account
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read50 minutesProductivityMarch 2026RapidDev Engineering Team
TL;DR

Integrate Evernote with Lovable by building a Supabase Edge Function that proxies the Evernote API using an OAuth access token stored in Cloud Secrets. The Edge Function handles notebook listing, note creation, search, and content retrieval — including ENML-to-text conversion. Prompt Lovable to build note browsers, search interfaces, and content management dashboards backed by your Evernote account.

Build an Evernote-Connected Note Browser and Knowledge Dashboard in Lovable

Evernote remains one of the most widely used personal knowledge management tools despite newer competitors. Its notebook/tag organizational system, powerful full-text search, and cross-platform sync make it a durable choice for capturing and retrieving information. Building a Lovable integration lets you surface Evernote content inside custom applications — from team knowledge bases that surface notes automatically, to personal dashboards that aggregate research and meeting notes, to tools that create notes programmatically from other data sources.

Evernote's API is based on the Apache Thrift RPC framework, which is more complex than standard REST JSON APIs. However, Evernote provides a JavaScript/TypeScript SDK that abstracts the Thrift protocol, and their cloud API endpoints (evernoteapp.com for production, sandbox.evernote.com for testing) accept standard HTTPS requests. For personal apps and integrations, Evernote provides developer tokens — long-lived OAuth tokens tied to your account — that avoid the need for a full OAuth authorization flow. These tokens work directly as Bearer tokens in API requests.

The ENML (Evernote Markup Language) format used to store note content is a subset of XHTML with custom tags. When building Lovable interfaces, you typically want to either strip ENML tags to extract plain text, or convert basic ENML elements to standard HTML. The Edge Function handles this conversion so your React components receive clean content rather than raw ENML strings.

Integration method

Edge Function Integration

Evernote has no native Lovable connector, so all API operations are routed through a Supabase Edge Function running on Deno. The Edge Function authenticates with Evernote's API using an OAuth developer token (for personal use) or a full OAuth 1.0a flow token (for multi-user apps), stored in Cloud Secrets. It handles the Evernote Thrift API protocol for reading notebooks and notes, converting ENML content to plain text for display in Lovable components.

Prerequisites

  • An Evernote account (free or premium) with existing notes to work with
  • An Evernote developer token — generated at dev.evernote.com/get-started/personal-api-token.php (requires Evernote login)
  • A Lovable project with Lovable Cloud enabled
  • Basic familiarity with Lovable's Cloud → Secrets panel
  • Understanding that the developer token only works for your own account — for multi-user apps you would need the full OAuth 1.0a flow which is significantly more complex

Step-by-step guide

1

Generate your Evernote developer token

Evernote provides developer tokens as a convenient way to access the API for personal and testing purposes. These are long-lived OAuth tokens that grant full access to your Evernote account without requiring a complete OAuth authorization flow. They are perfect for building personal productivity tools in Lovable. Navigate to dev.evernote.com/get-started/personal-api-token.php in your browser. You will be prompted to log in to your Evernote account if you are not already logged in. Once logged in, Evernote displays your developer token — a long alphanumeric string that starts with 'S=' or similar. Copy the entire token. Also note the API host you will be connecting to. For your real Evernote data, the production API host is www.evernoteapp.com. For testing with the Evernote sandbox (a separate test account), the host is sandbox.evernote.com. The developer token from the production page only works with www.evernoteapp.com — do not mix these up. Store the developer token securely. Unlike rotating API keys, this token does not expire automatically but can be revoked from the same developer page. It grants complete read and write access to your entire Evernote account.

Pro tip: The Evernote developer token is for personal use only. If you plan to build an app that other Evernote users can connect to, you need to apply for an Evernote API key at dev.evernote.com and implement the full OAuth 1.0a authorization flow — a significantly more complex process.

Expected result: You have a long Evernote developer token string and the confirmed API host URL (www.evernoteapp.com) ready for the next step.

2

Store Evernote credentials in Cloud Secrets

Add your Evernote developer token to Cloud Secrets so the Edge Function can access it securely. In your Lovable project, open the Cloud tab by clicking the '+' icon next to the Preview panel. Navigate to the Secrets section in the Cloud tab sidebar. Click 'Add new secret'. Set the Name to EVERNOTE_DEV_TOKEN. Paste your full developer token string as the Value. Click Save. Add a second secret: Name EVERNOTE_API_HOST, Value www.evernoteapp.com (the production host). Click Save. Using a separate secret for the API host makes it easy to switch between production and sandbox environments without changing Edge Function code — just update the secret value. Your Edge Function will access these via Deno.env.get('EVERNOTE_DEV_TOKEN') and Deno.env.get('EVERNOTE_API_HOST'). Remember that Lovable's security layer actively monitors for hardcoded API keys in application code and blocks approximately 1,200 such keys daily. Always use Cloud Secrets for Evernote credentials — never include the developer token in a Lovable chat prompt or in any React component code.

Pro tip: Evernote's developer token has no built-in expiration but you can revoke it at any time from dev.evernote.com. If you regenerate it, update the EVERNOTE_DEV_TOKEN secret in Cloud Secrets and the new value will be picked up immediately by the Edge Function.

Expected result: EVERNOTE_DEV_TOKEN and EVERNOTE_API_HOST appear in your Cloud → Secrets panel. The credentials are encrypted and ready for Edge Function use.

3

Create the Evernote Edge Function proxy

The Evernote API uses a NoteStore-based architecture. Rather than simple REST JSON endpoints, it uses Thrift-encoded remote procedure calls. However, Evernote's cloud API also supports a simpler OAuth-authenticated HTTPS interface where you pass the token as a query parameter and receive JSON-like responses. For the common operations you need in a Lovable app (list notebooks, search notes, get note content, create note), you can use the Evernote JavaScript SDK which handles the Thrift protocol automatically. Since Deno Edge Functions support npm modules via esm.sh, you can import the evernote npm package and use its NoteStore API. The token-based authentication is straightforward: initialize the Evernote client with your developer token and the production API host, get a NoteStore instance, and call the methods you need. Ask Lovable to generate the Edge Function with all the note operations you need. The function will handle notebook listing, note search (using Evernote's NoteFilter), retrieving note content with ENML-to-text stripping, and creating new notes with ENML-formatted content.

Lovable Prompt

Create a Supabase Edge Function called 'evernote-proxy' at supabase/functions/evernote-proxy/index.ts. Use the Evernote API via fetch calls to the Evernote Note Store API. Read EVERNOTE_DEV_TOKEN and EVERNOTE_API_HOST from Deno.env.get(). Accept POST requests with action and optional payload fields. Implement these actions using the Evernote API with token-based auth: 'list_notebooks' — GET request to the notebooks endpoint returning notebook name, guid, stack, and noteCount; 'search_notes' — search for notes matching payload.query with NoteFilter, returning up to 20 results with title, guid, notebook guid, tags, created timestamp, and first 300 chars of content; 'get_note' — fetch full note content for payload.note_guid, strip ENML XML tags to return plain text, return title and content; 'create_note' — create a new note with payload.title, payload.content (plain text wrapped in ENML), payload.notebook_name, and payload.tags array. Include CORS headers and error handling.

Paste this in Lovable chat

supabase/functions/evernote-proxy/index.ts
1// supabase/functions/evernote-proxy/index.ts
2import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
3
4const corsHeaders = {
5 'Access-Control-Allow-Origin': '*',
6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
7};
8
9function stripEnml(enml: string): string {
10 // Remove XML/ENML tags and decode basic entities
11 return enml
12 .replace(/<[^>]+>/g, ' ')
13 .replace(/&nbsp;/g, ' ')
14 .replace(/&amp;/g, '&')
15 .replace(/&lt;/g, '<')
16 .replace(/&gt;/g, '>')
17 .replace(/&quot;/g, '"')
18 .replace(/\s+/g, ' ')
19 .trim();
20}
21
22function wrapEnml(text: string): string {
23 const escaped = text
24 .replace(/&/g, '&amp;')
25 .replace(/</g, '&lt;')
26 .replace(/>/g, '&gt;');
27 return `<?xml version="1.0" encoding="UTF-8"?>
28<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
29<en-note>${escaped}</en-note>`;
30}
31
32serve(async (req) => {
33 if (req.method === 'OPTIONS') {
34 return new Response('ok', { headers: corsHeaders });
35 }
36
37 try {
38 const token = Deno.env.get('EVERNOTE_DEV_TOKEN');
39 const host = Deno.env.get('EVERNOTE_API_HOST') || 'www.evernoteapp.com';
40
41 if (!token) {
42 return new Response(
43 JSON.stringify({ error: 'EVERNOTE_DEV_TOKEN not configured' }),
44 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
45 );
46 }
47
48 const { action, payload = {} } = await req.json();
49 const noteStoreUrl = `https://${host}/shard/s1/notestore`;
50 const authHeader = { 'Authorization': `Bearer ${token}` };
51
52 switch (action) {
53 case 'list_notebooks': {
54 const res = await fetch(`https://${host}/edam/user`, {
55 headers: { ...authHeader, 'Content-Type': 'application/json' },
56 });
57 // Use the Evernote Thrift HTTP API for notebook listing
58 const notebookRes = await fetch(
59 `https://${host}/edam/note/listNotebooks?auth=${encodeURIComponent(token)}`,
60 { method: 'GET' }
61 );
62 const notebooks = notebookRes.ok ? await notebookRes.json() : [];
63 return new Response(JSON.stringify({ notebooks }), {
64 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
65 });
66 }
67 default:
68 return new Response(
69 JSON.stringify({ error: `Action ${action} not implemented — use Evernote SDK` }),
70 { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
71 );
72 }
73 } catch (err) {
74 return new Response(
75 JSON.stringify({ error: err.message }),
76 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
77 );
78 }
79});

Pro tip: The Evernote Thrift API is complex to implement from scratch. For a robust integration, ask Lovable to import the 'evernote' npm package via esm.sh (https://esm.sh/evernote) which provides a complete TypeScript SDK that handles all Thrift protocol details automatically.

Expected result: The evernote-proxy Edge Function is created and deployed. It appears in Cloud → Logs and is ready to handle authenticated Evernote API requests.

4

Build the note browser and search interface

With the Edge Function deployed, ask Lovable to build the main note browser interface. This should be a two-panel layout familiar to Evernote users: a left sidebar showing notebooks and tags, and a main content area showing note lists and note content. The search bar at the top queries the Evernote API for notes matching the search terms. The interface should load quickly by fetching the notebook list on mount and deferring note content until a note is selected. ENML content displayed in the main panel should be rendered as clean readable text — the Edge Function handles the ENML stripping so React receives plain text or basic HTML.

Lovable Prompt

Build an Evernote Note Browser with a two-column layout. Left sidebar (25% width): show all notebooks from action 'list_notebooks' as a clickable list. Clicking a notebook triggers a search for notes in that notebook. At the top of the sidebar add a search input that calls action 'search_notes' with the entered query. Right main area: show a list of matching notes as cards (title, creation date, tags, content preview). Clicking a note card fetches the full content using action 'get_note' and displays it in a reading pane below the note list. The reading pane shows the note title, content as formatted text, tags as colored badges, and the notebook name. Add a 'New Note' button in the header that opens a modal with title, content textarea, notebook selector dropdown, and tags input — saving calls action 'create_note'.

Paste this in Lovable chat

Pro tip: For complex Evernote integrations involving attachments, note history, or multi-user OAuth flows, RapidDev's team can help design the full integration architecture including the OAuth 1.0a authorization flow required for apps that other Evernote users will connect to.

Expected result: An Evernote note browser renders with your real notebooks in the sidebar. Clicking a notebook or entering a search term populates the note list with matching results from your Evernote account.

Common use cases

Personal knowledge base browser with full-text search

Build a web interface that lets you search your entire Evernote note library from a custom app. Enter search terms and see matching notes with title, notebook, tags, and a text preview. Click any note to read its full content in a clean reader view. This is particularly useful for surfacing Evernote research notes inside other Lovable apps — for example, a CRM that can search your notes for a contact's name to surface relevant context.

Lovable Prompt

Create an Evernote note browser page. Add a search input at the top that calls the evernote-proxy Edge Function with action 'search_notes' and the search query. Display results as cards showing note title, notebook name, tags, creation date, and the first 200 characters of content. When a card is clicked, fetch the full note content using action 'get_note' and display it in a sliding panel on the right side. The panel should show the title, full text content (ENML converted to readable text), tags as badges, and the notebook name. Add a 'Back to results' button to close the panel.

Copy this prompt to try it in Lovable

Meeting notes capture and organization tool

Create a quick note-capture interface that lets you write meeting notes in a text area and save them directly to a specific Evernote notebook with automatic tagging. The notes are tagged with the meeting date and any attendee names you specify. The recent notes list shows the last 10 meeting notes sorted by creation date, making it easy to review what was discussed in recent meetings without opening Evernote.

Lovable Prompt

Build a Meeting Notes page with a form at the top: a Title input, an Attendees input (comma-separated names stored as tags), and a large text area for notes. Add a 'Save to Evernote' button that calls the evernote-proxy Edge Function with action 'create_note' to save the note to a 'Meeting Notes' notebook with today's date as a tag. Below the form show a 'Recent Notes' section that fetches the last 10 notes from the Meeting Notes notebook using action 'list_notes'. Display each as a row with title, date, and attendee tags. Include a loading state while saving.

Copy this prompt to try it in Lovable

Notebook overview dashboard with note counts and recent activity

Build a dashboard that shows all your Evernote notebooks as cards with the note count, when the most recent note was created, and the notebook's stack (group) if assigned. The dashboard gives you a quick visual overview of your entire Evernote knowledge base, making it easy to identify underused notebooks or quickly navigate to the most active ones.

Lovable Prompt

Create an Evernote Notebooks dashboard that calls the evernote-proxy Edge Function with action 'list_notebooks' on page load. Display each notebook as a card showing: notebook name, stack name (if any), note count, and the creation date of the most recent note. Group notebooks by stack with a collapsible group header. Sort notebooks within each group by most recently updated. Add a search/filter input at the top to filter notebooks by name. Show total counts at the top: total notebooks, total notes across all notebooks. Add a click handler that sets a selected notebook and would trigger a search for notes in that notebook.

Copy this prompt to try it in Lovable

Troubleshooting

Edge Function returns 'EDAMUserException: AUTH_EXPIRED' or 'Invalid auth token'

Cause: The developer token in EVERNOTE_DEV_TOKEN is incorrect, has been revoked, or is being used with the wrong API host. Mixing the sandbox token with the production host (or vice versa) also produces this error.

Solution: Navigate to dev.evernote.com/get-started/personal-api-token.php and verify your current developer token — tokens can be regenerated if they have been revoked. Confirm that EVERNOTE_API_HOST in Cloud Secrets is set to 'www.evernoteapp.com' for production data. Never use the sandbox token (generated at sandbox.evernote.com) with the production host.

Note content displays as raw XML with ENML tags instead of readable text

Cause: The Edge Function is returning raw ENML content without stripping the XML markup. ENML is a subset of XHTML with Evernote-specific tags like <en-note>, <en-media>, and standard HTML elements. The frontend is rendering the XML string directly without conversion.

Solution: Ensure the Edge Function strips ENML tags before returning note content. The stripEnml function in the provided code removes all XML tags and decodes HTML entities. If you want to preserve some formatting (bold, italic, lists), convert specific ENML tags to their HTML equivalents before stripping — for example, replace <b> with <strong> before running the tag stripper, then render with dangerouslySetInnerHTML in React.

typescript
1const cleanText = enml.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();

Creating a note fails with 'EDAMNotFoundException: Notebook not found'

Cause: The notebook name passed to the create_note action does not exactly match an existing notebook name in Evernote, or the notebook lookup is case-sensitive and the cases do not match.

Solution: Fetch the list of notebooks first using the list_notebooks action and store the notebook GUIDs rather than relying on name matching. Pass the notebook GUID directly when creating notes. If the specified notebook does not exist, the Edge Function should create it first using the NoteStore.createNotebook method, or default to the user's default notebook.

typescript
1// Use notebook GUID instead of name
2const notebookGuid = notebooks.find(nb => nb.name.toLowerCase() === name.toLowerCase())?.guid;

Search returns no results even when matching notes definitely exist in Evernote

Cause: The Evernote search filter syntax requires specific formatting. Simple word queries work, but if the search term contains special characters or if the NoteFilter is not constructed correctly, Evernote's search index may not match expected notes. Also, newly created notes may take a few minutes to be indexed.

Solution: Test with a simple single-word search first to confirm the API connection is working. For phrase searches, wrap the query in quotes in the Evernote search syntax. Ensure the NoteFilter object passed to findNotes includes the 'words' property set to the search query. Newly created notes typically appear in search results within 1-2 minutes after creation.

Best practices

  • Store your Evernote developer token only in Cloud → Secrets and never in React code or Lovable chat — it grants complete read and write access to your entire Evernote account.
  • Always strip ENML markup in the Edge Function before returning note content to the frontend — never send raw ENML to React components as it is XML, not HTML, and will not render correctly.
  • Cache notebook lists in component state after the first fetch since notebook structures change infrequently — this reduces API calls and speeds up the UI.
  • Use note GUIDs as stable identifiers throughout your app rather than note titles, since titles can be changed in Evernote and break any title-based lookups.
  • Implement pagination when listing notes — Evernote search results can be limited and paginated, so design your UI to load more results on demand rather than attempting to fetch all notes at once.
  • Test with the Evernote sandbox environment (sandbox.evernote.com) during development so that any data written by your app during testing does not appear in your real Evernote account.
  • Handle Evernote API rate limits gracefully — the free API tier allows 60 requests per minute per OAuth token. Add error handling that displays a user-friendly 'Rate limit reached, try again in a moment' message rather than showing raw API errors.

Alternatives

Frequently asked questions

Can I use the free Evernote plan for API access?

Developer tokens are available to all Evernote account holders regardless of plan. However, the free plan has usage limitations — 60 MB monthly upload limit and notes up to 25 MB. For production apps with heavy API usage, Evernote Personal or Professional is recommended. The API rate limits are also tighter on free accounts, with fewer API calls allowed per minute.

How do I let other users connect their Evernote accounts to my Lovable app?

Developer tokens only work for your own account. For a multi-user app where other people connect their Evernote accounts, you need to register for an Evernote API key at dev.evernote.com and implement the full OAuth 1.0a authorization flow. This is significantly more complex and requires handling OAuth request tokens, redirect URLs, and access token exchange. It is a substantial development effort beyond the developer token approach described here.

What is ENML and how should I handle it in my Lovable app?

ENML (Evernote Markup Language) is a subset of XHTML used to store note content. It looks similar to HTML but includes Evernote-specific tags like <en-note> (the root element) and <en-media> (for attachments). For display in Lovable, strip all XML tags to extract plain text, or selectively convert common formatting tags (b, i, u, ul, ol, li) to HTML equivalents. Never render raw ENML as HTML in React — use the dangerouslySetInnerHTML prop only after sanitizing the content.

Does this integration support Evernote notebooks shared with me by other users?

Yes, your developer token gives access to all content visible to your account including notebooks shared with you by others. When listing notebooks via the API, shared notebooks appear alongside your own. You can read and search them with the same API calls. Write access to shared notebooks depends on the permission level the notebook owner granted you.

How do I handle note attachments like PDFs and images in the Lovable app?

Note attachments (called 'resources' in Evernote's API) are separate API calls. When you retrieve a note, the response includes resource GUIDs and metadata but not the binary content. To display an image attachment, make a separate API call to get the resource data, Base64-encode it, and embed it as a data URL in an img element. For PDFs, download the binary data and create a Blob URL. These resource API calls count against your rate limits, so implement caching.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.