Skip to content

feat(lp-2026): Next.js 16 hackathon LP, static-exported to Cloudflare Workers#11

Merged
YasunoriMATSUOKA merged 5 commits into
mainfrom
feat/lp-2026-nextjs
Jul 2, 2026
Merged

feat(lp-2026): Next.js 16 hackathon LP, static-exported to Cloudflare Workers#11
YasunoriMATSUOKA merged 5 commits into
mainfrom
feat/lp-2026-nextjs

Conversation

@YasunoriMATSUOKA

@YasunoriMATSUOKA YasunoriMATSUOKA commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

Adds the 2026 hackathon LP to the monorepo, hosted on Cloudflare Workers like the other years — but this one is a v0-generated Next.js 16 app-router app (React 19, Tailwind v4, shadcn/ui, framer-motion; pnpm), so it uses a build step + static export rather than a plain public/ folder.

Approach

  • Fully client-rendered, no server features (verified: no route handlers, middleware, server actions, next/headers, or dynamic rendering), so next build with output: 'export' emits ./out, served by an assets-only Worker — same Workers Builds + Static Assets model as the other LP years. (OpenNext not needed.)

Changes (all under apps/hackathon-lp-2026/)

  • The Next.js source (app/, components/, hooks/, lib/, public/, styles/, configs).
  • next.config.mjs: add output: 'export' (keeps images.unoptimized, ignoreBuildErrors).
  • wrangler.toml: assets-only Worker nemtus-hackathon-lp-2026, directory = "./out", custom domain hackathon-2026.nemtus.com (the aggregator already links there). Header comment documents the Workers Builds dashboard settings (Build command pnpm build).
  • .npmrc ignore-scripts=false to override the inherited repo-root hardening for this standalone pnpm app.
  • Fix a broken v0 lockfile: it pinned framer-motion@12.23.24 alongside motion-dom@12.42.2, which dropped the activeAnimations export framer-motion imports → build failure. Pinned motion-dom to 12.23.23 via pnpm.overrides.

Verification

  • pnpm install && pnpm build succeeds; / and /_not-found prerender as static.
  • out/ has index.html, 404.html, _next/… (215 files); largest asset 1.78 MiB (< the 25 MiB Workers limit).
  • wrangler deploy --dry-run reads out/ cleanly.
  • Build artifacts (node_modules, .next, out, next-env.d.ts) are gitignored (not committed).

Cloudflare dashboard (to do, like the other years)

Create Worker nemtus-hackathon-lp-2026, connect nemtus/apps, Root directory apps/hackathon-lp-2026, Build command pnpm build, Deploy command npx wrangler deploy, Build watch paths apps/hackathon-lp-2026/*, production branch main, Preview URLs on. The custom domain attaches via the routes entry on deploy.

Notes

  • Kept as a standalone pnpm app (not an npm workspace), matching how the other apps/* frontends stay standalone.
  • @vercel/analytics is a no-op off Vercel; left in place (optional to remove later).
  • If the LP ever needs SSR/API, switch to @opennextjs/cloudflare instead of static export.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a full hackathon landing page with animated sections (hero countdown, schedule, prizes, sponsors, judges, FAQ, entry flow, final CTA) and responsive navigation with dark-mode styling.
    • Introduced reusable UI components and utilities (dialogs, menus, charts, forms, toasts, tables, accordions, and more).
  • Documentation
    • Added landing-page app documentation with install/dev/build instructions.
  • Tests
    • Added unit/integration coverage plus Playwright end-to-end checks for key landing-page behaviors.
  • Chores
    • Added app configuration for static export/deployment, CI workflow, and repo ignore/formatting setup.

…lare Workers

- Add the v0-generated Next.js 16 app-router LP (React 19, Tailwind v4, shadcn/ui,
  framer-motion; pnpm) under apps/hackathon-lp-2026, hosted like the other years on a
  Cloudflare Workers Static Assets Worker via Workers Builds.
- next.config.mjs: output: 'export' (fully client-rendered, no server features) -> build
  emits ./out, served by the assets-only wrangler.toml (name nemtus-hackathon-lp-2026,
  custom domain hackathon-2026.nemtus.com; the aggregator already links there).
- Fix the v0 lockfile's broken motion resolution: it pinned framer-motion@12.23.24 with
  motion-dom@12.42.2, which dropped the "activeAnimations" export framer-motion imports,
  breaking the build. Pin motion-dom to 12.23.23 via pnpm.overrides.
- .npmrc ignore-scripts=false to override the inherited root hardening for this pnpm app.

Verified: pnpm build succeeds; out/ has index.html/404.html/_next (215 files, max asset
1.78MiB < 25MiB limit); wrangler deploy --dry-run reads out/ cleanly. Build artifacts
(node_modules/.next/out) are gitignored.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a standalone Next.js landing-page app for the hackathon, with build/deployment scaffolding, global theming, shared hooks/utilities, a reusable UI component set, and the landing page shell plus content sections.

Changes

Hackathon LP 2026 App

Layer / File(s) Summary
Project scaffolding and build config
apps/hackathon-lp-2026/package.json, tsconfig.json, next.config.mjs, postcss.config.mjs, components.json, .gitignore, .npmrc, wrangler.toml, .prettierignore, .prettierrc.json, eslint.config.mjs, vitest.config.ts, vitest.setup.ts, playwright.config.ts, .github/workflows/ci-hackathon-lp-2026.yml, socket.yml, README.md, e2e/home.spec.ts, test/*
Sets up the app’s package scripts, framework config, deployment config, lint/test tooling, ignore rules, and project documentation.
Global theming and CSS variables
apps/hackathon-lp-2026/app/globals.css, apps/hackathon-lp-2026/styles/globals.css
Defines light/dark CSS variables, Tailwind theme tokens, base styles, and animation utilities used by the app.
Shared hooks, constants, and utilities
apps/hackathon-lp-2026/hooks/*, apps/hackathon-lp-2026/components/ui/use-mobile.tsx, apps/hackathon-lp-2026/components/ui/use-toast.ts, apps/hackathon-lp-2026/lib/constants.ts, apps/hackathon-lp-2026/lib/utils.ts
Adds the in-view and mobile hooks, toast state helpers, the class merge helper, and hackathon date/URL constants.
App entry point
apps/hackathon-lp-2026/app/layout.tsx, apps/hackathon-lp-2026/app/page.tsx
Implements the root layout with fonts, metadata, JSON-LD, analytics, and the page composing all sections.
UI primitives for form inputs
apps/hackathon-lp-2026/components/ui/{button,input,textarea,checkbox,radio-group,switch,select,slider,toggle,toggle-group,label,form,field,input-group,input-otp,calendar}.tsx
Adds shared form controls and related field, input group, OTP, calendar, select, radio, button, and toggle components.
UI overlays, menus, navigation, and interactions
apps/hackathon-lp-2026/components/ui/{dialog,alert-dialog,drawer,sheet,popover,hover-card,tooltip,dropdown-menu,context-menu,menubar,navigation-menu,command,collapsible,accordion,tabs,pagination,breadcrumb,carousel}.tsx
Adds dialog, menu, navigation, and interaction components.
UI primitives for display and layout
apps/hackathon-lp-2026/components/ui/{card,badge,avatar,separator,aspect-ratio,skeleton,spinner,progress,table,item,empty,kbd,button-group,alert,resizable,scroll-area,label}.tsx
Adds layout and display primitives used throughout the landing page.
UI primitives: sidebar, chart and toast system
apps/hackathon-lp-2026/components/ui/{sidebar,chart,sonner,toast,toaster}.tsx
Adds the sidebar system, chart theming components, and toast notification UI.
Landing page background, navigation, and hero
apps/hackathon-lp-2026/components/{circuit-background,navigation,hero}.tsx
Implements the animated background, scroll-spy navigation, and hero countdown/entry CTA.
Landing page content sections
apps/hackathon-lp-2026/components/{about,participation-flow,themes,multi-chain,prizes,schedule,entry,highlights,judges,sponsors,faq,nemtus-info,final-cta,results,footer,theme-provider}.tsx
Implements the remaining landing page sections and the theme provider.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the new Next.js 16 hackathon landing page and its static export for Cloudflare Workers.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lp-2026-nextjs

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/hackathon-lp-2026/app/globals.css

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/hackathon-lp-2026/eslint.config.mjs
Error: end of the stream or a document separator is expected (10:12)

7 |
8 | export default tseslint.config(
9 | {
10 | ignores: [
-----------------^
11 | ".next/",
12 | "out/
",
at generateError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:196:10)
at throwError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:200:9)
at readDocument (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1720:5)
at loadDocuments (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1759:5)
at Object.load (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1783:21)
at loadLegacyConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

apps/hackathon-lp-2026/app/layout.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/hackathon-lp-2026/eslint.config.mjs
Error: end of the stream or a document separator is expected (10:12)

7 |
8 | export default tseslint.config(
9 | {
10 | ignores: [
-----------------^
11 | ".next/",
12 | "out/
",
at generateError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:196:10)
at throwError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:200:9)
at readDocument (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1720:5)
at loadDocuments (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1759:5)
at Object.load (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1783:21)
at loadLegacyConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

apps/hackathon-lp-2026/components/about.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

YAMLException: Cannot read config file: /apps/hackathon-lp-2026/eslint.config.mjs
Error: end of the stream or a document separator is expected (10:12)

7 |
8 | export default tseslint.config(
9 | {
10 | ignores: [
-----------------^
11 | ".next/",
12 | "out/
",
at generateError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:196:10)
at throwError (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:200:9)
at readDocument (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1720:5)
at loadDocuments (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1759:5)
at Object.load (/apps/hackathon/functions/node_modules/js-yaml/lib/loader.js:1783:21)
at loadLegacyConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2565:21)
at loadConfigFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2680:20)
at ConfigArrayFactory._loadConfigData (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2984:42)
at ConfigArrayFactory.loadFile (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2850:40)
at createCLIConfigArray (/apps/hackathon/functions/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3660:35)

  • 94 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Jul 2, 2026

Copy link
Copy Markdown

@socket-security

socket-security Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm framer-motion is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: apps/hackathon-lp-2026/package.jsonnpm/framer-motion@12.23.24

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/framer-motion@12.23.24. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm jiti is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: apps/hackathon-lp-2026/pnpm-lock.yamlnpm/@tailwindcss/postcss@4.2.0npm/eslint@9.39.4npm/vitest@4.1.9npm/@vitejs/plugin-react@6.0.3npm/jiti@2.6.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jiti@2.6.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm recharts is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: apps/hackathon-lp-2026/package.jsonnpm/recharts@2.15.4

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/recharts@2.15.4. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
nemtus-hackathon-lp-2023 891d960 Jul 02 2026, 02:38 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
nemtus-hackathon-lp 891d960 Jul 02 2026, 02:40 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
nemtus-hackathon-lp-2024 891d960 Jul 02 2026, 02:43 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
nemtus-hackathon-lp-2025 891d960 Jul 02 2026, 02:45 PM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🧹 Nitpick comments (14)
apps/hackathon-lp-2026/next.config.mjs (1)

5-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reconsider suppressing TypeScript build errors.

ignoreBuildErrors: true lets next build succeed even with type errors, defeating type safety for a codebase that will keep growing. If this was only added to work around v0-generated code that hasn't been fully typed yet, consider fixing the type errors and removing this flag before the app matures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/next.config.mjs` around lines 5 - 7, The Next.js
TypeScript config is suppressing build-time type checking via ignoreBuildErrors
in next.config.mjs, which weakens type safety. Remove that flag from the
typescript config in next.config.mjs and fix the underlying type issues so next
build runs with full TypeScript validation; use the next.config.mjs typescript
block as the target location.
apps/hackathon-lp-2026/hooks/use-toast.ts (1)

171-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

useEffect dependency causes needless resubscribe churn.

The effect depends on [state] (Line 182) but only pushes/removes the stable setState reference into listeners. Every toast dispatch re-runs cleanup+setup unnecessarily. Functionally harmless here (inherited from shadcn/ui boilerplate) but worth tightening.

♻️ Proposed fix
   React.useEffect(() => {
     listeners.push(setState)
     return () => {
       const index = listeners.indexOf(setState)
       if (index > -1) {
         listeners.splice(index, 1)
       }
     }
-  }, [state])
+  }, [])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/hooks/use-toast.ts` around lines 171 - 189, The
useEffect in useToast is resubscribing on every state change even though it only
uses the stable setState callback; update the dependency array to stop depending
on state so the listener is registered once and cleaned up once. Keep the
push/splice logic in useToast unchanged and ensure the effect depends only on
the stable setter reference, not the toast state itself.
apps/hackathon-lp-2026/app/layout.tsx (1)

55-84: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Escape the JSON-LD string before injecting it into <script>

JSON.stringify(...) is fine for the current hardcoded data, but add .replace(/</g, "\\u003c") here so a future dynamic field can’t break out of the script tag.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/app/layout.tsx` around lines 55 - 84, The JSON-LD
injection in the layout’s script block needs escaping before being inserted into
the `<script>` tag. Update the `dangerouslySetInnerHTML` payload in
`app/layout.tsx` so the `JSON.stringify(...)` result is post-processed with an
escape for `<` characters, preventing any future dynamic field from breaking out
of the script context. Keep the change localized to the Event schema block in
`layout.tsx`.

Source: Linters/SAST tools

apps/hackathon-lp-2026/components/ui/use-toast.ts (2)

174-182: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Unnecessary effect dependency causes repeated resubscription.

setState is stable across renders, so depending on [state] (Line 182) tears down and re-adds the listener on every dispatch instead of only on mount/unmount.

♻️ Proposed fix
   React.useEffect(() => {
     listeners.push(setState)
     return () => {
       const index = listeners.indexOf(setState)
       if (index > -1) {
         listeners.splice(index, 1)
       }
     }
-  }, [state])
+  }, [])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/ui/use-toast.ts` around lines 174 - 182,
The listener registration effect in use-toast.ts is resubscribing on every state
change because the React.useEffect dependency is [state] instead of the stable
setState callback. Update the effect that pushes/removes setState from listeners
so it only runs on mount/unmount by removing the changing state dependency and
using the stable setter reference in the cleanup.

1-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate toast state module across hooks/use-toast.ts and components/ui/use-toast.ts.

This file re-implements the same useToast/toast/reducer logic as the hooks/use-toast.ts module from another layer, resulting in two independent, unsynchronized toast stores. Components importing from different paths will not share toast state.

Consider consolidating to a single source of truth and re-exporting from the other location.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/ui/use-toast.ts` around lines 1 - 16, The
toast state logic is duplicated here and in hooks/use-toast.ts, creating two
separate unsynchronized stores. Consolidate the implementation into a single
source of truth in one module (for example the existing useToast/toast/reducer
code) and make the other module re-export it so all callers share the same toast
state. Keep the shared symbols like useToast, toast, and reducer in one place
and update imports accordingly.
apps/hackathon-lp-2026/components/ui/toaster.tsx (1)

1-36: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the dead toast stack and duplicate hooks. app/layout.tsx/app/page.tsx don’t mount either toast provider, and the repo still carries duplicate use-toast/use-mobile copies under components/ui/ beside the hooks/ versions. Keep one implementation to avoid stale, diverging code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/ui/toaster.tsx` around lines 1 - 36, The
Toaster component is rendering a toast stack that is not mounted anywhere, and
the repo also contains duplicate hook implementations under components/ui
alongside the canonical hooks versions. Remove the unused toaster wiring in
Toaster and keep only one source of truth for the toast/mobile hooks, updating
any imports to use the shared hooks use-toast/use-mobile symbols so there are no
stale duplicates.
apps/hackathon-lp-2026/components/ui/menubar.tsx (1)

219-241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent outline handling in MenubarSubTrigger.

Line 232 uses outline-none while every other interactive item in this file (MenubarItem, MenubarCheckboxItem, MenubarRadioItem) and the equivalent DropdownMenuSubTrigger use outline-hidden. In Tailwind v4, outline-none fully removes the outline (including in forced-colors/high-contrast mode), whereas outline-hidden preserves visibility for accessibility in that mode.

Suggested fix
       className={cn(
-        'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8',
+        'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8',
         className,
       )}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/ui/menubar.tsx` around lines 219 - 241, The
MenubarSubTrigger component is using outline-none while the other interactive
menu items and the matching DropdownMenuSubTrigger use outline-hidden. Update
the class list in MenubarSubTrigger to use outline-hidden so focus styling stays
accessible in forced-colors/high-contrast mode, keeping the change localized to
the MenubarPrimitive.SubTrigger wrapper.
apps/hackathon-lp-2026/components/ui/use-mobile.tsx (1)

1-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate useIsMobile implementation.

Identical to apps/hackathon-lp-2026/hooks/use-mobile.ts, which is the version actually imported by sidebar.tsx. Consider removing this copy and re-exporting/importing from the shared hook to avoid future divergence.

♻️ Proposed fix
-import * as React from 'react'
-
-const MOBILE_BREAKPOINT = 768
-
-export function useIsMobile() {
-  const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
-
-  React.useEffect(() => {
-    const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
-    const onChange = () => {
-      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
-    }
-    mql.addEventListener('change', onChange)
-    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
-    return () => mql.removeEventListener('change', onChange)
-  }, [])
-
-  return !!isMobile
-}
+export { useIsMobile } from '`@/hooks/use-mobile`'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/ui/use-mobile.tsx` around lines 1 - 20, The
useIsMobile hook here is a duplicate of the shared implementation, which risks
diverging behavior over time. Remove the local hook in use-mobile.tsx and make
this module re-export or import the canonical useIsMobile from the shared
hooks/use-mobile implementation so sidebar.tsx and other consumers all use the
same source of truth.
apps/hackathon-lp-2026/components/navigation.tsx (1)

32-47: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Unthrottled scroll handler runs getBoundingClientRect for every nav item on every scroll event.

handleScroll iterates all NAV_ITEMS and calls document.getElementById + getBoundingClientRect on each scroll tick without debouncing/throttling (e.g. via requestAnimationFrame). This can cause layout thrashing and janky scrolling, especially on lower-end devices.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/navigation.tsx` around lines 32 - 47, The
handleScroll scroll-spy logic in navigation.tsx is doing DOM reads on every
scroll event, which can cause janky scrolling. Update handleScroll to be
throttled or scheduled via requestAnimationFrame before calling
document.getElementById and getBoundingClientRect for NAV_ITEMS, and keep the
activeSection/isScrolled updates inside that optimized path.
apps/hackathon-lp-2026/components/circuit-background.tsx (1)

61-129: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Large number of continuously-animated SVG elements may hurt performance.

With gridSize = 8.3 over a 1400×1800 viewport, generateGridPaths() produces roughly 350-400 line entries, each rendering a static <line> plus an infinitely-looping motion.line (lines 69-93, 97-121). That's 700+ animated SVG elements running Framer Motion's animation loop simultaneously on every page load, purely as decoration — a real risk for jank/battery drain on low-end/mobile devices.

Consider increasing gridSize, capping the animated line count (e.g., only animate a subset), or switching to a lighter technique (CSS @keyframes, canvas, or will-change + fewer elements) for this purely decorative background.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/circuit-background.tsx` around lines 61 -
129, The CircuitBackground decorative SVG is creating too many continuously
looping Framer Motion elements, which can hurt performance on low-end devices.
Reduce the number of animated paths in CircuitBackground by increasing the
density step, capping or sampling the gridPaths that get a motion.line, or
replacing the per-element animation with a lighter approach such as CSS
keyframes or canvas so the background stays visual without animating hundreds of
SVG nodes.
apps/hackathon-lp-2026/components/about.tsx (1)

1-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent in-view hook: uses framer-motion's useInView directly instead of the shared hook.

Every sibling section (participation-flow.tsx, themes.tsx, multi-chain.tsx, prizes.tsx, schedule.tsx) uses the shared @/hooks/use-in-view hook, which triggers once and stays true. This file instead calls framer-motion's own useInView(ref, { once: false, amount: 0.3 }) directly, giving it different semantics (re-toggles on every viewport exit/enter) from the rest of the page. This is a maintainability/consistency gap and unnecessary duplication of the "detect in view" concept.

♻️ Align with the shared hook used elsewhere
-import { motion, useInView } from "framer-motion"
-import { useRef } from "react"
+import { motion } from "framer-motion"
+import { useInView } from "`@/hooks/use-in-view`"
 import { Card } from "`@/components/ui/card`"

 export function About() {
-  const ref = useRef(null)
-  const isInView = useInView(ref, { once: false, amount: 0.3 })
+  const { ref, isInView } = useInView()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/about.tsx` around lines 1 - 9, The About
section is using framer-motion’s local useInView(ref, { once: false, amount: 0.3
}) directly instead of the shared `@/hooks/use-in-view` hook used by the other
page sections. Update About to use the shared hook for consistent once-only
in-view behavior and remove the duplicated in-view setup, keeping the
motion/Card logic in About aligned with participation-flow, themes, multi-chain,
prizes, and schedule.
apps/hackathon-lp-2026/components/entry.tsx (2)

22-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded "published" flags produce permanently dead code branches.

isDocumentsPublished/isRulesPublished are always true, so the disabled-button branches (Lines 70-79, 94-103, 139-148) can never render. If these were meant to be togglable like IS_HACKATHON_ENDED, move them into lib/constants.ts as real flags; otherwise drop the conditionals and unreachable branches.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/entry.tsx` around lines 22 - 23, The
hardcoded isDocumentsPublished and isRulesPublished constants in Entry make the
disabled button branches in Entry unreachable. Either move these flags into
lib/constants.ts as real toggles if they need to be configurable, or remove the
conditional rendering and dead disabled-button branches entirely from Entry and
keep only the always-enabled path.

45-151: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated Button/ExternalLink ternary pattern across both branches.

The same "asChild active button vs. disabled fallback with icon" shape is repeated 4 times with only className/href/label differing, and the two branches (open vs. ended) diverge inconsistently — e.g. the submit-PDF button in the "ended" branch (Lines 117-125) is unconditionally disabled instead of also checking isDocumentsPublished like the open branch does (Lines 58-80). Extracting a small LinkButton({ href, published, ... }) helper would remove the duplication and the inconsistency risk.

♻️ Example extraction
function ExternalLinkButton({
  href,
  published,
  disabled,
  size = "lg",
  variant,
  className,
  children,
}: {
  href: string
  published: boolean
  disabled?: boolean
  size?: "lg" | "sm"
  variant?: "outline"
  className: string
  children: React.ReactNode
}) {
  if (!published || disabled) {
    return (
      <Button size={size} disabled variant={variant} className={`${className} opacity-50 cursor-not-allowed`}>
        {children}
        <ExternalLink className="ml-2" size={size === "lg" ? 18 : 16} />
      </Button>
    )
  }
  return (
    <Button asChild size={size} variant={variant} className={className}>
      <a href={href} target="_blank" rel="noopener noreferrer">
        {children}
        <ExternalLink className="ml-2" size={size === "lg" ? 18 : 16} />
      </a>
    </Button>
  )
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/entry.tsx` around lines 45 - 151, The
button rendering in Entry uses the same active-vs-disabled ExternalLink pattern
repeatedly and the open/ended branches are drifting, especially for the
submit-PDF button where the ended branch ignores isDocumentsPublished. Extract a
reusable helper/component such as ExternalLinkButton inside entry.tsx and use it
for the ENTRY_URL, SUBMIT_PDF_URL, and RULES_PDF_URL cases so the
published/disabled logic lives in one place and both branches stay consistent.
apps/hackathon-lp-2026/components/sponsors.tsx (1)

138-153: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Toggle button lacks aria-expanded.

The expand/collapse control changes visible content but doesn't expose its state to assistive tech.

🛠 Suggested fix
             <button
               onClick={() => setIsExpanded(!isExpanded)}
+              aria-expanded={isExpanded}
               className="text-sm text-purple-400 hover:text-purple-300 transition-colors mt-2 flex items-center gap-1 self-start"
             >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/sponsors.tsx` around lines 138 - 153, The
expand/collapse button in sponsors.tsx does not expose its current state to
assistive technology. Update the toggle control in the shouldTruncate block to
include an aria-expanded attribute that reflects isExpanded, and keep it tied to
the existing onClick/setIsExpanded behavior. Use the button inside the
truncation UI as the reference point so the accessible state matches the visible
“もっと見る/閉じる” content.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/hackathon-lp-2026/app/globals.css`:
- Around line 93-97: The macOS system font fallback in the `@theme` inline block
is misspelled, so the intended font never applies. Update the --font-heading
value in globals.css to use the correct BlinkMacSystemFont token, matching the
existing --font-sans fallback style, and keep the rest of the font stack
unchanged.

In `@apps/hackathon-lp-2026/components/circuit-background.tsx`:
- Around line 5-59: The module-level grid generation in generateGridPaths is
using Math.random() to build gridPaths, which makes the server-rendered output
differ from the client during hydration. Move the randomization out of module
scope in circuit-background.tsx, either by generating the paths inside a
client-only effect/state after mount or by replacing Math.random() with
deterministic values derived from stable inputs like the path index. Make sure
the motion.line props that read path.direction, path.delay, and path.duration
still receive consistent values on both renders.

In `@apps/hackathon-lp-2026/components/final-cta.tsx`:
- Around line 9-11: The `FinalCTA` component is deriving `isEntryOpen` directly
from `new Date()` in the render body, so it will only update when `useInView()`
triggers a re-render and can become stale. Update `FinalCTA` to use the same
shared periodically-updating entry-state hook used by
`navigation.tsx`/`hero.tsx`, and compute `isEntryOpen` from that shared source
instead of inline time math. Ensure the hook or shared state is what drives the
CTA rendering so the entry status refreshes automatically without requiring a
reload.

In `@apps/hackathon-lp-2026/components/footer.tsx`:
- Around line 73-75: The footer copyright text is stale and should be updated in
the Footer component. Replace the hardcoded year in the copyright line with the
current year, ideally by deriving it dynamically using the Footer’s render logic
so it stays correct over time. Update the text where the © notice is rendered in
the footer markup.

In `@apps/hackathon-lp-2026/components/hero.tsx`:
- Around line 10-46: The countdown transition is not triggering a final state
update, so the UI can stay stale when the target date passes. Update
useCountdown to perform one last timeLeft state update when distance drops below
zero, and make sure Hero derives isEntryOpen from the same countdown state
instead of only recomputing new Date() on render. Use the useCountdown hook and
the isEntryOpen logic in Hero to keep the entry-open/ended branches in sync.

In `@apps/hackathon-lp-2026/components/highlights.tsx`:
- Around line 60-86: The hover-glow overlay is not triggering because the
`group-hover` overlay sits outside the element that has the `group` class in
`highlights`, and the same pattern appears in `judges` and `sponsors`. Move the
`group` class to a parent wrapper that contains both the glow overlay and the
`Card`, or otherwise make the overlay a descendant of the `.group` element so
Tailwind’s `group-hover` can apply. Update the affected wrapper structure in the
`highlight.icon` card block and mirror the same fix in the corresponding card
layouts in `judges` and `sponsors`.
- Line 44: The in-view setup in useInView currently uses an unsupported amount
option, so update it to use the proper threshold setting to wait for full
visibility. Also fix the glow so it’s rendered inside the hovered .group card
rather than as a sibling, ensuring group-hover:opacity-100 can actually trigger
it; adjust the highlights.tsx component structure around the useInView and glow
markup accordingly.

In `@apps/hackathon-lp-2026/components/navigation.tsx`:
- Around line 29-51: The Navigation component’s `isEntryOpen` is only set once
in the mount-only `useEffect`, so it never updates when `ENTRY_START_DATE` is
crossed during an open session. Update `navigation.tsx` by moving this logic
into a shared `useEntryStatus()` hook (or equivalent) that recomputes on a timer
or scheduled timeout, and use that same hook in `Navigation`, `Hero`, and
`FinalCTA` so all CTA states stay consistent without a page reload.

In `@apps/hackathon-lp-2026/components/results.tsx`:
- Line 27: The useInView configuration in results.tsx is using the wrong option
name, so the visibility trigger is not applied as intended. Update the useInView
call in the Results component to replace amount with threshold, keeping the same
0.3 value so the IntersectionObserver fires at 30% visibility.

In `@apps/hackathon-lp-2026/components/ui/carousel.tsx`:
- Around line 96-105: The carousel effect in `Carousel` registers both `reInit`
and `select` on `api`, but the cleanup only unsubscribes `select`, so stale
`reInit` listeners can accumulate when the effect reruns. Update the cleanup in
the `React.useEffect` block to remove both listeners from the same `api`
instance, keeping the subscribe/unsubscribe pair symmetric for `onSelect`,
`api.on`, and `api.off`.

In `@apps/hackathon-lp-2026/components/ui/chart.tsx`:
- Around line 235-239: Zero values are being rendered as a stray text node in
the chart tooltip because the conditional around item.value uses a truthy check.
Update the tooltip rendering in the chart component where item.value is
displayed so it matches the existing undefined check used elsewhere in this
file, and only render the span when item.value is actually defined rather than
relying on item.value && (...).

In `@apps/hackathon-lp-2026/components/ui/collapsible.tsx`:
- Around line 1-9: The Collapsible wrapper uses React.ComponentProps in the
Collapsible function without importing React, which will cause a TypeScript
error. Update the component module to follow the same pattern as the other UI
wrappers by adding the React import at the top, keeping the existing
CollapsiblePrimitive.Root usage unchanged.

In `@apps/hackathon-lp-2026/components/ui/empty.tsx`:
- Around line 1-4: The `empty.tsx` module uses `React.ComponentProps` in its
component type definitions, but it does not import the React namespace, so
TypeScript cannot resolve it. Update the top of the file to add the React import
alongside the existing `cva` and `cn` imports, keeping the component definitions
that reference `React.ComponentProps` unchanged.

In `@apps/hackathon-lp-2026/components/ui/navigation-menu.tsx`:
- Around line 1-7: The NavigationMenu wrapper needs a client boundary because it
uses interactive Radix primitives and icons that must run on the client. Add the
client directive at the top of the navigation-menu.tsx module so the
NavigationMenu component can be safely imported from Server Components. Keep the
change local to this wrapper file and ensure the directive appears before the
React and NavigationMenuPrimitive imports.

In `@apps/hackathon-lp-2026/styles/globals.css`:
- Around line 21-23: The destructive color tokens in globals.css are mismatched
because --destructive-foreground currently uses the same value as --destructive,
making destructive text unreadable. Update the theme token in the globals.css
variables block so --destructive-foreground uses a contrasting foreground color,
and verify any components that rely on destructive variants (for example button
and alert styles) inherit the corrected token.

---

Nitpick comments:
In `@apps/hackathon-lp-2026/app/layout.tsx`:
- Around line 55-84: The JSON-LD injection in the layout’s script block needs
escaping before being inserted into the `<script>` tag. Update the
`dangerouslySetInnerHTML` payload in `app/layout.tsx` so the
`JSON.stringify(...)` result is post-processed with an escape for `<`
characters, preventing any future dynamic field from breaking out of the script
context. Keep the change localized to the Event schema block in `layout.tsx`.

In `@apps/hackathon-lp-2026/components/about.tsx`:
- Around line 1-9: The About section is using framer-motion’s local
useInView(ref, { once: false, amount: 0.3 }) directly instead of the shared
`@/hooks/use-in-view` hook used by the other page sections. Update About to use
the shared hook for consistent once-only in-view behavior and remove the
duplicated in-view setup, keeping the motion/Card logic in About aligned with
participation-flow, themes, multi-chain, prizes, and schedule.

In `@apps/hackathon-lp-2026/components/circuit-background.tsx`:
- Around line 61-129: The CircuitBackground decorative SVG is creating too many
continuously looping Framer Motion elements, which can hurt performance on
low-end devices. Reduce the number of animated paths in CircuitBackground by
increasing the density step, capping or sampling the gridPaths that get a
motion.line, or replacing the per-element animation with a lighter approach such
as CSS keyframes or canvas so the background stays visual without animating
hundreds of SVG nodes.

In `@apps/hackathon-lp-2026/components/entry.tsx`:
- Around line 22-23: The hardcoded isDocumentsPublished and isRulesPublished
constants in Entry make the disabled button branches in Entry unreachable.
Either move these flags into lib/constants.ts as real toggles if they need to be
configurable, or remove the conditional rendering and dead disabled-button
branches entirely from Entry and keep only the always-enabled path.
- Around line 45-151: The button rendering in Entry uses the same
active-vs-disabled ExternalLink pattern repeatedly and the open/ended branches
are drifting, especially for the submit-PDF button where the ended branch
ignores isDocumentsPublished. Extract a reusable helper/component such as
ExternalLinkButton inside entry.tsx and use it for the ENTRY_URL,
SUBMIT_PDF_URL, and RULES_PDF_URL cases so the published/disabled logic lives in
one place and both branches stay consistent.

In `@apps/hackathon-lp-2026/components/navigation.tsx`:
- Around line 32-47: The handleScroll scroll-spy logic in navigation.tsx is
doing DOM reads on every scroll event, which can cause janky scrolling. Update
handleScroll to be throttled or scheduled via requestAnimationFrame before
calling document.getElementById and getBoundingClientRect for NAV_ITEMS, and
keep the activeSection/isScrolled updates inside that optimized path.

In `@apps/hackathon-lp-2026/components/sponsors.tsx`:
- Around line 138-153: The expand/collapse button in sponsors.tsx does not
expose its current state to assistive technology. Update the toggle control in
the shouldTruncate block to include an aria-expanded attribute that reflects
isExpanded, and keep it tied to the existing onClick/setIsExpanded behavior. Use
the button inside the truncation UI as the reference point so the accessible
state matches the visible “もっと見る/閉じる” content.

In `@apps/hackathon-lp-2026/components/ui/menubar.tsx`:
- Around line 219-241: The MenubarSubTrigger component is using outline-none
while the other interactive menu items and the matching DropdownMenuSubTrigger
use outline-hidden. Update the class list in MenubarSubTrigger to use
outline-hidden so focus styling stays accessible in forced-colors/high-contrast
mode, keeping the change localized to the MenubarPrimitive.SubTrigger wrapper.

In `@apps/hackathon-lp-2026/components/ui/toaster.tsx`:
- Around line 1-36: The Toaster component is rendering a toast stack that is not
mounted anywhere, and the repo also contains duplicate hook implementations
under components/ui alongside the canonical hooks versions. Remove the unused
toaster wiring in Toaster and keep only one source of truth for the toast/mobile
hooks, updating any imports to use the shared hooks use-toast/use-mobile symbols
so there are no stale duplicates.

In `@apps/hackathon-lp-2026/components/ui/use-mobile.tsx`:
- Around line 1-20: The useIsMobile hook here is a duplicate of the shared
implementation, which risks diverging behavior over time. Remove the local hook
in use-mobile.tsx and make this module re-export or import the canonical
useIsMobile from the shared hooks/use-mobile implementation so sidebar.tsx and
other consumers all use the same source of truth.

In `@apps/hackathon-lp-2026/components/ui/use-toast.ts`:
- Around line 174-182: The listener registration effect in use-toast.ts is
resubscribing on every state change because the React.useEffect dependency is
[state] instead of the stable setState callback. Update the effect that
pushes/removes setState from listeners so it only runs on mount/unmount by
removing the changing state dependency and using the stable setter reference in
the cleanup.
- Around line 1-16: The toast state logic is duplicated here and in
hooks/use-toast.ts, creating two separate unsynchronized stores. Consolidate the
implementation into a single source of truth in one module (for example the
existing useToast/toast/reducer code) and make the other module re-export it so
all callers share the same toast state. Keep the shared symbols like useToast,
toast, and reducer in one place and update imports accordingly.

In `@apps/hackathon-lp-2026/hooks/use-toast.ts`:
- Around line 171-189: The useEffect in useToast is resubscribing on every state
change even though it only uses the stable setState callback; update the
dependency array to stop depending on state so the listener is registered once
and cleaned up once. Keep the push/splice logic in useToast unchanged and ensure
the effect depends only on the stable setter reference, not the toast state
itself.

In `@apps/hackathon-lp-2026/next.config.mjs`:
- Around line 5-7: The Next.js TypeScript config is suppressing build-time type
checking via ignoreBuildErrors in next.config.mjs, which weakens type safety.
Remove that flag from the typescript config in next.config.mjs and fix the
underlying type issues so next build runs with full TypeScript validation; use
the next.config.mjs typescript block as the target location.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e2e74beb-2ee6-4ece-bc3e-218735d1b1fd

📥 Commits

Reviewing files that changed from the base of the PR and between fbc788f and d75085d.

⛔ Files ignored due to path filters (42)
  • apps/hackathon-lp-2026/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • apps/hackathon-lp-2026/public/Jaguar.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/SP_Astar_Color_Black.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/SP_SEKKA_SHIRETOKO.jpeg is excluded by !**/*.jpeg
  • apps/hackathon-lp-2026/public/SP_as_logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/apple-icon.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/Astar_logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/BitcoinLogo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/CosmosLogo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/NEM_Logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/Symbol_Logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/avalanche_logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/eth.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/mona.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/soneiumLogo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/cryptlogo/suilogo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/goto.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/hayakawa_profile.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/icon-dark-32x32.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/icon-light-32x32.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/icon.svg is excluded by !**/*.svg
  • apps/hackathon-lp-2026/public/images/Daoka.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/chaintokyo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/design-mode/logo_hacktus_%EF%BD%82_2026S.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/logo-hacktus-fabi.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/pleasanter.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/sp-gox-logo-w.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/sp-hatchet-avatar.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/sp-one-line-full-color-light.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/sp-progate.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/images/sp-wavee2.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/kuramochi.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/logo-hacktus-2026.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/mizuki.jpg is excluded by !**/*.jpg
  • apps/hackathon-lp-2026/public/placeholder-logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/placeholder-logo.svg is excluded by !**/*.svg
  • apps/hackathon-lp-2026/public/placeholder-user.jpg is excluded by !**/*.jpg
  • apps/hackathon-lp-2026/public/placeholder.jpg is excluded by !**/*.jpg
  • apps/hackathon-lp-2026/public/placeholder.svg is excluded by !**/*.svg
  • apps/hackathon-lp-2026/public/sp_fushiginayado.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/sp_tss_logo.png is excluded by !**/*.png
  • apps/hackathon-lp-2026/public/takahashi.png is excluded by !**/*.png
📒 Files selected for processing (94)
  • apps/hackathon-lp-2026/.gitignore
  • apps/hackathon-lp-2026/.npmrc
  • apps/hackathon-lp-2026/README.md
  • apps/hackathon-lp-2026/app/globals.css
  • apps/hackathon-lp-2026/app/layout.tsx
  • apps/hackathon-lp-2026/app/page.tsx
  • apps/hackathon-lp-2026/components.json
  • apps/hackathon-lp-2026/components/about.tsx
  • apps/hackathon-lp-2026/components/circuit-background.tsx
  • apps/hackathon-lp-2026/components/entry.tsx
  • apps/hackathon-lp-2026/components/faq.tsx
  • apps/hackathon-lp-2026/components/final-cta.tsx
  • apps/hackathon-lp-2026/components/footer.tsx
  • apps/hackathon-lp-2026/components/hero.tsx
  • apps/hackathon-lp-2026/components/highlights.tsx
  • apps/hackathon-lp-2026/components/judges.tsx
  • apps/hackathon-lp-2026/components/multi-chain.tsx
  • apps/hackathon-lp-2026/components/navigation.tsx
  • apps/hackathon-lp-2026/components/nemtus-info.tsx
  • apps/hackathon-lp-2026/components/participation-flow.tsx
  • apps/hackathon-lp-2026/components/prizes.tsx
  • apps/hackathon-lp-2026/components/results.tsx
  • apps/hackathon-lp-2026/components/schedule.tsx
  • apps/hackathon-lp-2026/components/sponsors.tsx
  • apps/hackathon-lp-2026/components/theme-provider.tsx
  • apps/hackathon-lp-2026/components/themes.tsx
  • apps/hackathon-lp-2026/components/ui/accordion.tsx
  • apps/hackathon-lp-2026/components/ui/alert-dialog.tsx
  • apps/hackathon-lp-2026/components/ui/alert.tsx
  • apps/hackathon-lp-2026/components/ui/aspect-ratio.tsx
  • apps/hackathon-lp-2026/components/ui/avatar.tsx
  • apps/hackathon-lp-2026/components/ui/badge.tsx
  • apps/hackathon-lp-2026/components/ui/breadcrumb.tsx
  • apps/hackathon-lp-2026/components/ui/button-group.tsx
  • apps/hackathon-lp-2026/components/ui/button.tsx
  • apps/hackathon-lp-2026/components/ui/calendar.tsx
  • apps/hackathon-lp-2026/components/ui/card.tsx
  • apps/hackathon-lp-2026/components/ui/carousel.tsx
  • apps/hackathon-lp-2026/components/ui/chart.tsx
  • apps/hackathon-lp-2026/components/ui/checkbox.tsx
  • apps/hackathon-lp-2026/components/ui/collapsible.tsx
  • apps/hackathon-lp-2026/components/ui/command.tsx
  • apps/hackathon-lp-2026/components/ui/context-menu.tsx
  • apps/hackathon-lp-2026/components/ui/dialog.tsx
  • apps/hackathon-lp-2026/components/ui/drawer.tsx
  • apps/hackathon-lp-2026/components/ui/dropdown-menu.tsx
  • apps/hackathon-lp-2026/components/ui/empty.tsx
  • apps/hackathon-lp-2026/components/ui/field.tsx
  • apps/hackathon-lp-2026/components/ui/form.tsx
  • apps/hackathon-lp-2026/components/ui/hover-card.tsx
  • apps/hackathon-lp-2026/components/ui/input-group.tsx
  • apps/hackathon-lp-2026/components/ui/input-otp.tsx
  • apps/hackathon-lp-2026/components/ui/input.tsx
  • apps/hackathon-lp-2026/components/ui/item.tsx
  • apps/hackathon-lp-2026/components/ui/kbd.tsx
  • apps/hackathon-lp-2026/components/ui/label.tsx
  • apps/hackathon-lp-2026/components/ui/menubar.tsx
  • apps/hackathon-lp-2026/components/ui/navigation-menu.tsx
  • apps/hackathon-lp-2026/components/ui/pagination.tsx
  • apps/hackathon-lp-2026/components/ui/popover.tsx
  • apps/hackathon-lp-2026/components/ui/progress.tsx
  • apps/hackathon-lp-2026/components/ui/radio-group.tsx
  • apps/hackathon-lp-2026/components/ui/resizable.tsx
  • apps/hackathon-lp-2026/components/ui/scroll-area.tsx
  • apps/hackathon-lp-2026/components/ui/select.tsx
  • apps/hackathon-lp-2026/components/ui/separator.tsx
  • apps/hackathon-lp-2026/components/ui/sheet.tsx
  • apps/hackathon-lp-2026/components/ui/sidebar.tsx
  • apps/hackathon-lp-2026/components/ui/skeleton.tsx
  • apps/hackathon-lp-2026/components/ui/slider.tsx
  • apps/hackathon-lp-2026/components/ui/sonner.tsx
  • apps/hackathon-lp-2026/components/ui/spinner.tsx
  • apps/hackathon-lp-2026/components/ui/switch.tsx
  • apps/hackathon-lp-2026/components/ui/table.tsx
  • apps/hackathon-lp-2026/components/ui/tabs.tsx
  • apps/hackathon-lp-2026/components/ui/textarea.tsx
  • apps/hackathon-lp-2026/components/ui/toast.tsx
  • apps/hackathon-lp-2026/components/ui/toaster.tsx
  • apps/hackathon-lp-2026/components/ui/toggle-group.tsx
  • apps/hackathon-lp-2026/components/ui/toggle.tsx
  • apps/hackathon-lp-2026/components/ui/tooltip.tsx
  • apps/hackathon-lp-2026/components/ui/use-mobile.tsx
  • apps/hackathon-lp-2026/components/ui/use-toast.ts
  • apps/hackathon-lp-2026/hooks/use-in-view.tsx
  • apps/hackathon-lp-2026/hooks/use-mobile.ts
  • apps/hackathon-lp-2026/hooks/use-toast.ts
  • apps/hackathon-lp-2026/lib/constants.ts
  • apps/hackathon-lp-2026/lib/utils.ts
  • apps/hackathon-lp-2026/next.config.mjs
  • apps/hackathon-lp-2026/package.json
  • apps/hackathon-lp-2026/postcss.config.mjs
  • apps/hackathon-lp-2026/styles/globals.css
  • apps/hackathon-lp-2026/tsconfig.json
  • apps/hackathon-lp-2026/wrangler.toml

Comment thread apps/hackathon-lp-2026/app/globals.css Outdated
Comment thread apps/hackathon-lp-2026/components/circuit-background.tsx Outdated
Comment thread apps/hackathon-lp-2026/components/final-cta.tsx
Comment thread apps/hackathon-lp-2026/components/footer.tsx Outdated
Comment thread apps/hackathon-lp-2026/components/hero.tsx
Comment thread apps/hackathon-lp-2026/components/ui/chart.tsx
Comment thread apps/hackathon-lp-2026/components/ui/collapsible.tsx Outdated
Comment thread apps/hackathon-lp-2026/components/ui/empty.tsx Outdated
Comment thread apps/hackathon-lp-2026/components/ui/navigation-menu.tsx Outdated
Comment thread apps/hackathon-lp-2026/styles/globals.css
YasunoriMATSUOKA and others added 4 commits July 2, 2026 22:46
…it/e2e/audit/socket)

Tooling for apps/hackathon-lp-2026 (pnpm, standalone):
- ESLint 9 flat config (typescript-eslint + react + react-hooks + @next/next) — passes
- Prettier (.prettierrc) + format / format:check — codebase formatted to a baseline
- type:check (tsc --noEmit): fixed the 5 v0 type errors centrally in hooks/use-in-view
  (generic ref + amount->threshold), so they are caught rather than masked here
- Vitest + Testing Library (jsdom) — 14 guardrail tests: constants invariants, cn(),
  useInView behavior, Entry CTA gating on IS_HACKATHON_ENDED (both states), FAQ accordion
- Playwright e2e against the static export (out/) — 4 tests: title, key sections,
  entry inert while ended, FAQ interaction, no JS runtime errors

Scripts: lint / format / format:check / type:check / test / e2e / preview.

CI: .github/workflows/ci-hackathon-lp-2026.yml (path-filtered, pnpm) with jobs:
- verify: audit (--audit-level=high) + frozen install + lint + format:check + type:check
  + build + unit
- e2e: playwright (chromium)
- socket: runs `socket ci` when SOCKET_SECURITY_API_KEY is set, else no-op
Deployment stays with Cloudflare Workers Builds (Git integration) — CI is checks only.

Security: bumped next 16.0.10 -> 16.2.10 (clears 9 Next SSR/middleware advisories that do
not apply to a static export); allowlisted the remaining transitive lodash `_.template`
advisory (GHSA-r5fr-rjxr-66jc via recharts, unreachable in this static LP) through
pnpm.auditConfig.ignoreGhsas so audit stays green and still blocks NEW high vulns.

Storybook deferred: the vitest component/interaction tests + playwright e2e already cover
the interactive behavior; a full Storybook harness adds limited value for this LP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…p secret job

Mirror nemtus/symbol-rest-api-client's token-free Socket setup instead of the
API-key-based `socket ci` job:
- Socket Firewall Free (SocketDev/action@…, mode: firewall-free — no token) wraps
  the pnpm install in the verify and e2e jobs (`sfw pnpm install --frozen-lockfile`),
  blocking confirmed-malicious packages at fetch time.
- Add repo-root socket.yml for the Socket GitHub App (PR dependency-risk comments),
  with monorepo trigger paths (npm workspace + standalone npm apps + the pnpm 2026 app).
- Remove the socket job that required SOCKET_SECURITY_API_KEY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ydration)

- app/globals.css: fix BlinkMacMacSystemFont -> BlinkMacSystemFont (font fallback typo)
- footer: (c) 2025 -> 2026
- circuit-background: move Math.random() grid generation from module scope into a
  client-only useEffect/useState, avoiding a static-export hydration mismatch/flicker

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…loudflare cutover

hackathon-2026.nemtus.com currently points at Vercel via an existing Cloudflare DNS
record. Keeping the custom_domain route active would make the first Workers Builds
deploy fail on a DNS conflict, so comment it out to deploy to *.workers.dev for safe
verification. Restored by a follow-up PR once the Vercel DNS record is deleted.
@YasunoriMATSUOKA YasunoriMATSUOKA merged commit 8b95474 into main Jul 2, 2026
4 checks passed
@YasunoriMATSUOKA YasunoriMATSUOKA deleted the feat/lp-2026-nextjs branch July 2, 2026 14:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
apps/hackathon-lp-2026/components/sponsors.tsx (2)

88-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: extract a Sponsor interface instead of (typeof SPONSOR_LOGOS)[0].

Deriving the prop type from the array element works but is slightly indirect; an explicit interface Sponsor { name: string; logo: string; description: string; url: string } would be clearer and reusable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/sponsors.tsx` around lines 88 - 92, The
SponsorCard props currently infer sponsor from (typeof SPONSOR_LOGOS)[0], which
is indirect and harder to reuse. Define a named Sponsor interface in
sponsors.tsx with the sponsor fields, update SponsorCard to accept sponsor:
Sponsor, and use that interface anywhere the sponsor shape is needed so the type
is explicit and reusable.

131-131: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider next/image for LCP, with static-export caveats.

Lint flags plain <img> for LCP/bandwidth. Since this app builds with output: 'export', next/image's default optimizer requires images.unoptimized: true or a custom loader (e.g., Cloudflare Images) to work with static export. Worth confirming this was a deliberate tradeoff rather than an oversight.

Also applies to: 220-220

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/components/sponsors.tsx` at line 131, The sponsor
image usage in the relevant component still relies on plain <img>, which
triggers the LCP/bandwidth lint warning. Update the image rendering in
sponsors.tsx to use next/image where appropriate, and make sure the
static-export setup is handled correctly by either setting images.unoptimized:
true or using a compatible custom loader. Also review the other img occurrence
mentioned in the same component and apply the same choice consistently.

Source: Linters/SAST tools

apps/hackathon-lp-2026/test/use-in-view.test.tsx (1)

43-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the once: false reset behavior.

Current tests cover the amountthreshold mapping and the latch-to-true case, but the newly added once option's reset-to-false path (hooks/use-in-view.tsx Line 26-28) isn't exercised.

✅ Suggested additional test
+  it("resets isInView to false on exit when once=false", () => {
+    function OnceFalseProbe() {
+      const { ref, isInView } = useInView<HTMLDivElement>({ once: false })
+      return <div ref={ref} data-testid="probe" data-inview={String(isInView)} />
+    }
+    const { getByTestId } = render(<OnceFalseProbe />)
+    act(() => {
+      lastCallback?.([{ isIntersecting: true }])
+    })
+    expect(getByTestId("probe").getAttribute("data-inview")).toBe("true")
+    act(() => {
+      lastCallback?.([{ isIntersecting: false }])
+    })
+    expect(getByTestId("probe").getAttribute("data-inview")).toBe("false")
+  })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/test/use-in-view.test.tsx` around lines 43 - 52, Add a
test in use-in-view.test.tsx to cover the once: false reset path in useInView,
since the current Probe-based tests only verify the latch-to-true behavior.
Update the existing test suite near the latches isInView test to simulate an
intersecting callback followed by a non-intersecting one, and assert that the
hook resets data-inview back to false when once is false. Use the existing Probe
component, lastCallback, and useInView-related test setup to keep the coverage
aligned with hooks/use-in-view.tsx.
apps/hackathon-lp-2026/e2e/home.spec.ts (1)

7-13: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Broad console-error filter could mask real regressions.

Failed to load resource is matched loosely against any console error text, so a genuinely broken static asset (e.g. a missing JS chunk from the static export) would be silently ignored rather than failing the test, alongside the intended favicon-probe noise.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/hackathon-lp-2026/e2e/home.spec.ts` around lines 7 - 13, The console
error filter in the e2e home spec is too broad and can hide real asset
regressions. Tighten the guard inside the page.on("console") handler so it only
ignores the specific benign probe you intend to skip (for example, the favicon
request), rather than any msg.text() containing “Failed to load resource”; keep
failing on broken static assets while still allowing harmless browser noise. Use
the existing consoleErrors collection and the page.on("console") logic as the
place to update.
.github/workflows/ci-hackathon-lp-2026.yml (1)

64-85: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider gating e2e on verify succeeding.

The e2e job has no needs: verify, so Playwright runs (including its own install/build) even when lint/typecheck/unit tests already failed, wasting CI minutes on a doomed PR.

   e2e:
     name: e2e (playwright)
+    needs: verify
     runs-on: ubuntu-latest
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-hackathon-lp-2026.yml around lines 64 - 85, The e2e job
currently runs independently, so it can spend time on Playwright install/build
even after earlier checks fail. Update the e2e job in the workflow to depend on
the verify job by adding a needs relationship, so e2e only starts after verify
succeeds; keep the rest of the e2e steps unchanged and reference the e2e and
verify job names when locating the workflow block.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci-hackathon-lp-2026.yml:
- Line 39: Both jobs use actions/checkout without disabling persisted Git
credentials, which leaves the GITHUB_TOKEN available to later processes in the
job. Update each checkout step in ci-hackathon-lp-2026.yml to set
persist-credentials to false on the actions/checkout invocation so the token is
not written to local git config. Make the change in both checkout usages,
keeping the rest of the job behavior unchanged.

---

Nitpick comments:
In @.github/workflows/ci-hackathon-lp-2026.yml:
- Around line 64-85: The e2e job currently runs independently, so it can spend
time on Playwright install/build even after earlier checks fail. Update the e2e
job in the workflow to depend on the verify job by adding a needs relationship,
so e2e only starts after verify succeeds; keep the rest of the e2e steps
unchanged and reference the e2e and verify job names when locating the workflow
block.

In `@apps/hackathon-lp-2026/components/sponsors.tsx`:
- Around line 88-92: The SponsorCard props currently infer sponsor from (typeof
SPONSOR_LOGOS)[0], which is indirect and harder to reuse. Define a named Sponsor
interface in sponsors.tsx with the sponsor fields, update SponsorCard to accept
sponsor: Sponsor, and use that interface anywhere the sponsor shape is needed so
the type is explicit and reusable.
- Line 131: The sponsor image usage in the relevant component still relies on
plain <img>, which triggers the LCP/bandwidth lint warning. Update the image
rendering in sponsors.tsx to use next/image where appropriate, and make sure the
static-export setup is handled correctly by either setting images.unoptimized:
true or using a compatible custom loader. Also review the other img occurrence
mentioned in the same component and apply the same choice consistently.

In `@apps/hackathon-lp-2026/e2e/home.spec.ts`:
- Around line 7-13: The console error filter in the e2e home spec is too broad
and can hide real asset regressions. Tighten the guard inside the
page.on("console") handler so it only ignores the specific benign probe you
intend to skip (for example, the favicon request), rather than any msg.text()
containing “Failed to load resource”; keep failing on broken static assets while
still allowing harmless browser noise. Use the existing consoleErrors collection
and the page.on("console") logic as the place to update.

In `@apps/hackathon-lp-2026/test/use-in-view.test.tsx`:
- Around line 43-52: Add a test in use-in-view.test.tsx to cover the once: false
reset path in useInView, since the current Probe-based tests only verify the
latch-to-true behavior. Update the existing test suite near the latches isInView
test to simulate an intersecting callback followed by a non-intersecting one,
and assert that the hook resets data-inview back to false when once is false.
Use the existing Probe component, lastCallback, and useInView-related test setup
to keep the coverage aligned with hooks/use-in-view.tsx.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d69ac340-199c-4b97-b815-53a8415fcc10

📥 Commits

Reviewing files that changed from the base of the PR and between d75085d and 891d960.

⛔ Files ignored due to path filters (1)
  • apps/hackathon-lp-2026/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (106)
  • .github/workflows/ci-hackathon-lp-2026.yml
  • apps/hackathon-lp-2026/.gitignore
  • apps/hackathon-lp-2026/.prettierignore
  • apps/hackathon-lp-2026/.prettierrc.json
  • apps/hackathon-lp-2026/README.md
  • apps/hackathon-lp-2026/app/globals.css
  • apps/hackathon-lp-2026/app/layout.tsx
  • apps/hackathon-lp-2026/components/about.tsx
  • apps/hackathon-lp-2026/components/circuit-background.tsx
  • apps/hackathon-lp-2026/components/entry.tsx
  • apps/hackathon-lp-2026/components/faq.tsx
  • apps/hackathon-lp-2026/components/final-cta.tsx
  • apps/hackathon-lp-2026/components/footer.tsx
  • apps/hackathon-lp-2026/components/hero.tsx
  • apps/hackathon-lp-2026/components/highlights.tsx
  • apps/hackathon-lp-2026/components/judges.tsx
  • apps/hackathon-lp-2026/components/multi-chain.tsx
  • apps/hackathon-lp-2026/components/navigation.tsx
  • apps/hackathon-lp-2026/components/nemtus-info.tsx
  • apps/hackathon-lp-2026/components/participation-flow.tsx
  • apps/hackathon-lp-2026/components/prizes.tsx
  • apps/hackathon-lp-2026/components/results.tsx
  • apps/hackathon-lp-2026/components/schedule.tsx
  • apps/hackathon-lp-2026/components/sponsors.tsx
  • apps/hackathon-lp-2026/components/theme-provider.tsx
  • apps/hackathon-lp-2026/components/themes.tsx
  • apps/hackathon-lp-2026/components/ui/accordion.tsx
  • apps/hackathon-lp-2026/components/ui/alert-dialog.tsx
  • apps/hackathon-lp-2026/components/ui/alert.tsx
  • apps/hackathon-lp-2026/components/ui/aspect-ratio.tsx
  • apps/hackathon-lp-2026/components/ui/avatar.tsx
  • apps/hackathon-lp-2026/components/ui/badge.tsx
  • apps/hackathon-lp-2026/components/ui/breadcrumb.tsx
  • apps/hackathon-lp-2026/components/ui/button-group.tsx
  • apps/hackathon-lp-2026/components/ui/button.tsx
  • apps/hackathon-lp-2026/components/ui/calendar.tsx
  • apps/hackathon-lp-2026/components/ui/card.tsx
  • apps/hackathon-lp-2026/components/ui/carousel.tsx
  • apps/hackathon-lp-2026/components/ui/chart.tsx
  • apps/hackathon-lp-2026/components/ui/checkbox.tsx
  • apps/hackathon-lp-2026/components/ui/collapsible.tsx
  • apps/hackathon-lp-2026/components/ui/command.tsx
  • apps/hackathon-lp-2026/components/ui/context-menu.tsx
  • apps/hackathon-lp-2026/components/ui/dialog.tsx
  • apps/hackathon-lp-2026/components/ui/drawer.tsx
  • apps/hackathon-lp-2026/components/ui/dropdown-menu.tsx
  • apps/hackathon-lp-2026/components/ui/empty.tsx
  • apps/hackathon-lp-2026/components/ui/field.tsx
  • apps/hackathon-lp-2026/components/ui/form.tsx
  • apps/hackathon-lp-2026/components/ui/hover-card.tsx
  • apps/hackathon-lp-2026/components/ui/input-group.tsx
  • apps/hackathon-lp-2026/components/ui/input-otp.tsx
  • apps/hackathon-lp-2026/components/ui/input.tsx
  • apps/hackathon-lp-2026/components/ui/item.tsx
  • apps/hackathon-lp-2026/components/ui/kbd.tsx
  • apps/hackathon-lp-2026/components/ui/label.tsx
  • apps/hackathon-lp-2026/components/ui/menubar.tsx
  • apps/hackathon-lp-2026/components/ui/navigation-menu.tsx
  • apps/hackathon-lp-2026/components/ui/pagination.tsx
  • apps/hackathon-lp-2026/components/ui/popover.tsx
  • apps/hackathon-lp-2026/components/ui/progress.tsx
  • apps/hackathon-lp-2026/components/ui/radio-group.tsx
  • apps/hackathon-lp-2026/components/ui/resizable.tsx
  • apps/hackathon-lp-2026/components/ui/scroll-area.tsx
  • apps/hackathon-lp-2026/components/ui/select.tsx
  • apps/hackathon-lp-2026/components/ui/separator.tsx
  • apps/hackathon-lp-2026/components/ui/sheet.tsx
  • apps/hackathon-lp-2026/components/ui/sidebar.tsx
  • apps/hackathon-lp-2026/components/ui/skeleton.tsx
  • apps/hackathon-lp-2026/components/ui/slider.tsx
  • apps/hackathon-lp-2026/components/ui/sonner.tsx
  • apps/hackathon-lp-2026/components/ui/spinner.tsx
  • apps/hackathon-lp-2026/components/ui/switch.tsx
  • apps/hackathon-lp-2026/components/ui/table.tsx
  • apps/hackathon-lp-2026/components/ui/tabs.tsx
  • apps/hackathon-lp-2026/components/ui/textarea.tsx
  • apps/hackathon-lp-2026/components/ui/toast.tsx
  • apps/hackathon-lp-2026/components/ui/toaster.tsx
  • apps/hackathon-lp-2026/components/ui/toggle-group.tsx
  • apps/hackathon-lp-2026/components/ui/toggle.tsx
  • apps/hackathon-lp-2026/components/ui/tooltip.tsx
  • apps/hackathon-lp-2026/components/ui/use-mobile.tsx
  • apps/hackathon-lp-2026/components/ui/use-toast.ts
  • apps/hackathon-lp-2026/e2e/home.spec.ts
  • apps/hackathon-lp-2026/eslint.config.mjs
  • apps/hackathon-lp-2026/hooks/use-in-view.tsx
  • apps/hackathon-lp-2026/hooks/use-mobile.ts
  • apps/hackathon-lp-2026/hooks/use-toast.ts
  • apps/hackathon-lp-2026/lib/constants.ts
  • apps/hackathon-lp-2026/lib/utils.ts
  • apps/hackathon-lp-2026/next.config.mjs
  • apps/hackathon-lp-2026/package.json
  • apps/hackathon-lp-2026/playwright.config.ts
  • apps/hackathon-lp-2026/postcss.config.mjs
  • apps/hackathon-lp-2026/styles/globals.css
  • apps/hackathon-lp-2026/test/constants.test.ts
  • apps/hackathon-lp-2026/test/entry-open.test.tsx
  • apps/hackathon-lp-2026/test/entry.test.tsx
  • apps/hackathon-lp-2026/test/faq.test.tsx
  • apps/hackathon-lp-2026/test/use-in-view.test.tsx
  • apps/hackathon-lp-2026/test/utils.test.ts
  • apps/hackathon-lp-2026/tsconfig.json
  • apps/hackathon-lp-2026/vitest.config.ts
  • apps/hackathon-lp-2026/vitest.setup.ts
  • apps/hackathon-lp-2026/wrangler.toml
  • socket.yml
✅ Files skipped from review due to trivial changes (11)
  • apps/hackathon-lp-2026/.prettierignore
  • apps/hackathon-lp-2026/test/utils.test.ts
  • apps/hackathon-lp-2026/.gitignore
  • apps/hackathon-lp-2026/lib/constants.ts
  • apps/hackathon-lp-2026/.prettierrc.json
  • apps/hackathon-lp-2026/components/ui/input.tsx
  • apps/hackathon-lp-2026/postcss.config.mjs
  • apps/hackathon-lp-2026/next.config.mjs
  • apps/hackathon-lp-2026/README.md
  • apps/hackathon-lp-2026/vitest.config.ts
  • apps/hackathon-lp-2026/components/ui/button-group.tsx
🚧 Files skipped from review as they are similar to previous changes (76)
  • apps/hackathon-lp-2026/components/ui/toggle.tsx
  • apps/hackathon-lp-2026/components/ui/checkbox.tsx
  • apps/hackathon-lp-2026/components/ui/textarea.tsx
  • apps/hackathon-lp-2026/components/theme-provider.tsx
  • apps/hackathon-lp-2026/components/participation-flow.tsx
  • apps/hackathon-lp-2026/hooks/use-mobile.ts
  • apps/hackathon-lp-2026/components/ui/toaster.tsx
  • apps/hackathon-lp-2026/components/ui/sonner.tsx
  • apps/hackathon-lp-2026/components/ui/collapsible.tsx
  • apps/hackathon-lp-2026/components/nemtus-info.tsx
  • apps/hackathon-lp-2026/components/ui/aspect-ratio.tsx
  • apps/hackathon-lp-2026/lib/utils.ts
  • apps/hackathon-lp-2026/components/ui/radio-group.tsx
  • apps/hackathon-lp-2026/tsconfig.json
  • apps/hackathon-lp-2026/components/ui/avatar.tsx
  • apps/hackathon-lp-2026/components/ui/skeleton.tsx
  • apps/hackathon-lp-2026/components/ui/kbd.tsx
  • apps/hackathon-lp-2026/components/ui/label.tsx
  • apps/hackathon-lp-2026/components/ui/switch.tsx
  • apps/hackathon-lp-2026/components/ui/tabs.tsx
  • apps/hackathon-lp-2026/components/ui/separator.tsx
  • apps/hackathon-lp-2026/components/ui/spinner.tsx
  • apps/hackathon-lp-2026/components/results.tsx
  • apps/hackathon-lp-2026/components/themes.tsx
  • apps/hackathon-lp-2026/components/ui/button.tsx
  • apps/hackathon-lp-2026/components/ui/progress.tsx
  • apps/hackathon-lp-2026/components/ui/resizable.tsx
  • apps/hackathon-lp-2026/styles/globals.css
  • apps/hackathon-lp-2026/components/prizes.tsx
  • apps/hackathon-lp-2026/components/ui/alert.tsx
  • apps/hackathon-lp-2026/components/schedule.tsx
  • apps/hackathon-lp-2026/components/ui/accordion.tsx
  • apps/hackathon-lp-2026/components/highlights.tsx
  • apps/hackathon-lp-2026/components/ui/slider.tsx
  • apps/hackathon-lp-2026/components/ui/input-otp.tsx
  • apps/hackathon-lp-2026/app/layout.tsx
  • apps/hackathon-lp-2026/components/ui/alert-dialog.tsx
  • apps/hackathon-lp-2026/components/ui/toggle-group.tsx
  • apps/hackathon-lp-2026/components/ui/item.tsx
  • apps/hackathon-lp-2026/components/ui/breadcrumb.tsx
  • apps/hackathon-lp-2026/components/ui/scroll-area.tsx
  • apps/hackathon-lp-2026/components/ui/use-mobile.tsx
  • apps/hackathon-lp-2026/components/ui/command.tsx
  • apps/hackathon-lp-2026/components/about.tsx
  • apps/hackathon-lp-2026/components/navigation.tsx
  • apps/hackathon-lp-2026/components/ui/drawer.tsx
  • apps/hackathon-lp-2026/components/faq.tsx
  • apps/hackathon-lp-2026/components/judges.tsx
  • apps/hackathon-lp-2026/components/ui/navigation-menu.tsx
  • apps/hackathon-lp-2026/components/ui/table.tsx
  • apps/hackathon-lp-2026/components/ui/badge.tsx
  • apps/hackathon-lp-2026/components/final-cta.tsx
  • apps/hackathon-lp-2026/components/ui/hover-card.tsx
  • apps/hackathon-lp-2026/components/ui/sheet.tsx
  • apps/hackathon-lp-2026/components/ui/pagination.tsx
  • apps/hackathon-lp-2026/components/multi-chain.tsx
  • apps/hackathon-lp-2026/components/ui/use-toast.ts
  • apps/hackathon-lp-2026/components/footer.tsx
  • apps/hackathon-lp-2026/components/ui/toast.tsx
  • apps/hackathon-lp-2026/components/ui/carousel.tsx
  • apps/hackathon-lp-2026/components/ui/chart.tsx
  • apps/hackathon-lp-2026/components/ui/popover.tsx
  • apps/hackathon-lp-2026/components/ui/dialog.tsx
  • apps/hackathon-lp-2026/components/ui/calendar.tsx
  • apps/hackathon-lp-2026/components/ui/select.tsx
  • apps/hackathon-lp-2026/components/ui/card.tsx
  • apps/hackathon-lp-2026/components/hero.tsx
  • apps/hackathon-lp-2026/hooks/use-toast.ts
  • apps/hackathon-lp-2026/components/ui/dropdown-menu.tsx
  • apps/hackathon-lp-2026/components/ui/menubar.tsx
  • apps/hackathon-lp-2026/components/ui/context-menu.tsx
  • apps/hackathon-lp-2026/components/ui/input-group.tsx
  • apps/hackathon-lp-2026/components/ui/tooltip.tsx
  • apps/hackathon-lp-2026/components/entry.tsx
  • apps/hackathon-lp-2026/components/ui/field.tsx
  • apps/hackathon-lp-2026/components/ui/sidebar.tsx

name: lint / format / types / build / unit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Set persist-credentials: false on checkout.

Both jobs check out the repo without persist-credentials: false, leaving the GITHUB_TOKEN in the local git config for the remainder of the job. Since pnpm install runs with scripts enabled (per .npmrc ignore-scripts=false) against third-party packages, a malicious/compromised transitive dependency's postinstall script could read and exfiltrate the token. permissions: contents: read limits blast radius but doesn't prevent local credential exposure to spawned processes.

🔒 Suggested fix
       - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+        with:
+          persist-credentials: false

Apply to both checkout steps (lines 39 and 68).

Also applies to: 68-68

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 39-39: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-hackathon-lp-2026.yml at line 39, Both jobs use
actions/checkout without disabling persisted Git credentials, which leaves the
GITHUB_TOKEN available to later processes in the job. Update each checkout step
in ci-hackathon-lp-2026.yml to set persist-credentials to false on the
actions/checkout invocation so the token is not written to local git config.
Make the change in both checkout usages, keeping the rest of the job behavior
unchanged.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant