Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
4493b31
docs: add Discord community invitation link to README and CONTRIBUTIN…
Harxhit May 17, 2026
c11b701
feat: add copy profile link button (#120)
amritbej May 18, 2026
e43ca72
fix: use randomBytes() instead of Math.random() for OAuth state gener…
MehtabSandhu11 May 18, 2026
3b4a027
fix: pass JWT via URL fragment instead of query param in mobile redir…
MehtabSandhu11 May 18, 2026
8cea9f5
feat: add themed custom scrollbar (#169)
smirk-dev May 19, 2026
7742c1a
Improve mobile UI/UX responsiveness and layout consistency (#129)
SMishra-27 May 19, 2026
d6afc79
fix(backend): add and configure ESLint for backend workspace (#150)
Harxhit May 19, 2026
63bddb2
Revert "fix(backend): add and configure ESLint for backend workspace …
ShantKhatri May 19, 2026
2108d70
fix: improve mobile layout for features section (#184)
nazneen-p1 May 20, 2026
acaf43d
fix(follow): use boolean flag instead of reply.statusCode for success…
MehtabSandhu11 May 20, 2026
58cdf89
feat(events): add event creation, attendee management, and public eve…
Harxhit May 20, 2026
3b9e458
chore: add typed Fastify augmentation and global error handler utilit…
Harxhit May 20, 2026
85c9551
fix(backend): add and configure ESLint for backend workspace (#181)
Harxhit May 20, 2026
96ea639
feat: hybrid follow engine — LinkedIn WebView interaction, session ma…
Itzzavdheshh May 21, 2026
fc745d2
implement rate limiting for public profile endpoints (#72)
parthpatidar03 May 21, 2026
da4d4e2
Feat/nfc payload endpoint (#189)
Midoriya-w May 21, 2026
f414719
fix(connect): add missing randomBytes import and rename parseGoogleSt…
MehtabSandhu11 May 21, 2026
0b03d68
pnpm-lock file added (#220)
ShantKhatri May 21, 2026
677ac41
fix(auth): encrypt OAuth tokens using encryption utility directly (#144)
Ridanshi May 21, 2026
89d1caa
fix(auth): validate OAuth state cookie to prevent CSRF attacks (#171)
MehtabSandhu11 May 22, 2026
fb55f15
fix: resolve ESLint issues in apps/backend/src/routes/cards.ts (#228)
anuragbraveboy-sudo May 23, 2026
11e279f
Add mobile loading skeletons and empty states (#138)
jamunatg2006-sys May 23, 2026
407718d
fix(cards): verify linkIds belong to authenticated user before creati…
MehtabSandhu11 May 23, 2026
e291637
backend: add typing and test for /health endpoint (#77)
nazneen-p1 May 23, 2026
410b7c3
feat: improve card UI in light mode with better shadows and spacing (…
nazneen-p1 May 23, 2026
d3ecbef
feat: add context-card diffing utility and validation layer (#167)
Midoriya-w May 23, 2026
9ab996d
fix: standardize error handling in follow route (#205)
pari7maheshwari May 23, 2026
e49ad0d
fix: improve error handling in public.ts (#209)
SMishra-27 May 23, 2026
af0b2a8
fix: improve copy toast rendering and timeout handling (#213)
Dhrupad-05 May 23, 2026
a66cd6c
fix(events): use relative route paths to match Fastify prefix registr…
Ridanshi May 23, 2026
561cfc5
fix(connect): validate platform param in disconnect route + prior cle…
Srejoye May 23, 2026
464db62
fix(events): use _count for correct attendees pagination total (#236)
Srejoye May 23, 2026
df4e5c6
docs: add secret generation guidance to .env.example and README (#207…
Sweksha-Kakkar May 23, 2026
c41ef95
fix: improve devcard scrolling behavior (#258)
Bhavikapatel06 May 23, 2026
7a6655f
Update README with contributors and project support (#260)
RehanAhmad25 May 23, 2026
a937047
Implement mobile responsiveness, performance, accessibility, SEO impr…
silentguyracer May 23, 2026
8f92fa0
fix(public): validate QR size bounds to prevent unauthenticated DoS (…
Ridanshi May 23, 2026
ed63811
fix(auth): guard /dev-login endpoint behind NODE_ENV !== productionTh…
MehtabSandhu11 May 23, 2026
0d43ebc
fix(connect): validate OAuth state nonce via Redis to prevent CSRFThe…
MehtabSandhu11 May 23, 2026
c122569
fix: resolve implicit any in event attendees mapping (#214)
pari7maheshwari May 23, 2026
04f0973
fix: replace hardcoded localhost URL with BACKEND_URL env var in devc…
anshul23102 May 23, 2026
fe788d7
Fix: Platform-specific username validation & Unhandled backend except…
mramansayyad May 23, 2026
ab4e523
fix(profiles): handle Prisma P2002 on concurrent username claims (#271)
Ridanshi May 23, 2026
d4c2635
fix(backend): automatically handle default card reassignment on card …
mramansayyad May 23, 2026
356d65a
fix(security): fail fast when JWT_SECRET is absent or insecure (close…
Ridanshi May 23, 2026
b27c2af
fix(cards): validate platformLink ownership before creating card link…
Ridanshi May 23, 2026
f287331
fix: linting issues on app.ts. (#315)
Harxhit May 24, 2026
974965c
fix: encode dynamic URL parameters in NFC payload generation (#304)
Midoriya-w May 24, 2026
60b1106
fix: improve light mode panel consistency (#336)
sahilsultane May 26, 2026
8421d23
Fix/follow log analytics poisoning (#337)
Ridanshi May 27, 2026
6a1c6a2
fix: remove unauthenticated public upload access (#350)
Midoriya-w May 27, 2026
10f47b9
feat: add centralized authenticated API request handler for mobile (#…
Midoriya-w May 27, 2026
f4213b6
feat: add centralized API request abstraction for web frontend (#339)
Midoriya-w May 27, 2026
3ae414a
fix(cards): improve typing, transaction safety, and resolve lint issu…
Harxhit May 27, 2026
af5c829
fix(analytic): resolve analytics lint issues, add route generics, and…
Harxhit May 27, 2026
31bdf09
build analytics dashboard page at /devcard/analytics (#73)
parthpatidar03 May 28, 2026
4ce5978
Revert "build analytics dashboard page at /devcard/analytics (#73)" (…
ShantKhatri May 28, 2026
13f70aa
fix(security): authenticate connect callback and replace Math.random …
anshul23102 May 28, 2026
9e59814
fix: feature cards visibility in light mode (#206) (#267)
Kartikeyji17 May 28, 2026
575fbb9
fix(oauth): isolate follow token from auth token to prevent scope ove…
Ridanshi May 28, 2026
92d4620
fix(auth): replace console.log with structured logging to prevent sta…
hariom888 May 28, 2026
29324d2
fix(public): merge duplicate nested route registrations in publicRout…
MehtabSandhu11 May 28, 2026
f1d37b5
feat: implement team routes and membership management (#314)
Harxhit May 28, 2026
4c7437f
refactor: standardize catch block error naming (#366)
garimatiwari1912-alt May 28, 2026
94593d6
feat(workflow): add workflow to unassign inactive issue assignees (#341)
Harxhit May 28, 2026
ab0ab6a
fix: wrap card delete in transaction with count guard and default pro…
anshul23102 May 28, 2026
b520391
feat: Redis profile cache and offline QR session tokens (Dev-Card#46)…
amritbej May 28, 2026
e2c6f88
test(shared): add unit tests for getProfileUrl, getWebViewUrl, getDee…
amritbej May 28, 2026
0dd15fe
feat: done mass cleanup and reafctoring (#383)
ShantKhatri May 29, 2026
42ee1ac
feat(workflows): add first-time contributor welcome workflow and fix …
Harxhit May 29, 2026
02320c0
fix(workflow): add 5-day assignment check and protected assignee hand…
Harxhit May 29, 2026
1b66bad
refactor (#369)
roshankumar0036singh May 30, 2026
67133ee
feat: implement API service layer and refactor network requests acros…
ShantKhatri May 30, 2026
be7a7c2
chore: update dependencies and switch start script from expo to react…
ShantKhatri May 30, 2026
453b52c
feat: add Contacts and Teams modules with associated screens, hooks, …
ShantKhatri May 30, 2026
5744efe
chore: updated package-lock.yaml (#416)
ShantKhatri May 30, 2026
67976d2
fix: update NFC payload URL to use environment variable (#417)
roshankumar0036singh May 30, 2026
6bb38e6
fix: add cascade delete for TeamMember when Team is deleted (#422)
Pcmhacker-piro May 31, 2026
5a082eb
Fix first time issue creator workflow trigger (#425)
roshankumar0036singh May 31, 2026
82a70f1
feat(workflow): add merged PR discord reminder for GSSoC labels (#409)
Harxhit May 31, 2026
c535f20
feat: add CI pipeline with lint, typecheck, test, and PR title enforc…
Midoriya-w Jun 1, 2026
f6ee844
fix: wrap card creation in transaction to prevent race condition (#349)
Midoriya-w Jun 1, 2026
5a5ebba
Revert "feat: add CI pipeline with lint, typecheck, test, and PR titl…
ShantKhatri Jun 1, 2026
55d7d56
feat(ci): add selective backend/web/mobile checks with PR comments (#…
Harxhit Jun 1, 2026
1833d1f
Revert "fix: wrap card creation in transaction to prevent race condit…
Harxhit Jun 1, 2026
ff3da15
fix(ci): improve selective checks and detailed PR comment reporting (…
Harxhit Jun 1, 2026
176a2bc
fix(ci): refine workflow execution, reporting, and collaborator handl…
Harxhit Jun 1, 2026
c5f3cc2
fix(ci): expose backendTests output and improve smart test execution …
Harxhit Jun 1, 2026
b7d307b
fix(event): replace organizerId with organizer public fields in GET /…
anshul23102 Jun 2, 2026
01e038d
fix(workflow): use pull_request_target for discord reminder workflow …
Harxhit Jun 2, 2026
4ebb949
fix(analytics): count inbound follows instead of outbound in totalFol…
Srejoye Jun 2, 2026
7762fa2
Feat/oauth rate limiting (#446)
roshankumar0036singh Jun 3, 2026
5fd5d98
Revert "Feat/oauth rate limiting (#446)" (#461)
Harxhit Jun 3, 2026
60304ae
refactor: migrate web app from SvelteKit to React with new component …
ShantKhatri Jun 3, 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
9 changes: 8 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ DATABASE_URL=postgresql://devcard:devcard@localhost:5432/devcard?schema=public
# ─── Redis ───
REDIS_URL=redis://localhost:6379

# ─── Set The Url ───
PUBLIC_APP_URL=

# ─── JWT ───
# JWT_SECRET: any long random string, minimum 32 characters
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
JWT_SECRET=your-super-secret-jwt-key-change-in-production

# ─── Encryption (for OAuth tokens) ───
# ENCRYPTION_KEY: must be exactly 32 bytes = 64 hex characters
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=your-32-byte-hex-encryption-key-here

# ─── GitHub OAuth ───
Expand All @@ -25,4 +32,4 @@ MOBILE_REDIRECT_URI=devcard://oauth/callback

# ─── Server ───
PORT=3000
NODE_ENV=development
NODE_ENV=development
101 changes: 101 additions & 0 deletions .github/scripts/ciScript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module.exports = async ({ github, context, core }) => {
const owner = context.repo.owner;
const repo = context.repo.repo;
const pr = context.payload.pull_request;
const prNumber = pr.number;
const prState = pr.state;

const backendFiles = [];
const backendTests = [];
const mobileFiles = [];
const webFiles = [];

try {
if (prState === 'closed') {
console.log(`PR state is: ${prState}`);
return {
backendChanged: false,
mobileChanged: false,
webChanged: false
};
}

const changedFiles = await github.paginate(
github.rest.pulls.listFiles,
{
owner,
repo,
pull_number: prNumber
}
);

changedFiles.forEach((file) => {
const fileName = file.filename;

if (fileName.startsWith('apps/backend/')) {
backendFiles.push(fileName);

const relative = fileName.replace('apps/backend/src/', '');
const baseName = relative
.split('/')
.pop()
?.replace(/\.(ts|tsx|js|jsx)$/, '');

if (baseName) {
backendTests.push(`src/__tests__/${baseName}.test.ts`);
}

} else if (fileName.startsWith('apps/mobile/')) {
mobileFiles.push(fileName);
} else if (fileName.startsWith('apps/web/')) {
webFiles.push(fileName);
}
});

console.log({
backendFiles,
backendTests,
mobileFiles,
webFiles,
});

core.setOutput(
"backendFiles",
backendFiles
.map(file => file.replace("apps/backend/", ""))
.join(" ")
);

core.setOutput(
"backendTests",
[...new Set(backendTests)].join(" ")
);

core.setOutput(
"mobileFiles",
mobileFiles
.map(file => file.replace("apps/mobile/", ""))
.join(" ")
);

core.setOutput(
"webFiles",
webFiles
.map(file => file.replace("apps/web/", ""))
.join(" ")
);

core.setOutput("backendChanged", backendFiles.length > 0);
core.setOutput("mobileChanged", mobileFiles.length > 0);
core.setOutput("webChanged", webFiles.length > 0);

} catch (error) {
console.error(error);

return {
backendChanged: false,
mobileChanged: false,
webChanged: false
};
}
};
101 changes: 101 additions & 0 deletions .github/scripts/commentResults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module.exports = async ({
github,
context,
backend,
mobile,
web,
backendLint,
backendTest,
backendTypecheck,
mobileLint,
mobileTest,
webCheck,
webBuild
}) => {
const owner = context.repo.owner;
const repo = context.repo.repo;
const prNumber = context.payload.pull_request.number;

const emoji = (status) => {
if (status === 'success') return '✅';
if (status === 'failure') return '❌';
if (status === 'skipped') return '⏭️';
return '⚪';
};

const label = (status) => {
if (!status) return '⚪ unknown';
return `${emoji(status)} ${status}`;
};

const anyFailure = [
backend,
mobile,
web
].includes('failure');

const title = anyFailure
? '❌ Some checks failed'
: '✅ CI completed';

const timestamp = new Date().toUTCString();

const body = `## CI Results — ${title}

### 🖥️ Backend (${label(backend)})
| Check | Status |
|---|---|
| Lint | ${label(backendLint)} |
| Test | ${label(backendTest)} |
| Typecheck | ${label(backendTypecheck)} |

### 📱 Mobile (${label(mobile)})
| Check | Status |
|---|---|
| Lint | ${label(mobileLint)} |
| Test | ${label(mobileTest)} |

### 🌐 Web (${label(web)})
| Check | Status |
|---|---|
| Check | ${label(webCheck)} |
| Build | ${label(webBuild)} |

---
🕐 Last updated: \`${timestamp}\``;

const COMMENT_MARKER = '## CI Results —';

try {
const comments = await github.paginate(
github.rest.issues.listComments,
{
owner,
repo,
issue_number: prNumber
}
);

const existing = comments.find(
c => c.body && c.body.startsWith(COMMENT_MARKER)
);

if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body
});
}
} catch (err) {
console.error(err);
}
};
37 changes: 37 additions & 0 deletions .github/scripts/discordPinReminder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module.exports = async ({ github, context }) => {
const pr = context.payload.pull_request;
const ignoreUsers = [
'ShantKhatri',
'Harxhit',
'blankirigaya'
]
try {
// Only continue if merged
if (!pr || !pr.merged) {
console.log('PR not merged.');
return;
}

const prNumber = pr.number;
const contributor = pr.user.login;

if(ignoreUsers.includes(contributor)){
console.log(`Ignoring PR #${prNumber} by ${contributor}`);
return;
}

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `Congratulations @${contributor} on getting PR #${prNumber} merged!

Thank you for your contribution. Please mention @Harxhit in our Discord server to receive the appropriate GSSoC labels and recognition.
`
});

console.log(`Comment added to PR #${prNumber}`);
} catch (error) {
console.error(error)
}
};
Loading
Loading