Create a central platform for the ShardUp community where members can:
- Discover people
- Showcase their work
- Access resources
- Participate in programs
- Stay engaged through community-driven interactions
Email-based Sign Up / Login with user roles:
- Member
- Admin
Future use cases:
- Event access control
- Hackathon registrations
- Mock interviews
- Exclusive resources
Each member gets a profile containing:
- Name
- Batch / Branch
- Skills
- Social Links
- Current Projects
- Achievements
Purpose:
- Help members discover and connect with builders in the community
- Make ongoing work visible
Community-curated repository of learning resources:
- Books
- Articles
- Courses
- Learning Resources
Categories:
- Development
- Competitive Programming
- AI/ML
- System Design
- Startups
- Productivity
Central archive for:
- Session Notes
- Workshop Materials
- Speaker Resources
- Recordings & References
Purpose:
- Preserve community knowledge
- Help new members onboard faster
Showcase:
- Internal competition winners
- Hackathon achievements
- Open-source contributions
- Community milestones
Purpose:
- Recognition and motivation
- Visibility for members
Members can challenge or nudge other members.
Examples:
- "Solve this LeetCode problem"
- "Complete this challenge"
- "Read this article"
Flow:
- User A sends a Nudge
- User B accepts
- On completion the nudge is removed and User B's solved count increments
Nudges are ephemeral: completing, declining, or cancelling a nudge deletes it. A global Nudge scoreboard in the nudges section ranks members by the number of nudges they have solved (completed as the recipient).
Purpose:
- Increase participation
- Create accountability
- Bring group-chat interactions onto the platform
Application form for:
- New Cohorts
- Recruitment Cycles
- Internal Programs
Admin Features:
- Review Applications
- Accept / Reject
- Track Status
Competitive Programming Portal:
- 1v1 Duels
- Mock Contests
- Leaderboards
- Challenge Creation
- Internal Rating System
Note: High development effort and not required for MVP validation.
The app uses Auth.js with Google OAuth, Prisma, and Postgres for the authentication and registration foundation.
1. Start a local Postgres (runs in Docker — requires Docker Desktop):
docker compose up -d # start Postgres on localhost:5432
docker compose down # stop it (data is preserved)
docker compose down -v # stop it and wipe all data2. Configure environment variables. Copy .env.example and fill it in:
DATABASE_URLgoes in.env(the Prisma CLI only reads.env).- Everything else (
AUTH_*,ADMIN_EMAILS,LOCAL_DEV_AUTH_ENABLED) goes in.env.local.
3. Create the schema and start the app:
npm run prisma:migrate # apply migrations to the local database
npm run devGoogle OAuth is the real sign-in method. Callback URLs:
- Local:
http://localhost:3000/api/auth/callback/google - Production:
https://YOUR_DOMAIN/api/auth/callback/google
For local development, Google credentials are optional. Set LOCAL_DEV_AUTH_ENABLED=true in .env.local and the /join page shows two development-only sign-ins:
- Continue as applicant (dev) — signs in as
applicant@shardup.localto test the application flow. This is a throwaway test account: it is reset toPENDINGwith a fresh blank application on every login, so you can re-run the flow repeatedly. - Continue as member (dev) — signs in as
member@shardup.local, an ACTIVE member used for chat and member-only feature testing. - Continue as admin (dev) — signs in as
admin@shardup.localto test application review. Make sureadmin@shardup.localis inADMIN_EMAILS.
npm run prisma:generatenpm run prisma:migratenpm run prisma:seednpm run prisma:studionpm run devnpm run chat:gatewaynpm run build
Messages are queued in PostgreSQL before realtime fan-out. Browsers persist delivered messages in
IndexedDB and then acknowledge them; the server removes each recipient delivery and deletes the
payload after the final acknowledgement. Offline messages expire after 30 days. Run the open-source
WebSocket gateway with npm run chat:gateway; Redis is not needed for a single gateway process.
See docs/chat-gateway.md for local and Oracle VM deployment.
Events are published manually for now. Seed sample events with npm run prisma:seed, or manage rows directly in Prisma Studio. Add an optional imageUrl to show an event image on the list and detail pages. RSVP is available only to active members; signed-out users can view events but must sign in before RSVPing.
Practice problems are also seed-managed for now. npm run prisma:seed publishes the sample Sum Two Numbers problem with sample and hidden test cases. Anyone can view problems; only active members can submit solutions.
Practice problems are also seed-managed for now. npm run prisma:seed publishes the sample Sum Two Numbers problem with sample and hidden test cases. Anyone can view problems; only active members can submit solutions.
ShardUp runs community coding contests on a roughly biweekly cadence. Admins create contests at /admin/contests, attach unpublished problems, publish the contest, and finalize ratings after it ends. Contest submissions reuse the same self-hosted Piston judge as practice.
- Members register on
/contestsand solve problems during the live window. - Standings use LeetCode-style scoring (solved count, then time taken plus a 5-minute penalty per wrong submission on solved problems).
- Finalize recomputes Codeforces-style contest ratings (everyone starts at 1000, the bottom "Rough" tier, and climbs) and auto-assigns rating-tier badges on member profiles.
- Finalizing a contest also publishes its problems to the Practice tab, so every contest question becomes practice material once the contest is over.
After deploying contest schema changes, run npm run prisma:migrate against your database before publishing a contest.
ShardUp does not use the public Piston API. Host your own Piston API and point the app at it with JUDGE_BASE_URL.
For local development, either:
- Set
JUDGE_PROVIDER=faketo use the deterministic fake judge used by E2E tests. - Or run a self-hosted Piston instance and set
JUDGE_BASE_URL=http://localhost:2000/api/v2(replace the host with your deployment).
Production should set:
JUDGE_BASE_URL— base URL for the self-hosted Piston API, ending at/api/v2.JUDGE_API_KEY— shared secret enforced by your reverse proxy before requests reach Piston.PISTON_PYTHON_VERSION— optional override, defaults to3.10.0.PISTON_CPP_VERSION— optional override, defaults to10.2.0.
Do not set JUDGE_PROVIDER=fake in production.
Recommended hosting options:
- Oracle Cloud Always Free VM — best $0 option. Run Docker + Piston on Ubuntu, put Caddy/nginx in front, and require
Authorization: Bearer <JUDGE_API_KEY>. Seedocs/oracle-piston.mdandinfra/oracle-piston-cloud-init.yaml. - Tiny paid VM — Hetzner, DigitalOcean, Fly.io, Railway, or Render. Expect roughly $4-7/month, lower setup risk than free tiers.
- Avoid serverless-only hosts for Piston. The judge needs a persistent Linux/container environment, installed runtimes, and strict resource limits.
Regression tests guard the design language, page features, and code health. If these pass, your change is safe to merge. The same checks run in CI on every pull request (.github/workflows/ci.yml).
Run the full local gate:
npm run format:check # Prettier formatting
npm run lint # ESLint / Next.js rules
npm run typecheck # TypeScript (tsc --noEmit)
npm run test:unit # Vitest unit + component + design-token guards
npm run build # production buildnpm test/npm run test:unitrun the Vitest suite intests/unit/(pure logic inlib/, theRsvpControl/SiteHeader/AccountBarcomponents, and a design-language guard overapp/globals.css).npm run test:watchre-runs unit tests on change.npm run formatauto-fixes formatting.
Playwright drives the real app in tests/e2e/ (auth-aware navigation, events + RSVP gating, practice submissions, route redirects, the health endpoint). It uses the development-only sign-in and JUDGE_PROVIDER=fake, so it requires a Postgres database and runs the dev server automatically.
# One-time: install the browser
npx playwright install chromium
# Requires a running Postgres. Point DATABASE_URL at a test database.
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/shardup?schema=public" npm run test:e2eglobal-setup applies migrations and seeds a deterministic, always-future event before the suite runs. npm run test:e2e:ui opens the Playwright UI runner.
End-to-end runs in CI against a Postgres service container. Visual-regression and Lighthouse performance suites are added in follow-up PRs.
Every pull request runs the verify job (prettier, lint, typecheck, unit tests, build) and the e2e job (Playwright against a Postgres service). Superseded runs on the same branch are auto-cancelled via a workflow concurrency group.
To make a green suite required before merging, branch protection on main is enabled (required status checks for both CI jobs, enforced for admins). It was applied with:
gh api -X PUT repos/codenamed22/Agora/branches/main/protection --input - <<'JSON'
{
"required_status_checks": { "strict": true, "contexts": ["Static checks & unit tests", "End-to-end tests"] },
"enforce_admins": true,
"required_pull_request_reviews": null,
"restrictions": null
}
JSONWith this, main cannot be pushed to or merged into unless both CI jobs pass.
This is a Next.js app that deploys directly to Vercel.
-
Framework preset: Next.js
-
Build command:
prisma generate && next build -
Install command:
npm install -
Environment variables: Add these in the Vercel dashboard:
DATABASE_URL— PostgreSQL connection string (e.g., from Supabase, Neon, or Railway)AUTH_SECRET— generate withopenssl rand -base64 32AUTH_TRUST_HOST—truefor Vercel deploymentsAUTH_GOOGLE_ID— Google OAuth client IDAUTH_GOOGLE_SECRET— Google OAuth client secretAUTH_URL—https://YOUR_DOMAIN(no trailing slash)ADMIN_EMAILS— comma-separated admin emailsJUDGE_BASE_URL— self-hosted Piston base URL, e.g.https://judge.YOUR_DOMAIN/api/v2JUDGE_API_KEY— bearer token your judge reverse proxy requiresAUTH_DEBUG— optional temporary valuetruefor Auth.js debugging in Vercel logsNEXT_PUBLIC_prefix is not needed for any current variable
-
Google OAuth redirect URI: Add
https://YOUR_DOMAIN/api/auth/callback/googleto the Google Cloud OAuth client.
Vercel builds do not automatically apply Prisma migrations. Run migrations from your local machine against the production database:
DATABASE_URL="postgresql://..." npm run prisma:migrateOr set up a Vercel Deploy Hook / CI step that runs prisma migrate deploy after production deploys.
Seed sample events against production only when needed:
DATABASE_URL="postgresql://..." npm run prisma:seed- The local development-only auth path is disabled in production (
NODE_ENV=production). - Make sure your production Postgres provider allows connections from Vercel serverless functions.
- Some providers require a connection pooler URL for serverless environments.
- Make sure the self-hosted Piston API is reachable from Vercel serverless functions and is not the deprecated/public Piston endpoint.
- Do not commit
.env.localor any real credentials to the repo. - Visit
/api/healthafter deployment to verify required environment variables and database connectivity without exposing secret values.