Bookmarked: Your Go-To Tool for Curating Tweets in Notion

A full-stack application that enables users to save tweets to Notion via Telegram bot.

What is Bookmarked?

erDiagram
%% Relationships
users ||--o{ blogs : writes
blogs ||--|| blog_seo_metadata : has
blogs ||--o{ blog_images : includes
blogs ||--o{ sitemap_entries : generates
blogs ||--o{ blog_category_relation : has
blog_categories ||--o{ blog_category_relation : contains
blogs ||--o{ comments : receives
blogs ||--o{ revisions : versioned_by
users ||--o{ revisions : authored
blogs ||--o{ audit_logs : affected_by
users ||--o{ audit_logs : logs
%% Tables
users {
UUID id PK
TEXT full_name
TEXT email
TEXT avatar_url
TEXT password_hash
TEXT salt
BOOLEAN email_verified
TEXT role
TEXT status
TIMESTAMP last_login_at
TIMESTAMP created_at
}
blogs {
UUID id PK
UUID author_id FK
TEXT title
TEXT slug
TEXT excerpt
TEXT[] tags
TEXT cover_image_url
JSONB content_json
TEXT content_html
INT read_time_minutes
INT word_count
BIGINT views_count
TEXT status
TIMESTAMP published_at
TIMESTAMP created_at
TIMESTAMP updated_at
}
blog_seo_metadata {
UUID blog_id PK
TEXT meta_title
TEXT meta_description
TEXT canonical_url
TEXT og_image_url
TEXT og_type
TEXT twitter_card
TEXT twitter_creator
TEXT[] meta_keywords
TEXT robots_directive
JSONB custom_json_ld
}
blog_images {
UUID id PK
UUID blog_id FK
TEXT url
TEXT alt_text
TEXT caption
TEXT credit
INT width
INT height
INT file_size_kb
TEXT folder
JSONB transformation_params
BOOLEAN is_featured
TIMESTAMP created_at
}
sitemap_entries {
UUID id PK
UUID blog_id FK
TEXT url
DECIMAL priority
TEXT changefreq
TIMESTAMP last_updated
}
blog_categories {
UUID id PK
TEXT name
TEXT slug
TEXT description
UUID parent_id FK
TEXT image_url
}
blog_category_relation {
UUID blog_id FK
UUID category_id FK
}
comments {
UUID id PK
UUID blog_id FK
UUID user_id FK
TEXT author_name
TEXT author_email
TEXT content
UUID parent_comment_id FK
TEXT status
TIMESTAMP created_at
TIMESTAMP updated_at
}
revisions {
UUID id PK
UUID blog_id FK
UUID author_id FK
JSONB content_json
TEXT content_html
TEXT revision_type
TIMESTAMP created_at
}
settings {
TEXT key PK
JSONB value
TEXT description
}
audit_logs {
UUID id PK
UUID user_id FK
TEXT action
TEXT entity_type
UUID entity_id
JSONB details
INET ip_address
TEXT user_agent
TIMESTAMP created_at
}

Bookmarked bridges the gap between how you consume content and how you organize it. Instead of losing that brilliant tweet buried in your timeline, forward it to our Telegram bot. Seconds later, it's in your Notion database—beautifully formatted, tagged, and searchable.

The Genesis

I was spending hours every week manually copying tweets and articles into Notion. The workflow was broken: switch apps, copy, switch again, paste, format. I realized I could automate this entirely. Thus Bookmarked was born.

This project emerged from a personal pain point that resonated with thousands of users across Twitter, Reddit, and Product Hunt.

How It Works

  1. Forward any tweet or link to the Bookmarked Telegram bot
  2. We parse metadata (author, timestamps, media, URLs)
  3. It automatically appears in your Notion workspace
  4. Your personal knowledge base grows effortlessly

Core Architecture

Tech Stack

  • Frontend: Next.js 14 with TypeScript and React Server Components
  • Backend: Express.js API for bot logic and webhook handling
  • Integrations: Telegram Bot API, Notion API v1, Twitter API v2
  • Database: PostgreSQL with Prisma ORM for type safety
  • Queue: Bull for background job processing
  • Deployment: Docker on AWS ECS with auto-scaling

System Design

The architecture follows a microservices-inspired approach:

Telegram Bot → Express Server → Job Queue → Notion API
↓ ↓ ↓
User Input Parsing Background
& Routing Processing

Key Features

  • Smart Parsing: Automatically extracts title, author, date, and media
  • Dual Sync: Works with both Twitter/X and Telegram links
  • Tag Templates: Pre-configured tags for quick organization
  • Notion Formatting: Rich formatting with inline tags and properties
  • Rate Limiting: Handle thousands of forwards without API throttling
  • Error Recovery: Failures are queued and retried automatically

Technical Challenges

Challenge 1: Rate Limiting Hell

Notion API has strict rate limits (3 requests/second). When bulk importing, we'd hit them constantly.

Solution: Implemented a sophisticated queue system that intelligently batches requests and respects Notion's rate limits using exponential backoff.

// Exponential backoff retry strategy
async function retryWithBackoff(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error.status === 429) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}

Challenge 2: Media Handling

Twitter contains embedded images and videos. How do we preserve them in Notion? We download media, optimize it, upload to a CDN, and embed the links in Notion. Network operations are concurrent with proper error handling.

Challenge 3: Parsing Consistency

Different link formats (tweets, threads, links) need different parsing strategies. We built a plugin architecture where each source type has its own parser, making it easy to add new sources.

Challenge 4: State Management

Users might send the same link twice. We needed deduplication without false negatives.

Solution: Content hashing with fuzzy matching to detect duplicates while allowing intentional multiple saves.

Performance Metrics

  • Average processing time: 2-3 seconds from forward to Notion
  • 99.9% uptime: Months without downtime
  • 30K+ bookmarks: Processed successfully since launch
  • Sub-100ms API latency: Optimized database queries and caching

Database Schema Highlights

Users → Bookmarks → Notion Pages
↓ ↓
Settings Metadata

Scaling & DevOps

  • Deployed on AWS ECS with auto-scaling based on queue depth
  • CloudFront CDN for media delivery
  • RDS PostgreSQL with multi-AZ for availability
  • GitHub Actions for CI/CD pipeline
  • Monitoring with DataDog for real-time alerts

Lessons Learned

  • Integrating with third-party APIs requires defensive programming
  • Queue-based architecture is essential for reliability
  • User feedback iterations drove 80% of our best features
  • Type safety (TypeScript + Prisma) prevented countless bugs
  • Monitoring and alerting saved us from silent failures

Business Impact

  • 5K+ active users across 3 continents
  • Saved users thousands of hours of manual work
  • 98% retention rate for premium users
  • Featured in several product communities

What's Next

  • Browser extension for non-Telegram sources
  • AI-powered auto-tagging using embeddings
  • Advanced search with semantic understanding
  • Team/collaborative Notion workspace support
  • Mobile apps for iOS and Android

Open Source Contributions

The project uses many amazing libraries. We've given back by contributing improvements to:

  • Prisma ORM
  • Bull queue library
  • Notion SDK

Built with ❤️ for people who love collecting ideas and organizing thoughts.