Skip to content

Latest commit

 

History

History
297 lines (241 loc) · 11.2 KB

File metadata and controls

297 lines (241 loc) · 11.2 KB

Development Guide

Everything you need to run DevTrack locally from scratch in under 10 minutes.


Prerequisites

Tool Version Check
Node.js >= 18 node -v
npm >= 9 npm -v
Git any git --version

You also need free accounts on:

  • Supabase — for the database
  • GitHub — for OAuth (you already have this)

1. Clone and install

git clone https://github.com/Priyanshu-byte-coder/devtrack.git
cd devtrack
npm install

2. Set up Supabase

  1. Go to supabase.comNew Project
  2. Pick a name, region, and database password — save the password somewhere
  3. Wait ~1 minute for project to provision
  4. Go to SQL EditorNew Query
  5. Paste the full contents of supabase/schema.sql and click Run
  6. Go to Project Settings → API and copy three values:
    • Project URLNEXT_PUBLIC_SUPABASE_URL
    • anon / public key → NEXT_PUBLIC_SUPABASE_ANON_KEY
    • service_role secret → SUPABASE_SERVICE_ROLE_KEY

The service_role key has admin access. Never expose it client-side. DevTrack uses it only in server-side API routes.


3. Create a GitHub OAuth App

  1. Go to github.com/settings/applications/new
  2. Fill in:
    • Application name: DevTrack (local)
    • Homepage URL: http://localhost:3000
    • Authorization callback URL: http://localhost:3000/api/auth/callback/github
  3. Click Register application
  4. Copy Client IDGITHUB_ID
  5. Click Generate a new client secret → copy it → GITHUB_SECRET

4. Configure environment

cp .env.example .env.local

Open .env.local and fill in all values:

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxxxxxxxxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...

# NextAuth
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=generate_with_openssl_rand_base64_32

# GitHub OAuth
GITHUB_ID=Ov23...
GITHUB_SECRET=your_github_client_secret

Generate NEXTAUTH_SECRET:

# macOS / Linux
openssl rand -base64 32

# Windows PowerShell
[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))

5. Run the dev server

npm run dev

Open http://localhost:3000. Click Sign in with GitHub.


Project Structure

src/
├── app/
│   ├── api/
│   │   ├── auth/
│   │   │   ├── [...nextauth]/        # GitHub OAuth via NextAuth
│   │   │   └── link-github/          # Link additional GitHub accounts
│   │   │       └── callback/
│   │   ├── badge/
│   │   │   ├── badge-utils.ts        # Shared badge helpers
│   │   │   ├── commits/              # GET commit-count badge
│   │   │   └── streak-shield/        # GET streak shield (shields.io)
│   │   ├── goals/
│   │   │   ├── route.ts              # GET + POST /api/goals
│   │   │   └── [id]/route.ts         # DELETE /api/goals/:id
│   │   ├── leaderboard/route.ts      # GET public leaderboard data
│   │   ├── metrics/
│   │   │   ├── ci/                   # GET CI build analytics
│   │   │   ├── compare/              # GET side-by-side user comparison
│   │   │   ├── contributions/        # GET /api/metrics/contributions?days=30
│   │   │   ├── issues/               # GET issue open/close metrics
│   │   │   ├── languages/            # GET language breakdown
│   │   │   ├── pinned-repos/         # GET pinned repositories
│   │   │   ├── pr-breakdown/         # GET PR open/merged/closed counts
│   │   │   ├── pr-review-time/       # GET PR review time trend
│   │   │   ├── prs/                  # GET /api/metrics/prs
│   │   │   ├── repo-health/          # GET repository health score
│   │   │   ├── repos/                # GET /api/metrics/repos?days=30
│   │   │   ├── streak/               # GET /api/metrics/streak
│   │   │   └── weekly-summary/       # GET weekly activity digest
│   │   ├── public/[username]/        # GET public profile data
│   │   ├── streak/
│   │   │   └── freeze/route.ts       # POST streak freeze
│   │   ├── user/
│   │   │   ├── github-accounts/      # GET + POST linked accounts
│   │   │   │   └── [githubId]/       # DELETE a linked account
│   │   │   └── settings/route.ts     # GET + PATCH user settings
│   │   └── webhooks/github/route.ts  # GitHub push webhook receiver
│   ├── dashboard/
│   │   ├── page.tsx                  # Dashboard layout — add new widgets here
│   │   └── settings/page.tsx         # User settings page
│   ├── leaderboard/page.tsx          # Public leaderboard page
│   ├── u/[username]/page.tsx         # Public profile page
│   ├── error.tsx                     # Global error boundary
│   ├── layout.tsx                    # Root layout
│   ├── not-found.tsx                 # 404 page
│   ├── page.tsx                      # Landing page
│   └── providers.tsx                 # Session + theme providers
├── components/
│   ├── AccountContext.tsx            # Multi-account state context
│   ├── AccountToggle.tsx             # Switch between linked accounts
│   ├── BackToTopButton.tsx           # Scroll-to-top button
│   ├── BadgeSection.tsx              # Embeddable badge display
│   ├── CIAnalytics.tsx               # CI build success/failure chart
│   ├── CommitTimeChart.tsx           # Commits by hour-of-day bar chart
│   ├── ContributionGraph.tsx         # Bar chart with time range selector
│   ├── ContributionHeatmap.tsx       # GitHub-style activity heatmap
│   ├── CopyLinkButton.tsx            # Copy-to-clipboard helper
│   ├── DashboardHeader.tsx           # Top bar with user avatar + sign out
│   ├── ExportButton.tsx              # Export metrics to PDF
│   ├── FriendComparison.tsx          # Side-by-side user comparison
│   ├── GoalTracker.tsx               # Weekly goals progress bars
│   ├── IssueMetrics.tsx              # Issue open/close stats
│   ├── KeyboardShortcuts.tsx         # Global keyboard shortcut handler
│   ├── LanguageBreakdown.tsx         # Language usage breakdown chart
│   ├── PRBreakdownChart.tsx          # PR status pie chart
│   ├── PRMetrics.tsx                 # PR stats card grid
│   ├── PRReviewTrendChart.tsx        # PR review time trend line chart
│   ├── PRStatusDonutChart.tsx        # PR open/merged/closed donut
│   ├── PersonalRecords.tsx           # All-time personal bests widget
│   ├── PinnedRepos.tsx               # User's pinned repositories list
│   ├── ShortcutsModal.tsx            # Keyboard shortcuts reference modal
│   ├── SignOutButton.tsx             # Sign-out button
│   ├── StatsCard.tsx                 # Shareable stats card (PNG export)
│   ├── StreakAtRiskBanner.tsx        # Warning banner when streak is at risk
│   ├── StreakTracker.tsx             # Current + longest commit streak
│   ├── ThemeContext.tsx              # Light/dark theme context
│   ├── ThemeToggle.tsx               # Light/dark mode toggle button
│   ├── TopRepos.tsx                  # Most active repos ranked list
│   ├── UserAvatar.tsx                # User avatar image
│   └── WeeklySummaryCard.tsx         # Weekly activity digest card
├── hooks/
│   ├── useCountUp.ts                 # Animated number count-up hook
│   └── useHeatmapTheme.ts            # Heatmap colour theme hook
├── lib/
│   ├── auth.ts                       # NextAuth config, GitHub scopes, Supabase upsert
│   ├── crypto.ts                     # HMAC/signature utilities
│   ├── dateUtils.ts                  # Shared date helpers
│   ├── github-accounts.ts            # Multi-account GitHub API helpers
│   ├── github.ts                     # GitHub REST API client
│   ├── metrics-cache.ts              # Server-side metrics cache layer
│   ├── repo-health.ts                # Repository health score logic
│   ├── resolve-user.ts               # Resolve session to Supabase user
│   └── supabase.ts                   # Supabase admin client (server-only)
├── middleware.ts                     # Auth middleware (route protection)
└── types/
    ├── next-auth.d.ts                # NextAuth session type extensions
    └── repo-health.ts                # RepoHealth type definitions
supabase/
└── schema.sql                        # DB schema — run once in Supabase SQL Editor

How data flows

Browser → Next.js API route → GitHub API (with user's OAuth token)
                           → Supabase (for goals, user records)

All GitHub API calls use the signed-in user's OAuth token — stored in the session via NextAuth. No shared API key.


Available scripts

Command What it does
npm run dev Start dev server at localhost:3000
npm run build Production build
npm run lint ESLint
npm run type-check TypeScript compiler check (no emit)

Run lint and type-check before pushing:

npm run lint && npm run type-check

Adding a new dashboard widget

  1. Create src/components/MyWidget.tsx — use "use client", fetch from your API route
  2. Create src/app/api/metrics/my-widget/route.ts — add export const dynamic = "force-dynamic", guard with getServerSession
  3. Import and place in src/app/dashboard/page.tsx

Pattern for an API route:

import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";

export const dynamic = "force-dynamic";

export async function GET() {
  const session = await getServerSession(authOptions);
  if (!session?.accessToken) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }
  // fetch from GitHub API using session.accessToken
  // fetch from Supabase using session.githubId
}

Common errors

NEXTAUTH_SECRET missing

[next-auth][error][NO_SECRET]

Add NEXTAUTH_SECRET to .env.local.


GitHub OAuth callback mismatch

The redirect_uri is not associated with this application

Ensure the Authorization callback URL in your GitHub OAuth App is exactly: http://localhost:3000/api/auth/callback/github


Supabase "relation does not exist"

relation "users" does not exist

You forgot to run supabase/schema.sql. Go to Supabase SQL Editor and run it.


GitHub API rate limit

{ "message": "API rate limit exceeded" }

You hit the 30 requests/minute search API limit. Wait 1 minute. In production this won't happen for normal usage.


Questions?

Open a GitHub Discussion — not an issue.