Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Next-15 & Expo-53 #1312

Merged
merged 49 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f4c756e
Next 15 + React 19
ahkhanjani Oct 25, 2024
8d75f50
downgrade turbo
ahkhanjani Oct 25, 2024
12b003c
fix ui package exports for turbopack
ahkhanjani Oct 25, 2024
f607ca9
update some packages
ahkhanjani Oct 25, 2024
bb7468d
fix expo react types
ahkhanjani Oct 25, 2024
e588b04
add a new line
ahkhanjani Oct 25, 2024
8ff52ae
Revert "add a new line"
ahkhanjani Oct 25, 2024
f19fb01
revert next.config.ts + bring back jiti v1
ahkhanjani Oct 28, 2024
4e77873
pnpm and node up
ahkhanjani Oct 28, 2024
ec0da7f
expo: revert hoisting and custom path behaviors
ahkhanjani Oct 29, 2024
aed485b
update
ahkhanjani Oct 29, 2024
5df3249
dedupe deps
ahkhanjani Oct 29, 2024
3475c8a
update deps
ahkhanjani Nov 2, 2024
7d0fd02
Merge branch 'main' into next15
ahkhanjani Nov 4, 2024
3d44450
update
ahkhanjani Nov 4, 2024
2ffef7c
revert @auth/core update
ahkhanjani Nov 5, 2024
399af1a
disable react-hooks/exhaustive-deps eslint rule
ahkhanjani Nov 11, 2024
19939fb
Revert "disable react-hooks/exhaustive-deps eslint rule"
ahkhanjani Nov 11, 2024
9b81100
Update mobile app to Expo52
czystyl Nov 18, 2024
8193e6c
update deps
ahkhanjani Nov 21, 2024
6c95116
update node patch version
ahkhanjani Nov 21, 2024
9508d3d
Merge branch 'main' into next15
juliusmarminge Nov 23, 2024
f0c8da2
r18 types??
juliusmarminge Nov 23, 2024
d796f59
Merge branch 'main' into next15
juliusmarminge Nov 23, 2024
ede820e
Merge branch 'main' into next15
juliusmarminge Nov 23, 2024
b54db70
cookie jag
juliusmarminge Nov 23, 2024
245fff0
reorder workspace
juliusmarminge Nov 23, 2024
4b82909
Merge branch 'main' into feat/expo-52
juliusmarminge Nov 23, 2024
e7db044
package bumps
juliusmarminge Nov 23, 2024
bc634de
format
juliusmarminge Nov 23, 2024
507fa5f
remove `withMonorepoPaths`
juliusmarminge Nov 23, 2024
2c0fa8c
remove hoisting --- poooooggeers
juliusmarminge Nov 23, 2024
1784609
update splash config
juliusmarminge Nov 23, 2024
953c8fe
light-dark icons
juliusmarminge Nov 23, 2024
366bffb
ignore
juliusmarminge Nov 23, 2024
4c15022
node 22
ahkhanjani Nov 29, 2024
729525e
Bring back the hoisted option
czystyl Dec 18, 2024
715a27a
Merge branch 'main' into feat/expo-52
juliusmarminge Jan 25, 2025
5f82261
update deps
juliusmarminge Jan 25, 2025
b803f87
try getting 0.78 working
juliusmarminge Jan 25, 2025
4e017e1
chore: merge next-15 branch and expo-52 branch
vanja-popovic Mar 4, 2025
f942b55
chore: merge main
vanja-popovic Mar 4, 2025
8a79f70
chore: update trpc
vanja-popovic Mar 4, 2025
6c45855
fix: changes from upstream
vanja-popovic Mar 4, 2025
7deb8a5
fix: await params for nextauth
vanja-popovic Mar 4, 2025
e2748ed
fmt + lint
juliusmarminge Mar 4, 2025
b7708c9
minor bumpbs
juliusmarminge Mar 4, 2025
e0b3de7
chore: update README.md
vanja-popovic Mar 4, 2025
950ff02
chore: update README.md
VaniaPopovic Mar 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,17 @@ apps
| ├─ Nitro server to proxy OAuth requests in preview deployments
| └─ Uses Auth.js Core
├─ expo
| ├─ Expo SDK 51
| ├─ React Native using React 18
| ├─ Expo SDK 53 (EXPERIMENTAL)
| | > [!WARNING]
| | > Using Expo SDK 53 (canary) to unblock Next.js 15 / React 19 support.
| | > This is experimental and might not work as expected.
| ├─ React Native using React 19
| ├─ Navigation using Expo Router
| ├─ Tailwind using NativeWind
| └─ Typesafe API calls using tRPC
└─ next.js
├─ Next.js 14
├─ React 18
├─ Next.js 15
├─ React 19
├─ Tailwind CSS
└─ E2E Typesafe API Server & Client
packages
Expand Down
2 changes: 1 addition & 1 deletion apps/auth-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@auth/core": "0.37.2"
"@auth/core": "catalog:"
},
"devDependencies": {
"@acme/eslint-config": "workspace:*",
Expand Down
1 change: 1 addition & 0 deletions apps/expo/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nativewind-env.d.ts
31 changes: 23 additions & 8 deletions apps/expo/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
scheme: "expo",
version: "0.1.0",
orientation: "portrait",
icon: "./assets/icon.png",
icon: "./assets/icon-light.png",
userInterfaceStyle: "automatic",
splash: {
image: "./assets/icon.png",
resizeMode: "contain",
backgroundColor: "#1F104A",
},
updates: {
fallbackToCacheTimeout: 0,
},
assetBundlePatterns: ["**/*"],
ios: {
bundleIdentifier: "your.bundle.identifier",
supportsTablet: true,
icon: {
light: "./assets/icon-light.png",
dark: "./assets/icon-dark.png",
// tinted: "",
},
},
android: {
package: "your.bundle.identifier",
adaptiveIcon: {
foregroundImage: "./assets/icon.png",
foregroundImage: "./assets/icon-light.png",
backgroundColor: "#1F104A",
},
},
Expand All @@ -38,5 +38,20 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
tsconfigPaths: true,
typedRoutes: true,
},
plugins: ["expo-router"],
plugins: [
"expo-router",
"expo-secure-store",
"expo-web-browser",
[
"expo-splash-screen",
{
backgroundColor: "#E4E4E7",
image: "./assets/icon-light.png",
dark: {
backgroundColor: "#18181B",
image: "./assets/icon-dark.png",
},
},
],
],
});
Binary file added apps/expo/assets/icon-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/expo/assets/icon-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed apps/expo/assets/icon.png
Binary file not shown.
3 changes: 2 additions & 1 deletion apps/expo/eas.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"cli": {
"version": ">= 4.1.2"
"version": ">= 4.1.2",
"appVersionSource": "remote"
},
"build": {
"base": {
Expand Down
36 changes: 5 additions & 31 deletions apps/expo/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ const { getDefaultConfig } = require("expo/metro-config");
const { FileStore } = require("metro-cache");
const { withNativeWind } = require("nativewind/metro");

const path = require("path");
const path = require("node:path");

const config = withTurborepoManagedCache(
withMonorepoPaths(
withNativeWind(getDefaultConfig(__dirname), {
input: "./src/styles.css",
configPath: "./tailwind.config.ts",
}),
),
withNativeWind(getDefaultConfig(__dirname), {
input: "./src/styles.css",
configPath: "./tailwind.config.ts",
}),
);

// XXX: Resolve our exports in workspace packages
Expand All @@ -20,30 +18,6 @@ config.resolver.unstable_enablePackageExports = true;

module.exports = config;

/**
* Add the monorepo paths to the Metro config.
* This allows Metro to resolve modules from the monorepo.
*
* @see https://docs.expo.dev/guides/monorepos/#modify-the-metro-config
* @param {import('expo/metro-config').MetroConfig} config
* @returns {import('expo/metro-config').MetroConfig}
*/
function withMonorepoPaths(config) {
const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, "../..");

// #1 - Watch all files in the monorepo
config.watchFolders = [workspaceRoot];

// #2 - Resolve modules within the project's `node_modules` first, then all monorepo modules
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, "node_modules"),
path.resolve(workspaceRoot, "node_modules"),
];

return config;
}

/**
* Move the Metro cache to the `.cache/metro` folder.
* If you have any environment variables, you can configure Turborepo to invalidate it when needed.
Expand Down
39 changes: 19 additions & 20 deletions apps/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,35 @@
"dev:ios": "expo start --ios",
"android": "expo run:android",
"ios": "expo run:ios",
"format": "prettier --check . --ignore-path ../../.gitignore",
"format": "prettier --check . --ignore-path ../../.gitignore --ignore-path .prettierignore",
"lint": "eslint",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@bacons/text-decoder": "^0.0.0",
"@expo/metro-config": "^0.19.9",
"@shopify/flash-list": "1.7.2",
"@shopify/flash-list": "1.7.3",
"@tanstack/react-query": "catalog:",
"@trpc/client": "catalog:",
"@trpc/server": "catalog:",
"@trpc/tanstack-react-query": "catalog:",
"expo": "~52.0.27",
"expo-constants": "~17.0.4",
"expo-dev-client": "~5.0.10",
"expo-linking": "~7.0.4",
"expo-router": "~4.0.17",
"expo-secure-store": "^14.0.1",
"expo-splash-screen": "~0.29.21",
"expo-status-bar": "~2.0.1",
"expo-web-browser": "^14.0.2",
"expo": "53.0.0-canary-20250304-f08e984",
"expo-constants": "18.0.0-canary-20250304-f08e984",
"expo-dev-client": "5.0.13-canary-20250304-f08e984",
"expo-linking": "7.1.0-canary-20250304-f08e984",
"expo-router": "4.0.18-canary-20250304-f08e984",
"expo-secure-store": "14.0.2-canary-20250304-f08e984",
"expo-splash-screen": "0.29.23-canary-20250304-f08e984",
"expo-status-bar": "2.0.2-canary-20250304-f08e984",
"expo-web-browser": "14.1.0-canary-20250304-f08e984",
"nativewind": "~4.1.23",
"react": "catalog:react18",
"react-dom": "catalog:react18",
"react-native": "~0.77.0",
"react": "catalog:react19",
"react-dom": "catalog:react19",
"react-native": "0.78.0",
"react-native-css-interop": "~0.1.22",
"react-native-gesture-handler": "~2.22.1",
"react-native-reanimated": "~3.16.7",
"react-native-safe-area-context": "~5.1.0",
"react-native-screens": "~4.5.0",
"react-native-gesture-handler": "~2.24.0",
"react-native-reanimated": "~3.17.1",
"react-native-safe-area-context": "~5.2.0-beta.0",
"react-native-screens": "~4.9.1",
"superjson": "2.2.2"
},
"devDependencies": {
Expand All @@ -52,7 +51,7 @@
"@babel/preset-env": "^7.26.7",
"@babel/runtime": "^7.26.7",
"@types/babel__core": "^7.20.5",
"@types/react": "catalog:react18",
"@types/react": "catalog:react19",
"eslint": "catalog:",
"prettier": "catalog:",
"tailwindcss": "catalog:",
Expand Down
2 changes: 0 additions & 2 deletions apps/expo/src/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import "@bacons/text-decoder/install";

import { Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { useColorScheme } from "nativewind";
Expand Down
4 changes: 2 additions & 2 deletions apps/expo/src/utils/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const useSignIn = () => {
const success = await signIn();
if (!success) return;

await queryClient.invalidateQueries(trpc.queryFilter());
await queryClient.invalidateQueries(trpc.pathFilter());
router.replace("/");
};
};
Expand All @@ -52,7 +52,7 @@ export const useSignOut = () => {
const res = await signOut.mutateAsync();
if (!res.success) return;
await deleteToken();
await queryClient.invalidateQueries(trpc.queryFilter());
await queryClient.invalidateQueries(trpc.pathFilter());
router.replace("/");
};
};
1 change: 0 additions & 1 deletion apps/expo/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"~/*": ["./src/*"]
},
"jsx": "react-native",
"types": ["nativewind/types"],
"checkJs": false,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
Expand Down
2 changes: 0 additions & 2 deletions apps/nextjs/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ createJiti(fileURLToPath(import.meta.url))("./src/env");

/** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,

/** Enables hot reloading for local packages without a build step */
transpilePackages: [
"@acme/api",
Expand Down
12 changes: 6 additions & 6 deletions apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "pnpm with-env next build",
"clean": "git clean -xdf .cache .next .turbo node_modules",
"dev": "pnpm with-env next dev",
"dev": "pnpm with-env next dev --turbopack",
"format": "prettier --check . --ignore-path ../../.gitignore",
"lint": "eslint",
"start": "pnpm with-env next start",
Expand All @@ -25,9 +25,9 @@
"@trpc/server": "catalog:",
"@trpc/tanstack-react-query": "catalog:",
"geist": "^1.3.1",
"next": "^14.2.23",
"react": "catalog:react18",
"react-dom": "catalog:react18",
"next": "^15.2.1",
"react": "catalog:react19",
"react-dom": "catalog:react19",
"superjson": "2.2.2",
"zod": "catalog:"
},
Expand All @@ -37,8 +37,8 @@
"@acme/tailwind-config": "workspace:*",
"@acme/tsconfig": "workspace:*",
"@types/node": "^22.10.10",
"@types/react": "catalog:react18",
"@types/react-dom": "catalog:react18",
"@types/react": "catalog:react19",
"@types/react-dom": "catalog:react19",
"dotenv-cli": "^8.0.0",
"eslint": "catalog:",
"jiti": "^1.21.7",
Expand Down
4 changes: 2 additions & 2 deletions apps/nextjs/src/app/_components/posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function CreatePostForm() {
trpc.post.create.mutationOptions({
onSuccess: async () => {
form.reset();
await queryClient.invalidateQueries(trpc.post.queryFilter());
await queryClient.invalidateQueries(trpc.post.pathFilter());
},
onError: (err) => {
toast.error(
Expand Down Expand Up @@ -123,7 +123,7 @@ export function PostCard(props: {
const deletePost = useMutation(
trpc.post.delete.mutationOptions({
onSuccess: async () => {
await queryClient.invalidateQueries(trpc.post.queryFilter());
await queryClient.invalidateQueries(trpc.post.pathFilter());
},
onError: (err) => {
toast.error(
Expand Down
16 changes: 8 additions & 8 deletions apps/nextjs/src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function rewriteRequestUrlInDevelopment(req: NextRequest) {
}

async function handleExpoSigninCallback(req: NextRequest, redirectURL: string) {
cookies().delete(EXPO_COOKIE_NAME);
(await cookies()).delete(EXPO_COOKIE_NAME);

// Run original handler, then extract the session token from the response
// Send it back via a query param in the Expo deep link. The Expo app
Expand All @@ -49,13 +49,13 @@ async function handleExpoSigninCallback(req: NextRequest, redirectURL: string) {

export const POST = async (
_req: NextRequest,
props: { params: { nextauth: string[] } },
props: { params: Promise<{ nextauth: string[] }> },
) => {
// First step must be to correct the request URL.
const req = rewriteRequestUrlInDevelopment(_req);

const nextauthAction = props.params.nextauth[0];
const isExpoCallback = cookies().get(EXPO_COOKIE_NAME);
const nextauthAction = (await props.params).nextauth[0];
const isExpoCallback = (await cookies()).get(EXPO_COOKIE_NAME);

// callback handler required separately in the POST handler
// since Apple sends a POST request instead of a GET
Expand All @@ -68,19 +68,19 @@ export const POST = async (

export const GET = async (
_req: NextRequest,
props: { params: { nextauth: string[] } },
props: { params: Promise<{ nextauth: string[] }> },
) => {
// First step must be to correct the request URL.
const req = rewriteRequestUrlInDevelopment(_req);

const nextauthAction = props.params.nextauth[0];
const nextauthAction = (await props.params).nextauth[0];
const isExpoSignIn = req.nextUrl.searchParams.get("expo-redirect");
const isExpoCallback = cookies().get(EXPO_COOKIE_NAME);
const isExpoCallback = (await cookies()).get(EXPO_COOKIE_NAME);

if (nextauthAction === "signin" && !!isExpoSignIn) {
// set a cookie we can read in the callback
// to know to send the user back to expo
cookies().set({
(await cookies()).set({
name: EXPO_COOKIE_NAME,
value: isExpoSignIn,
maxAge: 60 * 10, // 10 min
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs/src/trpc/server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { createQueryClient } from "./query-client";
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(async () => {
const heads = new Headers(headers());
const heads = new Headers(await headers());
heads.set("x-trpc-source", "rsc");

return createTRPCContext({
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "create-t3-turbo",
"private": true,
"engines": {
"node": ">=22.10.0",
"node": ">=22.11.0",
"pnpm": "^9.15.4"
},
"packageManager": "[email protected]",
Expand Down
13 changes: 7 additions & 6 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@
},
"dependencies": {
"@acme/db": "workspace:*",
"@auth/core": "0.37.2",
"@auth/drizzle-adapter": "1.7.4",
"@auth/core": "catalog:",
"@auth/drizzle-adapter": "catalog:",
"@t3-oss/env-nextjs": "^0.12.0",
"next": "^14.2.23",
"next-auth": "5.0.0-beta.25",
"react": "catalog:react18",
"react-dom": "catalog:react18",
"next": "^15.2.1",
"next-auth": "catalog:",
"react": "catalog:react19",
"react-dom": "catalog:react19",
"zod": "catalog:"
},
"devDependencies": {
"@acme/eslint-config": "workspace:*",
"@acme/prettier-config": "workspace:*",
"@acme/tsconfig": "workspace:*",
"@types/react": "catalog:react19",
"eslint": "catalog:",
"prettier": "catalog:",
"typescript": "catalog:"
Expand Down
Loading