A single catalog of the cross-cutting bugs, dead code, and unresolved duplication discovered while writing these specs (August 2026), gathered from static reading of the code — none of this has been verified by running the app. Each item also appears inline in its relevant feature spec; this file exists so an agent can get the full picture in one read before making changes near any of these areas. Treat entries here as things to be aware of, not necessarily things to fix unless you were asked to — several are large enough in scope that they deserve their own ticket/PR.
- Root
npm run devdoesn't work — it runsturbo run dev, butturboisn't installed. The monorepo migration addedturboas a root devDependency and pointed the rootdev/build/lint/type-check/testscripts at it, but there's no unified orchestration actually wired up yet (see docs/LocalDevSetup.md, which has each app run its ownnpm run devin a separate terminal instead). Runningnpm run devfrom the repo root fails withturbo: command not foundunless you separatelynpm installturbo at the root. Fix: either install/use turbo properly with real pipeline config, or drop the root scripts until that's done so they don't imply a workflow that doesn't exist..claude/launch.json'skarmacircle-devconfig hit this directly and now runsnpm --prefix apps/web run devinstead of the root script. docs/DockerSetup.mdlists backend env vars for what is actually a frontend-onlydocker-compose.dev.yaml. The guide's "Step 3 - Add env variables" listsMONGO_URI,RAZORPAY_KEY_ID,KEY_ID,KEY_SECRET— none of which the frontend container reads (it only needsVITE_API_URL/VITE_RAZORPAY_KEY_ID, perapps/web/.env.example). Predates the monorepo migration; likely copy-pasted from backend docs at some point. Fix: rewrite that section to match whatapps/web's own.env.exampleactually documents.apps/web/.env.exampledocuments the wrong variable name. It showsVITE_MILANAPI, but every API call in the code readsimport.meta.env.VITE_API_URL. A contributor following the example file verbatim will get a broken app with no base URL. Fix: rename the example var toVITE_API_URL(or add both, with a comment).QueryClientProvider(@tanstack/react-query) wraps the whole app but nothing uses it. All data fetching goes through SWR or rawaxios. Either start using it deliberately or remove the wrapper/dependency to reduce confusion for future contributors.
/donatehas no route, even thoughapps/web/src/features/donate-shop-trending/pages/Donate.tsxexists (and that file is separately broken — see below)./events/:id-equivalent has no route, even thoughapps/web/src/features/events/pages/DetailedEvent.tsxexists as a one-line stub.apps/web/src/features/onboarding-profile/pages/UserProfile.tsxhas no route despite being a fairly complete page — see onboarding-profile.md.- Footer links to
/terms,/privacy,/cookies— none of these routes exist; clicking them hits the 404 page. - Navbar's account dropdown links to
/event/create(organization users only) — no such route exists.
apps/web/src/features/donate-shop-trending/pages/Donate.tsximports../../components/Cards/SingleOrganizationEvent/SingleOrganizationEventand../../components/Loading, neither of which exists anymore. Since the page also has no route, this currently doesn't break the app (Vite doesn't bundle unreachable-but-still-source-present files until something imports the chain at build time — verify this is actually true for your Vite/Rollup config before relying on it; if the file is ever wired into a route or otherwise imported, the build will fail immediately).apps/web/src/features/events/components/HostedEvents.tsxis a completely empty file (0 bytes) — importing it fails immediately (no default export).
- Two "create event" components (
features/events/components/CreateEvent.tsxandfeatures/events/components/CreateEvents.tsx) with different fields, different validation, and — critically — the shared one calls the user profile update endpoint instead of the event-creation endpoint. See events.md. - Two public profile pages (
features/onboarding-profile/pages/Profile.tsx, routed;features/onboarding-profile/pages/UserProfile.tsx, not routed) covering overlapping functionality, with different "is this my own profile" checks (Redux vs. an unused cookie). See onboarding-profile.md. - Two profile-edit modals (
ProfileCompletion.tsx,ProfileUpdate.tsx) that are ~80% identical JSX/logic, plus aProfileCompletioncomponent that itself has two Save buttons wired to two different code paths. See onboarding-profile.md. - Two auth submit-button implementations —
AuthButton.tsx(unused) vs. inline markup inAuth.tsx(live). See authentication.md. - Two validation systems for signup — the lightweight two-field check inside
useAuth.ts(live) vs. the much more completeuseValidation.ts+useFormLogic.tspair (unused by any page). See authentication.md. - Three different "is the user logged in" checks and three different logout cleanup sequences, none centralized. See state-management.md.
userEndpoints.updatevsuserEndpoints.updateProfile— two endpoint constants pointing at different URLs; onlyupdateProfileis actually used. See api-integration.md.
Organizations.tsx and Events.tsx both render arrays of 20 hardcoded fake records instead of calling the getOrganizations()/getEvents() functions that already exist for exactly this purpose (apps/web/src/features/organizations/services/Organizations.ts, apps/web/src/features/events/services/Events.ts).
EventCard, FeaturedEventCard, and FeaturedEventImage don't even accept/use props — all content is static JSX.
Dashboard.tsx's cover photo, profile photo, and follower/event counts are static.
OrganizationCard's banner image and follower/event counts are static regardless of the organization prop.
Landing.tsx's "Trusted by 300+ users" avatars are static.
TrackSection's analytics numbers are static and its tab-switcher isn't wired to anything.
See the relevant feature spec (organizations.md, events.md, dashboard.md, landing-home.md) for exactly which fields would need to become dynamic.
Both useProfileCompletion.validateForm and ProfileUpdate.validateForm compute newErrors, call setErrors(newErrors), and then call their respective PATCH API function unconditionally, regardless of whether newErrors is non-empty.
The Object.keys(newErrors).length === 0 check only affects the function's return value, not whether the request fires.
In practice, the Save buttons are also disabled while required fields are empty, which covers the "required field missing" case at the UI layer — but the length/format checks (description 100–500 chars, numeric pincode) can still be bypassed and will still hit the API. See onboarding-profile.md.
These exist, work as isolated units, and appear to be intended for future/finished use — prefer extending or wiring these up over writing new ones that duplicate their purpose:
ProfileElements.ts+getProfileFields.ts— generic profile-field metadata, unused by the (hardcoded-field)ProfileCompletion/ProfileUpdateforms.useValidation.ts+useFormLogic.ts— a fuller signup validator/handler pair, unused by the liveAuthpage.AuthButton.tsx— unused by the live auth page.Modal.tsx— a generic modal shell, unused; every modal in the app builds its own overlay markup instead.MilanInfoBanner— a finished marketing section, unmounted fromHome.tsx.Header.tsx+HeaderData.ts— has ready-made "organizations"/"events" copy, butOrganizations.tsx/Events.tsxboth build their own inline header instead of using it.PatchFetcher.ts— an SWR-style PATCH fetcher, unused (mutations go through directMilanApi.tscalls +mutate()instead).ClickAwayListener.tsx— unused generic utility.getEvents()/getOrganizations()(apps/web/src/features/events/services/Events.ts,apps/web/src/features/organizations/services/Organizations.ts) — real fetchers for events/organizations, unused because the pages that need them use hardcoded arrays instead.
Profile.tsxrenders its Subscribe/Sponsor/Edit/Logout button block twice in a row (copy-paste duplication, not an intentional repeated layout).Profile.tsx's map<iframe>readsuser?.iframe(the viewer's own Redux state) instead ofdetails?.iframe(the profile being viewed).Dashboard.tsxhas a strayconsole.login its "Edit Profile" click handler.useEvent.ts'ssubmitCallbackchecks a module-scopeerrorsobject populated by the lastvalidateEvent()call rather than re-validating the event being submitted right now — callers must callvalidateEvent()immediately beforehand to keep these in sync (whichCreateEvents.tsxdoes today, but it's an easy thing to break).ApiConnector.tshas a dead/unreachable status check (if (response.status === 400) console.error("... status 600 ...")) — the comment references 600 but the condition checks 400, and axios throws rather than resolving on 4xx by default, so this branch doesn't currently fire in practice.
Each feature folder now has a SPEC.md colocated inside it (e.g. apps/web/src/features/dashboard/SPEC.md) with full implementation-level detail; this section is a short index of the most significant new findings from that pass, for readers who only skim this file. Full explanation of each lives in the linked spec.
Dashboard.tsxpasses the wrong prop names toProfileCompletion(setOpenModal/editinstead of the component's actualsetShowEditModal) — clickingProfileCompletion's header "Save" button while it's rendered from/dashboardcallssetShowEditModal(false)onundefinedand throws, uncaught (no error boundary exists anywhere — see below). See dashboard/SPEC.md.ProfileCompletionandProfileUpdatecan both be mounted at once on/dashboard— their two trigger conditions (hasCompletedProfile === falseandopenModal === true) aren't mutually exclusive. See dashboard/SPEC.md.Dashboard.tsx's "Edit Profile" handler callshandleSetDefaultValues(profileData?.user)from its own, separateuseProfileCompletion()hook instance — since hook state isn't shared across separate call sites, this pre-fill has no effect on theProfileCompletionmodal that actually renders. See dashboard/SPEC.md.useProfileCompletion.validateFormandProfileUpdate.validateFormboth throw an uncaughtTypeError(data.statusonundefined) if their API call fails with no HTTP response at all (pure network failure) — on top of the already-documented non-blocking-validation bug. See onboarding-profile/SPEC.md.ProfileCompletion's two Save buttons take genuinely different code paths — only the header button closes the modal and refetches on success; the form's own bottom "Submit" button (via the hook'svalidateForm) leaves the modal open with no refetch. Refines the existing "two Save buttons" entry above. See onboarding-profile/SPEC.md.events/components/CreateEvent.tsx's Save button can never be enabled at all — 4 of the 6 required address fields it checks (city/state/country/pincode) are never written to by any input in the form; 8 visually distinct inputs across the form actually share only 2 real state slots (address.line1/address.line2). This is more severe than the already-documented "wrong endpoint" bug — the form cannot be submitted through normal interaction at all, so the wrong-endpoint bug can't even be observed by a real user. See events/SPEC.md.donate-shop-trending/services/PaymentGateway.tsreadsdata.currency/data.idinstead ofdata.data.currency/data.data.idoff the Axios response — both would beundefined, which would very likely break Razorpay's checkout widget (order_idis required) even afterDonate.tsx's broken imports and login-gate are fixed. See donate-shop-trending/SPEC.md.Donate.tsx'sloadScriptuseEffecthas no dependency array — it re-injects the Razorpay checkout<script>tag intodocument.bodyon every render, not just on mount. Same file's offline login-gate also redirects to/user/login, a route that doesn't exist (should be/auth/signin). See donate-shop-trending/SPEC.md.AuthButton.tsx(already-unused, see above) also navigates to/auth/login, a route that doesn't exist (should be/auth/signin) — latent since the component isn't rendered anywhere today. See authentication/SPEC.md.onboarding-profile/pages/UserProfile.tsx(already unrouted, see above) mixes hardcoded placeholder text directly with real fetched data (Lorem Ipsum and a hardcoded "Kolkata, West Bengal, India" address are concatenated onto, not replaced by, the realabout/city/state/country fields) and hardcodes(He/Him)as the pronoun line for every profile — this page needs more than a routing fix and a cookie-check fix before it's usable. See onboarding-profile/SPEC.md.- No app-wide React error boundary exists anywhere in the app — an uncaught render error (including the
Dashboard.tsx/ProfileCompletioncrash above) produces a blank white screen, not a fallback UI. See error-handling/SPEC.md. Profile.tsx's "Edit profile" button does nothing —showProfileModal/editProfileare set on click but never read anywhere in the file to renderProfileCompletion,ProfileUpdate, or anything else. Corrects an earlier version of this file (and ofonboarding-profile.md/onboarding-profile/SPEC.md), which described this button as openingProfileCompletion.ProfileCompletionis in fact only ever rendered fromDashboard.tsx. See onboarding-profile/SPEC.md.ProfileUpdate.tsx'shandleResetFieldsdrops thenamefield — copy-pasted fromuseProfileCompletion.ts's version, whose credentials shape never hadname— closing and reopening the modal after a reset shows a blank Organization Name. See onboarding-profile/SPEC.md.UserProfile.tsx's Logout button passes a plainonClick, which the sharedButtoncomponent silently discards (it spreads...propsand then explicitly overwritesonClickwith its ownonClickfunction, undefined here) — this button has never worked. Low-impact since this page isn't routed. See onboarding-profile/SPEC.md.- Correction, not a bug:
checkInternetConnection()does show a toast when offline (a rawtoast.error("Please check your internet connection"), fired from insidecheckInternetConnection()itself) — the earlier framing in this file and inerror-handling.md("the user just sees nothing") undersold this; there's still no persistent offline banner, just a one-shot generic toast per failed check. See error-handling/SPEC.md.