diff --git a/.env.example b/.env.example deleted file mode 100644 index 6937031..0000000 --- a/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -# 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 diff --git a/app/(auth-pages)/forgot-password/page.tsx b/app/(auth-pages)/forgot-password/page.tsx deleted file mode 100644 index bcf9725..0000000 --- a/app/(auth-pages)/forgot-password/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { forgotPasswordAction } from "@/app/actions"; -import { FormMessage, Message } from "@/components/form-message"; -import { SubmitButton } from "@/components/submit-button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import Link from "next/link"; -import { SmtpMessage } from "../smtp-message"; - -export default async function ForgotPassword(props: { - searchParams: Promise; -}) { - const searchParams = await props.searchParams; - return ( - <> -
-
-

Reset Password

-

- Already have an account?{" "} - - Sign in - -

-
-
- - - - Reset Password - - -
-
- - - ); -} diff --git a/app/(auth-pages)/layout.tsx b/app/(auth-pages)/layout.tsx deleted file mode 100644 index e038de1..0000000 --- a/app/(auth-pages)/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -export default async function Layout({ - children, -}: { - children: React.ReactNode; -}) { - return ( -
{children}
- ); -} diff --git a/app/(auth-pages)/sign-in/page.tsx b/app/(auth-pages)/sign-in/page.tsx deleted file mode 100644 index 7628cc7..0000000 --- a/app/(auth-pages)/sign-in/page.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { signInAction } from "@/app/actions"; -import { FormMessage, Message } from "@/components/form-message"; -import { SubmitButton } from "@/components/submit-button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import Link from "next/link"; - -export default async function Login(props: { searchParams: Promise }) { - const searchParams = await props.searchParams; - return ( -
-

Sign in

-

- Don't have an account?{" "} - - Sign up - -

-
- - -
- - - Forgot Password? - -
- - - Sign in - - -
-
- ); -} diff --git a/app/(auth-pages)/sign-up/page.tsx b/app/(auth-pages)/sign-up/page.tsx deleted file mode 100644 index 31b5a6d..0000000 --- a/app/(auth-pages)/sign-up/page.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { signUpAction } from "@/app/actions"; -import { FormMessage, Message } from "@/components/form-message"; -import { SubmitButton } from "@/components/submit-button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import Link from "next/link"; -import { SmtpMessage } from "../smtp-message"; - -export default async function Signup(props: { - searchParams: Promise; -}) { - const searchParams = await props.searchParams; - if ("message" in searchParams) { - return ( -
- -
- ); - } - - return ( - <> -
-

Sign up

-

- Already have an account?{" "} - - Sign in - -

-
- - - - - - Sign up - - -
-
- - - ); -} diff --git a/app/(auth-pages)/smtp-message.tsx b/app/(auth-pages)/smtp-message.tsx deleted file mode 100644 index 84c21fc..0000000 --- a/app/(auth-pages)/smtp-message.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { ArrowUpRight, InfoIcon } from "lucide-react"; -import Link from "next/link"; - -export function SmtpMessage() { - return ( -
- -
- - Note: Emails are rate limited. Enable Custom SMTP to - increase the rate limit. - -
- - Learn more - -
-
-
- ); -} diff --git a/app/actions.ts b/app/actions.ts deleted file mode 100644 index dbf8a26..0000000 --- a/app/actions.ts +++ /dev/null @@ -1,134 +0,0 @@ -"use server"; - -import { encodedRedirect } from "@/utils/utils"; -import { createClient } from "@/utils/supabase/server"; -import { headers } from "next/headers"; -import { redirect } from "next/navigation"; - -export const signUpAction = async (formData: FormData) => { - const email = formData.get("email")?.toString(); - const password = formData.get("password")?.toString(); - const supabase = await createClient(); - const origin = (await headers()).get("origin"); - - if (!email || !password) { - return encodedRedirect( - "error", - "/sign-up", - "Email and password are required", - ); - } - - const { error } = await supabase.auth.signUp({ - email, - password, - options: { - emailRedirectTo: `${origin}/auth/callback`, - }, - }); - - if (error) { - console.error(error.code + " " + error.message); - return encodedRedirect("error", "/sign-up", error.message); - } else { - return encodedRedirect( - "success", - "/sign-up", - "Thanks for signing up! Please check your email for a verification link.", - ); - } -}; - -export const signInAction = async (formData: FormData) => { - const email = formData.get("email") as string; - const password = formData.get("password") as string; - const supabase = await createClient(); - - const { error } = await supabase.auth.signInWithPassword({ - email, - password, - }); - - if (error) { - return encodedRedirect("error", "/sign-in", error.message); - } - - return redirect("/protected"); -}; - -export const forgotPasswordAction = async (formData: FormData) => { - const email = formData.get("email")?.toString(); - const supabase = await createClient(); - const origin = (await headers()).get("origin"); - const callbackUrl = formData.get("callbackUrl")?.toString(); - - if (!email) { - return encodedRedirect("error", "/forgot-password", "Email is required"); - } - - const { error } = await supabase.auth.resetPasswordForEmail(email, { - redirectTo: `${origin}/auth/callback?redirect_to=/protected/reset-password`, - }); - - if (error) { - console.error(error.message); - return encodedRedirect( - "error", - "/forgot-password", - "Could not reset password", - ); - } - - if (callbackUrl) { - return redirect(callbackUrl); - } - - return encodedRedirect( - "success", - "/forgot-password", - "Check your email for a link to reset your password.", - ); -}; - -export const resetPasswordAction = async (formData: FormData) => { - const supabase = await createClient(); - - const password = formData.get("password") as string; - const confirmPassword = formData.get("confirmPassword") as string; - - if (!password || !confirmPassword) { - encodedRedirect( - "error", - "/protected/reset-password", - "Password and confirm password are required", - ); - } - - if (password !== confirmPassword) { - encodedRedirect( - "error", - "/protected/reset-password", - "Passwords do not match", - ); - } - - const { error } = await supabase.auth.updateUser({ - password: password, - }); - - if (error) { - encodedRedirect( - "error", - "/protected/reset-password", - "Password update failed", - ); - } - - encodedRedirect("success", "/protected/reset-password", "Password updated"); -}; - -export const signOutAction = async () => { - const supabase = await createClient(); - await supabase.auth.signOut(); - return redirect("/sign-in"); -}; diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts deleted file mode 100644 index dd415a4..0000000 --- a/app/auth/callback/route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createClient } from "@/utils/supabase/server"; -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 SSR package. It exchanges an auth code for the user's session. - // https://supabase.com/docs/guides/auth/server-side/nextjs - const requestUrl = new URL(request.url); - const code = requestUrl.searchParams.get("code"); - const origin = requestUrl.origin; - const redirectTo = requestUrl.searchParams.get("redirect_to")?.toString(); - - if (code) { - const supabase = await createClient(); - await supabase.auth.exchangeCodeForSession(code); - } - - if (redirectTo) { - return NextResponse.redirect(`${origin}${redirectTo}`); - } - - // URL to redirect to after sign up process completes - return NextResponse.redirect(`${origin}/protected`); -} diff --git a/app/favicon.ico b/app/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/app/favicon.ico and /dev/null differ diff --git a/app/globals.css b/app/globals.css deleted file mode 100644 index f450d1e..0000000 --- a/app/globals.css +++ /dev/null @@ -1,69 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } - - .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} diff --git a/app/layout.tsx b/app/layout.tsx deleted file mode 100644 index 8d80488..0000000 --- a/app/layout.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import DeployButton from "@/components/deploy-button"; -import { EnvVarWarning } from "@/components/env-var-warning"; -import HeaderAuth from "@/components/header-auth"; -import { ThemeSwitcher } from "@/components/theme-switcher"; -import { hasEnvVars } from "@/utils/supabase/check-env-vars"; -import { GeistSans } from "geist/font/sans"; -import { ThemeProvider } from "next-themes"; -import Link from "next/link"; -import "./globals.css"; - -const defaultUrl = process.env.VERCEL_URL - ? `https://${process.env.VERCEL_URL}` - : "http://localhost:3000"; - -export const metadata = { - metadataBase: new URL(defaultUrl), - title: "Next.js and Supabase Starter Kit", - description: "The fastest way to build apps with Next.js and Supabase", -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - - -
-
- -
- {children} -
- - -
-
-
- - - ); -} diff --git a/app/opengraph-image.png b/app/opengraph-image.png deleted file mode 100644 index 57595e6..0000000 Binary files a/app/opengraph-image.png and /dev/null differ diff --git a/app/page.tsx b/app/page.tsx deleted file mode 100644 index 7e2e91a..0000000 --- a/app/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import Hero from "@/components/hero"; -import ConnectSupabaseSteps from "@/components/tutorial/connect-supabase-steps"; -import SignUpUserSteps from "@/components/tutorial/sign-up-user-steps"; -import { hasEnvVars } from "@/utils/supabase/check-env-vars"; - -export default async function Index() { - return ( - <> - -
-

Next steps

- {hasEnvVars ? : } -
- - ); -} diff --git a/app/protected/page.tsx b/app/protected/page.tsx deleted file mode 100644 index 5508aba..0000000 --- a/app/protected/page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import FetchDataSteps from "@/components/tutorial/fetch-data-steps"; -import { createClient } from "@/utils/supabase/server"; -import { InfoIcon } from "lucide-react"; -import { redirect } from "next/navigation"; - -export default async function ProtectedPage() { - const supabase = await createClient(); - - const { - data: { user }, - } = await supabase.auth.getUser(); - - if (!user) { - return redirect("/sign-in"); - } - - return ( -
-
-
- - This is a protected page that you can only see as an authenticated - user -
-
-
-

Your user details

-
-          {JSON.stringify(user, null, 2)}
-        
-
-
-

Next steps

- -
-
- ); -} diff --git a/app/protected/reset-password/page.tsx b/app/protected/reset-password/page.tsx deleted file mode 100644 index 9cd7084..0000000 --- a/app/protected/reset-password/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { resetPasswordAction } from "@/app/actions"; -import { FormMessage, Message } from "@/components/form-message"; -import { SubmitButton } from "@/components/submit-button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; - -export default async function ResetPassword(props: { - searchParams: Promise; -}) { - const searchParams = await props.searchParams; - return ( -
-

Reset password

-

- Please enter your new password below. -

- - - - - - Reset password - - - - ); -} diff --git a/app/twitter-image.png b/app/twitter-image.png deleted file mode 100644 index 57595e6..0000000 Binary files a/app/twitter-image.png and /dev/null differ diff --git a/components/deploy-button.tsx b/components/deploy-button.tsx deleted file mode 100644 index 8a5a192..0000000 --- a/components/deploy-button.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import Link from "next/link"; -import { Button } from "./ui/button"; - -export default function DeployButton() { - return ( - <> - - - - - ); -} diff --git a/components/env-var-warning.tsx b/components/env-var-warning.tsx deleted file mode 100644 index b6a193f..0000000 --- a/components/env-var-warning.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Link from "next/link"; -import { Badge } from "./ui/badge"; -import { Button } from "./ui/button"; - -export function EnvVarWarning() { - return ( -
- - Supabase environment variables required - -
- - -
-
- ); -} diff --git a/components/form-message.tsx b/components/form-message.tsx deleted file mode 100644 index 547fb9f..0000000 --- a/components/form-message.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export type Message = - | { success: string } - | { error: string } - | { message: string }; - -export function FormMessage({ message }: { message: Message }) { - return ( -
- {"success" in message && ( -
- {message.success} -
- )} - {"error" in message && ( -
- {message.error} -
- )} - {"message" in message && ( -
{message.message}
- )} -
- ); -} diff --git a/components/header-auth.tsx b/components/header-auth.tsx deleted file mode 100644 index eb9d65c..0000000 --- a/components/header-auth.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { signOutAction } from "@/app/actions"; -import { hasEnvVars } from "@/utils/supabase/check-env-vars"; -import Link from "next/link"; -import { Badge } from "./ui/badge"; -import { Button } from "./ui/button"; -import { createClient } from "@/utils/supabase/server"; - -export default async function AuthButton() { - const supabase = await createClient(); - - const { - data: { user }, - } = await supabase.auth.getUser(); - - if (!hasEnvVars) { - return ( - <> -
-
- - Please update .env.local file with anon key and url - -
-
- - -
-
- - ); - } - return user ? ( -
- Hey, {user.email}! -
- -
-
- ) : ( -
- - -
- ); -} diff --git a/components/hero.tsx b/components/hero.tsx deleted file mode 100644 index 6afca6b..0000000 --- a/components/hero.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import NextLogo from "./next-logo"; -import SupabaseLogo from "./supabase-logo"; - -export default function Header() { - return ( -
-
- - - - - - - -
-

Supabase and Next.js Starter Template

-

- The fastest way to build apps with{" "} - - Supabase - {" "} - and{" "} - - Next.js - -

-
-
- ); -} diff --git a/components/next-logo.tsx b/components/next-logo.tsx deleted file mode 100644 index 1655582..0000000 --- a/components/next-logo.tsx +++ /dev/null @@ -1,46 +0,0 @@ -export default function NextLogo() { - return ( - - - - - - - - - - - ); -} diff --git a/components/submit-button.tsx b/components/submit-button.tsx deleted file mode 100644 index c1cd9f8..0000000 --- a/components/submit-button.tsx +++ /dev/null @@ -1,23 +0,0 @@ -"use client"; - -import { Button } from "@/components/ui/button"; -import { type ComponentProps } from "react"; -import { useFormStatus } from "react-dom"; - -type Props = ComponentProps & { - pendingText?: string; -}; - -export function SubmitButton({ - children, - pendingText = "Submitting...", - ...props -}: Props) { - const { pending } = useFormStatus(); - - return ( - - ); -} diff --git a/components/supabase-logo.tsx b/components/supabase-logo.tsx deleted file mode 100644 index 96a56a5..0000000 --- a/components/supabase-logo.tsx +++ /dev/null @@ -1,102 +0,0 @@ -export default function SupabaseLogo() { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/components/theme-switcher.tsx b/components/theme-switcher.tsx deleted file mode 100644 index d838e40..0000000 --- a/components/theme-switcher.tsx +++ /dev/null @@ -1,78 +0,0 @@ -"use client"; - -import { Button } from "@/components/ui/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuRadioGroup, - DropdownMenuRadioItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { Laptop, Moon, Sun } from "lucide-react"; -import { useTheme } from "next-themes"; -import { useEffect, useState } from "react"; - -const ThemeSwitcher = () => { - const [mounted, setMounted] = useState(false); - const { theme, setTheme } = useTheme(); - - // useEffect only runs on the client, so now we can safely show the UI - useEffect(() => { - setMounted(true); - }, []); - - if (!mounted) { - return null; - } - - const ICON_SIZE = 16; - - return ( - - - - - - setTheme(e)} - > - - {" "} - Light - - - {" "} - Dark - - - {" "} - System - - - - - ); -}; - -export { ThemeSwitcher }; diff --git a/components/tutorial/code-block.tsx b/components/tutorial/code-block.tsx deleted file mode 100644 index 9f1b13d..0000000 --- a/components/tutorial/code-block.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { Button } from "../ui/button"; - -const CopyIcon = () => ( - - - - -); - -const CheckIcon = () => ( - - - -); - -export function CodeBlock({ code }: { code: string }) { - const [icon, setIcon] = useState(CopyIcon); - - const copy = async () => { - await navigator?.clipboard?.writeText(code); - setIcon(CheckIcon); - setTimeout(() => setIcon(CopyIcon), 2000); - }; - - return ( -
-      
-      {code}
-    
- ); -} diff --git a/components/tutorial/connect-supabase-steps.tsx b/components/tutorial/connect-supabase-steps.tsx deleted file mode 100644 index 04ca37f..0000000 --- a/components/tutorial/connect-supabase-steps.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { TutorialStep } from "./tutorial-step"; - -export default function ConnectSupabaseSteps() { - return ( -
    - -

    - Head over to{" "} - - database.new - {" "} - and create a new Supabase project. -

    -
    - - -

    - Rename the{" "} - - .env.example - {" "} - file in your Next.js app to{" "} - - .env.local - {" "} - and populate with values from{" "} - - your Supabase project's API Settings - - . -

    -
    - - -

    - You may need to quit your Next.js development server and run{" "} - - npm run dev - {" "} - again to load the new environment variables. -

    -
    - - -

    - You may need to refresh the page for Next.js to load the new - environment variables. -

    -
    -
- ); -} diff --git a/components/tutorial/fetch-data-steps.tsx b/components/tutorial/fetch-data-steps.tsx deleted file mode 100644 index f0193fe..0000000 --- a/components/tutorial/fetch-data-steps.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { TutorialStep } from "./tutorial-step"; -import { CodeBlock } from "./code-block"; - -const create = `create table notes ( - id bigserial primary key, - title text -); - -insert into notes(title) -values - ('Today I created a Supabase project.'), - ('I added some data and queried it from Next.js.'), - ('It was awesome!'); -`.trim(); - -const server = `import { createClient } from '@/utils/supabase/server' - -export default async function Page() { - const supabase = createClient() - const { data: notes } = await supabase.from('notes').select() - - return
{JSON.stringify(notes, null, 2)}
-} -`.trim(); - -const client = `'use client' - -import { createClient } from '@/utils/supabase/client' -import { useEffect, useState } from 'react' - -export default function Page() { - const [notes, setNotes] = useState(null) - const supabase = createClient() - - useEffect(() => { - const getData = async () => { - const { data } = await supabase.from('notes').select() - setNotes(data) - } - getData() - }, []) - - return
{JSON.stringify(notes, null, 2)}
-} -`.trim(); - -export default function FetchDataSteps() { - return ( -
    - -

    - Head over to the{" "} - - Table Editor - {" "} - for your Supabase project to create a table and insert some example - data. If you're stuck for creativity, you can copy and paste the - following into the{" "} - - SQL Editor - {" "} - and click RUN! -

    - -
    - - -

    - To create a Supabase client and query data from an Async Server - Component, create a new page.tsx file at{" "} - - /app/notes/page.tsx - {" "} - and add the following. -

    - -

    Alternatively, you can use a Client Component.

    - -
    - - -

    You're ready to launch your product to the world! 🚀

    -
    -
- ); -} diff --git a/components/tutorial/sign-up-user-steps.tsx b/components/tutorial/sign-up-user-steps.tsx deleted file mode 100644 index c00fb66..0000000 --- a/components/tutorial/sign-up-user-steps.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import Link from "next/link"; -import { TutorialStep } from "./tutorial-step"; -import { ArrowUpRight } from "lucide-react"; - -export default function SignUpUserSteps() { - return ( -
    - {process.env.VERCEL_ENV === "preview" || - process.env.VERCEL_ENV === "production" ? ( - -

    It looks like this App is hosted on Vercel.

    -

    - This particular deployment is - - "{process.env.VERCEL_ENV}" - {" "} - on - - https://{process.env.VERCEL_URL} - - . -

    -

    - You will need to{" "} - - update your Supabase project - {" "} - with redirect URLs based on your Vercel deployment URLs. -

    -
      -
    • - -{" "} - - http://localhost:3000/** - -
    • -
    • - -{" "} - - {`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}/**`} - -
    • -
    • - -{" "} - - {`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL?.replace(".vercel.app", "")}-*-[vercel-team-url].vercel.app/**`} - {" "} - (Vercel Team URL can be found in{" "} - - Vercel Team settings - - ) -
    • -
    - - Redirect URLs Docs - -
    - ) : null} - -

    - Head over to the{" "} - - Sign up - {" "} - page and sign up your first user. It's okay if this is just you for - now. Your awesome idea will have plenty of users later! -

    -
    -
- ); -} diff --git a/components/tutorial/tutorial-step.tsx b/components/tutorial/tutorial-step.tsx deleted file mode 100644 index 0ab9cd4..0000000 --- a/components/tutorial/tutorial-step.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Checkbox } from "../ui/checkbox"; - -export function TutorialStep({ - title, - children, -}: { - title: string; - children: React.ReactNode; -}) { - return ( -
  • - - -
  • - ); -} diff --git a/components/typography/inline-code.tsx b/components/typography/inline-code.tsx deleted file mode 100644 index 288f9e3..0000000 --- a/components/typography/inline-code.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export function TypographyInlineCode() { - return ( - - @radix-ui/react-alert-dialog - - ); -} diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx deleted file mode 100644 index d3d5d60..0000000 --- a/components/ui/badge.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", - { - variants: { - variant: { - default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", - secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: - "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - }, -); - -export interface BadgeProps - extends React.HTMLAttributes, - VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return ( -
    - ); -} - -export { Badge, badgeVariants }; diff --git a/components/ui/button.tsx b/components/ui/button.tsx deleted file mode 100644 index 57c9fe4..0000000 --- a/components/ui/button.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - }, -); - -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean; -} - -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - return ( - - ); - }, -); -Button.displayName = "Button"; - -export { Button, buttonVariants }; diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx deleted file mode 100644 index 5985e3c..0000000 --- a/components/ui/checkbox.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client"; - -import * as React from "react"; -import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; -import { Check } from "lucide-react"; - -import { cn } from "@/lib/utils"; - -const Checkbox = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - - - -)); -Checkbox.displayName = CheckboxPrimitive.Root.displayName; - -export { Checkbox }; diff --git a/components/ui/dropdown-menu.tsx b/components/ui/dropdown-menu.tsx deleted file mode 100644 index 3a0c7fe..0000000 --- a/components/ui/dropdown-menu.tsx +++ /dev/null @@ -1,200 +0,0 @@ -"use client"; - -import * as React from "react"; -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; -import { Check, ChevronRight, Circle } from "lucide-react"; - -import { cn } from "@/lib/utils"; - -const DropdownMenu = DropdownMenuPrimitive.Root; - -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; - -const DropdownMenuGroup = DropdownMenuPrimitive.Group; - -const DropdownMenuPortal = DropdownMenuPrimitive.Portal; - -const DropdownMenuSub = DropdownMenuPrimitive.Sub; - -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; - -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)); -DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName; - -const DropdownMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName; - -const DropdownMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)); -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; - -const DropdownMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - -)); -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName; - -const DropdownMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; - -const DropdownMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - -)); -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; - -const DropdownMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; - -const DropdownMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ); -}; -DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuRadioItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuRadioGroup, -}; diff --git a/components/ui/input.tsx b/components/ui/input.tsx deleted file mode 100644 index 9d631e7..0000000 --- a/components/ui/input.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from "react"; - -import { cn } from "@/lib/utils"; - -export interface InputProps - extends React.InputHTMLAttributes {} - -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ); - }, -); -Input.displayName = "Input"; - -export { Input }; diff --git a/components/ui/label.tsx b/components/ui/label.tsx deleted file mode 100644 index 84f8b0c..0000000 --- a/components/ui/label.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import * as React from "react"; -import * as LabelPrimitive from "@radix-ui/react-label"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", -); - -const Label = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, ...props }, ref) => ( - -)); -Label.displayName = LabelPrimitive.Root.displayName; - -export { Label }; diff --git a/lib/utils.ts b/lib/utils.ts deleted file mode 100644 index 365058c..0000000 --- a/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type ClassValue, clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} diff --git a/middleware.ts b/middleware.ts deleted file mode 100644 index 53428f8..0000000 --- a/middleware.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { type NextRequest } from "next/server"; -import { updateSession } from "@/utils/supabase/middleware"; - -export async function middleware(request: NextRequest) { - return await updateSession(request); -} - -export const config = { - matcher: [ - /* - * Match all request paths except: - * - _next/static (static files) - * - _next/image (image optimization files) - * - favicon.ico (favicon file) - * - images - .svg, .png, .jpg, .jpeg, .gif, .webp - * Feel free to modify this pattern to include more paths. - */ - "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)", - ], -}; diff --git a/next.config.js b/next.config.js deleted file mode 100644 index 658404a..0000000 --- a/next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -module.exports = nextConfig; diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index 12a703d..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/utils/cn.ts b/utils/cn.ts deleted file mode 100644 index a5ef193..0000000 --- a/utils/cn.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} diff --git a/utils/supabase/check-env-vars.ts b/utils/supabase/check-env-vars.ts deleted file mode 100644 index 7180f45..0000000 --- a/utils/supabase/check-env-vars.ts +++ /dev/null @@ -1,6 +0,0 @@ -// This check can be removed -// it is just for tutorial purposes - -export const hasEnvVars = - process.env.NEXT_PUBLIC_SUPABASE_URL && - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; diff --git a/utils/supabase/client.ts b/utils/supabase/client.ts deleted file mode 100644 index e2660d0..0000000 --- a/utils/supabase/client.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createBrowserClient } from "@supabase/ssr"; - -export const createClient = () => - createBrowserClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, - ); diff --git a/utils/supabase/middleware.ts b/utils/supabase/middleware.ts deleted file mode 100644 index 8619ec0..0000000 --- a/utils/supabase/middleware.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { createServerClient } from "@supabase/ssr"; -import { type NextRequest, NextResponse } from "next/server"; - -export const updateSession = async (request: NextRequest) => { - // This `try/catch` block is only here for the interactive tutorial. - // Feel free to remove once you have Supabase connected. - try { - // Create an unmodified response - let response = NextResponse.next({ - request: { - headers: request.headers, - }, - }); - - const supabase = createServerClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, - { - cookies: { - getAll() { - return request.cookies.getAll(); - }, - setAll(cookiesToSet) { - cookiesToSet.forEach(({ name, value }) => - request.cookies.set(name, value), - ); - response = NextResponse.next({ - request, - }); - cookiesToSet.forEach(({ name, value, options }) => - response.cookies.set(name, value, options), - ); - }, - }, - }, - ); - - // This will refresh session if expired - required for Server Components - // https://supabase.com/docs/guides/auth/server-side/nextjs - const user = await supabase.auth.getUser(); - - // protected routes - if (request.nextUrl.pathname.startsWith("/protected") && user.error) { - return NextResponse.redirect(new URL("/sign-in", request.url)); - } - - if (request.nextUrl.pathname === "/" && !user.error) { - return NextResponse.redirect(new URL("/protected", request.url)); - } - - return response; - } catch (e) { - // If you are here, a Supabase client could not be created! - // This is likely because you have not set up environment variables. - // Check out http://localhost:3000 for Next Steps. - return NextResponse.next({ - request: { - headers: request.headers, - }, - }); - } -}; diff --git a/utils/supabase/server.ts b/utils/supabase/server.ts deleted file mode 100644 index 2c00bbc..0000000 --- a/utils/supabase/server.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { createServerClient } from "@supabase/ssr"; -import { cookies } from "next/headers"; - -export const createClient = async () => { - const cookieStore = await cookies(); - - return createServerClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, - { - cookies: { - getAll() { - return cookieStore.getAll(); - }, - setAll(cookiesToSet) { - try { - cookiesToSet.forEach(({ name, value, options }) => { - cookieStore.set(name, value, options); - }); - } catch (error) { - // The `set` method was called from a Server Component. - // This can be ignored if you have middleware refreshing - // user sessions. - } - }, - }, - }, - ); -}; diff --git a/utils/utils.ts b/utils/utils.ts deleted file mode 100644 index c9fbbe8..0000000 --- a/utils/utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { redirect } from "next/navigation"; - -/** - * Redirects to a specified path with an encoded message as a query parameter. - * @param {('error' | 'success')} type - The type of message, either 'error' or 'success'. - * @param {string} path - The path to redirect to. - * @param {string} message - The message to be encoded and added as a query parameter. - * @returns {never} This function doesn't return as it triggers a redirect. - */ -export function encodedRedirect( - type: "error" | "success", - path: string, - message: string, -) { - return redirect(`${path}?${type}=${encodeURIComponent(message)}`); -}