Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
302899c
fix: improve AccountToggle active tab visibility in light mode
MaitrayeeK May 26, 2026
84f0116
fix: persist unread notification count across refreshes (#1116)
seffhunnn May 27, 2026
2404cab
fix: improve sign out button theme contrast (#1120)
seffhunnn May 27, 2026
9ebbb46
added repo list new UI (#1122)
indresh404 May 27, 2026
c44279d
feat: add back to dashboard link on settings page (#1135)
shakshi127 May 27, 2026
5448760
Fix/refresh loading state (#1141)
patelnitya54 May 27, 2026
a1fe5ab
test: add unit tests for scoreAvgPrOpenTimeHours function (#1169)
bhavyanjain3004 May 27, 2026
48b803c
Add .editorconfig for consistent coding styles (#1212)
bashyamharika May 27, 2026
da1be17
#1216 Fix hydration mismatch issue in AIMentorWidget (#1218)
karansankrit01 May 27, 2026
3d7c2a6
fix: disable streak freeze button after activation (#1196)
sanzzzz-g May 27, 2026
b3bddb1
Fix undefined language badge for repos without detected language (#1232)
Akankshya-35-45 May 27, 2026
0cadbc8
fix(theme): correct theme toggle text inversion and match transition …
Logesh-Pro May 27, 2026
168bd35
feat(activity): add DiscussionEvent and DiscussionCommentEvent suppor…
mallya-m May 27, 2026
749eeb1
fix: make public profile lookup case-insensitive (#1200)
sanzzzz-g May 27, 2026
a1193d8
fix: use unified metrics cache in compare endpoint (#811) (#1219)
Vaibhavi-14shetty May 27, 2026
0b42b50
feat: enhance ParticleBackground with mouse attract, shooting stars, …
Shweta-nasc May 27, 2026
fabafd1
refactor: extract formatActivity and add tests (#1220)
manisha2008-creator May 27, 2026
45d8822
fix(theme): fix theme toggle icon flicker using useSafeLayoutEffect (…
seffhunnn May 27, 2026
341b8c2
fix: defer Vercel analytics loading (#1199)
gitsofyash May 27, 2026
d75c265
fix: correct sign-in container alignment and footer dark theme render…
Niteshagarwal01 May 27, 2026
4e5e3c4
feat(toprepos): add client-side search filter to Repos widget (#965) …
mallya-m May 27, 2026
30e461c
feat: complete WakaTime integration (#1191)
VIDYANKSHINI May 27, 2026
96ad300
fix: resolve merge conflict in package.json (lucide-react version)
Priyanshu-byte-coder May 27, 2026
e36e5f5
fix: resolve duplicate formatActivity import and package-lock.json co…
Priyanshu-byte-coder May 27, 2026
b0da05e
chore: trigger Vercel deployment for e36e5f5 fix commit
Priyanshu-byte-coder May 27, 2026
078a215
chore: normalize vercel.json trailing newline
Priyanshu-byte-coder May 27, 2026
a0b8d90
chore: normalize vercel.json trailing newline (#1256)
Priyanshu-byte-coder May 27, 2026
dd28de7
fix: change goals/sync cron to daily for Hobby plan compatibility
Priyanshu-byte-coder May 27, 2026
57f4560
Merge branch 'chore/trigger-vercel-deploy'
Priyanshu-byte-coder May 27, 2026
d65bc88
feat: add external github indicator to top repositories (#1187)
SARTHAKJINDAL1 May 27, 2026
51060d7
fix: Improve pin repository tooltip clarity in Top Repositories (#1198)
SARTHAKJINDAL1 May 27, 2026
0c4dfde
feat: add GitHub Sponsors integration
Priyanshu-byte-coder May 27, 2026
3ffa80a
fix: improve AccountToggle active tab visibility in light mode
MaitrayeeK May 26, 2026
2f61f16
Merge branch 'fix/tab-active-indicator' of https://github.com/Maitray…
MaitrayeeK May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: Priyanshu-byte-coder
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ jobs:
run: npm ci

- name: Install Playwright browsers
run: npx -y @playwright/test@1.49.1 install --with-deps chromium
run: npx playwright install --with-deps chromium

- name: Run Playwright tests
run: npx -y @playwright/test@1.49.1 test
run: npx playwright test

- name: Upload Playwright report
uses: actions/upload-artifact@v4
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ Thumbs.db
desktop.ini

test-results/

.vercel
.env*
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
[![Contributors](https://img.shields.io/github/contributors/Priyanshu-byte-coder/devtrack?color=brightgreen)](https://github.com/Priyanshu-byte-coder/devtrack/graphs/contributors)
[![Last Commit](https://img.shields.io/github/last-commit/Priyanshu-byte-coder/devtrack)](https://github.com/Priyanshu-byte-coder/devtrack/commits/main)
[![Open Issues](https://img.shields.io/github/issues/Priyanshu-byte-coder/devtrack)](https://github.com/Priyanshu-byte-coder/devtrack/issues)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/Priyanshu-byte-coder?label=sponsors&color=ea4aaa)](https://github.com/sponsors/Priyanshu-byte-coder)

**[🌐 Live Demo](https://devtrack-delta.vercel.app)** · **[📖 Dev Guide](./DEVELOPMENT.md)** · **[🐛 Report Bug](https://github.com/Priyanshu-byte-coder/devtrack/issues/new?template=bug_report.md)** · **[✨ Request Feature](https://github.com/Priyanshu-byte-coder/devtrack/issues/new?template=feature_request.md)**
**[🌐 Live Demo](https://devtrack-delta.vercel.app)** · **[📖 Dev Guide](./DEVELOPMENT.md)** · **[🐛 Report Bug](https://github.com/Priyanshu-byte-coder/devtrack/issues/new?template=bug_report.md)** · **[✨ Request Feature](https://github.com/Priyanshu-byte-coder/devtrack/issues/new?template=feature_request.md)** · **[💖 Sponsor](https://github.com/sponsors/Priyanshu-byte-coder)**

</div>

Expand All @@ -33,6 +34,7 @@
- [Getting Started](#-getting-started)
- [Roadmap](#-roadmap)
- [Contributing](#-contributing)
- [Sponsors](#-sponsors)
- [License](#-license)

---
Expand Down Expand Up @@ -240,6 +242,21 @@ See **[CONTRIBUTING.md](./CONTRIBUTING.md)** for full guidelines, commit style,

---

## 💖 Sponsors

DevTrack is free and open source. Sponsoring helps cover infrastructure costs (Supabase, Vercel, API usage) and lets me dedicate more time to new features.

| Tier | Amount | Perks |
|------|--------|-------|
| ☕ Coffee | $5 / mo | Your name in this README |
| 🎯 Backer | $15 / mo | Name + priority response on issues |
| 🏆 Champion | $50 / mo | Name + logo in README + feature request priority |
| 💝 One-time | $10+ | One-time thanks, no recurring commitment |

**[→ Sponsor DevTrack on GitHub](https://github.com/sponsors/Priyanshu-byte-coder)**

---

## 📄 License

MIT — see [LICENSE](./LICENSE) for details.
Expand Down
42 changes: 42 additions & 0 deletions e2e/dashboard-widgets.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ test.beforeEach(async ({ page }) => {
"**/api/metrics/pr-review-trend**",
"**/api/metrics/inactive-repos**",
"**/api/notifications**",
"**/api/local-coding/stats**",
"**/api/metrics/coding-time**",
"**/api/metrics/coding-activity-insights**",
];

for (const pattern of metricRoutes) {
Expand All @@ -182,6 +185,15 @@ for (const pattern of metricRoutes) {
});
}

await page.route("**/api/stream**", async (route) => {
await route.fulfill({
status: 200,
contentType: "text/event-stream",
body: "data: {}\n\n",
});
});


});
test("dashboard widgets render with mocked metrics", async ({ page }) => {
await page.goto("/dashboard", { waitUntil: "load" });
Expand Down Expand Up @@ -293,5 +305,35 @@ function mockMetricResponse(url) {
if (url.includes("/api/user/github-accounts")) {
return { accounts: [] };
}
if (url.includes("/api/local-coding/stats")) {
return {
dailyData: [],
totals: { totalSeconds: 0, totalDays: 0, avgSecondsPerDay: 0 },
hasData: false,
};
}
if (url.includes("/api/metrics/coding-time")) {
return {
hasData: false,
not_configured: true,
todaysSeconds: 0,
totalSeconds7Days: 0,
chartData: [],
topLanguage: "",
topProject: "",
};
}
if (url.includes("/api/metrics/coding-activity-insights")) {
return {
hourlyCounts: [],
mostActiveHour: { hour: 0, count: 0, label: "" },
leastActiveHour: { hour: 0, count: 0, label: "" },
totalActivities: 0,
averageDailyCommits: 0,
consistencyScore: 0,
productivityLevel: "Low",
timezone: "UTC",
};
}
return {};
}
2 changes: 0 additions & 2 deletions e2e/landing.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ test("landing page shows dashboard link", async ({ page }) => {
test("landing shows footer", async ({ page }) => {
await page.goto("/");


await expect(page.getByRole("contentinfo").first()).toBeVisible();
});


1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions src/app/api/metrics/activity/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ import {
} from "@/lib/metrics-cache";
import { supabaseAdmin } from "@/lib/supabase";
import { resolveAppUser } from "@/lib/resolve-user";

export const dynamic = "force-dynamic";

import {
type ActivityItem,
type RawEvent,
formatActivity,
} from "@/lib/activity-formatter";

export const dynamic = "force-dynamic";


async function fetchFormattedActivity(token: string): Promise<ActivityItem[]> {
const events = (await fetchUserEvents(token)) as RawEvent[];
Expand Down
100 changes: 0 additions & 100 deletions src/app/api/metrics/coding-time/route.ts

This file was deleted.

63 changes: 54 additions & 9 deletions src/app/api/metrics/compare/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { authOptions } from "@/lib/auth";
import { dateDiffDays, toDateStr } from "@/lib/dateUtils";
import { normalizeGitHubUsername } from "@/lib/validate-github-username";

import {
isMetricsCacheBypassed,
METRICS_CACHE_TTL_SECONDS,
metricsCacheKey,
withMetricsCache,
} from "@/lib/metrics-cache";

export const dynamic = "force-dynamic";

const GITHUB_API = "https://api.github.com";
Expand Down Expand Up @@ -34,6 +41,24 @@ export async function GET(req: NextRequest) {
}

const encodedUsername = encodeURIComponent(normalizedUsername);
const bypass = isMetricsCacheBypassed(req);
const cacheKey = metricsCacheKey(
session.githubId ?? session.githubLogin,
"compare",
{
username: normalizedUsername,
}
);

try {
const data = await withMetricsCache(
{
bypass,
key: cacheKey,
ttlSeconds: METRICS_CACHE_TTL_SECONDS.compare,
},
async () => {


// 1. Verify user exists
const userRes = await fetch(`${GITHUB_API}/users/${encodedUsername}`, {
Expand All @@ -42,10 +67,13 @@ export async function GET(req: NextRequest) {
});

if (!userRes.ok) {
if (userRes.status === 404) return Response.json({ error: "User not found" }, { status: 404 });
return Response.json({ error: "GitHub API error or User is private" }, { status: 502 });
if (userRes.status === 404) {
throw new Error("User not found");
}

throw new Error("GitHub API error or User is private");
}

// 2. Commits & Streak (fetch 90 days)
const since90 = new Date();
since90.setDate(since90.getDate() - 90);
Expand Down Expand Up @@ -149,11 +177,28 @@ export async function GET(req: NextRequest) {
prs = prsData.total_count || 0;
}

return Response.json({
username: normalizedUsername,
streak,
commits30d,
topLanguage,
prs
});
return {
username: normalizedUsername,
streak,
commits30d,
topLanguage,
prs,
};
}
);

return Response.json(data);
} catch (error) {
if (error instanceof Error && error.message === "User not found") {
return Response.json(
{ error: "User not found" },
{ status: 404 }
);
}

return Response.json(
{ error: "GitHub API error or User is private" },
{ status: 502 }
);
}
}
Loading
Loading