Link Loom is an intelligent bookmark organization tool that uses AI to cluster and categorize your chaotic browser bookmarks into a structured, easy-to-navigate hierarchy.
- AI-Powered Clustering: Automatically analyzes your bookmarks and groups them by topic using K-Means clustering and OpenAI embeddings.
- Smart Organization: Creates a logical folder structure for your links.
- Chrome Extension: A user-friendly browser extension to manage the weaving process.
- Visual Progress: Real-time feedback on the organization process.
- Preview: View the proposed structure before applying changes.
- Dark/Light Mode: Premium design with frosted glass effects.
- Modern Stack: Built with a robust monorepo architecture.
This project is a monorepo managed by Turborepo and pnpm.
apps/extension: Chrome Extension built with React, Vite, and CRXJS.apps/backend: Fastify API for bookmark ingestion, embedding (OpenAI), and clustering (ml-kmeans). Uses Supabase (Postgres) for storage and SQS/Lambda for production queues.apps/web: Next.js application (Marketing/Dashboard).
packages/ui: Shared UI components.packages/tsconfig: Shared TypeScript configurations.packages/shared: Shared utilities and types.
- Node.js (>= 18)
- pnpm (>= 8)
- Docker (for local Supabase)
- Supabase CLI
- OpenAI API Key
-
Clone the repository
git clone <repo-url> cd link-loom
-
Install dependencies
pnpm install
-
Environment Setup
- Copy
.env.exampleto.env.localinapps/web,apps/backend, andapps/extension. - Use
npx supabase statusafter starting Supabase to copy the local API URL, anon key, service role key, and DB URL into those files. apps/backendalso needsOPENAI_API_KEYfor AI processing.
- Copy
-
Start Infrastructure
- Ensure Docker is running.
- Start local Supabase:
npx supabase start - Bookmark processing runs inline in local development; production should set
QUEUE_DRIVER=sqsand use SQS-triggered Lambda workers. - For web login/signup work only, Supabase plus
pnpm --filter web devis enough.
-
Run Development Server
pnpm dev
This command starts all applications in parallel using Turbo.
-
Production Lambda Deploy
- Production deploys use
apps/*/.env.productionas the source of truth. - The root
Makefilemaps those values into TerraformTF_VAR_*variables. - Check the mapping without printing secrets:
make tf-env-print
- Validate and deploy the Lambda/SQS backend:
make tf-check make tf-plan make deploy make smoke-prod
- There is no Redis/ElastiCache in production; SQS-triggered Lambda workers process jobs.
- Production deploys use
-
Stripe Local Development To test premium features locally, you need to forward Stripe webhooks to your local environment.
- Set
STRIPE_SECRET_KEY,STRIPE_PRICE_ID_PRO,STRIPE_WEBHOOK_SECRET, andNEXT_PUBLIC_SITE_URL=http://localhost:3000inapps/web/.env.local. - Match Stripe modes:
sk_test_...must use a test-modeprice_...;sk_live_...must use a live-modeprice_.... - Use
STRIPE_CHECKOUT_MODE=paymentfor the one-time lifetime Pro plan. Usesubscriptiononly with a recurring Stripe Price. - Install the Stripe CLI.
- Log in to your Stripe account:
stripe login
- Start forwarding webhook events to your local Next.js API:
stripe listen --forward-to localhost:3000/api/webhooks/stripe
- Copy the generated webhook secret (
whsec_...) and add it to yourapps/web/.env.localasSTRIPE_WEBHOOK_SECRET. - In the web app, test upgrades from
http://localhost:3000/dashboard/billing. The dashboard uses/api/checkoutand the current Supabase web session; the extension signup flow uses/api/create-checkout-sessionwith its Supabase bearer token. - In Stripe test mode, complete Checkout with card
4242 4242 4242 4242, any future expiry, any CVC, and any ZIP.
- Set
To load the extension in Chrome:
-
Run the build or dev command:
# For popup/web development pnpm dev # Build the Chrome extension against local Supabase/web/backend envs pnpm --filter extension build:local # OR build the production extension bundle pnpm build
apps/extension/.env.localis for local development, whileapps/extension/.env.productionis used by the normal production build. If the unpacked extension should log into local Supabase users, load a bundle built withpnpm --filter extension build:local. -
Open Chrome and navigate to
chrome://extensions/. -
Enable Developer mode (top right).
-
Click Load unpacked.
-
Select the
apps/extension/distfolder.
Note: Do not load the
apps/extensionroot folder; you must load thedistfolder generated by the build.
link-loom/
├── apps/
│ ├── backend/ # Fastify API & Job Workers
│ ├── extension/ # Chrome Extension (React/Vite)
│ └── web/ # Next.js Frontend
├── packages/
│ ├── tsconfig/ # Shared TS Config
│ ├── ui/ # Shared Components
│ └── shared/ # Shared Logic
├── turbo.json # Turborepo Config
└── package.json # Root Config
Link Loom uses a combination of Vitest (for backend unit tests) and Playwright (for frontend E2E tests).
The backend uses Vitest to test the AI background workers (ingestion, enrichment, embedding, and clustering queues).
cd apps/backend
pnpm run testThe web application uses Playwright to perform end-to-end tests on critical user paths like the marketing pages.
cd apps/web
pnpm run test:e2eTo run the Playwright tests in interactive UI mode:
cd apps/web
pnpm run test:e2e:uipnpm build: Build all apps and packages.pnpm dev: Start all apps in development mode.pnpm lint: Lint all code.pnpm format: Format code with Prettier.