Changelog
Every update, in order — newest first.
GitHub submission UI removed, AI chat upgraded with live activity streaming and token optimisations, task descriptions now render markdown, copy button added to task card, and results page polished.
- Live activity log in AI chat — each step Claude takes (Thinking…, Creating index.html, Editing style.css, Writing response…) appears as an animated entry with bouncing dots on the active step and a green checkmark when done; replaces the single spinner
- Copy button on task card — copies the full question as clean plain text (all markdown syntax stripped) to the clipboard, ready to paste into any LLM
- Task description markdown rendering — TaskCard now parses and renders **bold** lines as section headings, - bullet lines as custom dot lists, and --- as a divider; both template and custom host descriptions are supported
- Sandbox rules injected into AI's initial user message — rules (no CDN, no localStorage, vanilla only, index.html entry point, exact link/script tags) are now part of the human turn rather than the system prompt, making Haiku follow them more reliably
- AI max output tokens raised from 2048 to 6000 — eliminates truncated file generation that caused Claude to loop and re-create the same file repeatedly
- Agentic loop capped at 8 iterations — prevents infinite tool-call loops when Claude gets stuck retrying failed edits
- edit_file error now returns current file content to Claude inline — Claude can self-correct old_string without a separate read_file round trip, cutting retry cycles from 2 turns to 1
- summarizeSession now rebuilds context from session.files (current state) instead of initialFiles — Claude no longer loses all file changes after conversation compaction
- Tool descriptions trimmed to one line each — guidance already covered by system prompt removed to save tokens on every API call
- Summary prompt reduced from 2-3 sentences / 256 tokens to 1-2 sentences / 128 tokens
- Template descriptions stripped of markdown syntax when applied — textarea shows clean plain text (Problem:, Requirements:, bullet points) instead of raw **bold** and --- markers
- Dashboard contest card strips markdown from description preview — no more **bold** syntax visible in the one-line truncated preview
- Sandbox rules removed from template descriptions — no longer appended on apply, keeping copied question text lean for LLM use
- Smart Todo template updated — localStorage persistence requirement and matching evaluation criterion removed; sandbox blocks localStorage
- Results page vote button tooltips upgraded from native browser title to custom animated dark tooltips with an arrow, smooth fade+slide via framer-motion, and descriptive text explaining what each vote type means
- Results page rank badge resized from w-10 h-10 to w-6 h-6 with rounded-md; avatar/initial sized to match; username bumped to text-base font-bold so the name is visually dominant over the position number
- GitHub submission UI removed from the coding environment — Platform/GitHub toggle, GitHub submission panel, connect button, and repo picker all hidden; backend GitHub functionality remains intact for future re-enablement
- GitHub repo link buttons removed from results page and public share page
- GitHub mention removed from the welcome popup and landing page copy
- Add a note input removed from the coding environment header
- Fixed ERR_INCOMPLETE_CHUNKED_ENCODING on AI chat SSE stream — added X-Accel-Buffering: no header to bypass nginx buffering, a 20s heartbeat comment to keep proxy connections alive, and client disconnect detection to break the generator loop cleanly
- Fixed ghFiles ReferenceError on results page — leftover useEffect referencing the deleted ghFiles state variable was removed
- Fixed sandbox rules still appearing on existing contest task cards — TaskCard now strips everything from **Sandbox Rules onward before rendering or copying, cleaning up DB-stored descriptions at display time without a migration
Claude AI assistant integrated into the coding environment — participants can now chat with Claude to build and edit their project in real time. Streaming fixed end-to-end, nginx infra cleaned up, and the layout locked to 100vh with proper internal scrolling.
- Claude AI chat panel built into the editor sidebar — click the Bot icon to open a persistent chat; Claude can read, create, edit, and delete project files directly during a contest
- Agentic tool-use loop — Claude calls create_file, edit_file, delete_file, and read_file tools in sequence until the task is complete, applying every change live to the editor and preview
- Real-time SSE streaming — Claude's response streams token-by-token into the chat bubble with an animated cursor; tool call badges (Created / Edited / Deleted) appear inline as each file operation fires
- Session memory — conversation history and current file state are kept server-side per user; Claude has full context of what was built and changed across every prompt in a session
- Prompt caching — static system prompt and initial file context are cached with Anthropic's ephemeral cache, reducing input token cost by up to 90% on repeated tool loops within a single prompt
- Per-user rate limiting — capped at 10 prompts per minute per user to prevent abuse; sessions expire after 2 hours and are cleaned up automatically
- Changed-files delta — after the first prompt, only files the user manually edited since the last AI response are sent to Claude, keeping context lean across turns
- Session summarization — when conversation history grows beyond 20 messages, Claude summarizes what was built so far and resets the message log, preventing context window overflow
- All inner panels (chat history, file tree, Monaco editor, preview iframe) now scroll independently within their allocated space rather than pushing the page taller
- Fixed ERR_INCOMPLETE_CHUNKED_ENCODING on the Claude AI chat endpoint — nginx was buffering the SSE stream and closing the connection mid-response; added a dedicated location block for /api/ai/chat with proxy_buffering off, proxy_cache off, and 300s read/send timeouts
- Fixed nginx failing to reload due to a duplicate default_server on port 80 — caused by a stale default.save file left in sites-enabled; removed the file to restore a single canonical default server
- Fixed coding environment layout overflowing beyond 100vh — contest layout changed from min-h-screen to h-screen overflow-hidden, and intermediate flex containers given min-h-0 so the entire flex chain is properly constrained to the viewport
- Audited Claude AI token consumption — intra-turn caching (across tool-use loops) confirmed working correctly with cache_read hitting on loop 2+ within a single prompt; cross-turn cache misses attributed to the 5-minute ephemeral TTL expiring between user prompts, which is expected behavior
First successful live contest completed with real participants. Auto-submit fallback fixed for GitHub tab with no repo selected.
- First successful end-to-end live contest — real participants joined, coded, and submitted within the timer; results and voting worked correctly
- Collected player feedback and mapped next improvements: HTTPS, branded email sending, copy button on task, markdown rendering in task, Claude terminal in editor, share-your-prompt feature, team support, contest history, and tutorials for ✅ and 🎉
- Investigated email scalability — current Nodemailer + Gmail SMTP hits a 500/day cap, has no retry logic, and sends from a personal Gmail account; decided to migrate to Resend with a verified domain (contact@vibe-coding-game.com) for reliable transactional delivery at scale
Live domain migration, auth redirect chain fixed end-to-end, auto-submit race condition resolved, waiting lobby redesigned, and a welcome popup added to the coding environment.
- Welcome popup on coding environment entry — informs users that platform code auto-saves and is submitted when the timer ends; warns GitHub submitters to connect and select a repo early; shows a Connect GitHub button if not yet linked
- Landing page copy updated — ZIP references replaced with 'vibe code live in the editor or link your GitHub repo before time runs out'
- Hero subtitle and OG meta description updated to reflect AI-assisted vibe coding rather than manual coding
- Open Graph and Twitter Card meta tags added to root layout — og:image, og:title, og:description, and twitter:card now populated for every page on the platform
- Waiting lobby redesigned — circular countdown timer centered at the top, participants displayed as avatar bubbles (photo or first-letter initial) with username and host badge; side-by-side grid and TaskCard removed from this view
- Task card capped at max-h-96 with internal scroll so long contest descriptions no longer stretch the layout
- Verify-email page simplified — success screen and manual redirect button removed; page auto-redirects immediately after the code is verified
- Fixed auto-submit race condition — frontend triggers auto-submit at remaining ≤ 5 seconds and backend accepts final submissions within a 5-second grace window, preventing the server from rejecting last-second submits while saveDraft still rejects once time is up
- Fixed stale localStorage auth — API interceptor now catches any 401, clears token and persisted auth store, and redirects to /login with the original path preserved; covers both expired tokens and deleted users
- Fixed post-login redirect lost when going through register → verify-email — EmailVerificationGuard passes ?redirect= into /verify-email, useAuth.register threads it through, and verify-email respects it on completion
- Fixed verify-email always redirecting to /dashboard — all redirect points (useEffect, useAuth.register, EmailVerificationGuard) now use the ?redirect= param with /dashboard as fallback
- Fixed CORS errors on live domain — www.vibe-coding-game.com and vibe-coding-game.com (http + https) added to allowed origins alongside the server IP
- Fixed GitHub manage-repo and OAuth redirects pointing to the old IP — FRONTEND_URL env updated to the live domain
- End-to-end flow: register → verify email → auto-redirect to contest → join → code in editor → auto-submit on timer expiry → results page
- Redirect chain: unauthenticated user hits contest URL → login or register → verify email → lands back on original contest URL
- Stale auth: old localStorage token triggers 401 → storage cleared → redirected to login → after login returns to original page
- Auto-submit: code present in editor at timer expiry is successfully submitted within the 5-second grace window
Email verification, auth hardening, contest flow fixes, auto-submit on timer expiry, and 10 built-in creative JS challenge templates.
- Email verification on registration — a 6-digit OTP is sent to the user's email via Gmail SMTP; unverified users are blocked from the dashboard and contest pages
- Resend verification code button on the verify-email page — generates a fresh code with a new 15-minute expiry
- Login also gates unverified local accounts — redirected to /verify-email until confirmed
- EmailVerificationGuard component wraps dashboard and contest layouts — covers every protected route in a single place
- Auto-submit on timer expiry — when a running contest's countdown hits zero, each participant's current code is submitted automatically without any action needed
- 10 built-in creative JS question templates on the Create Contest page — covers tag input, color palette generator, fuzzy search, slot machine, memory card game, and more
- Template picker on Create Contest — collapsible card list; selecting a template fills the title and description (including sandbox rules) instantly
- Contest URL sharing during WAITING state — visitors who aren't yet participants see a join screen with contest details and a Join button
- Auto-join on RUNNING contest — visiting a live contest URL automatically adds the user as a participant and shows the coding environment
- GitHub repo code execution on results page — submissions linked to a GitHub repo are fetched via the owner's GitHub App installation token, served into the sandbox iframe, and rendered as a live preview alongside platform-coded submissions
- fetchRepoFiles utility reads root-level HTML, CSS, JS, TS, and JSON files from the repo's default branch using the GitHub Trees API, then inlines them into the preview builder
- Results page now shows a consistent live preview for both platform-coded and GitHub-linked submissions — no more code-only fallback for GitHub entries
- Auth guard now redirects unauthenticated users to /login?redirect=<path> — after login they land back on the page they were trying to reach (join links, contest rooms)
- Manual code submit no longer ends the contest for other participants — redirects the submitter to results while others keep coding
- GitHub tab restored after OAuth redirect — returnTo URL includes ?submitMode=github so the GitHub submission panel re-opens automatically
- Duration picker on Create Contest simplified to preset buttons only (15 min, 30 min, 1 hr, 2 hr) — custom seconds input removed
- Default contest duration changed to 15 minutes to match the vibe-coding format
- Nodemon configured to watch .env file — server restarts automatically when SMTP or other credentials change
- Fixed contest auto-ending when the first user submitted — auto-close logic now checks for isDraft: false submissions only; draft auto-saves no longer satisfy the 'everyone submitted' condition
- Fixed dashboard accessible after logout — EmailVerificationGuard now redirects unauthenticated users to /login instead of rendering children freely
- Fixed triple verification email on registration — removed auto-resend useEffect that fired twice under React StrictMode
- Fixed /auth/verify-email 404 — route group (auth) does not add to the URL path; all references corrected to /verify-email
- Fixed auto-submit firing on page load — added countdownStartedRef so the effect only fires when remaining transitions from > 0 to 0, not on initial mount
Full in-browser vibe coding environment — Monaco editor, multi-file projects, live preview, auto-save drafts, and public share pages.
- In-browser Monaco code editor replaces GitHub-only submission — write HTML, CSS, and JS without leaving the contest page
- Multi-file project support — create, rename, and delete files and folders in a VS Code-style file tree
- Live preview iframe updates the rendered project in real time as you code
- Starter project pre-loaded (index.html, style.css, script.js) so every contest starts with working boilerplate
- Auto-save draft every few seconds — work is never lost if the tab closes
- Public share page at /s/[id] — anyone can view code and live preview without an account
- "View Code" button on every results card opens a read-only Monaco editor + live preview in a modal
- Two submission modes: platform code editor (saves code to DB) or GitHub repo link — both work together
- New PATCH /api/contests/:id/submissions/draft backend endpoint for incremental auto-saves
- New public GET /api/submissions/:id endpoint powers the share page (no auth required)
- fetch() polyfill injected into previews so local file references (style.css, script.js) resolve correctly inside the sandboxed iframe
- Code stored as multi-file JSON; legacy single-HTML strings are still decoded correctly
- Draft and final submit are separate actions — auto-saves never accidentally close the contest
- Share modal includes a copy-link button, open-in-new-tab, and GitHub repo link
- Submission model extended with code, language, and isDraft fields
Replaced GitHub OAuth with GitHub App installation flow — users now grant read-only access to selected repos only.
- GitHub App installation flow — users select specific repos to share during setup
- Repo picker dropdown on contest submission page loads repos from the installation
- "Manage repos" button lets users add or remove repos after connecting
- Read-only repo access — platform can never write or modify user code
- No stored access tokens — fresh installation token generated per request via private key
- Callback handles both install and update actions for re-configuring repos
- Added githubInstallationId to user model
- Removed encrypted githubAccessToken field from user model
- Removed GitHub OAuth login — email and password only
Tested v1.1 end-to-end and gathered a list of improvements needed before the next build.
- Full end-to-end test — contest creation, joining, submitting, voting
- GitHub connect flow found broken — root cause: OAuth App vs GitHub App architecture mismatch
- Identified that GitHub App installation flow is required for scoped read-only repo access
- Gathered improvements list: repo access redesign, UI fixes, submission flow cleanup
GitHub integration, repo-linked submissions, and a fully redesigned results page with consistent voting UI.
- Connect GitHub account — platform only requests public repo access
- Select any public GitHub repo from a live dropdown when submitting
- Submissions linked to a GitHub repo — 'Code' button on every results card
- Disconnect GitHub at any time from your profile
- Dedicated /auth/github-connected callback page with success/error feedback
- GitHub connect button shown inline on submit form if not yet linked
- Resubmit at any time to change repo or update note during a running contest
- GitHub access token encrypted at rest (AES-256-GCM) — never exposed to the client
- Submit button disabled until GitHub is connected and a repo is selected
- Vote button shows a spinning loader while request is in flight
- All other vote buttons dim to 40% opacity during any active vote request
- User avatars shown on submission cards alongside username
- Page-level loading replaced with a centered animated spinner
- Tooltips on all vote buttons explain exactly why they are locked or active
- Fixed 3-slot action layout on every card — Code / ✅ / 🎉 always in the same position
- Buttons no longer shift or disappear based on contest state
- ZIP upload removed — submissions are now GitHub repo links, not local archives
Initial release — full contest lifecycle, two-tier voting, live leaderboard, and Google + GitHub login.
- Email + password registration with validation (3–20 char username, 8+ char password)
- Login with JWT session persisted to localStorage
- Google OAuth and GitHub OAuth sign-in
- Protected routes — unauthenticated users redirected to /login with return URL preserved
- Zustand auth store with persistent state across page reloads
- Dashboard home with greeting, quick-action cards, and recent contests preview
- Contests list page with status filters (Waiting / Running / Ended)
- Create contest — title, optional description, duration presets (15 min → 2 hr) + custom input
- Share code generated on creation with one-click copy
- Delete contest (blocked while running)
- Sidebar nav with logo, page links, user profile, and logout
- Join by share code at /join/[code] with contest preview
- Lobby: circular countdown timer, live participant list with host badge, Start button
- Running: live HH:MM:SS countdown, urgent red pulse under 60 seconds
- Task description visible in split-screen during contest
- Code submitted as a ZIP archive (up to 50 MB) — drag-and-drop or click to browse
- Optional submission note (max 300 chars)
- Two-tier voting: ✅ +1 (unlimited) and 🎉 Tada (once per contest)
- Ranked submission cards with 1st / 2nd / 3rd badges
- Winner banner with animated trophy when contest ends
- Tie detection — shows all tied usernames when top Tada counts match
- Share results page via copy-link button
Built with Next.js, Prisma, PostgreSQL, and a lot of coffee.