Skip to content

sanudin-dev/focusmark

Repository files navigation

Focusmark

A personal productivity platform combining a daily focus tracker and a bookmark manager, accessible from the web and a Chrome extension.

Features

  • Daily Focus — pick up to 3 tasks to complete today. Resets automatically at midnight UTC.
  • Bookmark Manager — save URLs with auto-fetched metadata (title, description, favicon), organize into folders, tag, and search.
  • Chrome Extension — one-click bookmark saving from any page.
  • URL Shortener — create short links with click tracking.
  • Full-text Search — search across bookmark titles, descriptions, URLs, and tags.

Tech Stack

Layer Technology
Backend NestJS + TypeScript + Prisma + PostgreSQL
Frontend Next.js 16 (App Router) + Tailwind CSS v4
Extension Chrome MV3 + React + Vite
Auth JWT (access token + httpOnly cookie refresh token)
Queue BullMQ + Redis (async metadata fetching)
Deploy Railway (API) + Vercel (Web)

Prerequisites

Getting Started

1. Clone and install

git clone https://github.com/sanudin-dev/focusmark.git
cd focusmark
pnpm install

2. Configure environment variables

Copy the example files and fill in your values:

cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env
cp apps/extension/.env.example apps/extension/.env

apps/api/.env

DATABASE_URL=postgresql://user:password@localhost:5432/focusmark
REDIS_URL=redis://localhost:6379
JWT_ACCESS_SECRET=your_secret_here
JWT_REFRESH_SECRET=your_secret_here
JWT_ACCESS_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
PORT=3001
ALLOWED_ORIGINS=http://localhost:3000

apps/web/.env

NEXT_PUBLIC_API_URL=http://localhost:3001

apps/extension/.env

VITE_API_URL=http://localhost:3001

3. Start the database and cache

docker compose up -d

4. Run database migrations

pnpm --filter api prisma migrate dev

5. Start all apps

pnpm dev
App URL
Web http://localhost:3000
API http://localhost:3001
Swagger http://localhost:3001/api/docs

Chrome Extension

Build the extension and load it into Chrome:

pnpm --filter extension build
  1. Open chrome://extensions
  2. Enable Developer mode
  3. Click Load unpacked
  4. Select apps/extension/dist/

Project Structure

focusmark/
├── apps/
│   ├── api/          ← NestJS backend
│   ├── web/          ← Next.js frontend
│   └── extension/    ← Chrome Extension
├── packages/
│   ├── types/        ← Shared TypeScript types & Zod schemas
│   ├── constants/    ← Shared validation limits & magic numbers
│   └── utils/        ← Shared utility functions (countdown, tag parsing)
├── docker-compose.yml
├── turbo.json
└── package.json

API Overview

All routes except /auth/* and /s/:slug require a Bearer token.

Method Route Description
POST /auth/register Create account
POST /auth/login Login
POST /auth/refresh Rotate refresh token
POST /auth/logout Invalidate session
GET /focus Today's focuses
POST /focus Add focus (max 3/day)
PATCH /focus/:id Mark done/undone
DELETE /focus/:id Delete focus
GET /bookmarks List bookmarks (paginated)
POST /bookmarks Save bookmark
PATCH /bookmarks/:id Update bookmark
DELETE /bookmarks/:id Delete bookmark
GET /folders List folders
POST /folders Create folder
GET /search?q= Full-text search
GET /short-links List short links
POST /short-links Create short link
DELETE /short-links/:id Delete short link
GET /s/:slug Redirect (public)

Development

# Run a specific app only
pnpm --filter api dev
pnpm --filter web dev
pnpm --filter extension build --watch

# Type-check all apps
pnpm --filter api build
pnpm --filter web type-check

# Generate Prisma client after schema changes
pnpm --filter api prisma generate

# Create a new migration
pnpm --filter api prisma migrate dev --name your_migration_name

About

A personal productivity platform

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors