Meltype
눈 녹듯 반각·전각 장벽을 녹여주는 일본어 입력
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기One inbox for everything you save. Collects bookmarks from your browser, X, Reddit, Instagram, LinkedIn and YouTube Watch Later through a Chrome extension, with AI summaries and search by meaning
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Every post you saved, on every platform, in one inbox — summarised, linked across platforms, and resurfaced so you actually use it.
https://github.com/user-attachments/assets/8dd438a1-adcc-41dd-8c75-b49fd279c393
bookmark-captain-extension.zip
from the latest release
and unzip it into a folder you'll keep. Chrome runs the extension from that folder.chrome://extensions, turn on Developer mode (top right), click Load unpacked
and choose the unzipped folder (the one containing manifest.json).Updates don't install themselves yet: download the new zip, replace the folder's contents, and
click the reload icon (↻) on Bookmark Captain in chrome://extensions.
Using the app? Read the User Guide: setup, connecting platforms, the inbox, and troubleshooting.
utm_*, fbclid, si, …) are stripped, and the same
page saved twice (or from another platform) is detected instead of duplicated.bookmarks.html — exports from Chrome, Firefox, Safari or Edge, with folder paths.apps/
api/ Express 5 API — auth, API tokens, bookmarks, live events (SSE)
web/ Next.js 16 web app (App Router, Tailwind CSS 4, TanStack Query)
extension/ Chrome extension (Manifest V3), bundled with esbuild
packages/
db/ Drizzle ORM schema, Postgres client (Neon-ready), SQL migrations
shared/ Types, zod schemas, URL normaliser; `@bc/shared/constants` is dependency-free
e2e/ Playwright end-to-end tests (API + web + real Chromium with the extension)
Tooling: pnpm workspaces, Turborepo, TypeScript (strict), ESLint (type-aware), Prettier, Vitest + Supertest, Playwright, GitHub Actions CI.
.nvmrc) and pnpm 10 (corepack enable)production, dev (local development) and
test (wiped by the test suites). Docker is optional (pnpm db:up) for working offline.pnpm install
cp .env.example .env # fill in the Neon connection strings (see "Using Neon")
pnpm db:migrate # apply migrations to DATABASE_URL
pnpm dev # API on :4000, web on :3000, extension rebuilt on change
Open http://localhost:3000 and use Development sign-in (any email) — no Google setup needed locally.
pnpm --filter @bc/extension build (or keep pnpm dev running).chrome://extensions, turn on Developer mode, click Load unpacked and choose
apps/extension/dist.The extension is built for the URLs in .env (NEXT_PUBLIC_API_URL, WEB_URL); override with
EXTENSION_API_URL / EXTENSION_WEB_URL for other environments.
| Command | What it does |
|---|---|
pnpm dev | Run every app in watch mode |
pnpm test | Unit + integration tests (uses TEST_DATABASE_URL) |
pnpm test:e2e | End-to-end tests on ports 3100/4100 against TEST_DATABASE_URL |
pnpm lint | ESLint with type-aware rules |
pnpm typecheck | tsc in every package |
pnpm format | Prettier |
pnpm build | Production builds (API bundle, web app, extension) |
pnpm db:generate | Create a SQL migration after editing packages/db/src/schema.ts |
pnpm db:migrate | Apply pending migrations |
pnpm db:studio | Browse the database with Drizzle Studio |
The first pnpm test:e2e needs a browser: pnpm --filter @bc/e2e exec playwright install chromium.
The e2e suite builds its own copies of the web app (apps/web/.next-e2e) and extension
(e2e/.extension), so it never disturbs pnpm dev or your dev data.
| Method & path | Auth | Purpose |
|---|---|---|
GET /bookmarks | session or token | List with view, platform, q, cursor paging |
POST /bookmarks | session or token | Save one link (returns the existing one if saved) |
POST /bookmarks/ingest | session or token | Idempotent bulk upsert (≤ 500 items per request) |
POST /bookmarks/remove | session or token | Mirror deletions made at the source |
PATCH /bookmarks/:id | session or token | Change status / snooze |
DELETE /bookmarks/:id | session or token | Delete |
GET /events | session or token | Server-sent events: bookmarks.changed |
GET/POST /api-tokens | session only | List / create API tokens (e.g. for the extension) |
DELETE /api-tokens/:id | session only | Revoke a token |
DELETE /api-tokens/current | token only | A client revokes its own token (disconnect) |
/auth/*, GET /me | — | Sign-in, sign-out, current user |
Errors always have the shape { "error": { "code", "message", "details?" } }.
dev and test branches
from production (or neonctl branches create --name dev).dev branch, copy the pooled connection string into DATABASE_URL and the
direct one into DATABASE_URL_UNPOOLED. Migrations use the direct connection.test branch's direct connection string into TEST_DATABASE_URL.sslmode=verify-full in every URL.pnpm db:migrateThe production branch is only touched by deployments (pnpm db:migrate with production env vars).
Point your host's health check at /healthz (process liveness, no database access), not
/readyz — frequent readiness probes would keep the Neon compute from scaling to zero.
{API_URL}/auth/google/callback (locally http://localhost:4000/auth/google/callback).GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.HttpOnly, SameSite=Lax
cookie; the database stores only its SHA-256 hash. Sliding 30-day expiry.bct_…) for the extension are also stored hashed, expire after a year, can only be
created from a browser session, and can be revoked from Settings → Connected devices.window.postMessage on the web app's own connect page;
the background worker only accepts it from that exact origin and path.state check.SameSite=Lax plus an Origin allow-list on every cookie-authenticated state change.app.example.com and api.example.com, set COOKIE_DOMAIN=example.com
so the Next.js server can read the session cookie.TRUST_PROXY to the number of proxies in front of the API so client IPs and rate limits are correct.LISTEN/NOTIFY.pnpm --filter @bc/api build && pnpm --filter @bc/api start (bundled to apps/api/dist).