Skip to content

Commit

Permalink
Initial commit from Create Next App
Browse files Browse the repository at this point in the history
  • Loading branch information
arabacibahadir committed Jul 7, 2023
0 parents commit f8a0375
Show file tree
Hide file tree
Showing 26 changed files with 2,726 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Update these with your Supabase details from your project settings > API
# https://app.supabase.com/project/_/settings/api
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Supabase Starter

This starter configures Supabase Auth to use cookies, making the user's session available throughout the entire Next.js app - Client Components, Server Components, Route Handlers, Server Actions and Middleware.

## Deploy your own

The Vercel deployment will guide you through creating a Supabase account and project. After installation of the Supabase integration, all relevant environment variables will be set up so that the project is usable immediately after deployment 🚀

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&integration-ids=oac_jUduyjQgOyzev1fjrW83NYOv)

## How to use

1. Create a [new Supabase project](https://database.new)
1. Run `npx create-next-app -e with-supabase` to create a Next.js app using the Supabase Starter template
1. Use `cd` to change into the app's directory
1. Run `npm install` to install dependencies
1. Rename `.env.local.example` to `.env.local` and update the values for `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` from [your Supabase project's API settings](https://app.supabase.com/project/_/settings/api)
1. Run `npm run dev` to start the local development server

> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally.
### Create a Supabase client

Check out the [`/app/_examples`](./app/_examples/) folder for an example of creating a Supabase client in:

- [Client Components](./app/_examples/client-component/page.tsx)
- [Server Components](./app/_examples/server-component/page.tsx)
- [Route Handlers](./app/_examples/route-handler/route.ts)
- [Server Actions](./app/_examples/server-action/page.tsx)

### Create `todo` table and seed with data (optional)

Navigate to [your project's SQL Editor](https://app.supabase.com/project/_/sql), click `New query`, paste the contents of the [init.sql](./supabase/migrations/20230618024722_init.sql) file and click `RUN`.

This will create a basic `todos` table, enable Row Level Security (RLS), and write RLS policies enabling `select` and `insert` actions for `authenticated` users.

To seed your `todos` table with some dummy data, run the contents of the [seed.sql](./supabase/seed.sql) file.

## Feedback and issues

Please file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose).

## More Supabase examples

- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments)
- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF)
- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs)
- [Next.js Auth Helpers Docs](https://supabase.com/docs/guides/auth/auth-helpers/nextjs)
29 changes: 29 additions & 0 deletions app/_examples/client-component/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client'

// TODO: Duplicate or move this file outside the `_examples` folder to make it a route

import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { useEffect, useState } from 'react'

export default function ClientComponent() {
const [todos, setTodos] = useState<any[]>([])

// Create a Supabase client configured to use cookies
const supabase = createClientComponentClient()

useEffect(() => {
const getTodos = async () => {
// This assumes you have a `todos` table in Supabase. Check out
// the `Create Table and seed with data` section of the README 👇
// https://github.com/vercel/next.js/blob/canary/examples/with-supabase/README.md
const { data } = await supabase.from('todos').select()
if (data) {
setTodos(data)
}
}

getTodos()
}, [supabase, setTodos])

return <pre>{JSON.stringify(todos, null, 2)}</pre>
}
81 changes: 81 additions & 0 deletions app/_examples/protected-route/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// TODO: Duplicate or move this file outside the `_examples` folder to make it a route

import {
createServerActionClient,
createServerComponentClient,
} from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import Image from 'next/image'
import { redirect } from 'next/navigation'

export default async function ProtectedRoute() {
const supabase = createServerComponentClient({ cookies })

const {
data: { user },
} = await supabase.auth.getUser()

if (!user) {
// This route can only be accessed by authenticated users.
// Unauthenticated users will be redirected to the `/login` route.
redirect('/login')
}

const signOut = async () => {
'use server'
const supabase = createServerActionClient({ cookies })
await supabase.auth.signOut()
redirect('/login')
}

return (
<div className="flex-1 flex flex-col max-w-3xl mt-24">
<h1 className="text-2xl mb-2 flex justify-between">
<span className="sr-only">Supabase and Next.js Starter Template</span>
</h1>

<div className="flex border-b py-3 text-sm text-neutral-100">
<div className="flex items-center justify-between w-full">
<code className="bg-neutral-700 px-3 py-1 rounded-lg text-sm">
Protected page
</code>
<span className="flex gap-4">
Hey, {user.email}! <span className="border-r"></span>{' '}
<form action={signOut}>
<button className="text-neutral-100">Logout</button>
</form>
</span>
</div>
</div>

<div className="flex gap-8 justify-center mt-12">
<Image
src="/supabase.svg"
alt="Supabase Logo"
width={225}
height={45}
priority
/>
<div className="border-l rotate-45 h-10"></div>
<Image
src="/next.svg"
alt="Vercel Logo"
width={150}
height={36}
priority
/>
</div>

<p className="text-3xl mx-auto max-w-2xl text-center mt-8 text-white">
The fastest way to get started building apps with{' '}
<strong>Supabase</strong> and <strong>Next.js</strong>
</p>

<div className="flex justify-center mt-12">
<span className="bg-neutral-100 py-3 px-6 rounded-lg font-mono text-sm text-neutral-900">
Get started by editing <strong>app/page.tsx</strong>
</span>
</div>
</div>
)
}
17 changes: 17 additions & 0 deletions app/_examples/route-handler/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// TODO: Duplicate or move this file outside the `_examples` folder to make it a route

import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'

export async function GET() {
// Create a Supabase client configured to use cookies
const supabase = createRouteHandlerClient({ cookies })

// This assumes you have a `todos` table in Supabase. Check out
// the `Create Table and seed with data` section of the README 👇
// https://github.com/vercel/next.js/blob/canary/examples/with-supabase/README.md
const { data: todos } = await supabase.from('todos').select()

return NextResponse.json(todos)
}
29 changes: 29 additions & 0 deletions app/_examples/server-action/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// TODO: Duplicate or move this file outside the `_examples` folder to make it a route

import { createServerActionClient } from '@supabase/auth-helpers-nextjs'
import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'

export default async function ServerAction() {
const addTodo = async (formData: FormData) => {
'use server'
const title = formData.get('title')

if (title) {
// Create a Supabase client configured to use cookies
const supabase = createServerActionClient({ cookies })

// This assumes you have a `todos` table in Supabase. Check out
// the `Create Table and seed with data` section of the README 👇
// https://github.com/vercel/next.js/blob/canary/examples/with-supabase/README.md
await supabase.from('todos').insert({ title })
revalidatePath('/server-action-example')
}
}

return (
<form action={addTodo}>
<input name="title" />
</form>
)
}
16 changes: 16 additions & 0 deletions app/_examples/server-component/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// TODO: Duplicate or move this file outside the `_examples` folder to make it a route

import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'

export default async function ServerComponent() {
// Create a Supabase client configured to use cookies
const supabase = createServerComponentClient({ cookies })

// This assumes you have a `todos` table in Supabase. Check out
// the `Create Table and seed with data` section of the README 👇
// https://github.com/vercel/next.js/blob/canary/examples/with-supabase/README.md
const { data: todos } = await supabase.from('todos').select()

return <pre>{JSON.stringify(todos, null, 2)}</pre>
}
19 changes: 19 additions & 0 deletions app/auth/callback/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'

export async function GET(request: Request) {
// The `/auth/callback` route is required for the server-side auth flow implemented
// by the Auth Helpers package. It exchanges an auth code for the user's session.
// https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-sign-in-with-code-exchange
const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code')

if (code) {
const supabase = createRouteHandlerClient({ cookies })
await supabase.auth.exchangeCodeForSession(code)
}

// URL to redirect to after sign in process completes
return NextResponse.redirect(requestUrl.origin)
}
Binary file added app/favicon.ico
Binary file not shown.
42 changes: 42 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 200 20% 98%;
--btn-background: 200 10% 91%;
--btn-background-hover: 200 10% 89%;
--foreground: 200 50% 3%;
}

@media (prefers-color-scheme: dark) {
:root {
--background: 200 50% 3%;
--btn-background: 200 10% 9%;
--btn-background-hover: 200 10% 12%;
--foreground: 200 20% 96%;
}
}
}

@layer base {
* {
@apply border-foreground/20;
}
}

.animate-in {
animation: animateIn 0.3s ease 0.15s both;
}

@keyframes animateIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
22 changes: 22 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import './globals.css'

export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<main className="min-h-screen bg-background flex flex-col items-center">
{children}
</main>
</body>
</html>
)
}
Loading

0 comments on commit f8a0375

Please sign in to comment.