Skip to content

Commit 41de302

Browse files
feat: next 15 (#2000)
Co-authored-by: Julius Marminge <[email protected]>
1 parent 42d468e commit 41de302

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+239
-546
lines changed

.changeset/grumpy-otters-kneel.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-t3-app": minor
3+
---
4+
5+
update to next.js 15 and next-auth v5

.github/workflows/e2e.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ jobs:
6161
- run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} && pnpm build
6262
if: ${{ steps.matrix-valid.outputs.continue == 'true' }}
6363
env:
64-
NEXTAUTH_SECRET: foo
65-
DISCORD_CLIENT_ID: bar
66-
DISCORD_CLIENT_SECRET: baz
64+
AUTH_SECRET: foo
65+
AUTH_DISCORD_ID: bar
66+
AUTH_DISCORD_SECRET: baz
6767
SKIP_ENV_VALIDATION: true
6868

6969
build-t3-app-with-bun:
@@ -101,7 +101,7 @@ jobs:
101101
- run: cd ../ci-bun && bun run build
102102
# - run: cd ../ci-bun && bun --bun run build
103103
env:
104-
NEXTAUTH_SECRET: foo
104+
AUTH_SECRET: foo
105+
AUTH_DISCORD_ID: bar
106+
AUTH_DISCORD_SECRET: baz
105107
DATABASE_URL: mysql://root:root@localhost:3306/test # can't use url from example env cause we block that in t3-env
106-
DISCORD_CLIENT_ID: bar
107-
DISCORD_CLIENT_SECRET: baz

cli/src/helpers/logNextSteps.ts

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ export const logNextSteps = async ({
4747
}
4848
}
4949

50+
if (packages?.nextAuth.inUse) {
51+
logger.info(
52+
` Fill in your .env with necessary values. See https://create.t3.gg/en/usage/first-steps for more info.`
53+
);
54+
}
55+
5056
if (["npm", "bun"].includes(pkgManager)) {
5157
logger.info(` ${pkgManager} run dev`);
5258
} else {

cli/src/installers/dependencyVersionMap.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
*/
55
export const dependencyVersionMap = {
66
// NextAuth.js
7-
"next-auth": "^4.24.7",
8-
"@auth/prisma-adapter": "^1.6.0",
9-
"@auth/drizzle-adapter": "^1.1.0",
7+
"next-auth": "5.0.0-beta.25",
8+
"@auth/prisma-adapter": "^2.7.2",
9+
"@auth/drizzle-adapter": "^1.7.2",
1010

1111
// Prisma
1212
prisma: "^5.14.0",

cli/src/installers/envVars.ts

+26-16
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,19 @@ export const envVariablesInstaller: Installer = ({
5151
const envDest = path.join(projectDir, ".env");
5252
const envExampleDest = path.join(projectDir, ".env.example");
5353

54-
fs.writeFileSync(envDest, envContent, "utf-8");
55-
fs.writeFileSync(envExampleDest, exampleEnvContent + envContent, "utf-8");
54+
const _exampleEnvContent = exampleEnvContent + envContent;
55+
56+
// Generate an auth secret and put in .env, not .env.example
57+
const secret = Buffer.from(
58+
crypto.getRandomValues(new Uint8Array(32))
59+
).toString("base64");
60+
const _envContent = envContent.replace(
61+
'AUTH_SECRET=""',
62+
`AUTH_SECRET="${secret}" # Generated by create-t3-app.`
63+
);
64+
65+
fs.writeFileSync(envDest, _envContent, "utf-8");
66+
fs.writeFileSync(envExampleDest, _exampleEnvContent, "utf-8");
5667
};
5768

5869
const getEnvContent = (
@@ -69,6 +80,19 @@ const getEnvContent = (
6980
.trim()
7081
.concat("\n");
7182

83+
if (usingAuth)
84+
content += `
85+
# Next Auth
86+
# You can generate a new secret on the command line with:
87+
# npx auth secret
88+
# https://next-auth.js.org/configuration/options#secret
89+
AUTH_SECRET=""
90+
91+
# Next Auth Discord Provider
92+
AUTH_DISCORD_ID=""
93+
AUTH_DISCORD_SECRET=""
94+
`;
95+
7296
if (usingPrisma)
7397
content += `
7498
# Prisma
@@ -97,20 +121,6 @@ DATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?sslaccept=strict'`;
97121
content += "\n";
98122
}
99123

100-
if (usingAuth)
101-
content += `
102-
# Next Auth
103-
# You can generate a new secret on the command line with:
104-
# openssl rand -base64 32
105-
# https://next-auth.js.org/configuration/options#secret
106-
# NEXTAUTH_SECRET=""
107-
NEXTAUTH_URL="http://localhost:3000"
108-
109-
# Next Auth Discord Provider
110-
DISCORD_CLIENT_ID=""
111-
DISCORD_CLIENT_SECRET=""
112-
`;
113-
114124
if (!usingAuth && !usingPrisma)
115125
content += `
116126
# Example:

cli/src/installers/nextAuth.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ import { type AvailableDependencies } from "~/installers/dependencyVersionMap.js
66
import { type Installer } from "~/installers/index.js";
77
import { addPackageDependency } from "~/utils/addPackageDependency.js";
88

9-
export const nextAuthInstaller: Installer = ({
10-
projectDir,
11-
packages,
12-
appRouter,
13-
}) => {
9+
export const nextAuthInstaller: Installer = ({ projectDir, packages }) => {
1410
const usingPrisma = packages?.prisma.inUse;
1511
const usingDrizzle = packages?.drizzle.inUse;
1612

@@ -26,25 +22,26 @@ export const nextAuthInstaller: Installer = ({
2622

2723
const extrasDir = path.join(PKG_ROOT, "template/extras");
2824

29-
const apiHandlerFile = "src/pages/api/auth/[...nextauth].ts";
30-
const routeHandlerFile = "src/app/api/auth/[...nextauth]/route.ts";
31-
const srcToUse = appRouter ? routeHandlerFile : apiHandlerFile;
25+
const apiHandlerFile = "src/app/api/auth/[...nextauth]/route.ts";
3226

33-
const apiHandlerSrc = path.join(extrasDir, srcToUse);
34-
const apiHandlerDest = path.join(projectDir, srcToUse);
27+
const apiHandlerSrc = path.join(extrasDir, apiHandlerFile);
28+
const apiHandlerDest = path.join(projectDir, apiHandlerFile);
3529

3630
const authConfigSrc = path.join(
3731
extrasDir,
38-
"src/server",
39-
appRouter ? "auth-app" : "auth-pages",
32+
"src/server/auth/config",
4033
usingPrisma
4134
? "with-prisma.ts"
4235
: usingDrizzle
4336
? "with-drizzle.ts"
4437
: "base.ts"
4538
);
46-
const authConfigDest = path.join(projectDir, "src/server/auth.ts");
39+
const authConfigDest = path.join(projectDir, "src/server/auth/config.ts");
40+
41+
const authIndexSrc = path.join(extrasDir, "src/server/auth/index.ts");
42+
const authIndexDest = path.join(projectDir, "src/server/auth/index.ts");
4743

4844
fs.copySync(apiHandlerSrc, apiHandlerDest);
4945
fs.copySync(authConfigSrc, authConfigDest);
46+
fs.copySync(authIndexSrc, authIndexDest);
5047
};

cli/src/installers/tailwind.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export const tailwindInstaller: Installer = ({ projectDir }) => {
2323
const twCfgSrc = path.join(extrasDir, "config/tailwind.config.ts");
2424
const twCfgDest = path.join(projectDir, "tailwind.config.ts");
2525

26-
const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.cjs");
27-
const postcssCfgDest = path.join(projectDir, "postcss.config.cjs");
26+
const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.js");
27+
const postcssCfgDest = path.join(projectDir, "postcss.config.js");
2828

2929
const prettierSrc = path.join(extrasDir, "config/_prettier.config.js");
3030
const prettierDest = path.join(projectDir, "prettier.config.js");

cli/template/base/next.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
33
* for Docker builds.
44
*/
5-
await import("./src/env.js");
5+
import "./src/env.js";
66

77
/** @type {import("next").NextConfig} */
88
const config = {

cli/template/base/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"type": "module",
55
"private": true,
66
"scripts": {
7-
"dev": "next dev",
7+
"dev": "next dev --turbo",
88
"build": "next build",
99
"start": "next start",
1010
"lint": "next lint",
@@ -16,7 +16,7 @@
1616
"dependencies": {
1717
"@t3-oss/env-nextjs": "^0.10.1",
1818
"geist": "^1.3.0",
19-
"next": "^14.2.4",
19+
"next": "^15.0.1",
2020
"react": "^18.3.1",
2121
"react-dom": "^18.3.1",
2222
"zod": "^3.23.3"
@@ -29,7 +29,7 @@
2929
"@typescript-eslint/eslint-plugin": "^8.1.0",
3030
"@typescript-eslint/parser": "^8.1.0",
3131
"eslint": "^8.57.0",
32-
"eslint-config-next": "^14.2.4",
32+
"eslint-config-next": "^15.0.1",
3333
"typescript": "^5.5.3"
3434
}
3535
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
2-
const config = {
2+
export default {
33
plugins: ["prettier-plugin-tailwindcss"],
44
};
5-
6-
export default config;

cli/template/extras/config/next-config-appdir.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
33
* for Docker builds.
44
*/
5-
await import("./src/env.js");
5+
import "./src/env.js";
66

77
/** @type {import("next").NextConfig} */
88
const config = {};

cli/template/extras/config/postcss.config.cjs

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
plugins: {
3+
tailwindcss: {},
4+
},
5+
};
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import NextAuth from "next-auth";
1+
import { handlers } from "~/server/auth";
22

3-
import { authOptions } from "~/server/auth";
4-
5-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
6-
const handler = NextAuth(authOptions);
7-
export { handler as GET, handler as POST };
3+
export const { GET, POST } = handlers;

cli/template/extras/src/app/page/with-auth-trpc-tw.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import Link from "next/link";
22

33
import { LatestPost } from "~/app/_components/post";
4-
import { getServerAuthSession } from "~/server/auth";
4+
import { auth } from "~/server/auth";
55
import { api, HydrateClient } from "~/trpc/server";
66

77
export default async function Home() {
88
const hello = await api.post.hello({ text: "from tRPC" });
9-
const session = await getServerAuthSession();
9+
const session = await auth();
1010

1111
if (session?.user) {
1212
void api.post.getLatest.prefetch();

cli/template/extras/src/app/page/with-auth-trpc.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import Link from "next/link";
22

33
import { LatestPost } from "~/app/_components/post";
4-
import { getServerAuthSession } from "~/server/auth";
4+
import { auth } from "~/server/auth";
55
import { api, HydrateClient } from "~/trpc/server";
66
import styles from "./index.module.css";
77

88
export default async function Home() {
99
const hello = await api.post.hello({ text: "from tRPC" });
10-
const session = await getServerAuthSession();
10+
const session = await auth();
1111

1212
if (session?.user) {
1313
void api.post.getLatest.prefetch();

cli/template/extras/src/env/with-auth-db-planetscale.js

+9-17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ export const env = createEnv({
77
* isn't built with invalid env vars.
88
*/
99
server: {
10+
AUTH_SECRET:
11+
process.env.NODE_ENV === "production"
12+
? z.string()
13+
: z.string().optional(),
14+
AUTH_DISCORD_ID: z.string(),
15+
AUTH_DISCORD_SECRET: z.string(),
1016
DATABASE_URL: z
1117
.string()
1218
.url()
@@ -17,19 +23,6 @@ export const env = createEnv({
1723
NODE_ENV: z
1824
.enum(["development", "test", "production"])
1925
.default("development"),
20-
NEXTAUTH_SECRET:
21-
process.env.NODE_ENV === "production"
22-
? z.string()
23-
: z.string().optional(),
24-
NEXTAUTH_URL: z.preprocess(
25-
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
26-
// Since NextAuth.js automatically uses the VERCEL_URL if present.
27-
(str) => process.env.VERCEL_URL ?? str,
28-
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
29-
process.env.VERCEL ? z.string() : z.string().url()
30-
),
31-
DISCORD_CLIENT_ID: z.string(),
32-
DISCORD_CLIENT_SECRET: z.string(),
3326
},
3427

3528
/**
@@ -46,12 +39,11 @@ export const env = createEnv({
4639
* middlewares) or client-side so we need to destruct manually.
4740
*/
4841
runtimeEnv: {
42+
AUTH_SECRET: process.env.AUTH_SECRET,
43+
AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,
44+
AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,
4945
DATABASE_URL: process.env.DATABASE_URL,
5046
NODE_ENV: process.env.NODE_ENV,
51-
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
52-
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
53-
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
54-
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
5547
},
5648
/**
5749
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially

cli/template/extras/src/env/with-auth-db.js

+9-17
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,16 @@ export const env = createEnv({
77
* isn't built with invalid env vars.
88
*/
99
server: {
10+
AUTH_SECRET:
11+
process.env.NODE_ENV === "production"
12+
? z.string()
13+
: z.string().optional(),
14+
AUTH_DISCORD_ID: z.string(),
15+
AUTH_DISCORD_SECRET: z.string(),
1016
DATABASE_URL: z.string().url(),
1117
NODE_ENV: z
1218
.enum(["development", "test", "production"])
1319
.default("development"),
14-
NEXTAUTH_SECRET:
15-
process.env.NODE_ENV === "production"
16-
? z.string()
17-
: z.string().optional(),
18-
NEXTAUTH_URL: z.preprocess(
19-
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
20-
// Since NextAuth.js automatically uses the VERCEL_URL if present.
21-
(str) => process.env.VERCEL_URL ?? str,
22-
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
23-
process.env.VERCEL ? z.string() : z.string().url()
24-
),
25-
DISCORD_CLIENT_ID: z.string(),
26-
DISCORD_CLIENT_SECRET: z.string(),
2720
},
2821

2922
/**
@@ -40,12 +33,11 @@ export const env = createEnv({
4033
* middlewares) or client-side so we need to destruct manually.
4134
*/
4235
runtimeEnv: {
36+
AUTH_SECRET: process.env.AUTH_SECRET,
37+
AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,
38+
AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,
4339
DATABASE_URL: process.env.DATABASE_URL,
4440
NODE_ENV: process.env.NODE_ENV,
45-
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
46-
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
47-
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
48-
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
4941
},
5042
/**
5143
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially

0 commit comments

Comments
 (0)