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

How to Integrate Lovable with OmniFocus

OmniFocus has no public REST API, so integrating it with Lovable requires an automation bridge: use iOS Shortcuts or AppleScript to export tasks as JSON and POST them to a Supabase Edge Function webhook. The Edge Function stores the task data in Supabase, which your Lovable app queries to build GTD review dashboards, project overviews, and inbox-processing interfaces.

What you'll learn

  • How to export OmniFocus task data as structured JSON using iOS Shortcuts or AppleScript automation
  • How to build a Supabase Edge Function webhook that receives and validates incoming OmniFocus task data
  • How to design a Supabase database schema for storing OmniFocus tasks, projects, and contexts
  • How to build a GTD weekly review dashboard in Lovable showing inbox, active projects, and next actions
  • How to trigger OmniFocus data syncs on a schedule using iOS Shortcuts automations
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read60 minutesProductivityMarch 2026RapidDev Engineering Team
TL;DR

OmniFocus has no public REST API, so integrating it with Lovable requires an automation bridge: use iOS Shortcuts or AppleScript to export tasks as JSON and POST them to a Supabase Edge Function webhook. The Edge Function stores the task data in Supabase, which your Lovable app queries to build GTD review dashboards, project overviews, and inbox-processing interfaces.

Connect OmniFocus to Lovable with an Automation Bridge for GTD Dashboards

OmniFocus is the gold standard for GTD (Getting Things Done) practitioners on Apple platforms. Its sophisticated project hierarchy, perspective system, review cycles, and tag-based filtering make it unmatched for complex personal knowledge management. However, because OmniFocus is a native macOS and iOS application with no public REST API, connecting it to web-based tools requires a creative automation bridge approach rather than direct API integration.

The bridge pattern works like this: OmniFocus stores all its data locally in an SQLite database that automation tools can query. On macOS, AppleScript can read projects, tasks, tags, and completion status. On iOS, the Shortcuts app can access OmniFocus data through its action library. Both export routes can format the data as JSON and POST it to a Supabase Edge Function URL — which acts as a webhook receiver. The Edge Function validates the incoming data and stores it in Supabase PostgreSQL. Your Lovable app reads from Supabase to power dashboards.

This is a push-based, one-way integration: OmniFocus sends data to Lovable when you trigger the export. You can run this manually (tap a Shortcut before your weekly review), on a time-based schedule (every morning at 8 AM via Shortcuts automation), or triggered by OmniFocus review prompts. The result is a custom GTD dashboard that shows your full task landscape in a web app, making it accessible on any device even without the OmniFocus app installed.

Integration method

Edge Function Integration

OmniFocus has no public REST API. The integration uses an automation bridge pattern: iOS Shortcuts or AppleScript exports OmniFocus task data as structured JSON and sends it to a Supabase Edge Function webhook endpoint. The Edge Function receives and stores the task data in Supabase PostgreSQL, which your Lovable app then queries to build GTD review interfaces, project dashboards, and weekly review pages. This is a one-way push from OmniFocus to Lovable, not a real-time sync.

Prerequisites

  • OmniFocus 3 or later on macOS and/or iOS (the Shortcuts integration works on iOS 13+ with OmniFocus 3.4+)
  • A Lovable project with Lovable Cloud enabled
  • Basic familiarity with iOS Shortcuts app or macOS Automator/Script Editor for AppleScript
  • A free webhook testing tool like webhook.site for validating the Edge Function receives data correctly
  • Understanding of OmniFocus's data model: Folders (Areas), Projects, Tasks, Tags, and Due/Defer dates

Step-by-step guide

1

Design the Supabase schema for OmniFocus data

Before building the automation bridge, define the database schema that will hold your OmniFocus data in Supabase. You need tables for tasks, projects, and optionally tags and folders (areas). The schema should mirror enough of OmniFocus's data model to support the GTD review interfaces you want to build. Ask Lovable to create the schema by describing the data structure you need. OmniFocus tasks have a unique ID, name, project association, tags, due date, defer date, completion status, flag status, and estimated duration. Projects have a name, folder/area parent, review interval, last review date, and status. Keep the schema practical — you do not need to replicate every OmniFocus field, just the ones your dashboard will display.

Lovable Prompt

Create Supabase tables for OmniFocus data sync. Table 'omnifocus_tasks': id (text primary key, the OmniFocus task ID), name (text), project_id (text, foreign key to omnifocus_projects), tags (text array), due_date (timestamptz), defer_date (timestamptz), completed (boolean default false), completed_at (timestamptz), flagged (boolean default false), estimated_minutes (integer), note (text), synced_at (timestamptz default now()). Table 'omnifocus_projects': id (text primary key), name (text), folder_name (text), status (text — 'active', 'on_hold', 'dropped', 'completed'), last_review_date (date), review_interval_days (integer), task_count (integer), completed_task_count (integer), synced_at (timestamptz default now()). Add RLS policies so authenticated users can read and the service role can upsert. Also create a 'sync_log' table with timestamp and item_count columns to track when syncs ran.

Paste this in Lovable chat

Pro tip: Use upsert operations (INSERT ... ON CONFLICT DO UPDATE) when syncing OmniFocus data so that re-running the sync updates existing records rather than creating duplicates.

Expected result: Supabase tables omnifocus_tasks, omnifocus_projects, and sync_log are created with the appropriate columns and RLS policies.

2

Create the Edge Function webhook receiver

Build the Edge Function that will receive OmniFocus data from your iOS Shortcut or AppleScript automation. This function acts as a secure webhook endpoint — it validates an incoming shared secret token (to prevent unauthorized pushes), parses the task and project JSON, upserts the records into Supabase, and logs the sync. The webhook URL will be in the format https://your-project.supabase.co/functions/v1/omnifocus-sync. After Lovable deploys the Edge Function, this URL is what you will configure in your iOS Shortcut as the POST destination. The shared secret prevents anyone who discovers the URL from pushing garbage data into your database.

Lovable Prompt

Create a Supabase Edge Function called 'omnifocus-sync' at supabase/functions/omnifocus-sync/index.ts. It receives POST requests from iOS Shortcuts containing OmniFocus data. The request body should be JSON with structure: { secret: string, tasks: array, projects: array }. First validate that the 'secret' field matches OMNIFOCUS_WEBHOOK_SECRET from Deno.env.get() — return 401 if it does not match. Then use the Supabase admin client (initialized with SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY) to upsert all items in the tasks array into the omnifocus_tasks table and all items in the projects array into the omnifocus_projects table using the id field as the conflict key. Update the synced_at field to now() for all upserted records. Insert a row into the sync_log table with the current timestamp and total item count. Return a 200 response with a summary of items processed. Include CORS headers.

Paste this in Lovable chat

supabase/functions/omnifocus-sync/index.ts
1// supabase/functions/omnifocus-sync/index.ts
2import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
3import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
4
5const corsHeaders = {
6 'Access-Control-Allow-Origin': '*',
7 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
8};
9
10serve(async (req) => {
11 if (req.method === 'OPTIONS') {
12 return new Response('ok', { headers: corsHeaders });
13 }
14
15 try {
16 const body = await req.json();
17 const expectedSecret = Deno.env.get('OMNIFOCUS_WEBHOOK_SECRET');
18
19 if (body.secret !== expectedSecret) {
20 return new Response(
21 JSON.stringify({ error: 'Unauthorized' }),
22 { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
23 );
24 }
25
26 const supabase = createClient(
27 Deno.env.get('SUPABASE_URL')!,
28 Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
29 );
30
31 const now = new Date().toISOString();
32 const tasks = (body.tasks || []).map((t: Record<string, unknown>) => ({ ...t, synced_at: now }));
33 const projects = (body.projects || []).map((p: Record<string, unknown>) => ({ ...p, synced_at: now }));
34
35 if (projects.length > 0) {
36 const { error: projErr } = await supabase
37 .from('omnifocus_projects')
38 .upsert(projects, { onConflict: 'id' });
39 if (projErr) throw projErr;
40 }
41
42 if (tasks.length > 0) {
43 const { error: taskErr } = await supabase
44 .from('omnifocus_tasks')
45 .upsert(tasks, { onConflict: 'id' });
46 if (taskErr) throw taskErr;
47 }
48
49 await supabase.from('sync_log').insert({
50 timestamp: now,
51 item_count: tasks.length + projects.length,
52 });
53
54 return new Response(
55 JSON.stringify({ success: true, tasks: tasks.length, projects: projects.length }),
56 { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
57 );
58 } catch (err) {
59 return new Response(
60 JSON.stringify({ error: err.message }),
61 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
62 );
63 }
64});

Pro tip: Add OMNIFOCUS_WEBHOOK_SECRET to Cloud → Secrets before deploying. Use a long random string (32+ characters) as the secret — you can generate one at random.org or use any password generator.

Expected result: The omnifocus-sync Edge Function is deployed and accessible at a public URL. You can test it with webhook.site by sending a POST request with the correct secret and sample task data.

3

Build the iOS Shortcut for OmniFocus export

Create an iOS Shortcut that reads your OmniFocus data and sends it to the Edge Function webhook. This is the automation bridge that replaces the missing REST API. On iPhone or iPad, open the Shortcuts app and create a new shortcut. You will use OmniFocus-specific Shortcuts actions to fetch tasks and projects, format them as JSON, and POST to your Edge Function URL. The Shortcut needs to: (1) Use the 'Find OmniFocus Tasks' action to get incomplete tasks from all projects, (2) Use 'Find OmniFocus Projects' to get all active projects, (3) Format each item as a dictionary matching your Supabase schema, (4) Combine into a JSON payload with the shared secret, and (5) Use the 'Get Contents of URL' action to POST to the Edge Function URL. For macOS users who prefer AppleScript, the same export can be achieved with an AppleScript that accesses OmniFocus via its AppleScript dictionary and uses curl to POST to the webhook. The Shortcut approach is recommended because it works on both iPhone and Mac without terminal access.

omnifocus-export.applescript
1-- AppleScript alternative for macOS
2-- Save as: ~/Documents/omnifocus-export.scpt
3-- Run from Script Editor or Automator
4
5set webhookURL to "https://YOUR-PROJECT.supabase.co/functions/v1/omnifocus-sync"
6set webhookSecret to "YOUR-WEBHOOK-SECRET"
7
8tell application "OmniFocus"
9 set theDoc to default document
10
11 -- Collect tasks
12 set taskList to "{\"tasks\":["
13 set allTasks to every inbox task of theDoc
14 set taskCount to count of allTasks
15
16 repeat with i from 1 to taskCount
17 set t to item i of allTasks
18 set taskJSON to "{\"id\":\"" & id of t & "\",\"name\":\"" & name of t & "\",\"completed\":" & (completed of t as string) & "}"
19 set taskList to taskList & taskJSON
20 if i < taskCount then set taskList to taskList & ","
21 end repeat
22
23 set taskList to taskList & "]}"
24end tell
25
26-- POST to Edge Function (requires curl available on macOS)
27do shell script "curl -s -X POST '" & webhookURL & "' -H 'Content-Type: application/json' -d '{\"secret\":\"" & webhookSecret & "\"," & (characters 2 thru -1 of taskList as string) & "'"

Pro tip: For the iOS Shortcut, use the 'Find OmniFocus Tasks where Status is Incomplete' action with 'Limit' set to 500 to avoid extremely large payloads. Add the Shortcut to your Home Screen so you can trigger a sync with one tap before a weekly review.

Expected result: Running the iOS Shortcut or AppleScript sends your OmniFocus task and project data to the Edge Function webhook. Check Cloud → Logs to confirm the function received the data and Supabase to verify rows were inserted.

4

Build the GTD review dashboard in Lovable

With OmniFocus data flowing into Supabase, ask Lovable to build the review dashboard. The dashboard reads directly from your Supabase tables — no Edge Function call is needed for reading since the data is already in the database. The Supabase client in Lovable handles all read queries directly from the frontend using the publishable key, protected by the RLS policies you set up. The GTD weekly review dashboard should help you process the full landscape of your task system: inbox items awaiting processing, projects overdue for review, tasks due this week, and stalled projects with no next actions. Think of this as a custom OmniFocus perspective that works in any browser, not just on your Apple devices.

Lovable Prompt

Create a GTD Review dashboard that reads from the Supabase omnifocus_tasks and omnifocus_projects tables. Show a 'Last Synced' banner at the top reading from the sync_log table's latest row. Divide the page into four sections with collapsible headers: 1) Inbox (tasks where project_id is null) — show task name and a 'Process' button placeholder. 2) Projects Needing Review — projects where last_review_date is more than (review_interval_days) ago, shown as a table with project name, folder, last reviewed, and a 'Mark Reviewed' button that updates the Supabase record. 3) Due This Week — tasks where due_date is within the next 7 days, sorted by date, grouped by project. 4) Stalled Projects — active projects where no linked task has been modified in the past 14 days. Show a count badge on each section header. Add a 'Sync Now' button at the top that opens a modal explaining how to run the iOS Shortcut.

Paste this in Lovable chat

Pro tip: For complex GTD dashboard requirements, RapidDev's team can help configure advanced OmniFocus automation bridges including bidirectional sync patterns and multi-device export coordination.

Expected result: A GTD Weekly Review dashboard displays your OmniFocus data from Supabase. You can see inbox items, review-due projects, and this week's tasks in a structured layout designed for the GTD review process.

Common use cases

GTD weekly review dashboard with project health indicators

Build a custom weekly review interface that pulls the latest OmniFocus snapshot (pushed via Shortcuts) into a structured dashboard. See all active projects with their last-reviewed date highlighted in red if overdue for review, a count of stalled projects with no next actions, and a summary of tasks due this week. The dashboard becomes your weekly review starting point, surfacing everything that needs attention before you open OmniFocus.

Lovable Prompt

Create a GTD Weekly Review dashboard that reads OmniFocus data from our Supabase database. Show three sections: 1) Inbox — tasks with no project assigned, listed with a quick 'Process' note field. 2) Projects Review — all active projects with columns for Project Name, Task Count, Last Reviewed date (highlight red if more than 7 days ago), and whether a next action exists. 3) Due This Week — tasks with due dates in the next 7 days sorted by date. Add a 'Last Synced' timestamp showing when the Shortcuts sync last ran. Use a clean GTD-style layout with clear section headers.

Copy this prompt to try it in Lovable

Next actions dashboard by area of focus

Create a filtered task view that organizes OmniFocus next actions by Area of Focus (OmniFocus's top-level containers for life domains like Work, Personal, Health). Instead of the OmniFocus Forecast perspective, this dashboard shows what is actionable right now grouped by life area, making it easy to pick the right task based on context and energy level. Perfect for a morning planning session view.

Lovable Prompt

Build a Next Actions dashboard that queries our Supabase tasks table for items flagged as 'next actions' in OmniFocus. Group them by their parent Area of Focus (stored as the top_level_folder field). For each group show the area name as a header and list the tasks with their project name, due date if set, and flag status. Add filter buttons at the top to filter by tag (stored as the tags array field). Mark overdue tasks in red. Show a count badge on each area header. Include a checkbox to mark tasks complete that updates the Supabase record.

Copy this prompt to try it in Lovable

Project portfolio view with completion tracking

Build an executive project portfolio view that shows all active OmniFocus projects as cards with a progress bar representing completed versus remaining tasks. Add a notes section for each project where you can jot down context stored in Supabase (separate from OmniFocus). This is particularly useful for founders who want to review their full project landscape without opening OmniFocus, and share a read-only version with accountability partners.

Lovable Prompt

Create a Project Portfolio page from our Supabase omnifocus_projects table. Show each project as a card with: project name, folder/area, task count, completed task count, and a progress bar showing percentage complete. Color the card border based on OmniFocus status — active projects green, on-hold projects gray, dropped red. Add a 'Notes' textarea on each card that saves to a separate project_notes table in Supabase (not synced back to OmniFocus). Sort projects by area then by most recently modified. Add a filter sidebar to show/hide projects by status and area.

Copy this prompt to try it in Lovable

Troubleshooting

The iOS Shortcut runs but no data appears in Supabase and Cloud Logs show no requests

Cause: The 'Get Contents of URL' action in the Shortcut is not configured correctly. Common issues include: the URL contains a typo, the Method is not set to POST, the Request Body type is not set to JSON, or the Shortcut is not actually completing the HTTP request step (it may be stopping at an earlier action that fails silently).

Solution: Test the Shortcut step by step by adding a 'Show Result' action after the 'Get Contents of URL' step to display the HTTP response. Verify the webhook URL by opening it in Safari — you should see a JSON error response rather than a 404, which confirms the function exists. Check that the Content-Type header is set to 'application/json' in the Shortcut's URL action headers.

Edge Function returns 401 Unauthorized even though the secret looks correct

Cause: The secret string in the Shortcut payload does not exactly match the OMNIFOCUS_WEBHOOK_SECRET stored in Cloud Secrets. This is often caused by extra whitespace, a trailing newline from copy-paste, or a character encoding difference.

Solution: Open Cloud → Secrets and view the OMNIFOCUS_WEBHOOK_SECRET value carefully. Re-type the secret manually in both the Shortcut and the Cloud Secret rather than copy-pasting to eliminate invisible characters. The comparison in the Edge Function uses strict equality, so even a single extra space causes a 401 response.

typescript
1if (body.secret?.trim() !== expectedSecret?.trim()) { /* reject */ }

Upsert succeeds but task data shows old values instead of updating

Cause: The upsert is working but the RLS policy on omnifocus_tasks only allows SELECT for authenticated users. The Edge Function uses the service role key which bypasses RLS, but if you are inadvertently using the anon key in the Edge Function, updates would silently fail due to policy restrictions.

Solution: Verify that the Edge Function uses SUPABASE_SERVICE_ROLE_KEY (not the anon key) when initializing the Supabase admin client. The service role key should only be used server-side in Edge Functions. Double-check Cloud → Secrets to confirm both SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY are set with the correct values from your Supabase project settings.

typescript
1const supabase = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!);

Dashboard shows tasks but the data is several days old and the Sync Now button does nothing

Cause: The Shortcut automation has not been run recently. Unlike API-connected tools that have webhooks or polling, OmniFocus data only updates in Supabase when you actively run the export Shortcut. The 'Sync Now' button in the dashboard cannot trigger the Shortcut remotely from a web app.

Solution: Set up an iOS Shortcuts Automation (not just a manual Shortcut) that triggers on a time schedule — for example, every Monday morning at 8 AM. In the Shortcuts app, go to the Automation tab, create a Personal Automation, set the trigger to 'Time of Day' on a recurring schedule, and add the OmniFocus sync Shortcut as the action. This makes the sync happen automatically without manual triggering.

Best practices

  • Never expose your OMNIFOCUS_WEBHOOK_SECRET in client-side code — it is only needed in the Edge Function via Deno.env.get() and in the Shortcuts app on your device.
  • Limit the OmniFocus export to incomplete tasks from the past 90 days to keep payload sizes manageable — completed old tasks rarely need to appear in a GTD review dashboard.
  • Add a timestamp-based deduplication check in the Edge Function: if a sync ran less than 5 minutes ago (check sync_log), reject the request to prevent accidental double-syncs.
  • Store OmniFocus task IDs as the primary key so that re-running the sync updates existing records rather than creating duplicates — OmniFocus assigns permanent UUIDs to all tasks and projects.
  • Build the Lovable dashboard to be useful even if the last sync was several days ago — always show 'Last synced: X days ago' prominently so users know when to run the Shortcut.
  • Use Supabase RLS policies that restrict task data to the authenticated user only, so that if you later build a shared version of the dashboard, each user's OmniFocus data stays private.
  • Consider a nightly iOS Shortcuts automation that runs at a fixed time rather than relying on manual syncs — this ensures your weekly review dashboard always has reasonably current data when you need it.

Alternatives

Frequently asked questions

Why doesn't OmniFocus have a public REST API like other task managers?

OmniFocus is designed as a native Apple platform application — macOS, iOS, iPadOS, and watchOS only. The Omni Group built it around native OS capabilities and local-first data storage rather than a cloud API model. The OmniFocus Sync service (which syncs between devices) is proprietary and not exposed as a public API. AppleScript and Shortcuts are the official automation paths, making the webhook bridge approach the only practical option for web integration.

Can I write tasks back to OmniFocus from the Lovable dashboard?

Yes, but not via a REST API. OmniFocus supports URL schemes (omnifocus:///add?name=Task+Name&note=Details) that can be triggered from iOS. From the Lovable web app, you can generate an OmniFocus URL and display it as a link — clicking it on an iOS device opens OmniFocus with the task pre-filled for capture. This is the standard web-to-OmniFocus write pattern used by many productivity tools.

How do I keep the dashboard data fresh without running the Shortcut manually every time?

Set up an iOS Shortcuts Personal Automation with a time trigger. In the Shortcuts app, go to the Automation tab, tap the plus icon, select Personal Automation, choose Time of Day, set a recurring time (such as every morning at 7 AM), and add your OmniFocus sync Shortcut as the action. This runs the export automatically on a schedule, keeping your Lovable dashboard up to date without manual intervention.

Does this integration work with OmniFocus on Mac without an iPhone?

Yes, the AppleScript approach works on macOS without any iOS device. On Mac, OmniFocus exposes a full AppleScript dictionary that can read all task and project data. The AppleScript can use the 'do shell script' command to POST to the Edge Function using curl, which is built into macOS. You can schedule the script to run automatically using macOS Automator's Calendar Alarm or launchd.

Can I connect multiple OmniFocus databases (work and personal) to the same Lovable app?

Yes. Create separate Shortcuts for work and personal OmniFocus databases. The Edge Function can accept a 'context' field in the payload to tag tasks as work or personal. Design your Supabase schema to include a context column, and use RLS policies to ensure users only see their own data. You can then add context filter tabs to the Lovable dashboard.

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.