Skip to content

Commit c2863ed

Browse files
chore(web): Upgrade to next 16 (#970)
1 parent a2f80a2 commit c2863ed

File tree

16 files changed

+1498
-684
lines changed

16 files changed

+1498
-684
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Changed
1111
- Upgraded Vercel AI SDK from v5 to v6. [#969](https://github.com/sourcebot-dev/sourcebot/pull/969)
1212
- Added support for using bearer tokens with anthropic. [#967](https://github.com/sourcebot-dev/sourcebot/pull/967)
13+
- Updated to Next.JS 16. [#970](https://github.com/sourcebot-dev/sourcebot/pull/970)
1314

1415
## [4.13.1] - 2026-02-28
1516

packages/web/.eslintignore

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/web/.eslintrc.json

Lines changed: 0 additions & 26 deletions
This file was deleted.

packages/web/eslint.config.mjs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import nextCoreWebVitals from 'eslint-config-next/core-web-vitals';
2+
import tseslint from 'typescript-eslint';
3+
import tanstackQuery from '@tanstack/eslint-plugin-query';
4+
5+
const config = [
6+
...nextCoreWebVitals,
7+
...tseslint.configs.recommended,
8+
...tanstackQuery.configs['flat/recommended'],
9+
{
10+
rules: {
11+
// New react-hooks v7 rules disabled as too strict for this codebase's existing patterns.
12+
// `set-state-in-effect` flags a very common legitimate pattern (reading external state
13+
// into local state on mount / dependency change). `incompatible-library` produces false
14+
// positives against @tanstack/react-table and similar libraries.
15+
'react-hooks/set-state-in-effect': 'off',
16+
'react-hooks/incompatible-library': 'off',
17+
// `preserve-manual-memoization` is only relevant when the React Compiler is enabled.
18+
'react-hooks/preserve-manual-memoization': 'off',
19+
// `immutability` produces false positives for recursive useCallback patterns and
20+
// intentional module-level regex lastIndex resets.
21+
'react-hooks/immutability': 'off',
22+
23+
'react-hooks/exhaustive-deps': 'warn',
24+
'no-unused-vars': 'off',
25+
'no-extra-semi': 'off',
26+
},
27+
},
28+
{
29+
files: ['**/*.ts', '**/*.tsx'],
30+
rules: {
31+
'@typescript-eslint/no-unused-vars': [
32+
'warn',
33+
{
34+
argsIgnorePattern: '^_',
35+
varsIgnorePattern: '^_',
36+
caughtErrorsIgnorePattern: '^_',
37+
},
38+
],
39+
},
40+
},
41+
{
42+
// Replaces .eslintignore
43+
ignores: [
44+
'src/components/**',
45+
'next-env.d.ts',
46+
'src/proto/**',
47+
],
48+
},
49+
];
50+
51+
export default config;

packages/web/next.config.mjs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ const nextConfig = {
5454

5555
export default withSentryConfig(nextConfig, {
5656
// For all available options, see:
57-
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
58-
5957
org: process.env.SENTRY_ORG,
6058
project: process.env.SENTRY_WEBAPP_PROJECT,
6159
authToken: process.env.SENTRY_SMUAT,
@@ -70,23 +68,9 @@ export default withSentryConfig(nextConfig, {
7068
// Upload a larger set of source maps for prettier stack traces (increases build time)
7169
widenClientFileUpload: true,
7270

73-
// Automatically annotate React components to show their full name in breadcrumbs and session replay
74-
reactComponentAnnotation: {
75-
enabled: true,
76-
},
77-
7871
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
7972
// This can increase your server load as well as your hosting bill.
8073
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
8174
// side errors will fail.
8275
tunnelRoute: "/monitoring",
83-
84-
// Automatically tree-shake Sentry logger statements to reduce bundle size
85-
disableLogger: true,
86-
87-
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
88-
// See the following for more information:
89-
// https://docs.sentry.io/product/crons/
90-
// https://vercel.com/docs/cron-jobs
91-
automaticVercelMonitors: true,
9276
});

packages/web/package.json

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
"@replit/codemirror-lang-solidity": "^6.0.2",
9393
"@replit/codemirror-lang-svelte": "^6.0.0",
9494
"@replit/codemirror-vim": "^6.2.1",
95-
"@sentry/nextjs": "^9",
95+
"@sentry/nextjs": "^10.40.0",
9696
"@shopify/lang-jsonc": "^1.0.0",
9797
"@sourcebot/codemirror-lang-tcl": "^1.0.12",
9898
"@sourcebot/db": "workspace:*",
@@ -151,7 +151,7 @@
151151
"linguist-languages": "^9.3.1",
152152
"lucide-react": "^0.517.0",
153153
"micromatch": "^4.0.8",
154-
"next": "15.5.10",
154+
"next": "16.1.6",
155155
"next-auth": "^5.0.0-beta.30",
156156
"next-navigation-guard": "^0.2.0",
157157
"next-themes": "^0.3.0",
@@ -163,9 +163,9 @@
163163
"posthog-node": "^5.24.15",
164164
"pretty-bytes": "^6.1.1",
165165
"psl": "^1.15.0",
166-
"react": "^19.2.1",
166+
"react": "19.2.4",
167167
"react-device-detect": "^2.2.3",
168-
"react-dom": "^19.2.1",
168+
"react-dom": "19.2.4",
169169
"react-hook-form": "^7.53.0",
170170
"react-hotkeys-hook": "^4.5.1",
171171
"react-icons": "^5.3.0",
@@ -202,28 +202,29 @@
202202
"@types/node": "^20",
203203
"@types/nodemailer": "^6.4.17",
204204
"@types/psl": "^1.1.3",
205-
"@types/react": "19.2.1",
206-
"@types/react-dom": "19.2.1",
205+
"@types/react": "19.2.14",
206+
"@types/react-dom": "19.2.3",
207207
"@typescript-eslint/eslint-plugin": "^8.40.0",
208208
"@typescript-eslint/parser": "^8.40.0",
209209
"cross-env": "^7.0.3",
210-
"eslint": "^8",
211-
"eslint-config-next": "15.5.0",
210+
"eslint": "^9",
211+
"eslint-config-next": "16.1.6",
212212
"eslint-plugin-react": "^7.37.5",
213-
"eslint-plugin-react-hooks": "^5.2.0",
213+
"eslint-plugin-react-hooks": "^7.0.1",
214214
"jsdom": "^25.0.1",
215215
"npm-run-all": "^4.1.5",
216216
"postcss": "^8",
217217
"react-email": "^5.1.0",
218218
"tailwindcss": "^3.4.1",
219219
"tsx": "^4.19.2",
220220
"typescript": "^5",
221+
"typescript-eslint": "^8.56.1",
221222
"vite-tsconfig-paths": "^5.1.3",
222223
"vitest": "^2.1.5",
223224
"vitest-mock-extended": "^3.1.0"
224225
},
225226
"resolutions": {
226-
"@types/react": "19.2.1",
227-
"@types/react-dom": "19.2.1"
227+
"@types/react": "19.2.14",
228+
"@types/react-dom": "19.2.3"
228229
}
229230
}

packages/web/src/app/[domain]/chat/[id]/opengraph-image.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ export default async function Image({ params }: ImageProps) {
118118
}}
119119
>
120120
{/* Avatar */}
121-
{/* eslint-disable-next-line @next/next/no-img-element */}
122121
<img
123122
src={creatorImage ?? `${env.AUTH_URL}/placeholder_avatar.png`}
124123
alt="Avatar"
@@ -165,7 +164,6 @@ export default async function Image({ params }: ImageProps) {
165164
>
166165
sourcebot.dev
167166
</span>
168-
{/* eslint-disable-next-line @next/next/no-img-element */}
169167
<img
170168
src={`${env.AUTH_URL}/sb_logo_dark_small.png`}
171169
alt="Sourcebot"

packages/web/src/app/[domain]/components/navigationMenu/trialIndicator.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const TrialIndicator = ({ subscription }: Props) => {
3333
<div className="flex items-center gap-2 px-3 py-1.5 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-full text-blue-700 dark:text-blue-400 text-xs font-medium hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors cursor-pointer">
3434
<span className="inline-block w-2 h-2 bg-blue-400 dark:bg-blue-500 rounded-full"></span>
3535
<span>
36+
{/* eslint-disable-next-line react-hooks/purity -- Date.now() during render is intentional for displaying remaining trial days */}
3637
{Math.ceil((subscription.nextBillingDate * 1000 - Date.now()) / (1000 * 60 * 60 * 24))} days left in trial
3738
</span>
3839
</div>

packages/web/src/app/error.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export default function Error({ error, reset }: { error: Error & { digest?: stri
2929
statusCode: serviceError.statusCode,
3030
}
3131
}
32-
/* eslint-disable no-empty */
32+
3333
} catch {}
3434

3535
return {

packages/web/src/app/page.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
import { auth } from "@/auth";
22
import { redirect } from "next/navigation";
33
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants";
4-
import { getOrgFromDomain } from "@/data/org";
4+
import { prisma } from "@/prisma";
5+
6+
// @note: we were hitting `PrismaClientInitializationError` errors during
7+
// build time. Next.js performs a static generation probe on all pages during
8+
// `next build`, running each page component to determine if it's static or
9+
// dynamic. `force-dynamic` skips the probe entirely so this page is always
10+
// rendered at request time.
11+
export const dynamic = 'force-dynamic';
512

613
export default async function Page() {
7-
const org = await getOrgFromDomain(SINGLE_TENANT_ORG_DOMAIN);
14+
const org = await prisma.org.findUnique({
15+
where: {
16+
domain: SINGLE_TENANT_ORG_DOMAIN
17+
}
18+
});
819

920
if (!org || !org.isOnboarded) {
1021
return redirect("/onboard");

0 commit comments

Comments
 (0)