async-params-and-build-errorsrun.md02_define/output/spec.mdNext 16 delivers params/searchParams to app router pages as Promises, but six pages in
apps/web typed and read them as plain objects, and next.config.ts set
typescript.ignoreBuildErrors: true, which hides exactly this class of bug from the build.
The user-visible consequences: search and pagination on /finances/invoices and
/finances/quotes silently do nothing, and /csat/[id] destructures its id from an
unresolved Promise so the CSAT detail page can never load a record.
All six affected pages now declare params/searchParams as Promise<...> in their prop
types and await them before reading values, matching the pattern the rest of the app
already uses. The two Promise.resolve(searchParams) workarounds (customer/activity,
customer/satisfaction) are replaced with plain typed awaits, and the mistyped
activity/[id] page gets the correct Promise type. With every app router entry point now
correctly typed (verified by a static sweep of every page.tsx/layout.tsx/route.ts in
apps/web), typescript.ignoreBuildErrors is removed from apps/web/next.config.ts so the
Vercel build type-checks again.
/finances/quotes and /finances/invoices./csat/[id] loads the record (customer-own form and read-only detail both render).Promise.resolve(searchParams) workarounds are replaced with typed awaits.next.config.ts no longer sets ignoreBuildErrors; the Vercel preview build passes with type checking on.access-control-hardening/finance-lists-scoping).03_build/output/notes.mdsearchParams was typed as a plain object
and read synchronously — page/search/limit came off an unresolved Promise, so search and
pagination were inert. Now Promise<...>-typed and awaited.const { id } = params destructured the id from a
Promise, so id was always undefined and the detail page never loaded a record. Now
Promise<{ id: string }>-typed and awaited.params via Promise.all, but the prop type said plain object. Now Promise-typed; the
concurrent Promise.all([getTenant(), params]) stays (it is the house pattern, see
proposals/create).await Promise.resolve(searchParams) workaround with a Promise-typed prop and a plain
await.typescript: { ignoreBuildErrors: true } so the Vercel
build type-checks again and this bug class stays fixed./finances/quotes and /finances/invoices — both pages
now await searchParams before deriving page/search/limit, so the values passed to
QuotesList/InvoicesList reflect the URL./csat/[id] loads the record — id is now awaited from params, so
csatService.findById and CsatDetail/CsatPublicFormWrapper receive a real id.Promise.resolve(searchParams) workarounds are replaced with typed awaits — both
customer pages now declare Promise<...> props and await searchParams directly.next.config.ts no longer sets ignoreBuildErrors — flag removed; the Vercel preview
build is the verifier that typechecking passes.ignoreBuildErrors off, next build
now validates every generated route entry against Next's PageProps (Promise-typed
params/searchParams). A static sweep of every page.tsx/layout.tsx/route.ts under
apps/web/app found no other synchronous params/searchParams access: all other pages
already use Promise<...> + await, no layout takes params, all route.ts files are
non-dynamic, and there are no generateMetadata/generateStaticParams exports. The six
fixed pages were the only offenders.tsc --noEmit (the CI Typechecking gate)
already covers all non-generated sources, so any new failure should come only from the
.next/types route validators. If the build flags a file under apps/web/components
(e.g. components/admin/*), note that another PR deletes dead component folders — do not
fix those there.