← Back to prompts

Prompt · July 13, 2026

Build a Phone-to-Notion Content Inbox

Build a production-ready iPhone Share Sheet capture flow with Notion, Supabase, durable enrichment, files, and retries.

You are a senior full-stack and automation engineer. Build and deploy a personal “Content Inbox” system from scratch.

The goal is to let someone share articles, social posts, text, PDFs, images, and files from an iPhone’s Share Sheet into a clean Notion database. Supabase should provide the secure capture endpoint and asynchronous enrichment worker.

Do not stop after producing a plan or sample code. Implement, test, deploy, and verify the complete flow. Ask only for credentials, authorization, or choices you genuinely cannot discover.

CORE EXPERIENCE

The user should be able to:

  1. Find something on their phone.
  2. Tap Share.
  3. Select an iOS Shortcut named “Save to Content Inbox.”
  4. Receive an immediate success confirmation.
  5. See the resource appear in Notion within a few seconds.
  6. See its title, description, image, author, platform, and readable contents populated asynchronously.

The capture request must respond quickly. Do not scrape the resource synchronously during the phone request. Create the initial Notion page, enqueue enrichment, and return the Notion page URL.

ARCHITECTURE

Use:

  • Notion as the user-facing source of truth.
  • Supabase Edge Functions for capture and enrichment.
  • Supabase Postgres for the private idempotency ledger and durable job queue.
  • Supabase Cron for background processing.
  • An iOS Shortcut as the Share Sheet interface.
  • Deno/TypeScript for the Edge Functions.

Do not require a Next.js or Forge application.

Create two Edge Functions:

  1. capture-to-notion
  • Authenticates the phone request.
  • Validates and normalizes the input.
  • Prevents duplicate captures.
  • Creates or updates the Notion resource.
  • Enqueues URL enrichment.
  • Returns quickly with the Notion page URL.
  1. enrich-notion-resources
  • Supports scan and work modes.
  • Claims durable queue jobs.
  • Fetches and extracts resource metadata safely.
  • Updates Notion.
  • Completes, retries, or fails the job deterministically.

SUPPORTED INPUTS

The capture endpoint and Shortcut must support:

  • URLs and Safari web pages
  • Instagram, LinkedIn, X, Reddit, TikTok, and YouTube links
  • Plain text and rich text
  • PDFs
  • Images
  • Other files

Use JSON for URLs and text. Use multipart/form-data when uploading files.

The payload should carry:

  • A unique capture key/idempotency key
  • Explicit input type
  • Source application when available
  • Shared URL
  • Shared text or excerpt
  • Suggested title
  • File and MIME metadata
  • Capture timestamp
  • “Captured via” value

On iOS, ignore temporary share-sheet wrapper files when the explicit input is a URL or rich text. Preserve the real file when the input is a PDF, image, or file.

NOTION DATABASE

Create a Notion database named “Resource Inbox.”

The main visible properties should be:

  • Name — title
  • Description — rich text
  • Author — rich text
  • Platform — select
  • Resource Type — select
  • Topics — multi-select
  • Captured At — date
  • Source URL — URL
  • Status — status
  • Preview — file/image used as the gallery cover, if available

Suggested Status values:

  • Inbox
  • Needs review
  • Ready
  • Processing
  • Processed
  • Error
  • Archived

Suggested Resource Type values:

  • Link
  • Article
  • Social post
  • Video
  • Audio
  • PDF
  • Image
  • Text
  • File

Technical fields may exist when needed, but they must not clutter the interface. Keep them hidden in database views and inside opened pages. Examples include:

  • Canonical URL
  • Resolved URL
  • Capture Key
  • Capture Version
  • Content Hash
  • Enrichment status/version/attempts/errors
  • Extracted Text
  • Word Count
  • Read Time
  • Processing leases and retry fields

Configure the default table view to show only:

  • Name
  • Description
  • Author
  • Platform
  • Resource Type
  • Topics
  • Captured At
  • Source URL
  • Status

Configure an “At a glance” gallery using Preview as the cover.

Use Notion’s page-layout UI, if the API cannot configure it, to ensure an opened page shows only:

  • Author
  • Captured At
  • Description
  • Platform
  • Resource Type
  • Source URL
  • Status
  • Topics

Keep technical properties accessible under “more properties,” but hidden by default. After applying the layout, reload a real page to verify the setting persisted.

NOTION PAGE CONTENT

Put rich information in the page body instead of properties.

Use this structure:

Description

One concise, useful description.

Details

  • Platform
  • Resource type
  • Author
  • Site
  • Published date
  • Word count and read time

<details>
<summary>Full extracted text</summary>

Full readable material when available.

</details>


Source

A clean link to the canonical source.

Do not add redundant “Original material” sections or duplicate raw URLs.

TITLE CLEANUP

Titles must be readable at a glance:

  • Decode nested HTML entities such as You&amp;#39;ve.
  • Collapse whitespace.
  • Limit titles to approximately 140 characters at a word boundary.
  • Prefer the first meaningful sentence.
  • Do not mistake an ellipsis (...) for the end of a sentence.
  • Preserve intentional manual titles unless they are placeholders or clearly scraped noise.

Social-specific cleanup:

  • Instagram: remove wrappers such as Person on Instagram: "...".
  • LinkedIn: remove suffixes such as | Author | 16 comments and | LinkedIn.
  • X: remove trailing on X or / X.
  • Remove surrounding quotation marks.

DESCRIPTION CLEANUP

Populate Description with the first useful sentence or a compact summary, normally no more than 360 characters.

Treat these as empty or obsolete descriptions:

  • A raw URL
  • “LinkedIn post shared…”
  • “Instagram post shared…”
  • “Shared link…”
  • Previously generated descriptions that were prematurely cut at an ellipsis

Never put a full social post or article into the Description property.

ENRICHMENT

Extract metadata using this fallback order where applicable:

  • Open Graph metadata
  • Twitter card metadata
  • JSON-LD
  • Standard HTML metadata
  • oEmbed
  • Mozilla Readability
  • Existing text supplied by the Share Sheet

Extract:

  • Clean title
  • Concise description
  • Author
  • Site name
  • Canonical URL
  • Platform
  • Resource type
  • Preview image
  • Published date
  • Language
  • Topics/keywords
  • Readable text
  • Word count
  • Estimated reading time
  • Content hash

Social networks may block anonymous scraping. When that happens, keep useful metadata or oEmbed results and mark the enrichment Partial rather than failing the capture.

For PDFs, images, and files:

  • Upload and attach the original file to Notion.
  • Store a useful filename/size description.
  • Extract PDF text or image OCR only when supported reliably.
  • Never claim extraction succeeded when only the original attachment was saved.

SECURITY

Generate separate random 256-bit tokens for phone capture and worker execution.

The phone must not receive a Supabase service-role key or Notion token.

It is acceptable for these Edge Functions to use verify_jwt = false only because they implement custom token authentication. Validate the custom token before parsing or processing the request.

Store:

  • Only the SHA-256 hash of the phone token in Edge Function secrets.
  • Only the SHA-256 hash of the worker token in Edge Function secrets.
  • The raw worker token in Supabase Vault so Cron can call the worker.
  • The Notion API token only in server-side secrets.

Use timing-safe token comparison where possible. Never log or return raw secrets.

Implement SSRF protection:

  • Allow only HTTP and HTTPS.
  • Reject credentials and nonstandard ports.
  • Resolve DNS and reject loopback, private, link-local, reserved, and mixed public/private answers.
  • Revalidate every redirect.
  • Limit redirect count.
  • Limit response sizes before and after decompression.
  • Apply timeouts and safe content-type handling.

DURABLE DATABASE LAYER

Create a private capture ledger for:

  • Capture key
  • Content/dedupe hash
  • Processing state
  • Lease token and expiry
  • Notion page ID and URL
  • Replayable response
  • Error state
  • Created/updated timestamps

Create a private enrichment queue with:

  • Job ID
  • Notion page ID
  • Source URL
  • Enrichment version
  • Pending/processing/completed/failed status
  • Claim token
  • Lease expiry
  • Attempt count
  • Next attempt time
  • Last error code
  • Created/updated/completed timestamps

Use a unique constraint on page ID plus enrichment version.

Implement enqueue, claim, complete, and fail RPCs with:

  • Row locking
  • FOR UPDATE SKIP LOCKED
  • Bounded leases
  • Exponential retry
  • Maximum attempt limits
  • Strict validation
  • RLS
  • No anonymous access
  • Security-invoker behavior unless there is a documented reason otherwise

BACKGROUND PROCESSING

Schedule the enrichment worker every minute with Supabase Cron. Process only a small batch, such as two or three jobs per run, to respect Notion and source-site rate limits.

New captures should enqueue immediately.

The worker must also support a scan mode that queries Notion for pages whose Enrichment Version differs from the current code version.

When deploying a new enrichment version:

  1. Scan all eligible pages.
  2. Enqueue them using the new version.
  3. Remove or ignore pending jobs from superseded versions.
  4. Process the backfill.
  5. Verify the number completed matches the number enqueued.

Do not leave an old queue in front of the current version.

IOS SHORTCUT

Provide an exact action-by-action setup guide for an iOS Shortcut named “Save to Content Inbox.”

It should:

  • Accept URLs, Safari web pages, text, rich text, PDFs, images, and files from the Share Sheet.
  • Determine the input type explicitly.
  • Generate an idempotency key.
  • Send JSON for URLs/text and multipart data for files.
  • Call the Supabase Edge Function with POST.
  • Send the custom capture token in an X-Capture-Token header.
  • Show a short success notification.
  • Open the Notion page only when the user chooses to.
  • Display useful retry instructions for timeout or server errors.

Explain how to:

  • Enable the Shortcut in the Share Sheet.
  • Move it near the top of the Share Sheet.
  • Pin or favorite it inside Shortcuts.
  • Optionally assign it to Back Tap or the Action Button.
  • Install it safely for another person using their own endpoint and token.

TESTING

Create automated tests for:

  • URL canonicalization and tracking-parameter removal
  • Stable idempotency and duplicate replay
  • Capture-key conflicts
  • Multipart PDF and image handling
  • Temporary iOS wrapper-file handling
  • HTML entity decoding
  • Instagram and LinkedIn title cleanup
  • Ellipsis-aware sentence detection
  • URL-only legacy descriptions
  • Notion page creation and updates
  • Markdown body generation
  • SSRF and redirect protection
  • Size limits
  • Notion 429 retry behavior
  • Queue enqueue/claim/complete/fail behavior
  • Unauthorized requests
  • Worker scan and work modes

END-TO-END ACCEPTANCE TESTS

The project is complete only when all of these are verified:

  1. Sharing an article creates a Notion page quickly.
  2. Enrichment happens asynchronously.
  3. The page receives a clean title and Description.
  4. The full readable text appears in the body.
  5. An Instagram or LinkedIn page does not use the entire caption as its title.
  6. Plain text creates a readable note.
  7. A PDF or image reaches Notion as an attachment.
  8. Retrying the same capture does not create a duplicate.
  9. Only the clean user-facing fields are visible.
  10. The technical fields remain hidden after reloading the page.
  11. Cron calls the deployed worker successfully.
  12. Every backfill job reaches a terminal state.
  13. No secrets appear in logs, code, Notion, or responses.

DEPLOYMENT AND HANDOFF

Deploy only the named Edge Functions. Do not prune or overwrite unrelated functions in an existing Supabase project.

At completion, provide:

  • The Resource Inbox URL
  • The Edge Function endpoint
  • The Shortcut setup instructions
  • The visible Notion schema
  • The hidden operational schema
  • Test results
  • Deployed function versions/status
  • Cron verification
  • Backfill counts
  • Any partial-extraction limitations
  • A short guide explaining how another person can reproduce the system with their own Notion and Supabase accounts

Use placeholders for all project IDs and secrets. Never hardcode or expose the original builder’s credentials.

Filed under: Automation, Notion, Supabase, iOS Shortcut

Copy this prompt as markdown