Skip to content

Commit 223f448

Browse files
committed
initial commit
0 parents  commit 223f448

Some content is hidden

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

56 files changed

+5259
-0
lines changed

.env.example

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Update these with your Supabase details from your project settings > API
2+
# https://app.supabase.com/project/_/settings/api
3+
NEXT_PUBLIC_SUPABASE_URL=your-project-url
4+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
.yarn/install-state.gz
8+
9+
# testing
10+
/coverage
11+
12+
# next.js
13+
/.next/
14+
/out/
15+
16+
# production
17+
/build
18+
19+
# misc
20+
.DS_Store
21+
*.pem
22+
23+
# debug
24+
npm-debug.log*
25+
yarn-debug.log*
26+
yarn-error.log*
27+
28+
# local env files
29+
.env*.local
30+
.env
31+
32+
# vercel
33+
.vercel
34+
35+
# typescript
36+
*.tsbuildinfo
37+
next-env.d.ts

README.md

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<a href="https://demo-nextjs-with-supabase.vercel.app/">
2+
<img alt="Next.js and Supabase Starter Kit - the fastest way to build apps with Next.js and Supabase" src="https://demo-nextjs-with-supabase.vercel.app/opengraph-image.png">
3+
<h1 align="center">Next.js and Supabase Starter Kit</h1>
4+
</a>
5+
6+
<p align="center">
7+
The fastest way to build apps with Next.js and Supabase
8+
</p>
9+
10+
<p align="center">
11+
<a href="#features"><strong>Features</strong></a> ·
12+
<a href="#demo"><strong>Demo</strong></a> ·
13+
<a href="#deploy-to-vercel"><strong>Deploy to Vercel</strong></a> ·
14+
<a href="#clone-and-run-locally"><strong>Clone and run locally</strong></a> ·
15+
<a href="#feedback-and-issues"><strong>Feedback and issues</strong></a>
16+
<a href="#more-supabase-examples"><strong>More Examples</strong></a>
17+
</p>
18+
<br/>
19+
20+
## Features
21+
22+
- Works across the entire [Next.js](https://nextjs.org) stack
23+
- App Router
24+
- Pages Router
25+
- Middleware
26+
- Client
27+
- Server
28+
- It just works!
29+
- supabase-ssr. A package to configure Supabase Auth to use cookies
30+
- Styling with [Tailwind CSS](https://tailwindcss.com)
31+
- Components with [shadcn/ui](https://ui.shadcn.com/)
32+
- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own)
33+
- Environment variables automatically assigned to Vercel project
34+
35+
## Demo
36+
37+
You can view a fully working demo at [demo-nextjs-with-supabase.vercel.app](https://demo-nextjs-with-supabase.vercel.app/).
38+
39+
## Deploy to Vercel
40+
41+
Vercel deployment will guide you through creating a Supabase account and project.
42+
43+
After installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning.
44+
45+
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This+starter+configures+Supabase+Auth+to+use+cookies%2C+making+the+user%27s+session+available+throughout+the+entire+Next.js+app+-+Client+Components%2C+Server+Components%2C+Route+Handlers%2C+Server+Actions+and+Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png)
46+
47+
The above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally.
48+
49+
If you wish to just develop locally and not deploy to Vercel, [follow the steps below](#clone-and-run-locally).
50+
51+
## Clone and run locally
52+
53+
1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new)
54+
55+
2. Create a Next.js app using the Supabase Starter template npx command
56+
57+
```bash
58+
npx create-next-app -e with-supabase
59+
```
60+
61+
3. Use `cd` to change into the app's directory
62+
63+
```bash
64+
cd name-of-new-app
65+
```
66+
67+
4. Rename `.env.example` to `.env.local` and update the following:
68+
69+
```
70+
NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL]
71+
NEXT_PUBLIC_SUPABASE_ANON_KEY=[INSERT SUPABASE PROJECT API ANON KEY]
72+
```
73+
74+
Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` can be found in [your Supabase project's API settings](https://app.supabase.com/project/_/settings/api)
75+
76+
5. You can now run the Next.js local development server:
77+
78+
```bash
79+
npm run dev
80+
```
81+
82+
The starter kit should now be running on [localhost:3000](http://localhost:3000/).
83+
84+
6. This template comes with the default shadcn/ui style initialized. If you instead want other ui.shadcn styles, delete `components.json` and [re-install shadcn/ui](https://ui.shadcn.com/docs/installation/next)
85+
86+
> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.
87+
88+
## Feedback and issues
89+
90+
Please file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose).
91+
92+
## More Supabase examples
93+
94+
- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments)
95+
- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF)
96+
- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs)
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { forgotPasswordAction } from "@/app/actions";
2+
import { FormMessage, Message } from "@/components/form-message";
3+
import { SubmitButton } from "@/components/submit-button";
4+
import { Input } from "@/components/ui/input";
5+
import { Label } from "@/components/ui/label";
6+
import Link from "next/link";
7+
import { SmtpMessage } from "../smtp-message";
8+
9+
export default function ForgotPassword({
10+
searchParams,
11+
}: {
12+
searchParams: Message;
13+
}) {
14+
return (
15+
<>
16+
<form className="flex-1 flex flex-col w-full gap-2 text-foreground [&>input]:mb-6 min-w-64 max-w-64 mx-auto">
17+
<div>
18+
<h1 className="text-2xl font-medium">Reset Password</h1>
19+
<p className="text-sm text-secondary-foreground">
20+
Already have an account?{" "}
21+
<Link className="text-primary underline" href="/sign-in">
22+
Sign in
23+
</Link>
24+
</p>
25+
</div>
26+
<div className="flex flex-col gap-2 [&>input]:mb-3 mt-8">
27+
<Label htmlFor="email">Email</Label>
28+
<Input name="email" placeholder="[email protected]" required />
29+
<SubmitButton formAction={forgotPasswordAction}>
30+
Reset Password
31+
</SubmitButton>
32+
<FormMessage message={searchParams} />
33+
</div>
34+
</form>
35+
<SmtpMessage />
36+
</>
37+
);
38+
}

app/(auth-pages)/layout.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default async function Layout({
2+
children,
3+
}: {
4+
children: React.ReactNode;
5+
}) {
6+
return (
7+
<div className="max-w-7xl flex flex-col gap-12 items-start">{children}</div>
8+
);
9+
}

app/(auth-pages)/sign-in/page.tsx

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { signInAction } from "@/app/actions";
2+
import { FormMessage, Message } from "@/components/form-message";
3+
import { SubmitButton } from "@/components/submit-button";
4+
import { Input } from "@/components/ui/input";
5+
import { Label } from "@/components/ui/label";
6+
import Link from "next/link";
7+
8+
export default function Login({ searchParams }: { searchParams: Message }) {
9+
return (
10+
<form className="flex-1 flex flex-col min-w-64">
11+
<h1 className="text-2xl font-medium">Sign in</h1>
12+
<p className="text-sm text-foreground">
13+
Don't have an account?{" "}
14+
<Link className="text-foreground font-medium underline" href="/sign-up">
15+
Sign up
16+
</Link>
17+
</p>
18+
<div className="flex flex-col gap-2 [&>input]:mb-3 mt-8">
19+
<Label htmlFor="email">Email</Label>
20+
<Input name="email" placeholder="[email protected]" required />
21+
<div className="flex justify-between items-center">
22+
<Label htmlFor="password">Password</Label>
23+
<Link
24+
className="text-xs text-foreground underline"
25+
href="/forgot-password"
26+
>
27+
Forgot Password?
28+
</Link>
29+
</div>
30+
<Input
31+
type="password"
32+
name="password"
33+
placeholder="Your password"
34+
required
35+
/>
36+
<SubmitButton pendingText="Signing In..." formAction={signInAction}>
37+
Sign in
38+
</SubmitButton>
39+
<FormMessage message={searchParams} />
40+
</div>
41+
</form>
42+
);
43+
}

app/(auth-pages)/sign-up/page.tsx

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { signUpAction } from "@/app/actions";
2+
import { FormMessage, Message } from "@/components/form-message";
3+
import { SubmitButton } from "@/components/submit-button";
4+
import { Input } from "@/components/ui/input";
5+
import { Label } from "@/components/ui/label";
6+
import Link from "next/link";
7+
import { SmtpMessage } from "../smtp-message";
8+
9+
export default function Signup({ searchParams }: { searchParams: Message }) {
10+
if ("message" in searchParams) {
11+
return (
12+
<div className="w-full flex-1 flex items-center h-screen sm:max-w-md justify-center gap-2 p-4">
13+
<FormMessage message={searchParams} />
14+
</div>
15+
);
16+
}
17+
18+
return (
19+
<>
20+
<form className="flex flex-col min-w-64 max-w-64 mx-auto">
21+
<h1 className="text-2xl font-medium">Sign up</h1>
22+
<p className="text-sm text text-foreground">
23+
Already have an account?{" "}
24+
<Link className="text-primary font-medium underline" href="/sign-in">
25+
Sign in
26+
</Link>
27+
</p>
28+
<div className="flex flex-col gap-2 [&>input]:mb-3 mt-8">
29+
<Label htmlFor="email">Email</Label>
30+
<Input name="email" placeholder="[email protected]" required />
31+
<Label htmlFor="password">Password</Label>
32+
<Input
33+
type="password"
34+
name="password"
35+
placeholder="Your password"
36+
minLength={6}
37+
required
38+
/>
39+
<SubmitButton formAction={signUpAction} pendingText="Signing up...">
40+
Sign up
41+
</SubmitButton>
42+
<FormMessage message={searchParams} />
43+
</div>
44+
</form>
45+
<SmtpMessage />
46+
</>
47+
);
48+
}

app/(auth-pages)/smtp-message.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ArrowUpRight, InfoIcon } from "lucide-react";
2+
import Link from "next/link";
3+
4+
export function SmtpMessage() {
5+
return (
6+
<div className="bg-muted/50 px-5 py-3 border rounded-md flex gap-4">
7+
<InfoIcon size={16} className="mt-0.5" />
8+
<div className="flex flex-col gap-1">
9+
<small className="text-sm text-secondary-foreground">
10+
<strong> Note:</strong> Emails are rate limited. Enable Custom SMTP to
11+
increase the rate limit.
12+
</small>
13+
<div>
14+
<Link
15+
href="https://supabase.com/docs/guides/auth/auth-smtp"
16+
target="_blank"
17+
className="text-primary/50 hover:text-primary flex items-center text-sm gap-1"
18+
>
19+
Learn more <ArrowUpRight size={14} />
20+
</Link>
21+
</div>
22+
</div>
23+
</div>
24+
);
25+
}

0 commit comments

Comments
 (0)