Skip to content
dicodingacademyPublic

About

Seamless time tracking for Basecamp. Never lose track of your hours. Automatically sync your time to Basecamp with a unified, flow-oriented dashboard.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Basetrack

Seamless time tracking for Basecamp. Never lose track of your hours. Automatically sync your time to Basecamp with a unified, flow-oriented dashboard.

Node React Router Tauri Prisma PostgreSQL

Report Bug · Request Feature


Why this exists

Basetrack solves the friction of tracking time directly inside Basecamp. Instead of switching tabs, manually calculating hours, or forgetting to stop a timer, Basetrack integrates natively via OAuth2 to provide a frictionless time-tracking experience.

Feature Basecamp Native Basetrack
Live Timer No Yes — instant optimistic UI
Auto-stop No Yes — configurable threshold (e.g., 8 hours)
Approval Workflow No Yes — review auto-stopped timers before syncing
Data Persistence Cloud only Local PostgreSQL cache & sync
Multi-tab Sync No Yes — Instant via WebSocket
Desktop Widget No Yes — Native always-on-top companion app
Clients (extension + desktop) No Yes — timers started from the Basecamp extension & desktop app
Monitoring dashboard No Yes — read-only: running timer, history, approvals
Table of contents

Architecture

Basetrack utilizes a modern monorepo architecture divided into distinct micro-apps and packages, running on Node.js and PostgreSQL.

┌─────────────────────────┐   ┌──────────────────────────┐   ┌────────────────────┐
│    React Router v7      │◄──┤  WebSocket Server (WS)   ├──►│ Tauri Desktop App  │
│    (Tracker App)        │   │   (Instant Sync Hub)     │   │  (Companion UI)    │
│                         │   └──────────────────────────┘   └────────────────────┘
│  - Auth (OAuth2)        │                ▲
│  - Monitoring dashboard │                │
│  - Extension REST API   │   ┌────────────┴─────────────┐
│  - Client management    │   │     Worker / Cron        │
│  - API routes           │   │   (Standalone service)   │
│  - Prisma Client        │   └────────────┬─────────────┘
└──────────┬──────────────┘                │
           ▼                               ▼
┌──────────────────────────────────────────┐
│           PostgreSQL (Prisma)            │
│           (Database package)             │
└──────────────────────────────────────────┘

(back to top)

Prerequisites

  • Node.js 22.22.0+ — Required for React Router v8
  • PostgreSQL 15+ — Database engine
  • Docker + Docker Compose — For quick database provisioning

(back to top)

Installation

1. Database Setup

Spin up the local PostgreSQL database using the provided Docker Compose configuration:

docker compose up -d

2. Install Dependencies

Install all monorepo dependencies from the root directory:

npm install

3. Environment Variables

Create .env files in the respective directories with the following configurations:

packages/db/.env

# Connection string to your PostgreSQL database (used by Prisma)
DATABASE_URL="postgresql://basetrack:basetrack@localhost:5433/basetrack?schema=public"

apps/tracker/.env

# A random secret string used to sign and encrypt browser session cookies
SESSION_SECRET="your-super-secret-session-key"

# Basecamp OAuth2 Credentials (obtained from Basecamp Developer Portal)
BASECAMP_CLIENT_ID="your-basecamp-client-id"
BASECAMP_CLIENT_SECRET="your-basecamp-client-secret"
BASECAMP_REDIRECT_URI="http://localhost:5173/auth/basecamp/callback"

# Google OAuth2 — no longer used by the tracker (the browser extension handles Google
# Calendar/Docs/Sheets/Slides). Kept for reference; safe to omit.
# GOOGLE_CLIENT_ID="your-google-client-id"
# GOOGLE_CLIENT_SECRET="your-google-client-secret"
# GOOGLE_REDIRECT_URI="http://localhost:5173/auth/google/callback"

# The public URL where the WebSocket server is accessible by the Web/Desktop client
WS_PUBLIC_URL="ws://localhost:8081"

# A shared secret key used to authenticate server-to-server requests
INTERNAL_API_KEY="dev-internal-key-123"

apps/ws/.env

# Must match the INTERNAL_API_KEY in apps/tracker to allow secure cross-server calls
INTERNAL_API_KEY="dev-internal-key-123"

# The internal endpoint of the Web App to trigger Basecamp timesheet syncs when stopped
TRACKER_INTERNAL_URL="http://localhost:5173/api/internal/stop"

4. Database Migration

Push the schema to your local database and generate the Prisma Client:

npm run db:migrate
npm run db:generate --workspace=@basetrack/db

5. Start Development Servers

Run the development servers concurrently (React Router UI, Node Cron Worker, and WebSocket Server):

npm run dev

The web application will be available at http://localhost:5173.

To run the Desktop Companion App locally:

npm run dev:desktop

(back to top)

Desktop App & CI/CD Pipeline

Basetrack includes a native Desktop App built with Tauri that provides an always-on-top floating timer to track your task duration without switching browser tabs. The app is fully synchronized with the Web App in real-time via WebSockets.

Multi-OS Automated Release

We use GitHub Actions to automate the build and release process for the desktop companion app. The workflow supports cross-compilation for:

  • macOS (Apple Silicon / M1/M2/M3)
  • macOS (Intel)
  • Windows
  • Linux (Ubuntu/Debian)

To trigger a release:

  1. Go to the Actions tab in GitHub.
  2. Select the Release Desktop App workflow.
  3. Click Run workflow and choose the version bump type (patch, minor, major).
  4. The action will automatically bump the version, commit, tag, and build the binaries before publishing them to the GitHub Releases page!

(back to top)

Workspace Structure

This project uses npm workspaces to manage dependencies across multiple packages.

Package / App Location Description
apps-tracker apps/tracker Read-only monitoring dashboard + API server (React Router v8). Handles OAuth, sessions, and the extension REST API.
@basetrack/desktop apps/desktop Tauri v2 Desktop Companion App with an always-on-top transparent UI.
@basetrack/ws apps/ws Standalone WebSocket Server for real-time timer sync across web and desktop.
@basetrack/cron apps/cron Background Node.js worker. Checks for orphaned timers and marks them for manual approval.
@basetrack/db packages/db Shared Prisma ORM layer. Contains schema.prisma, migrations, and generated client.

(back to top)

Clients

Timers are started and stopped by clients, never by the tracker dashboard. The tracker is read-only: it monitors and syncs.

Client How it starts timers
Browser extension (apps/extension) REST /api/ext/timer/{start,stop} — Basecamp, Google Calendar/Docs/Sheets/Slides, GitHub Projects
Desktop app (apps/desktop) WebSocket START_TIMER / STOP_TIMER using the personal API key
Cron (apps/cron) Auto-stop rules → NEEDS_APPROVAL entries you approve in the dashboard

To build a new client, use the extension REST API (see extension.authorize + /api/ext/*) or connect to the timer WebSocket and authenticate with the personal API key shown on the dashboard's Clients page.

(back to top)

Contributing

Bug reports and feature requests are welcome. For code changes:

npm install                 # root dev tooling
npm run lint -w apps-tracker # type-aware lint across the tracker app
npm run typecheck -w apps-tracker # tsc --noEmit

Keep pull requests scoped to one change, and make sure lint and typecheck pass before submitting.

(back to top)

About

Seamless time tracking for Basecamp. Never lose track of your hours. Automatically sync your time to Basecamp with a unified, flow-oriented dashboard.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages