Skip to content

πŸ“– a chrome extension that enables seamless online reading experience (e.g., add comment, ask questions about specific text in-browser and save to notion pages)

Notifications You must be signed in to change notification settings

thuthancs/inline

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

image_icon

Table of Contents

Demo

https://www.loom.com/share/38832d4660e44e34bc7862d5b41ec258

Why inline?

As someone who reads online most of the time, I find the current reading flow annoying and requires too much switching. When I read, I want to engage AND save information so that I can revisit it later. Now, all of my data lives in Notion, and whenever I read a research paper or something that requires serious attention, I need to open a split view, copy from one tab, paste it into Notion, and open another tab, like Claude or ChatGPT, to ask follow-up questions. I was thinking about how I can automate this process so that my online reading experience is more seamless while ensuring the right information is saved to my knowledge base. And this is why inline was born :)

Setup

Estimated Time Spent: ~15-20 mins

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js (v18 or higher) - Download
  • npm (comes with Node.js)
  • Chrome browser (for loading the extension)
  • Notion API key - Get one here

Getting Your Notion API Key

  1. Go to https://www.notion.so/my-integrations
  2. Click "+ New integration"
  3. Give it a name (e.g., "Inline Extension")
  4. Select the workspace where you want to save content
  5. Click "Submit" to create the integration
  6. Copy the "Internal Integration Token" - you'll need this for the NOTION_KEY environment variable
  7. Important: Share the pages/databases you want to use with this integration:
    • Open the Notion page or database you want to use
    • Click the "..." menu in the top right
    • Select "Add connections" or "Connections"
    • Find and select your integration

Installation Steps

1. Clone the Repository

git clone <repository-url>
cd inline

2. Set Up the Server

  1. Navigate to the server directory:

    cd server
  2. Install dependencies:

    npm install
  3. Create a .env file in the server directory:

    touch .env
  4. Add your Notion API key to the .env file:

    NOTION_KEY=your_notion_api_key_here
    PORT=64707

    Note: The default port is 3000, but the frontend expects 64707. You can change the port in the frontend's api.ts file if needed.

  5. Build the server:

    npm run build
  6. Start the server:

    # For development (with auto-reload):
    npm run dev
    
    # For production:
    npm start

    The server should now be running on http://localhost:64707 (or the port you specified).

3. Set Up the Frontend (Chrome Extension)

  1. Navigate to the frontend directory:

    cd ../frontend
  2. Install dependencies:

    npm install
  3. Build the extension:

    npm run build

    This will create a dist folder with the compiled extension files.

  4. Optional: If you need to change the server URL (if your server runs on a different port or host), edit frontend/src/api.ts:

    export const API_BASE = "http://localhost:64707"; // Change this to your server URL

    Then rebuild:

    npm run build

4. Load the Extension in Chrome

  1. Open Chrome and navigate to chrome://extensions/
  2. Enable "Developer mode" (toggle in the top right)
  3. Click "Load unpacked"
  4. Select the frontend/dist folder from the project directory
  5. The extension should now appear in your extensions list

5. Verify the Setup

  1. Make sure the server is running (you should see it listening on the configured port)
  2. Click the extension icon in Chrome to open the side panel
  3. Try searching for a Notion page or database
  4. If everything is set up correctly, you should see your Notion pages/databases in the search results

Development

For development with hot-reload:

Server:

cd server
npm run dev

Note: After making changes to the frontend, you'll need to rebuild (npm run build) and reload the extension in Chrome for changes to take effect.

Architecture

Overview

Inline is a Chrome extension that enables seamless saving of web content to Notion. The architecture consists of three main components:

  1. Chrome Extension (Frontend) - React-based UI and content scripts that interact with web pages
  2. Express.js Server (Backend) - API server that handles Notion API interactions
  3. Notion API - External service for reading and writing data
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Chrome Browser                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Content Script (content.ts)                         β”‚   β”‚
β”‚  β”‚  - Detects text selection                            β”‚   β”‚
β”‚  β”‚  - Shows tooltip with Save/Comment buttons           β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                 β”‚ chrome.runtime.sendMessage                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Service Worker (sw.ts)                              β”‚   β”‚
β”‚  β”‚  - Message routing                                   β”‚   β”‚
β”‚  β”‚  - API calls to backend                              β”‚   β”‚
β”‚  β”‚  - Storage management                                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                 β”‚ HTTP requests                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Side Panel (popup/App.tsx)                          β”‚   β”‚
β”‚  β”‚  - React UI for destination selection                β”‚   β”‚
β”‚  β”‚  - Search and browse Notion pages/databases          β”‚   β”‚
β”‚  β”‚  - Property form for database entries                β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β”‚ HTTP (REST API)
                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Express.js Server (server.ts)                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Routes:                                             β”‚   β”‚
β”‚  β”‚  - POST /search          - Search Notion             β”‚   β”‚
β”‚  β”‚  - GET  /children/:id    - Get child pages           β”‚   β”‚
β”‚  β”‚  - GET  /data-sources/:id - Get data sources         β”‚   β”‚
β”‚  β”‚  - POST /create-page     - Create new page           β”‚   β”‚
β”‚  β”‚  - PATCH /save           - Save content to page      β”‚   β”‚
β”‚  β”‚  - POST /save-with-comment - Save + comment          β”‚   β”‚
β”‚  β”‚  - POST /comment          - Add comment to block     β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                 β”‚ @notionhq/client                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚   Notion API    β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Components

1. Chrome Extension (Frontend)

The extension is built with React, TypeScript, and Vite, and consists of three main parts:

Content Script (content.ts)

  • Purpose: Injected into every webpage to detect user interactions
  • Key Features:
    • Monitors text selection events (mouseup, selectionchange)
    • Displays tooltip with "Save" and "Comment" buttons when text is selected
    • Highlights selected text with optimistic UI updates
    • Manages image hover detection for saving images
  • Communication: Sends messages to service worker via chrome.runtime.sendMessage()

Service Worker (sw.ts)

  • Purpose: Background script that handles extension logic and API communication
  • Key Features:
    • Routes messages from content script to appropriate handlers
    • Makes HTTP requests to the Express.js backend
    • Manages Chrome storage for destination persistence
    • Handles extension lifecycle (opens side panel on icon click)
    • Implements retry logic and timeout handling

Side Panel (popup/App.tsx)

  • Purpose: React-based UI for managing Notion destinations
  • Key Features:
    • Search interface for finding Notion pages, databases, and data sources
    • Nested hierarchy display (page β†’ database β†’ data source)
    • Destination selection and persistence
    • Property form for database entries (supports text, number, select, date, url types)
    • Create child pages directly from the UI

2. Express.js Server (Backend)

Built with Express.js and TypeScript, the server acts as a proxy between the extension and Notion API.

API Routes

  • POST /search - Searches Notion for pages and data sources matching a query
  • GET /children/:pageId - Retrieves child pages of a given page
  • GET /data-sources/:databaseId - Retrieves data sources connected to a database
  • GET /data-source/:dataSourceId - Gets details of a specific data source
  • POST /create-page - Creates a new Notion page with optional properties
  • PATCH /save - Appends content (text as quote blocks + images) to a Notion page
  • POST /save-with-comment - Combined endpoint that saves content and adds a comment in one request
  • POST /comment - Adds a comment to a specific block

Services

  • notionClient.ts - Initializes and exports the Notion API client
  • imageUpload.ts - Handles image uploads to Notion (converts images to base64 and creates image blocks)

3. Data Flow

Saving Text Highlight

  1. User selects text on a webpage
  2. Content script detects selection and shows tooltip
  3. User clicks "Save" button
  4. Content script sends SAVE_HIGHLIGHT message to service worker
  5. Service worker calls PATCH /save endpoint with page ID and content
  6. Server creates quote block in Notion page
  7. Response flows back through the chain
  8. Optimistic UI update shows success immediately

Adding Comment

  1. User selects text and clicks "Comment"
  2. Content script shows comment input box
  3. User enters comment and submits
  4. Content script sends COMMENT_HIGHLIGHT message
  5. Service worker calls POST /save-with-comment (or separate /save + /comment calls)
  6. Server saves content and adds comment thread
  7. Success feedback shown to user

Selecting Destination

  1. User opens side panel
  2. User searches for Notion page/database
  3. Frontend calls POST /search endpoint
  4. Server queries Notion API and returns results
  5. User selects a destination
  6. Destination saved to chrome.storage.local
  7. Content script listens for storage changes and updates UI visibility

Tech Stack

Frontend

  • React 19 - UI framework
  • TypeScript - Type safety
  • Vite - Build tool and dev server
  • Tailwind CSS v4 - Styling
  • Chrome Extension APIs - chrome.storage, chrome.runtime, chrome.sidePanel

Backend

  • Express.js - Web framework
  • TypeScript - Type safety
  • @notionhq/client - Official Notion API client
  • CORS - Cross-origin resource sharing
  • dotenv - Environment variable management

Key Design Decisions

1. Optimistic UI Updates

The extension shows success feedback immediately while processing in the background, improving perceived performance.

2. Combined Save + Comment Endpoint

The /save-with-comment endpoint reduces API calls from 2 to 1, improving speed when adding comments.

3. Shadow DOM for Tooltip

The tooltip is injected into a Shadow DOM to avoid CSS conflicts with host pages.

4. Extension Context Validation

Checks if extension context is still valid to handle cases where the extension was reloaded, preventing stale content script errors.

5. Retry Logic

Service worker implements retry logic for API calls to handle transient network issues and service worker wake-up delays.

File Structure

inline/
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ cs/
β”‚   β”‚   β”‚   └── content.ts          # Content script
β”‚   β”‚   β”œβ”€β”€ sw/
β”‚   β”‚   β”‚   └── sw.ts              # Service worker
β”‚   β”‚   β”œβ”€β”€ popup/
β”‚   β”‚   β”‚   β”œβ”€β”€ App.tsx            # Main React component
β”‚   β”‚   β”‚   β”œβ”€β”€ components/       # UI components
β”‚   β”‚   β”‚   └── hooks/            # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ api.ts                # API client
β”‚   β”‚   └── types.ts              # TypeScript types
β”‚   β”œβ”€β”€ public/
β”‚   β”‚   └── manifest.json         # Extension manifest
β”‚   └── dist/                     # Built extension files
β”‚
└── server/
    β”œβ”€β”€ routes/                    # API route handlers
    β”œβ”€β”€ services/                 # Business logic
    β”‚   β”œβ”€β”€ notionClient.ts
    β”‚   └── imageUpload.ts
    β”œβ”€β”€ helpers/                  # Utility functions
    └── server.ts                 # Express app entry point

Under Development

  • Add a cache feature to show the latest destinations so users don't have to search all over again
  • Add Gemini API for an "Ask" mode where users can ask questions about specific text directly in the tab without switching
  • Add voice mode for adding comment

About

πŸ“– a chrome extension that enables seamless online reading experience (e.g., add comment, ask questions about specific text in-browser and save to notion pages)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages