Skip to content

Commit 0f2204b

Browse files
authored
feat: Update to Next.js 13 & bump all deps (vercel#171)
* feat: bump all deps to latest and fix all breaking changes * feat: update stripe api version to 2022-11-15 and fix corresponding types in supabase
1 parent 9628c7b commit 0f2204b

28 files changed

+1686
-1503
lines changed

Diff for: components/Layout.tsx

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import { PropsWithChildren } from 'react';
12
import Head from 'next/head';
23
import { useRouter } from 'next/router';
34

4-
import Navbar from 'components/ui/Navbar';
5-
import Footer from 'components/ui/Footer';
6-
import { ReactNode } from 'react';
5+
import Navbar from '@/components/ui/Navbar';
6+
import Footer from '@/components/ui/Footer';
7+
78
import { PageMeta } from '../types';
89

9-
interface Props {
10-
children: ReactNode;
10+
interface Props extends PropsWithChildren {
1111
meta?: PageMeta;
1212
}
1313

@@ -27,7 +27,10 @@ export default function Layout({ children, meta: pageMeta }: Props) {
2727
<meta name="robots" content="follow, index" />
2828
<link href="/favicon.ico" rel="shortcut icon" />
2929
<meta content={meta.description} name="description" />
30-
<meta property="og:url" content={`https://subscription-starter.vercel.app${router.asPath}`} />
30+
<meta
31+
property="og:url"
32+
content={`https://subscription-starter.vercel.app${router.asPath}`}
33+
/>
3134
<meta property="og:type" content="website" />
3235
<meta property="og:site_name" content={meta.title} />
3336
<meta property="og:description" content={meta.description} />

Diff for: components/Pricing.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import cn from 'classnames';
2-
import { useRouter } from 'next/router';
31
import { useState } from 'react';
2+
import { useRouter } from 'next/router';
3+
import cn from 'classnames';
4+
5+
import Button from '@/components/ui/Button';
6+
import { postData } from '@/utils/helpers';
7+
import { getStripe } from '@/utils/stripe-client';
8+
import { useUser } from '@/utils/useUser';
49

5-
import Button from 'components/ui/Button';
6-
import { postData } from 'utils/helpers';
7-
import { getStripe } from 'utils/stripe-client';
8-
import { useUser } from 'utils/useUser';
910
import { Price, ProductWithPrice } from 'types';
1011

1112
interface Props {

Diff for: components/ui/Button/Button.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import cn from 'classnames';
22
import React, { forwardRef, useRef, ButtonHTMLAttributes } from 'react';
3-
import mergeRefs from 'react-merge-refs';
4-
import styles from './Button.module.css';
3+
import { mergeRefs } from 'react-merge-refs';
4+
5+
import LoadingDots from '@/components/ui/LoadingDots';
56

6-
import LoadingDots from 'components/ui/LoadingDots';
7+
import styles from './Button.module.css';
78

89
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
910
variant?: 'slim' | 'flat';

Diff for: components/ui/Footer/Footer.tsx

+42-34
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,57 @@
11
import Link from 'next/link';
2-
import s from './Footer.module.css';
32

4-
import Logo from 'components/icons/Logo';
5-
import GitHub from 'components/icons/GitHub';
3+
import Logo from '@/components/icons/Logo';
4+
import GitHub from '@/components/icons/GitHub';
5+
6+
import s from './Footer.module.css';
67

78
export default function Footer() {
89
return (
910
<footer className="mx-auto max-w-[1920px] px-6 bg-zinc-900">
1011
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 border-b border-zinc-600 py-12 text-white transition-colors duration-150 bg-zinc-900">
1112
<div className="col-span-1 lg:col-span-2">
12-
<Link href="/">
13-
<a className="flex flex-initial items-center font-bold md:mr-24">
14-
<span className="rounded-full border border-zinc-700 mr-2">
15-
<Logo />
16-
</span>
17-
<span>ACME</span>
18-
</a>
13+
<Link
14+
href="/"
15+
className="flex flex-initial items-center font-bold md:mr-24"
16+
>
17+
<span className="rounded-full border border-zinc-700 mr-2">
18+
<Logo />
19+
</span>
20+
<span>ACME</span>
1921
</Link>
2022
</div>
2123
<div className="col-span-1 lg:col-span-2">
2224
<ul className="flex flex-initial flex-col md:flex-1">
2325
<li className="py-3 md:py-0 md:pb-4">
24-
<Link href="/">
25-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
26-
Home
27-
</a>
26+
<Link
27+
href="/"
28+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
29+
>
30+
Home
2831
</Link>
2932
</li>
3033
<li className="py-3 md:py-0 md:pb-4">
31-
<Link href="/">
32-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
33-
About
34-
</a>
34+
<Link
35+
href="/"
36+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
37+
>
38+
About
3539
</Link>
3640
</li>
3741
<li className="py-3 md:py-0 md:pb-4">
38-
<Link href="/">
39-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
40-
Careers
41-
</a>
42+
<Link
43+
href="/"
44+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
45+
>
46+
Careers
4247
</Link>
4348
</li>
4449
<li className="py-3 md:py-0 md:pb-4">
45-
<Link href="/">
46-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
47-
Blog
48-
</a>
50+
<Link
51+
href="/"
52+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
53+
>
54+
Blog
4955
</Link>
5056
</li>
5157
</ul>
@@ -58,17 +64,19 @@ export default function Footer() {
5864
</p>
5965
</li>
6066
<li className="py-3 md:py-0 md:pb-4">
61-
<Link href="/">
62-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
63-
Privacy Policy
64-
</a>
67+
<Link
68+
href="/"
69+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
70+
>
71+
Privacy Policy
6572
</Link>
6673
</li>
6774
<li className="py-3 md:py-0 md:pb-4">
68-
<Link href="/">
69-
<a className="text-white hover:text-zinc-200 transition ease-in-out duration-150">
70-
Terms of Use
71-
</a>
75+
<Link
76+
href="/"
77+
className="text-white hover:text-zinc-200 transition ease-in-out duration-150"
78+
>
79+
Terms of Use
7280
</Link>
7381
</li>
7482
</ul>

Diff for: components/ui/Input/Input.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { InputHTMLAttributes, ChangeEvent } from 'react';
22
import cn from 'classnames';
3+
34
import s from './Input.module.css';
45

56
interface Props extends Omit<InputHTMLAttributes<any>, 'onChange'> {

Diff for: components/ui/Navbar/Navbar.tsx

+13-14
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import Link from 'next/link';
2-
import s from './Navbar.module.css';
3-
4-
import Logo from 'components/icons/Logo';
52
import { useRouter } from 'next/router';
6-
import { useUser } from 'utils/useUser';
73
import { useSupabaseClient } from '@supabase/auth-helpers-react';
84

5+
import Logo from '@/components/icons/Logo';
6+
import { useUser } from '@/utils/useUser';
7+
8+
import s from './Navbar.module.css';
9+
910
const Navbar = () => {
1011
const router = useRouter();
1112
const supabaseClient = useSupabaseClient();
@@ -19,17 +20,15 @@ const Navbar = () => {
1920
<div className="mx-auto max-w-6xl px-6">
2021
<div className="flex justify-between align-center flex-row py-4 md:py-6 relative">
2122
<div className="flex flex-1 items-center">
22-
<Link href="/">
23-
<a className={s.logo} aria-label="Logo">
24-
<Logo />
25-
</a>
23+
<Link href="/" className={s.logo} aria-label="Logo">
24+
<Logo />
2625
</Link>
2726
<nav className="space-x-2 ml-6 hidden lg:block">
28-
<Link href="/">
29-
<a className={s.link}>Pricing</a>
27+
<Link href="/" className={s.link}>
28+
Pricing
3029
</Link>
31-
<Link href="/account">
32-
<a className={s.link}>Account</a>
30+
<Link href="/account" className={s.link}>
31+
Account
3332
</Link>
3433
</nav>
3534
</div>
@@ -46,8 +45,8 @@ const Navbar = () => {
4645
Sign out
4746
</span>
4847
) : (
49-
<Link href="/signin">
50-
<a className={s.link}>Sign in</a>
48+
<Link href="/signin" className={s.link}>
49+
Sign in
5150
</Link>
5251
)}
5352
</div>

Diff for: next.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** @type {import('next').NextConfig} */
2+
const nextConfig = {
3+
reactStrictMode: true,
4+
};
5+
6+
module.exports = nextConfig;

Diff for: package.json

+20-20
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,28 @@
99
"stripe:listen": "stripe listen --forward-to=localhost:3000/api/webhooks --project-name=saas-starter"
1010
},
1111
"dependencies": {
12-
"@stripe/stripe-js": "1.22.0",
13-
"@supabase/auth-helpers-nextjs": "^0.4.1",
14-
"@supabase/auth-helpers-react": "^0.3.0",
15-
"@supabase/auth-ui-react": "^0.2.6",
16-
"@supabase/supabase-js": "^2.0.0",
17-
"classnames": "2.3.1",
18-
"next": "^12.2.5",
19-
"react": "17.0.2",
20-
"react-dom": "17.0.2",
21-
"react-merge-refs": "1.1.0",
22-
"stripe": "8.201.0",
23-
"swr": "1.2.0",
24-
"tailwindcss": "3.0.18"
12+
"@stripe/stripe-js": "^1.48.0",
13+
"@supabase/auth-helpers-nextjs": "^0.5.4",
14+
"@supabase/auth-helpers-react": "^0.3.1",
15+
"@supabase/auth-ui-react": "^0.3.3",
16+
"@supabase/auth-ui-shared": "^0.1.2",
17+
"@supabase/supabase-js": "^2.10.0",
18+
"classnames": "^2.3.2",
19+
"next": "^13.2.3",
20+
"react": "^18.2.0",
21+
"react-dom": "^18.2.0",
22+
"react-merge-refs": "^2.0.1",
23+
"stripe": "^11.13.0",
24+
"swr": "^2.0.4",
25+
"tailwindcss": "^3.2.7"
2526
},
2627
"devDependencies": {
27-
"@types/classnames": "2.3.1",
28-
"@types/node": "^17.0.13",
29-
"@types/react": "^17.0.38",
30-
"autoprefixer": "^10.4.2",
31-
"postcss": "8.4.5",
32-
"prettier": "2.5.1",
33-
"typescript": "^4.5.5"
28+
"@types/node": "^18.14.4",
29+
"@types/react": "^18.0.28",
30+
"autoprefixer": "^10.4.13",
31+
"postcss": "^8.4.21",
32+
"prettier": "^2.8.4",
33+
"typescript": "^4.9.5"
3434
},
3535
"prettier": {
3636
"arrowParens": "always",

Diff for: pages/_app.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import 'styles/main.css';
2-
import 'styles/chrome-bug.css';
31
import { useEffect, useState } from 'react';
42
import React from 'react';
5-
6-
import Layout from 'components/Layout';
3+
import { AppProps } from 'next/app';
74
import { SessionContextProvider } from '@supabase/auth-helpers-react';
85
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs';
9-
import { AppProps } from 'next/app';
10-
import { MyUserContextProvider } from 'utils/useUser';
6+
7+
import Layout from '@/components/Layout';
8+
import { MyUserContextProvider } from '@/utils/useUser';
119
import type { Database } from 'types_db';
1210

11+
import 'styles/main.css';
12+
import 'styles/chrome-bug.css';
13+
1314
export default function MyApp({ Component, pageProps }: AppProps) {
1415
const [supabaseClient] = useState(() =>
1516
createBrowserSupabaseClient<Database>()

Diff for: pages/account.tsx

+32-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import Link from 'next/link';
21
import { useState, ReactNode } from 'react';
2+
import Link from 'next/link';
3+
import { GetServerSidePropsContext } from 'next';
4+
import {
5+
createServerSupabaseClient,
6+
User
7+
} from '@supabase/auth-helpers-nextjs';
38

4-
import LoadingDots from 'components/ui/LoadingDots';
5-
import Button from 'components/ui/Button';
6-
import { useUser } from 'utils/useUser';
7-
import { postData } from 'utils/helpers';
8-
9-
import { User } from '@supabase/supabase-js';
10-
import { withPageAuth } from '@supabase/auth-helpers-nextjs';
9+
import LoadingDots from '@/components/ui/LoadingDots';
10+
import Button from '@/components/ui/Button';
11+
import { useUser } from '@/utils/useUser';
12+
import { postData } from '@/utils/helpers';
1113

1214
interface Props {
1315
title: string;
@@ -31,7 +33,27 @@ function Card({ title, description, footer, children }: Props) {
3133
);
3234
}
3335

34-
export const getServerSideProps = withPageAuth({ redirectTo: '/signin' });
36+
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
37+
const supabase = createServerSupabaseClient(ctx);
38+
const {
39+
data: { session }
40+
} = await supabase.auth.getSession();
41+
42+
if (!session)
43+
return {
44+
redirect: {
45+
destination: '/signin',
46+
permanent: false
47+
}
48+
};
49+
50+
return {
51+
props: {
52+
initialSession: session,
53+
user: session.user
54+
}
55+
};
56+
};
3557

3658
export default function Account({ user }: { user: User }) {
3759
const [loading, setLoading] = useState(false);
@@ -102,9 +124,7 @@ export default function Account({ user }: { user: User }) {
102124
) : subscription ? (
103125
`${subscriptionPrice}/${subscription?.prices?.interval}`
104126
) : (
105-
<Link href="/">
106-
<a>Choose your plan</a>
107-
</Link>
127+
<Link href="/">Choose your plan</Link>
108128
)}
109129
</div>
110130
</Card>

0 commit comments

Comments
 (0)