[
  {
    "path": ".eslintrc.cjs",
    "content": "/** @type {import(\"eslint\").Linter.Config} */\nconst config = {\n  root: true,\n  extends: [\n    \"next\",\n    \"next/core-web-vitals\",\n    \"plugin:@typescript-eslint/recommended\",\n  ],\n  plugins: [\"react\", \"@typescript-eslint\", \"unused-imports\"],\n  overrides: [\n    {\n      files: [\"*.ts\", \"*.tsx\", \"*.js\"],\n      parser: \"@typescript-eslint/parser\",\n    },\n  ],\n  rules: {\n    \"@typescript-eslint/no-misused-promises\": \"off\",\n    \"@typescript-eslint/consistent-type-imports\": [\n      \"warn\",\n      {\n        prefer: \"type-imports\",\n        fixStyle: \"inline-type-imports\",\n      },\n    ],\n    \"import/prefer-default-export\": \"off\",\n    \"react/jsx-filename-extension\": [\"warn\", { extensions: [\".tsx\"] }],\n    \"react/jsx-uses-react\": \"off\",\n    \"react/react-in-jsx-scope\": \"off\",\n\n    \"react/jsx-curly-brace-presence\": [\n      \"warn\",\n      { props: \"never\", children: \"never\" },\n    ],\n    \"@typescript-eslint/no-shadow\": [\"error\"],\n    \"@typescript-eslint/no-unused-vars\": \"off\",\n    \"no-param-reassign\": [\"error\"],\n    \"unused-imports/no-unused-imports\": \"error\",\n    \"unused-imports/no-unused-vars\": [\n      \"warn\",\n      {\n        vars: \"all\",\n        varsIgnorePattern: \"^_\",\n        args: \"after-used\",\n        argsIgnorePattern: \"^_\",\n      },\n    ],\n    \"padding-line-between-statements\": [\n      \"error\",\n      {\n        blankLine: \"always\",\n        prev: [\"const\", \"let\", \"var\", \"directive\"],\n        next: \"*\",\n      },\n      {\n        blankLine: \"any\",\n        prev: [\"const\", \"let\", \"var\"],\n        next: [\"const\", \"let\", \"var\"],\n      },\n      { blankLine: \"always\", prev: \"*\", next: \"return\" },\n      { blankLine: \"always\", prev: [\"block\", \"block-like\"], next: \"*\" },\n      { blankLine: \"always\", prev: \"*\", next: [\"function\"] },\n      {\n        blankLine: \"always\",\n        prev: \"import\",\n        next: [\"const\", \"let\", \"var\", \"function\", \"export\", \"block-like\"],\n      },\n    ],\n    \"no-nested-ternary\": \"error\",\n  },\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Motivation and context\n\n<!--- Why is this change required? What problem does it solve? -->\n<!--- Add here link to Jira, but let this not be the only content in this section -->\n\n## Description\n\n<!--- Describe what you have done and why have you done it this way -->\n\n## Steps to reproduce the behavior\n\n## Screenshots (if appropriate)\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "defaults:\n  run:\n    working-directory: ./\n\nname: CI on pull request\n\non: [pull_request]\n\njobs:\n  prettier-eslint:\n    name: prettier-eslint\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [18]\n    env:\n      SKIP_ENV_VALIDATION: true\n    steps:\n      - uses: actions/checkout@v3\n      - uses: pnpm/action-setup@v2\n        with:\n          version: 8\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: \"pnpm\"\n      - name: Install pnpm\n        run: pnpm install\n      - name: Run Lint\n        run: pnpm lint\n"
  },
  {
    "path": ".github/workflows/production.yaml",
    "content": "name: Deploy Migrations to Production\n\non:\n  push:\n    branches:\n      - prod\n  workflow_dispatch:\n\njobs:\n  deploy:\n    runs-on: ubuntu-22.04\n\n    env:\n      SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}\n      SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }}\n      PRODUCTION_PROJECT_ID: <YOUR_PROJECT_ID>\n\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: supabase/setup-cli@v1\n\n      - run: |\n          supabase link --project-ref $PRODUCTION_PROJECT_ID\n          supabase db push\n"
  },
  {
    "path": ".github/workflows/staging.yaml",
    "content": "name: Deploy Migrations to Staging\n\non:\n  push:\n    branches:\n      - staging\n  workflow_dispatch:\n\njobs:\n  deploy:\n    runs-on: ubuntu-22.04\n\n    env:\n      SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}\n      SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}\n      STAGING_PROJECT_ID: <YOUR_PROJECT_ID>\n\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: supabase/setup-cli@v1\n\n      - run: |\n          supabase link --project-ref $STAGING_PROJECT_ID\n          supabase db push\n"
  },
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# database\n/prisma/db.sqlite\n/prisma/db.sqlite-journal\n\n# next.js\n/.next/\n/out/\nnext-env.d.ts\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n.pnpm-debug.log*\n\n# local env files\n# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables\n.env\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": "README.md",
    "content": "# T3 stack + Supabase + App directory\n\nThis project is Edge ready (Vercel Edge runtime)\n\nThis is a starter project/boilerplate to start out with:\n\n- TRPC\n- App directory/router\n- Prisma\n- Supabase (Auth, Storage, Serverless Queries)\n- Tailwind\n- Edge Ready\n- Umami analytics\n\nIt allows us to call database in server components through supabase-js, for client component we are using trpc+prisma due to the superior DX\n\n## Projects using this starter\n\n- PortfolioQuiz [Website](https://www.portfolio-quiz.com/)\n- FreeLogo.dev [Website](https://www.freelogo.dev/)\n- FeastQR [Repo](https://github.com/jakubczarnowski/FeastQR) [Website](https://www.feastqr.com)\n- Instagram Clone [Repo](https://github.com/jakubczarnowski/instagram-clone) [Website](https://instagram-clone-eight-mu.vercel.app/)\n\n## What's next? How do I make an app with this?\n\n- Clone this project\n- Run\n\n```\npnpm install\n```\n\n- Copy the .env.example into .env and fill out the envs\n\n### Initial Setup\n\n## If you want to develop on local supabase instance, follow the steps below:\n\nThen go to supabase/config.toml file and change your service name.\n\nStart the database:\n\n- supabase start\n- pnpm prepare:local\n\n## If you want to develop on remote supabase instance, follow the steps below:\n\nConnect supabase to remote instance:\n\n- supabase link --project-ref <_your_project_id_>\n- pnpm prepare:remote\n\n## Common steps\n\n- Fill out environment variables\n- Create Secrets on Github\n\n#### If you want to create migrations by hand, go ahead and use this command:\n\n- supabase migration new <_migration_name_>\n\nThen go to supabase/migrations folder and add your SQL there.\n\n#### If you want to make changes with studio, use\n\n- pnpm db:diff <_migration_name_>\n\n## Run these initial commands\n\nEvery time you change something on local instance:\n\n```\npnpm prepare:local\n```\n\n- If you develop on cloud supabase run:\n\n```\npnpm prepare:remote\n```\n\n- Run the project\n\n```\npnpm dev\n```\n\nIf you are not familiar with the different technologies used in this project, please refer to the respective docs.\n\n- [Next.js app router](https://nextjs.org/docs)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n- [Supabase](https://supabase.com/docs)\n\n## Authors\n\n👤 **Milosz Jankiewicz**\n\n- Twitter: [@twitter.com/jaaneek/](https://twitter.com/jaaneek)\n- Github: [@Jaaneek](https://github.com/Jaaneek)\n- LinkedIn: [@https://www.linkedin.com/in/jaaneek](https://www.linkedin.com/in/mi%C5%82osz-jankiewicz-554562168/)\n\n👤 **Jakub Czarnowski**\n\n- Twitter: [@twitter.com/charnowsky/](https://twitter.com/charnowsky)\n- Github: [@jakubczarnowski](https://github.com/jakubczarnowski)\n- LinkedIn: [@https://www.linkedin.com/in/czarnowskijakub/](https://www.linkedin.com/in/czarnowskijakub/)\n\n## Learn More\n\nTo learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources:\n\n- [Documentation](https://create.t3.gg/)\n- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials\n\nYou can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome!\n\n## How do I deploy this?\n\nFollow deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.\n"
  },
  {
    "path": "components.json",
    "content": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"default\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"tailwind.config.ts\",\n    \"css\": \"src/styles/globals.css\",\n    \"baseColor\": \"slate\",\n    \"cssVariables\": true\n  },\n  \"aliases\": {\n    \"components\": \"~/components\",\n    \"utils\": \"~/utils/cn\"\n  }\n}\n"
  },
  {
    "path": "next.config.mjs",
    "content": "/**\n * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful\n * for Docker builds.\n */\nawait import(\"./src/env.mjs\");\n\n/** @type {import(\"next\").NextConfig} */\nconst config = {\n  reactStrictMode: true,\n\n  /**\n   * If you are using `appDir` then you must comment the below `i18n` config out.\n   *\n   * @see https://github.com/vercel/next.js/issues/41980\n   */\n  i18n: {\n    locales: [\"en\"],\n    defaultLocale: \"en\",\n  },\n};\n\nexport default config;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"t3-supabase-app-router-enhanced\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"next build\",\n    \"db:push\": \"prisma db push\",\n    \"dev\": \"next dev\",\n    \"postinstall\": \"prisma generate\",\n    \"start\": \"next start\",\n    \"lint\": \"next lint && pnpm check-types\",\n    \"check-types\": \"tsc --noEmit\",\n    \"update-types-local\": \"npx supabase gen types typescript --local > src/server/supabase/supabaseTypes.ts\",\n    \"update-types-remote\": \"npx supabase gen types typescript --project-id \\\"<YOUR_PROJECT_ID>\\\" --schema public > src/server/supabase/supabaseTypes.ts\",\n    \"prepare:local\": \"pnpm update-types-local && pnpm prisma db pull && pnpm prisma generate && pnpm prisma-case-format --file prisma/schema.prisma  && pnpm prisma generate\",\n    \"prepare:remote\": \"pnpm update-types-remote && pnpm prisma db pull && pnpm prisma generate && pnpm prisma-case-format --file prisma/schema.prisma  && pnpm prisma generate\",\n    \"db:reset\": \"npx supabase db reset\",\n    \"db:start\": \"npx supabase start\",\n    \"db:stop\": \"npx supabase stop\",\n    \"db:diff\": \"npx supabase db diff -f\"\n  },\n  \"dependencies\": {\n    \"@prisma/client\": \"^5.6.0\",\n    \"@radix-ui/react-dropdown-menu\": \"^2.0.6\",\n    \"@radix-ui/react-label\": \"^2.0.2\",\n    \"@radix-ui/react-slot\": \"^1.0.2\",\n    \"@radix-ui/react-toast\": \"^1.1.5\",\n    \"@supabase/auth-helpers-nextjs\": \"^0.8.7\",\n    \"@supabase/supabase-js\": \"^2.39.0\",\n    \"@t3-oss/env-nextjs\": \"^0.6.1\",\n    \"@tanstack/react-query\": \"^4.36.1\",\n    \"@tanstack/react-query-devtools\": \"^5.12.1\",\n    \"@trpc/client\": \"^10.44.1\",\n    \"@trpc/next\": \"^10.44.1\",\n    \"@trpc/react-query\": \"^10.44.1\",\n    \"@trpc/server\": \"^10.44.1\",\n    \"@vercel/analytics\": \"^1.1.1\",\n    \"accept-language\": \"^3.0.18\",\n    \"class-variance-authority\": \"^0.7.0\",\n    \"clsx\": \"^2.0.0\",\n    \"lucide-react\": \"^0.284.0\",\n    \"next\": \"^14.0.3\",\n    \"next-themes\": \"^0.2.1\",\n    \"react\": \"18.2.0\",\n    \"react-dom\": \"18.2.0\",\n    \"react-hook-form\": \"^7.49.2\",\n    \"superjson\": \"^1.13.3\",\n    \"tailwind-merge\": \"^1.14.0\",\n    \"tailwindcss-animate\": \"^1.0.7\",\n    \"zod\": \"^3.22.4\"\n  },\n  \"devDependencies\": {\n    \"@types/eslint\": \"^8.44.8\",\n    \"@types/node\": \"^18.19.0\",\n    \"@types/react\": \"^18.2.39\",\n    \"@types/react-dom\": \"^18.2.17\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.13.1\",\n    \"@typescript-eslint/parser\": \"^6.13.1\",\n    \"autoprefixer\": \"^10.4.16\",\n    \"eslint\": \"^8.54.0\",\n    \"eslint-config-next\": \"^13.5.6\",\n    \"eslint-plugin-unused-imports\": \"^3.0.0\",\n    \"postcss\": \"^8.4.31\",\n    \"prettier\": \"^3.1.0\",\n    \"prettier-plugin-tailwindcss\": \"^0.5.7\",\n    \"prisma\": \"^5.6.0\",\n    \"prisma-case-format\": \"^1.7.3\",\n    \"tailwindcss\": \"^3.3.5\",\n    \"typescript\": \"^5.3.2\"\n  },\n  \"ct3aMetadata\": {\n    \"initVersion\": \"7.20.2\"\n  },\n  \"packageManager\": \"pnpm@8.8.0\"\n}"
  },
  {
    "path": "postcss.config.cjs",
    "content": "const config = {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "prettier.config.mjs",
    "content": "/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').options} */\nconst config = {\n  plugins: [\"prettier-plugin-tailwindcss\"],\n};\n\nexport default config;\n"
  },
  {
    "path": "prisma/schema.prisma",
    "content": "generator client {\n  provider        = \"prisma-client-js\"\n  previewFeatures = [\"multiSchema\"]\n}\n\ndatasource db {\n  provider  = \"postgresql\"\n  url       = env(\"DATABASE_URL\")\n  directUrl = env(\"DIRECT_URL\")\n  schemas   = [\"auth\", \"public\"]\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel AuditLogEntries {\n  instanceId String?   @map(\"instance_id\") @db.Uuid\n  id         String    @id @db.Uuid\n  payload    Json?     @db.Json\n  createdAt  DateTime? @map(\"created_at\") @db.Timestamptz(6)\n  ipAddress  String    @default(\"\") @map(\"ip_address\") @db.VarChar(64)\n\n  @@index([instanceId], map: \"audit_logs_instance_id_idx\")\n  @@map(\"audit_log_entries\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel FlowState {\n  id                   String              @id @db.Uuid\n  userId               String?             @map(\"user_id\") @db.Uuid\n  authCode             String              @map(\"auth_code\")\n  codeChallengeMethod  CodeChallengeMethod @map(\"code_challenge_method\")\n  codeChallenge        String              @map(\"code_challenge\")\n  providerType         String              @map(\"provider_type\")\n  providerAccessToken  String?             @map(\"provider_access_token\")\n  providerRefreshToken String?             @map(\"provider_refresh_token\")\n  createdAt            DateTime?           @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt            DateTime?           @map(\"updated_at\") @db.Timestamptz(6)\n  authenticationMethod String              @map(\"authentication_method\")\n\n  @@index([authCode], map: \"idx_auth_code\")\n  @@index([userId, authenticationMethod], map: \"idx_user_id_auth_method\")\n  @@map(\"flow_state\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel Identities {\n  id           String\n  userId       String    @map(\"user_id\") @db.Uuid\n  identityData Json      @map(\"identity_data\")\n  provider     String\n  lastSignInAt DateTime? @map(\"last_sign_in_at\") @db.Timestamptz(6)\n  createdAt    DateTime? @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt    DateTime? @map(\"updated_at\") @db.Timestamptz(6)\n  email        String?   @default(dbgenerated(\"lower((identity_data ->> 'email'::text))\"))\n  users        Users     @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@id([provider, id])\n  @@index([email])\n  @@index([userId])\n  @@map(\"identities\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel Instances {\n  id            String    @id @db.Uuid\n  uuid          String?   @db.Uuid\n  rawBaseConfig String?   @map(\"raw_base_config\")\n  createdAt     DateTime? @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt     DateTime? @map(\"updated_at\") @db.Timestamptz(6)\n\n  @@map(\"instances\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel MfaAmrClaims {\n  sessionId            String   @map(\"session_id\") @db.Uuid\n  createdAt            DateTime @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt            DateTime @map(\"updated_at\") @db.Timestamptz(6)\n  authenticationMethod String   @map(\"authentication_method\")\n  id                   String   @id(map: \"amr_id_pk\") @db.Uuid\n  sessions             Sessions @relation(fields: [sessionId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@unique([sessionId, authenticationMethod], map: \"mfa_amr_claims_session_id_authentication_method_pkey\")\n  @@map(\"mfa_amr_claims\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel MfaChallenges {\n  id         String     @id @db.Uuid\n  factorId   String     @map(\"factor_id\") @db.Uuid\n  createdAt  DateTime   @map(\"created_at\") @db.Timestamptz(6)\n  verifiedAt DateTime?  @map(\"verified_at\") @db.Timestamptz(6)\n  ipAddress  String     @map(\"ip_address\") @db.Inet\n  mfaFactors MfaFactors @relation(fields: [factorId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: \"mfa_challenges_auth_factor_id_fkey\")\n\n  @@map(\"mfa_challenges\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel MfaFactors {\n  id            String          @id @db.Uuid\n  userId        String          @map(\"user_id\") @db.Uuid\n  friendlyName  String?         @map(\"friendly_name\")\n  factorType    FactorType      @map(\"factor_type\")\n  status        FactorStatus    @map(\"status\")\n  createdAt     DateTime        @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt     DateTime        @map(\"updated_at\") @db.Timestamptz(6)\n  secret        String?\n  mfaChallenges MfaChallenges[]\n  users         Users           @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([userId, createdAt], map: \"factor_id_created_at_idx\")\n  @@map(\"mfa_factors\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel RefreshTokens {\n  instanceId String?   @map(\"instance_id\") @db.Uuid\n  id         BigInt    @id @default(autoincrement())\n  token      String?   @unique(map: \"refresh_tokens_token_unique\") @db.VarChar(255)\n  userId     String?   @map(\"user_id\") @db.VarChar(255)\n  revoked    Boolean?\n  createdAt  DateTime? @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt  DateTime? @map(\"updated_at\") @db.Timestamptz(6)\n  parent     String?   @db.VarChar(255)\n  sessionId  String?   @map(\"session_id\") @db.Uuid\n  sessions   Sessions? @relation(fields: [sessionId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([instanceId])\n  @@index([instanceId, userId])\n  @@index([parent])\n  @@index([sessionId, revoked])\n  @@map(\"refresh_tokens\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel SamlProviders {\n  id               String       @id @db.Uuid\n  ssoProviderId    String       @map(\"sso_provider_id\") @db.Uuid\n  entityId         String       @unique @map(\"entity_id\")\n  metadataXml      String       @map(\"metadata_xml\")\n  metadataUrl      String?      @map(\"metadata_url\")\n  attributeMapping Json?        @map(\"attribute_mapping\")\n  createdAt        DateTime?    @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt        DateTime?    @map(\"updated_at\") @db.Timestamptz(6)\n  ssoProviders     SsoProviders @relation(fields: [ssoProviderId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([ssoProviderId])\n  @@map(\"saml_providers\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel SamlRelayStates {\n  id            String       @id @db.Uuid\n  ssoProviderId String       @map(\"sso_provider_id\") @db.Uuid\n  requestId     String       @map(\"request_id\")\n  forEmail      String?      @map(\"for_email\")\n  redirectTo    String?      @map(\"redirect_to\")\n  fromIpAddress String?      @map(\"from_ip_address\") @db.Inet\n  createdAt     DateTime?    @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt     DateTime?    @map(\"updated_at\") @db.Timestamptz(6)\n  ssoProviders  SsoProviders @relation(fields: [ssoProviderId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([forEmail])\n  @@index([ssoProviderId])\n  @@map(\"saml_relay_states\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel SchemaMigrations {\n  version String @id @db.VarChar(255)\n\n  @@map(\"schema_migrations\")\n  @@schema(\"auth\")\n}\n\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\nmodel Sessions {\n  id            String          @id @db.Uuid\n  userId        String          @map(\"user_id\") @db.Uuid\n  createdAt     DateTime?       @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt     DateTime?       @map(\"updated_at\") @db.Timestamptz(6)\n  factorId      String?         @map(\"factor_id\") @db.Uuid\n  aal           AalLevel?       @map(\"aal\")\n  notAfter      DateTime?       @map(\"not_after\") @db.Timestamptz(6)\n  mfaAmrClaims  MfaAmrClaims[]\n  refreshTokens RefreshTokens[]\n  users         Users           @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([userId])\n  @@index([userId, createdAt], map: \"user_id_created_at_idx\")\n  @@map(\"sessions\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\n/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info.\nmodel SsoDomains {\n  id            String       @id @db.Uuid\n  ssoProviderId String       @map(\"sso_provider_id\") @db.Uuid\n  domain        String\n  createdAt     DateTime?    @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt     DateTime?    @map(\"updated_at\") @db.Timestamptz(6)\n  ssoProviders  SsoProviders @relation(fields: [ssoProviderId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@index([ssoProviderId])\n  @@map(\"sso_domains\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\n/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info.\nmodel SsoProviders {\n  id              String            @id @db.Uuid\n  resourceId      String?           @map(\"resource_id\")\n  createdAt       DateTime?         @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt       DateTime?         @map(\"updated_at\") @db.Timestamptz(6)\n  samlProviders   SamlProviders[]\n  samlRelayStates SamlRelayStates[]\n  ssoDomains      SsoDomains[]\n\n  @@map(\"sso_providers\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments\n/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info.\nmodel Users {\n  instanceId               String?      @map(\"instance_id\") @db.Uuid\n  id                       String       @id @db.Uuid\n  aud                      String?      @db.VarChar(255)\n  role                     String?      @db.VarChar(255)\n  email                    String?      @db.VarChar(255)\n  encryptedPassword        String?      @map(\"encrypted_password\") @db.VarChar(255)\n  emailConfirmedAt         DateTime?    @map(\"email_confirmed_at\") @db.Timestamptz(6)\n  invitedAt                DateTime?    @map(\"invited_at\") @db.Timestamptz(6)\n  confirmationToken        String?      @map(\"confirmation_token\") @db.VarChar(255)\n  confirmationSentAt       DateTime?    @map(\"confirmation_sent_at\") @db.Timestamptz(6)\n  recoveryToken            String?      @map(\"recovery_token\") @db.VarChar(255)\n  recoverySentAt           DateTime?    @map(\"recovery_sent_at\") @db.Timestamptz(6)\n  emailChangeTokenNew      String?      @map(\"email_change_token_new\") @db.VarChar(255)\n  emailChange              String?      @map(\"email_change\") @db.VarChar(255)\n  emailChangeSentAt        DateTime?    @map(\"email_change_sent_at\") @db.Timestamptz(6)\n  lastSignInAt             DateTime?    @map(\"last_sign_in_at\") @db.Timestamptz(6)\n  rawAppMetaData           Json?        @map(\"raw_app_meta_data\")\n  rawUserMetaData          Json?        @map(\"raw_user_meta_data\")\n  isSuperAdmin             Boolean?     @map(\"is_super_admin\")\n  createdAt                DateTime?    @map(\"created_at\") @db.Timestamptz(6)\n  updatedAt                DateTime?    @map(\"updated_at\") @db.Timestamptz(6)\n  phone                    String?      @unique\n  phoneConfirmedAt         DateTime?    @map(\"phone_confirmed_at\") @db.Timestamptz(6)\n  phoneChange              String?      @default(\"\") @map(\"phone_change\")\n  phoneChangeToken         String?      @default(\"\") @map(\"phone_change_token\") @db.VarChar(255)\n  phoneChangeSentAt        DateTime?    @map(\"phone_change_sent_at\") @db.Timestamptz(6)\n  confirmedAt              DateTime?    @default(dbgenerated(\"LEAST(email_confirmed_at, phone_confirmed_at)\")) @map(\"confirmed_at\") @db.Timestamptz(6)\n  emailChangeTokenCurrent  String?      @default(\"\") @map(\"email_change_token_current\") @db.VarChar(255)\n  emailChangeConfirmStatus Int?         @default(0) @map(\"email_change_confirm_status\") @db.SmallInt\n  bannedUntil              DateTime?    @map(\"banned_until\") @db.Timestamptz(6)\n  reauthenticationToken    String?      @default(\"\") @map(\"reauthentication_token\") @db.VarChar(255)\n  reauthenticationSentAt   DateTime?    @map(\"reauthentication_sent_at\") @db.Timestamptz(6)\n  isSsoUser                Boolean      @default(false) @map(\"is_sso_user\")\n  deletedAt                DateTime?    @map(\"deleted_at\") @db.Timestamptz(6)\n  identities               Identities[]\n  mfaFactors               MfaFactors[]\n  sessions                 Sessions[]\n  profiles                 Profiles?\n\n  @@index([instanceId])\n  @@map(\"users\")\n  @@schema(\"auth\")\n}\n\n/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.\n/// This model contains row level security and requires additional setup for migrations. Visit https://pris.ly/d/row-level-security for more info.\nmodel Profiles {\n  id        String    @id @db.Uuid\n  updatedAt DateTime? @map(\"updated_at\") @db.Timestamptz(6)\n  email     String?   @unique\n  fullName  String?   @map(\"full_name\")\n  avatarUrl String?   @map(\"avatar_url\")\n  users     Users     @relation(fields: [id], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n  @@map(\"profiles\")\n  @@schema(\"public\")\n}\n\nenum AalLevel {\n  aal1\n  aal2\n  aal3\n\n  @@map(\"aal_level\")\n  @@schema(\"auth\")\n}\n\nenum CodeChallengeMethod {\n  s256\n  plain\n\n  @@map(\"code_challenge_method\")\n  @@schema(\"auth\")\n}\n\nenum FactorStatus {\n  unverified\n  verified\n\n  @@map(\"factor_status\")\n  @@schema(\"auth\")\n}\n\nenum FactorType {\n  totp\n  webauthn\n\n  @@map(\"factor_type\")\n  @@schema(\"auth\")\n}\n"
  },
  {
    "path": "src/app/(auth)/_components/DevLoginButtons.tsx",
    "content": "\"use client\";\n\nimport { supabase } from \"~/server/supabase/supabaseClient\";\n\nconst testAccounts = [\n  { email: \"random@gmail.com\", password: \"testPassword\" },\n  { email: \"random2@gmail.com\", password: \"testPassword2\" },\n];\n\nexport const DevLoginButtons = () => {\n  return (\n    <div className=\"flex flex-col gap-2\">\n      {testAccounts.map((account, index) => (\n        <div key={index} className=\"flex flex-col items-start text-white\">\n          <button\n            onClick={() => {\n              void supabase().auth.signInWithPassword(account);\n            }}\n          >\n            Login {account.email}\n          </button>\n          <button\n            onClick={() => {\n              void supabase().auth.signUp(account);\n            }}\n          >\n            Register {account.email}\n          </button>\n        </div>\n      ))}\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/app/(auth)/layout.tsx",
    "content": "import { type PropsWithChildren } from \"react\";\nimport { PublicRoute } from \"~/components/PublicRoute/PublicRoute\";\n\nconst Layout = async ({ children }: PropsWithChildren) => {\n  return <PublicRoute>{children}</PublicRoute>;\n};\n\nexport default Layout;\n"
  },
  {
    "path": "src/app/(auth)/login/page.tsx",
    "content": "\"use client\";\n\nimport { type Provider } from \"@supabase/supabase-js\";\nimport { Icons } from \"~/components/Icons\";\nimport { Button } from \"~/components/ui/button\";\nimport { supabase } from \"~/server/supabase/supabaseClient\";\nimport { DevLoginButtons } from \"../_components/DevLoginButtons\";\n\nconst Page = () => {\n  const signInWithOauth = (provider: Provider) => {\n    void supabase().auth.signInWithOAuth({\n      provider: provider,\n    });\n  };\n\n  return (\n    <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]\">\n      <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16 \">\n        <div className=\"flex flex-col items-center gap-6\">\n          <h1 className=\"text-3xl font-extrabold tracking-tight text-white\">\n            Login\n          </h1>\n\n          <div className=\"flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20\">\n            <Button\n              variant=\"outline\"\n              className=\"flex flex-row gap-2\"\n              onClick={() => {\n                signInWithOauth(\"google\");\n              }}\n            >\n              <Icons.google width={16} />\n              Google\n            </Button>\n            <Button\n              variant=\"outline\"\n              className=\"flex flex-row gap-2\"\n              onClick={() => {\n                signInWithOauth(\"github\");\n              }}\n            >\n              <Icons.gitHub width={16} />\n              Github\n            </Button>\n          </div>\n        </div>\n      </div>\n      {process.env.NEXT_PUBLIC_VERCEL_ENV !== \"production\" && (\n        <DevLoginButtons />\n      )}\n    </main>\n  );\n};\n\nexport default Page;\n"
  },
  {
    "path": "src/app/(authenticatedRoutes)/authenticated/page.tsx",
    "content": "\"use client\";\n\nimport { api } from \"~/trpc/react\";\n\nconst AuthenticatedExample = () => {\n  const { data } = api.auth.getProfile.useQuery();\n\n  return (\n    <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]\">\n      <div className=\"container flex flex-col items-center justify-center gap-12\">\n        <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n          Authenticated Route Example\n        </h1>\n        <div className=\"flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20\">\n          <h3 className=\"text-2xl font-bold\">User Information</h3>\n          <div className=\"text-lg\">Email: {data?.email}</div>\n          <div className=\"text-lg\">Name: {data?.fullName}</div>\n        </div>\n      </div>\n    </main>\n  );\n};\n\nexport default AuthenticatedExample;\n"
  },
  {
    "path": "src/app/(authenticatedRoutes)/layout.tsx",
    "content": "import { type PropsWithChildren } from \"react\";\nimport { PrefetchTRPCQuery } from \"~/components/PrefetchTRPCQuery/PrefetchTRPCQuery\";\nimport { PrivateRoute } from \"~/components/PrivateRoute/PrivateRoute\";\n\nexport default function Layout({ children }: PropsWithChildren) {\n  return (\n    <PrivateRoute>\n      <PrefetchTRPCQuery queryName=\"auth.getProfile\">\n        {children}\n      </PrefetchTRPCQuery>\n    </PrivateRoute>\n  );\n}\n"
  },
  {
    "path": "src/app/_components/ServerDataStreaming.tsx",
    "content": "import { api } from \"~/trpc/server\";\n\nexport async function ServerDataStreaming() {\n  const data = await api.example.hello.query({ text: \"from tRPC\" });\n\n  await new Promise((resolve) => setTimeout(resolve, 1000));\n\n  return <p className=\"text-2xl text-white\">{data.greeting}</p>;\n}\n"
  },
  {
    "path": "src/app/api/trpc/[trpc]/route.ts",
    "content": "import { fetchRequestHandler } from \"@trpc/server/adapters/fetch\";\nimport { type NextRequest } from \"next/server\";\nimport { env } from \"~/env.mjs\";\n\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\n\n/**\n * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when\n * handling a HTTP request (e.g. when you make requests from Client Components).\n */\nconst createContext = async (req: NextRequest) => {\n  return createTRPCContext({\n    headers: req.headers,\n  });\n};\n\nconst handler = (req: NextRequest) =>\n  fetchRequestHandler({\n    endpoint: \"/api/trpc\",\n    req,\n    router: appRouter,\n    createContext: () => createContext(req),\n    onError:\n      env.NODE_ENV === \"development\"\n        ? ({ path, error }) => {\n            console.error(\n              `❌ tRPC failed on ${path ?? \"<no-path>\"}: ${error.message}`,\n            );\n          }\n        : undefined,\n  });\n\nexport { handler as GET, handler as POST };\n"
  },
  {
    "path": "src/app/layout.tsx",
    "content": "import { TailwindIndicator } from \"~/components/TailwindIndicator\";\nimport { Providers } from \"~/providers\";\nimport \"~/styles/globals.css\";\nimport { cn } from \"~/utils/cn\";\nimport { Roboto } from \"next/font/google\";\nimport { Toaster } from \"~/components/ui/toaster\";\nimport { getServerUser } from \"~/utils/auth\";\nimport { AuthProvider } from \"~/providers/AuthProvider/AuthProvider\";\nimport { TRPCReactProvider } from \"~/trpc/react\";\nimport { headers } from \"next/headers\";\n\nexport const metadata = {\n  title: \"t3-app-dir-supabase\",\n  description: \"Boilerplate for t3-app-dir-supabase.\",\n};\n\nconst font = Roboto({\n  weight: [\"100\", \"300\", \"400\", \"500\", \"700\", \"900\"],\n  subsets: [\"latin\"],\n});\n\nasync function RootLayout({ children }: { children: React.ReactNode }) {\n  const user = await getServerUser();\n\n  return (\n    <>\n      <html lang=\"en\">\n        <head />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n        <body\n          className={cn(\n            \"min-h-screen bg-background font-sans antialiased\",\n            font.className,\n          )}\n        >\n          <TRPCReactProvider headers={headers()}>\n            <AuthProvider {...user}>\n              <Providers>\n                {children}\n                <Toaster />\n              </Providers>\n            </AuthProvider>\n          </TRPCReactProvider>\n          <TailwindIndicator />\n        </body>\n      </html>\n    </>\n  );\n}\n\nexport default RootLayout;\n"
  },
  {
    "path": "src/app/page.tsx",
    "content": "import Link from \"next/link\";\nimport { Suspense } from \"react\";\nimport { ServerDataStreaming } from \"./_components/ServerDataStreaming\";\n\nconst Homepage = async () => {\n  return (\n    <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]\">\n      <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16 \">\n        <div className=\"flex flex-col items-center gap-6\">\n          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Nextjs 14 App router starter\n          </h1>\n          <p className=\"font-extrabold tracking-tight text-white sm:text-[2rem]\">\n            Based On\n          </p>\n          <p className=\"text-xl font-extrabold tracking-tight text-white sm:text-[3rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </p>\n        </div>\n        <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8\">\n          <Link\n            className=\"flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20\"\n            href=\"https://create.t3.gg/en/usage/first-steps\"\n            target=\"_blank\"\n          >\n            <h3 className=\"text-2xl font-bold\">First Steps →</h3>\n            <div className=\"text-lg\">\n              Just the basics - Everything you need to know to set up your\n              database and authentication.\n            </div>\n          </Link>\n          <Link\n            className=\"flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20\"\n            href=\"https://create.t3.gg/en/introduction\"\n            target=\"_blank\"\n          >\n            <h3 className=\"text-2xl font-bold\">Documentation →</h3>\n            <div className=\"text-lg\">\n              Learn more about Create T3 App, the libraries it uses, and how to\n              deploy it.\n            </div>\n          </Link>\n        </div>\n        <div className=\"flex w-full flex-1 flex-col items-center gap-4\">\n          <Link href=\"/login\" className=\"text-lg text-white\">\n            Login\n          </Link>\n          <Link href=\"/authenticated\" className=\"text-lg text-white\">\n            Authenticated Route Example\n          </Link>\n        </div>\n        <Suspense\n          fallback={\n            <p className=\"text-2xl text-white\">Streaming TRPC Query...</p>\n          }\n        >\n          <ServerDataStreaming />\n        </Suspense>\n      </div>\n    </main>\n  );\n};\n\nexport default Homepage;\n"
  },
  {
    "path": "src/components/FormInput/FormInput.tsx",
    "content": "import {\n  FormControl,\n  FormDescription,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from \"../ui/form\";\n\nexport type FormInputProps = {\n  label?: string;\n  description?: string;\n  children: React.ReactNode;\n};\n\nexport const FormInput = ({ label, description, children }: FormInputProps) => (\n  <FormItem>\n    {label && <FormLabel>{label}</FormLabel>}\n    <FormControl>{children}</FormControl>\n    {description && <FormDescription>{description}</FormDescription>}\n\n    <FormMessage />\n  </FormItem>\n);\n"
  },
  {
    "path": "src/components/Icons/Icons.tsx",
    "content": "import {\n  AlertTriangle,\n  ArrowRight,\n  Check,\n  ChevronLeft,\n  ChevronRight,\n  Command,\n  CreditCard,\n  File,\n  FileText,\n  HelpCircle,\n  Image,\n  Laptop,\n  Loader2,\n  type LucideProps,\n  Moon,\n  MoreVertical,\n  Pizza,\n  Plus,\n  Settings,\n  SunMedium,\n  Trash,\n  Twitter,\n  User,\n  X,\n  Zap,\n  Palette,\n  Truck,\n  AlignHorizontalDistributeCenter,\n  Type,\n  Construction,\n  type LucideIcon,\n  Settings2,\n  Edit,\n  Star,\n  Sparkle,\n  MonitorSmartphone,\n  Scaling,\n  Sparkles,\n  Download,\n  Menu,\n  Facebook,\n  Instagram,\n  Linkedin,\n  Youtube,\n  Lock,\n  Flag,\n  Languages,\n} from \"lucide-react\";\n\nexport type Icon = LucideIcon;\n\nexport const Icons = {\n  languages: Languages,\n  logo: Command,\n  close: X,\n  spinner: Loader2,\n  chevronLeft: ChevronLeft,\n  chevronRight: ChevronRight,\n  trash: Trash,\n  post: FileText,\n  page: File,\n  media: Image,\n  settings: Settings,\n  billing: CreditCard,\n  ellipsis: MoreVertical,\n  add: Plus,\n  warning: AlertTriangle,\n  user: User,\n  arrowRight: ArrowRight,\n  help: HelpCircle,\n  pizza: Pizza,\n  sun: SunMedium,\n  moon: Moon,\n  laptop: Laptop,\n  zap: Zap,\n  palette: Palette,\n  truck: Truck,\n  type: Type,\n  customize: AlignHorizontalDistributeCenter,\n  construction: Construction,\n  settings2: Settings2,\n  edit: Edit,\n  star: Star,\n  sparkle: Sparkle,\n  devices: MonitorSmartphone,\n  scaling: Scaling,\n  sparkles: Sparkles,\n  download: Download,\n  menu: Menu,\n  facebook: Facebook,\n  instagram: Instagram,\n  linkedin: Linkedin,\n  youtube: Youtube,\n  lock: Lock,\n  flag: Flag,\n  gitHub: ({ ...props }) => (\n    <svg\n      aria-hidden=\"true\"\n      focusable=\"false\"\n      data-prefix=\"fab\"\n      data-icon=\"github\"\n      role=\"img\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 496 512\"\n      {...props}\n    >\n      <path\n        fill=\"currentColor\"\n        d=\"M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z\"\n      ></path>\n    </svg>\n  ),\n  google: ({ ...props }: LucideProps) => (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 512 512\"\n      id=\"google\"\n      {...props}\n    >\n      <path\n        fill=\"#fbbb00\"\n        d=\"M113.47 309.408 95.648 375.94l-65.139 1.378C11.042 341.211 0 299.9 0 256c0-42.451 10.324-82.483 28.624-117.732h.014L86.63 148.9l25.404 57.644c-5.317 15.501-8.215 32.141-8.215 49.456.002 18.792 3.406 36.797 9.651 53.408z\"\n      ></path>\n      <path\n        fill=\"#518ef8\"\n        d=\"M507.527 208.176C510.467 223.662 512 239.655 512 256c0 18.328-1.927 36.206-5.598 53.451-12.462 58.683-45.025 109.925-90.134 146.187l-.014-.014-73.044-3.727-10.338-64.535c29.932-17.554 53.324-45.025 65.646-77.911h-136.89V208.176h245.899z\"\n      ></path>\n      <path\n        fill=\"#28b446\"\n        d=\"m416.253 455.624.014.014C372.396 490.901 316.666 512 256 512c-97.491 0-182.252-54.491-225.491-134.681l82.961-67.91c21.619 57.698 77.278 98.771 142.53 98.771 28.047 0 54.323-7.582 76.87-20.818l83.383 68.262z\"\n      ></path>\n      <path\n        fill=\"#f14336\"\n        d=\"m419.404 58.936-82.933 67.896C313.136 112.246 285.552 103.82 256 103.82c-66.729 0-123.429 42.957-143.965 102.724l-83.397-68.276h-.014C71.23 56.123 157.06 0 256 0c62.115 0 119.068 22.126 163.404 58.936z\"\n      ></path>\n    </svg>\n  ),\n  discord: ({ ...props }: LucideProps) => (\n    <svg\n      width=\"256px\"\n      height=\"199px\"\n      viewBox=\"0 0 256 199\"\n      preserveAspectRatio=\"xMidYMid\"\n      fill=\"#6169ff\"\n      {...props}\n    >\n      <g>\n        <path\n          d=\"M216.856339,16.5966031 C200.285002,8.84328665 182.566144,3.2084988 164.041564,0 C161.766523,4.11318106 159.108624,9.64549908 157.276099,14.0464379 C137.583995,11.0849896 118.072967,11.0849896 98.7430163,14.0464379 C96.9108417,9.64549908 94.1925838,4.11318106 91.8971895,0 C73.3526068,3.2084988 55.6133949,8.86399117 39.0420583,16.6376612 C5.61752293,67.146514 -3.4433191,116.400813 1.08711069,164.955721 C23.2560196,181.510915 44.7403634,191.567697 65.8621325,198.148576 C71.0772151,190.971126 75.7283628,183.341335 79.7352139,175.300261 C72.104019,172.400575 64.7949724,168.822202 57.8887866,164.667963 C59.7209612,163.310589 61.5131304,161.891452 63.2445898,160.431257 C105.36741,180.133187 151.134928,180.133187 192.754523,160.431257 C194.506336,161.891452 196.298154,163.310589 198.110326,164.667963 C191.183787,168.842556 183.854737,172.420929 176.223542,175.320965 C180.230393,183.341335 184.861538,190.991831 190.096624,198.16893 C211.238746,191.588051 232.743023,181.531619 254.911949,164.955721 C260.227747,108.668201 245.831087,59.8662432 216.856339,16.5966031 Z M85.4738752,135.09489 C72.8290281,135.09489 62.4592217,123.290155 62.4592217,108.914901 C62.4592217,94.5396472 72.607595,82.7145587 85.4738752,82.7145587 C98.3405064,82.7145587 108.709962,94.5189427 108.488529,108.914901 C108.508531,123.290155 98.3405064,135.09489 85.4738752,135.09489 Z M170.525237,135.09489 C157.88039,135.09489 147.510584,123.290155 147.510584,108.914901 C147.510584,94.5396472 157.658606,82.7145587 170.525237,82.7145587 C183.391518,82.7145587 193.761324,94.5189427 193.539891,108.914901 C193.539891,123.290155 183.391518,135.09489 170.525237,135.09489 Z\"\n          fillRule=\"nonzero\"\n        ></path>\n      </g>\n    </svg>\n  ),\n  twitter: Twitter,\n  check: Check,\n};\n"
  },
  {
    "path": "src/components/Icons/index.ts",
    "content": "export * from \"./Icons\";\n"
  },
  {
    "path": "src/components/Loading/Loading.tsx",
    "content": "import React from \"react\";\nimport { Icons } from \"../Icons/Icons\";\nimport { type LucideProps } from \"lucide-react\";\nimport { cn } from \"~/utils/cn\";\n\nexport const Spinner = ({ className, ...props }: LucideProps) => (\n  <Icons.spinner\n    className={cn(\"h-5 w-5 animate-spin text-gray-500\", className)}\n    {...props}\n  />\n);\n\nexport const LoadingScreen = () => {\n  return (\n    <div className=\"absolute left-0 top-0 flex h-full w-full flex-col items-center justify-center\">\n      <Spinner className=\"h-10 w-10 \" />\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/components/Loading/index.ts",
    "content": "export * from \"./Loading\";\n"
  },
  {
    "path": "src/components/PrefetchTRPCQuery/PrefetchTRPCQuery.tsx",
    "content": "import { Hydrate, dehydrate } from \"@tanstack/react-query\";\nimport { api as serverApi } from \"~/trpc/server\";\nimport { getServerQueryClient } from \"~/utils/getQueryClient\";\nimport { type RouterInputs } from \"~/trpc/shared\";\n\ntype AccessPaths<T> = {\n  [K in keyof T]: {\n    [L in keyof T[K]]: `${string & K}.${string & L}`;\n  }[keyof T[K]];\n}[keyof T];\n\ntype ValueTypeAt<T, P extends string> = P extends `${infer K}.${infer L}`\n  ? K extends keyof T\n    ? L extends keyof T[K]\n      ? T[K][L]\n      : never\n    : never\n  : never;\n\ntype ParamsType<T extends AccessPaths<RouterInputs>> = ValueTypeAt<\n  RouterInputs,\n  T\n> extends void | undefined\n  ? { params?: undefined }\n  : { params: ValueTypeAt<RouterInputs, T> };\n\nexport const PrefetchTRPCQuery = async <T extends AccessPaths<RouterInputs>>({\n  children,\n  queryName,\n  params = undefined,\n}: {\n  children: React.ReactNode;\n  queryName: T;\n} & ParamsType<T>) => {\n  const queryClient = getServerQueryClient();\n  const [router, procedure] = queryName.split(\".\");\n\n  try {\n    // Just let the frontend handle it if it fails\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore\n    const data = await serverApi[router][procedure].query(params);\n\n    await queryClient.prefetchQuery(\n      [[router, procedure], { input: params, type: \"query\" }],\n      () => data,\n    );\n    const dehydratedState = dehydrate(queryClient);\n\n    return <Hydrate state={dehydratedState}>{children}</Hydrate>;\n  } catch (e) {\n    console.error(e, \"PrefetchTRPCQuery failed\");\n\n    return <>{children}</>;\n  }\n};\n"
  },
  {
    "path": "src/components/PrivateRoute/PrivateRoute.tsx",
    "content": "import { type PropsWithChildren } from \"react\";\nimport { getServerUser } from \"~/utils/auth\";\nimport { PrivateRouteBase } from \"./PrivateRouteBase\";\nimport { redirect } from \"next/navigation\";\n\nexport const PrivateRoute = async ({ children }: PropsWithChildren) => {\n  const user = await getServerUser();\n\n  if (!user) redirect(\"/login\");\n\n  return <PrivateRouteBase>{children}</PrivateRouteBase>;\n};\n"
  },
  {
    "path": "src/components/PrivateRoute/PrivateRouteBase.tsx",
    "content": "\"use client\";\n\nimport { type PropsWithChildren } from \"react\";\nimport { withPrivateRoute } from \"~/providers/AuthProvider/withPrivateRoute\";\n\nconst PrivateRouteBaseComponent = ({ children }: PropsWithChildren) => children;\n\nexport const PrivateRouteBase = withPrivateRoute(PrivateRouteBaseComponent);\n"
  },
  {
    "path": "src/components/PublicRoute/PublicRoute.tsx",
    "content": "\"use client\";\n\nimport { withPublicRoute } from \"~/providers/AuthProvider/withPublicRoute\";\n\nconst PublicRouteComponent = ({ children }: { children: React.ReactNode }) =>\n  children;\n\nexport const PublicRoute = withPublicRoute(PublicRouteComponent);\n"
  },
  {
    "path": "src/components/TailwindIndicator/TailwindIndicator.tsx",
    "content": "export function TailwindIndicator() {\n  if (process.env.NODE_ENV === \"production\") return null;\n\n  return (\n    <div className=\"fixed bottom-1 left-1 z-50 flex h-6 w-6 items-center justify-center rounded-full bg-gray-800 p-3 font-mono text-xs text-white\">\n      <div className=\"block sm:hidden\">xs</div>\n      <div className=\"hidden sm:block md:hidden lg:hidden xl:hidden 2xl:hidden\">\n        sm\n      </div>\n      <div className=\"hidden md:block lg:hidden xl:hidden 2xl:hidden\">md</div>\n      <div className=\"hidden lg:block xl:hidden 2xl:hidden\">lg</div>\n      <div className=\"hidden xl:block 2xl:hidden\">xl</div>\n      <div className=\"hidden 2xl:block\">2xl</div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TailwindIndicator/index.ts",
    "content": "export * from \"./TailwindIndicator\";\n"
  },
  {
    "path": "src/components/ui/button.tsx",
    "content": "import * as React from \"react\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { cn } from \"~/utils/cn\";\nimport { Spinner } from \"../Loading\";\n\nconst buttonVariants = cva(\n  \"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background\",\n  {\n    variants: {\n      variant: {\n        default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n        destructive:\n          \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n        outline:\n          \"border border-input hover:bg-accent hover:text-accent-foreground\",\n        secondary:\n          \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n        ghost: \"hover:bg-accent hover:text-accent-foreground\",\n        link: \"underline-offset-4 hover:underline text-primary\",\n        premium:\n          \"font-bold bg-clip-padding border-[2px] before:-m-[2px] rounded-md before:rounded-md border-transparent bg-white dark:bg-secondary text-primary hover:before:bg-gradient-to-r hover:before:from-pink-500 hover:before:to-purple-500 before:bg-gradient-to-r before:from-purple-500 before:to-pink-500 hover:bg-white/90 dark:hover:bg-secondary/90 relative before:content before:absolute before:z-[-1] before:inset-0 before:bg-primary before:transition-opacity before:duration-500 before:delay-100 hover:before:opacity-100\",\n      },\n      size: {\n        default: \"h-10 py-2 px-4\",\n        sm: \"h-9 px-3 rounded-md\",\n        lg: \"h-11 px-8 rounded-md\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  },\n);\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof buttonVariants> {\n  loading?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, children, loading, ...props }, ref) => {\n    return (\n      <button\n        className={cn(\n          \"relative flex select-none items-center justify-center\",\n          buttonVariants({ variant, size, className }),\n        )}\n        data-loading={loading}\n        ref={ref}\n        {...props}\n      >\n        {loading && <Spinner className=\"absolute text-primary\" />}\n        {loading ? <span className=\"opacity-0\"> {children}</span> : children}\n      </button>\n    );\n  },\n);\n\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n"
  },
  {
    "path": "src/components/ui/dropdown-menu.tsx",
    "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { Check, ChevronRight, Circle } from \"lucide-react\";\n\nimport { cn } from \"~/utils/cn\";\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n    inset?: boolean;\n  }\n>(({ className, inset, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubTrigger\n    ref={ref}\n    className={cn(\n      \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent\",\n      inset && \"pl-8\",\n      className,\n    )}\n    {...props}\n  >\n    {children}\n    <ChevronRight className=\"ml-auto h-4 w-4\" />\n  </DropdownMenuPrimitive.SubTrigger>\n));\n\nDropdownMenuSubTrigger.displayName =\n  DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubContent\n    ref={ref}\n    className={cn(\n      \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n      className,\n    )}\n    {...props}\n  />\n));\n\nDropdownMenuSubContent.displayName =\n  DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n  <DropdownMenuPrimitive.Portal>\n    <DropdownMenuPrimitive.Content\n      ref={ref}\n      sideOffset={sideOffset}\n      className={cn(\n        \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n        className,\n      )}\n      {...props}\n    />\n  </DropdownMenuPrimitive.Portal>\n));\n\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n    inset?: boolean;\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Item\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      inset && \"pl-8\",\n      className,\n    )}\n    {...props}\n  />\n));\n\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n  <DropdownMenuPrimitive.CheckboxItem\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      className,\n    )}\n    checked={checked}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Check className=\"h-4 w-4\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.CheckboxItem>\n));\n\nDropdownMenuCheckboxItem.displayName =\n  DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.RadioItem\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      className,\n    )}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Circle className=\"h-2 w-2 fill-current\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.RadioItem>\n));\n\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n    inset?: boolean;\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Label\n    ref={ref}\n    className={cn(\n      \"px-2 py-1.5 text-sm font-semibold\",\n      inset && \"pl-8\",\n      className,\n    )}\n    {...props}\n  />\n));\n\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.Separator\n    ref={ref}\n    className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n    {...props}\n  />\n));\n\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n  return (\n    <span\n      className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n      {...props}\n    />\n  );\n};\n\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n  DropdownMenu,\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuCheckboxItem,\n  DropdownMenuRadioItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuGroup,\n  DropdownMenuPortal,\n  DropdownMenuSub,\n  DropdownMenuSubContent,\n  DropdownMenuSubTrigger,\n  DropdownMenuRadioGroup,\n};\n"
  },
  {
    "path": "src/components/ui/form.tsx",
    "content": "import * as React from \"react\";\nimport type * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport {\n  Controller,\n  type ControllerProps,\n  type FieldPath,\n  type FieldValues,\n  FormProvider,\n  useFormContext,\n} from \"react-hook-form\";\n\nimport { cn } from \"~/utils/cn\";\nimport { Label } from \"~/components/ui/label\";\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n  name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>(\n  {} as FormFieldContextValue,\n);\n\nconst FormField = <\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n  ...props\n}: ControllerProps<TFieldValues, TName>) => {\n  return (\n    <FormFieldContext.Provider value={{ name: props.name }}>\n      <Controller {...props} />\n    </FormFieldContext.Provider>\n  );\n};\n\nconst useFormField = () => {\n  const fieldContext = React.useContext(FormFieldContext);\n  const itemContext = React.useContext(FormItemContext);\n  const { getFieldState, formState } = useFormContext();\n\n  const fieldState = getFieldState(fieldContext.name, formState);\n\n  if (!fieldContext) {\n    throw new Error(\"useFormField should be used within <FormField>\");\n  }\n\n  const { id } = itemContext;\n\n  return {\n    id,\n    name: fieldContext.name,\n    formItemId: `${id}-form-item`,\n    formDescriptionId: `${id}-form-item-description`,\n    formMessageId: `${id}-form-item-message`,\n    ...fieldState,\n  };\n};\n\ntype FormItemContextValue = {\n  id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n  {} as FormItemContextValue,\n);\n\nconst FormItem = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n  const id = React.useId();\n\n  return (\n    <FormItemContext.Provider value={{ id }}>\n      <div ref={ref} className={cn(\"space-y-2\", className)} {...props} />\n    </FormItemContext.Provider>\n  );\n});\n\nFormItem.displayName = \"FormItem\";\n\nconst FormLabel = React.forwardRef<\n  React.ElementRef<typeof LabelPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(({ className, ...props }, ref) => {\n  const { error, formItemId } = useFormField();\n\n  return (\n    <Label\n      ref={ref}\n      className={cn(error && \"text-destructive\", className)}\n      htmlFor={formItemId}\n      {...props}\n    />\n  );\n});\n\nFormLabel.displayName = \"FormLabel\";\n\nconst FormControl = React.forwardRef<\n  React.ElementRef<typeof Slot>,\n  React.ComponentPropsWithoutRef<typeof Slot>\n>(({ ...props }, ref) => {\n  const { error, formItemId, formDescriptionId, formMessageId } =\n    useFormField();\n\n  return (\n    <Slot\n      ref={ref}\n      id={formItemId}\n      aria-describedby={\n        !error\n          ? `${formDescriptionId}`\n          : `${formDescriptionId} ${formMessageId}`\n      }\n      aria-invalid={!!error}\n      {...props}\n    />\n  );\n});\n\nFormControl.displayName = \"FormControl\";\n\nconst FormDescription = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n  const { formDescriptionId } = useFormField();\n\n  return (\n    <p\n      ref={ref}\n      id={formDescriptionId}\n      className={cn(\"text-sm text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n});\n\nFormDescription.displayName = \"FormDescription\";\n\nconst FormMessage = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n  const { error, formMessageId } = useFormField();\n  const body = error ? String(error?.message) : children;\n\n  if (!body) {\n    return null;\n  }\n\n  return (\n    <p\n      ref={ref}\n      id={formMessageId}\n      className={cn(\"text-sm font-medium text-destructive\", className)}\n      {...props}\n    >\n      {body}\n    </p>\n  );\n});\n\nFormMessage.displayName = \"FormMessage\";\n\nexport {\n  useFormField,\n  Form,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormDescription,\n  FormMessage,\n  FormField,\n};\n"
  },
  {
    "path": "src/components/ui/input.tsx",
    "content": "import * as React from \"react\";\n\nimport { cn } from \"~/utils/cn\";\n\nexport interface InputProps\n  extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n  ({ className, type, ...props }, ref) => {\n    return (\n      <input\n        type={type}\n        className={cn(\n          \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n          className,\n        )}\n        ref={ref}\n        {...props}\n      />\n    );\n  },\n);\n\nInput.displayName = \"Input\";\n\nexport { Input };\n"
  },
  {
    "path": "src/components/ui/label.tsx",
    "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"~/utils/cn\";\n\nconst labelVariants = cva(\n  \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n  React.ElementRef<typeof LabelPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n    VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n  <LabelPrimitive.Root\n    ref={ref}\n    className={cn(labelVariants(), className)}\n    {...props}\n  />\n));\n\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n"
  },
  {
    "path": "src/components/ui/toast.tsx",
    "content": "import * as React from \"react\";\nimport * as ToastPrimitives from \"@radix-ui/react-toast\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\n\nimport { cn } from \"~/utils/cn\";\n\nconst ToastProvider = ToastPrimitives.Provider;\n\nconst ToastViewport = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Viewport>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>(({ className, ...props }, ref) => (\n  <ToastPrimitives.Viewport\n    ref={ref}\n    className={cn(\n      \"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]\",\n      className,\n    )}\n    {...props}\n  />\n));\n\nToastViewport.displayName = ToastPrimitives.Viewport.displayName;\n\nconst toastVariants = cva(\n  \"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full\",\n  {\n    variants: {\n      variant: {\n        default: \"border bg-background text-foreground\",\n        destructive:\n          \"destructive group border-destructive bg-destructive text-destructive-foreground\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  },\n);\n\nconst Toast = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Root>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &\n    VariantProps<typeof toastVariants>\n>(({ className, variant, ...props }, ref) => {\n  return (\n    <ToastPrimitives.Root\n      ref={ref}\n      className={cn(toastVariants({ variant }), className)}\n      {...props}\n    />\n  );\n});\n\nToast.displayName = ToastPrimitives.Root.displayName;\n\nconst ToastAction = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Action>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>(({ className, ...props }, ref) => (\n  <ToastPrimitives.Action\n    ref={ref}\n    className={cn(\n      \"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive\",\n      className,\n    )}\n    {...props}\n  />\n));\n\nToastAction.displayName = ToastPrimitives.Action.displayName;\n\nconst ToastClose = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Close>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>(({ className, ...props }, ref) => (\n  <ToastPrimitives.Close\n    ref={ref}\n    className={cn(\n      \"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600\",\n      className,\n    )}\n    toast-close=\"\"\n    {...props}\n  >\n    <X className=\"h-4 w-4\" />\n  </ToastPrimitives.Close>\n));\n\nToastClose.displayName = ToastPrimitives.Close.displayName;\n\nconst ToastTitle = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Title>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>(({ className, ...props }, ref) => (\n  <ToastPrimitives.Title\n    ref={ref}\n    className={cn(\"text-sm font-semibold\", className)}\n    {...props}\n  />\n));\n\nToastTitle.displayName = ToastPrimitives.Title.displayName;\n\nconst ToastDescription = React.forwardRef<\n  React.ElementRef<typeof ToastPrimitives.Description>,\n  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>(({ className, ...props }, ref) => (\n  <ToastPrimitives.Description\n    ref={ref}\n    className={cn(\"text-sm opacity-90\", className)}\n    {...props}\n  />\n));\n\nToastDescription.displayName = ToastPrimitives.Description.displayName;\n\ntype ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;\n\ntype ToastActionElement = React.ReactElement<typeof ToastAction>;\n\nexport {\n  type ToastProps,\n  type ToastActionElement,\n  ToastProvider,\n  ToastViewport,\n  Toast,\n  ToastTitle,\n  ToastDescription,\n  ToastClose,\n  ToastAction,\n};\n"
  },
  {
    "path": "src/components/ui/toaster.tsx",
    "content": "\"use client\";\n\nimport {\n  Toast,\n  ToastClose,\n  ToastDescription,\n  ToastProvider,\n  ToastTitle,\n  ToastViewport,\n} from \"~/components/ui/toast\";\nimport { useToast } from \"~/components/ui/use-toast\";\n\nexport function Toaster() {\n  const { toasts } = useToast();\n\n  return (\n    <ToastProvider>\n      {toasts.map(function ({ id, title, description, action, ...props }) {\n        return (\n          <Toast key={id} {...props}>\n            <div className=\"grid gap-1\">\n              {title && <ToastTitle>{title}</ToastTitle>}\n              {description && (\n                <ToastDescription>{description}</ToastDescription>\n              )}\n            </div>\n            {action}\n            <ToastClose />\n          </Toast>\n        );\n      })}\n      <ToastViewport />\n    </ToastProvider>\n  );\n}\n"
  },
  {
    "path": "src/components/ui/use-toast.ts",
    "content": "// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"~/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n  id: string;\n  title?: React.ReactNode;\n  description?: React.ReactNode;\n  action?: ToastActionElement;\n};\n\nconst actionTypes = {\n  ADD_TOAST: \"ADD_TOAST\",\n  UPDATE_TOAST: \"UPDATE_TOAST\",\n  DISMISS_TOAST: \"DISMISS_TOAST\",\n  REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n  count = (count + 1) % Number.MAX_VALUE;\n\n  return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n  | {\n      type: ActionType[\"ADD_TOAST\"];\n      toast: ToasterToast;\n    }\n  | {\n      type: ActionType[\"UPDATE_TOAST\"];\n      toast: Partial<ToasterToast>;\n    }\n  | {\n      type: ActionType[\"DISMISS_TOAST\"];\n      toastId?: ToasterToast[\"id\"];\n    }\n  | {\n      type: ActionType[\"REMOVE_TOAST\"];\n      toastId?: ToasterToast[\"id\"];\n    };\n\ninterface State {\n  toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n  if (toastTimeouts.has(toastId)) {\n    return;\n  }\n\n  const timeout = setTimeout(() => {\n    toastTimeouts.delete(toastId);\n    dispatch({\n      type: \"REMOVE_TOAST\",\n      toastId: toastId,\n    });\n  }, TOAST_REMOVE_DELAY);\n\n  toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n  switch (action.type) {\n    case \"ADD_TOAST\":\n      return {\n        ...state,\n        toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n      };\n\n    case \"UPDATE_TOAST\":\n      return {\n        ...state,\n        toasts: state.toasts.map((t) =>\n          t.id === action.toast.id ? { ...t, ...action.toast } : t,\n        ),\n      };\n\n    case \"DISMISS_TOAST\": {\n      const { toastId } = action;\n\n      // ! Side effects ! - This could be extracted into a dismissToast() action,\n      // but I'll keep it here for simplicity\n      if (toastId) {\n        addToRemoveQueue(toastId);\n      } else {\n        state.toasts.forEach((tst) => {\n          addToRemoveQueue(tst.id);\n        });\n      }\n\n      return {\n        ...state,\n        toasts: state.toasts.map((t) =>\n          t.id === toastId || toastId === undefined\n            ? {\n                ...t,\n                open: false,\n              }\n            : t,\n        ),\n      };\n    }\n\n    case \"REMOVE_TOAST\":\n      if (action.toastId === undefined) {\n        return {\n          ...state,\n          toasts: [],\n        };\n      }\n\n      return {\n        ...state,\n        toasts: state.toasts.filter((t) => t.id !== action.toastId),\n      };\n  }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n  memoryState = reducer(memoryState, action);\n  listeners.forEach((listener) => {\n    listener(memoryState);\n  });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n  const id = genId();\n\n  const update = (updateProps: ToasterToast) =>\n    dispatch({\n      type: \"UPDATE_TOAST\",\n      toast: { ...updateProps, id },\n    });\n  const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n  dispatch({\n    type: \"ADD_TOAST\",\n    toast: {\n      ...props,\n      id,\n      open: true,\n      onOpenChange: (open) => {\n        if (!open) dismiss();\n      },\n    },\n  });\n\n  return {\n    id: id,\n    dismiss,\n    update,\n  };\n}\n\nfunction useToast() {\n  const [state, setState] = React.useState<State>(memoryState);\n\n  React.useEffect(() => {\n    listeners.push(setState);\n\n    return () => {\n      const index = listeners.indexOf(setState);\n\n      if (index > -1) {\n        listeners.splice(index, 1);\n      }\n    };\n  }, [state]);\n\n  return {\n    ...state,\n    toast,\n    dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n  };\n}\n\nexport { useToast, toast };\n"
  },
  {
    "path": "src/env.mjs",
    "content": "import { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  /**\n   * Specify your server-side environment variables schema here. This way you can ensure the app\n   * isn't built with invalid env vars.\n   */\n  server: {\n    DATABASE_URL: z\n      .string()\n      .url()\n      .refine(\n        (str) => !str.includes(\"YOUR_MYSQL_URL_HERE\"),\n        \"You forgot to change the default URL\",\n      ),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"])\n      .default(\"development\"),\n    SUPABASE_SERVICE_KEY: z.string().min(1),\n    DIRECT_URL: z.string().min(1),\n  },\n\n  /**\n   * Specify your client-side environment variables schema here. This way you can ensure the app\n   * isn't built with invalid env vars. To expose them to the client, prefix them with\n   * `NEXT_PUBLIC_`.\n   */\n  client: {\n    NEXT_PUBLIC_SUPABASE_URL: z.string().url(),\n    NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(1),\n    NEXT_PUBLIC_UMAMI_WEBSITE_ID: z.string().optional(),\n  },\n\n  /**\n   * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.\n   * middlewares) or client-side so we need to destruct manually.\n   */\n  runtimeEnv: {\n    DATABASE_URL: process.env.DATABASE_URL,\n    NODE_ENV: process.env.NODE_ENV,\n    DIRECT_URL: process.env.DIRECT_URL,\n    NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,\n    NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n    SUPABASE_SERVICE_KEY: process.env.SUPABASE_SERVICE_KEY,\n    NEXT_PUBLIC_UMAMI_WEBSITE_ID: process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,\n  },\n  /**\n   * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially\n   * useful for Docker builds.\n   */\n  skipValidation: !!process.env.SKIP_ENV_VALIDATION,\n});\n"
  },
  {
    "path": "src/providers/AnalyticsProvider/AnalyticsProvider.tsx",
    "content": "\"use client\";\n\nimport { Analytics } from \"@vercel/analytics/react\";\n\nimport Script from \"next/script\";\nimport { env } from \"~/env.mjs\";\n\nexport const AnalyticsProvider = () => <Analytics />;\n\nexport const UmamiAnalyticsProvider = () => {\n  return env.NEXT_PUBLIC_UMAMI_WEBSITE_ID ? (\n    <Script\n      src=\"https://analytics.umami.is/script.js\"\n      data-website-id={process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID}\n      strategy=\"lazyOnload\"\n    />\n  ) : null;\n};\n"
  },
  {
    "path": "src/providers/AuthProvider/AuthProvider.tsx",
    "content": "\"use client\";\n\nimport React, {\n  type ReactNode,\n  createContext,\n  useContext,\n  useEffect,\n  useState,\n} from \"react\";\n\nimport { type Session, type User } from \"@supabase/supabase-js\";\nimport { supabase } from \"~/server/supabase/supabaseClient\";\nimport { ReactQueryDevtools } from \"@tanstack/react-query-devtools\";\n\nexport const AuthContext = createContext<{\n  user: User | null;\n  session: Session | null;\n  isLoading: boolean;\n}>({\n  user: null,\n  session: null,\n  isLoading: false,\n});\n\nconst setCookies = (session: Session | null) => {\n  if (session) {\n    const maxAge = 100 * 365 * 24 * 60 * 60; // 100 years, never expires\n\n    document.cookie = `access-token=${session.access_token}; path=/; max-age=${maxAge}; SameSite=Lax; secure`;\n    document.cookie = `refresh-token=${session.refresh_token}; path=/; max-age=${maxAge}; SameSite=Lax; secure`;\n  } else {\n    const expires = new Date(0).toUTCString();\n\n    document.cookie = `access-token=; path=/; expires=${expires}; SameSite=Lax; secure`;\n    document.cookie = `refresh-token=; path=/; expires=${expires}; SameSite=Lax; secure`;\n  }\n};\n\nexport const AuthProvider = ({\n  user: initialUser,\n  session: initialSession,\n  children,\n}: {\n  user: User | null;\n  session: Session | null;\n  children: ReactNode;\n}) => {\n  const [userSession, setUserSession] = useState<Session | null>(\n    initialSession,\n  );\n  const [user, setUser] = useState<User | null>(initialUser);\n  const [isLoading, setIsLoading] = useState(!initialUser);\n\n  useEffect(() => {\n    void supabase()\n      .auth.getSession()\n      .then(({ data: { session } }) => {\n        setUserSession(session);\n        setUser(session?.user ?? null);\n        setCookies(session);\n        setIsLoading(false);\n      });\n\n    const { data: authListener } = supabase().auth.onAuthStateChange(\n      (event, session) => {\n        setUserSession(session);\n        setUser(session?.user ?? null);\n        setCookies(session);\n        setIsLoading(false);\n      },\n    );\n\n    return () => {\n      authListener.subscription.unsubscribe();\n    };\n  }, []);\n\n  const value = {\n    session: userSession,\n    user,\n    isLoading,\n  };\n\n  return (\n    <AuthContext.Provider value={value}>\n      {children}\n      <ReactQueryDevtools />\n    </AuthContext.Provider>\n  );\n};\n\nexport const useUser = () => {\n  const context = useContext(AuthContext);\n\n  if (context === undefined) {\n    throw new Error(\"useUser must be used within a AuthContextProvider.\");\n  }\n\n  return context;\n};\n"
  },
  {
    "path": "src/providers/AuthProvider/withPrivateRoute.tsx",
    "content": "\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { useEffect } from \"react\";\nimport { useUser } from \"~/providers/AuthProvider/AuthProvider\";\n\nexport const withPrivateRoute = <T extends object>(\n  WrappedComponent: React.FunctionComponent<T>,\n) => {\n  const ComponentWithPrivateRoute = (props: T) => {\n    const router = useRouter();\n\n    const { user, isLoading } = useUser();\n\n    useEffect(() => {\n      if (!user && !isLoading) {\n        router.push(\"/login\");\n      }\n    }, [user, router, isLoading]);\n\n    if (!user) return null;\n\n    return <WrappedComponent {...props} />;\n  };\n\n  return ComponentWithPrivateRoute;\n};\n"
  },
  {
    "path": "src/providers/AuthProvider/withPublicRoute.tsx",
    "content": "\"use client\";\n\nimport React, { useEffect } from \"react\";\n\nimport { useRouter } from \"next/navigation\";\nimport { useUser } from \"~/providers/AuthProvider/AuthProvider\";\nimport { LoadingScreen } from \"~/components/Loading\";\n\nexport const withPublicRoute = <T extends object>(\n  WrappedComponent: React.FunctionComponent<T>,\n) => {\n  const ComponentwithPublicRoute = (props: T) => {\n    const router = useRouter();\n    const { user, isLoading } = useUser();\n    const isUserDataLoaded = !isLoading;\n\n    useEffect(() => {\n      if (user && isUserDataLoaded) {\n        router.push(\"/\");\n      }\n    }, [user, isUserDataLoaded, router]);\n\n    if (user ?? !isUserDataLoaded) return <LoadingScreen />;\n\n    return <WrappedComponent {...props} />;\n  };\n\n  return ComponentwithPublicRoute;\n};\n"
  },
  {
    "path": "src/providers/index.tsx",
    "content": "\"use client\";\n\nimport { ThemeProvider } from \"next-themes\";\nimport {\n  AnalyticsProvider,\n  UmamiAnalyticsProvider,\n} from \"./AnalyticsProvider/AnalyticsProvider\";\nimport React, { type PropsWithChildren } from \"react\";\n\nexport function Providers({ children }: PropsWithChildren) {\n  return (\n    <>\n      <ThemeProvider attribute=\"class\" forcedTheme=\"light\">\n        {children}\n      </ThemeProvider>\n      <AnalyticsProvider />\n      <UmamiAnalyticsProvider />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/server/api/root.ts",
    "content": "import { exampleRouter } from \"~/server/api/routers/example\";\nimport { createTRPCRouter } from \"~/server/api/trpc\";\nimport { authRouter } from \"./routers/auth\";\n\n/**\n * This is the primary router for your server.\n *\n * All routers added in /api/routers should be manually added here.\n */\nexport const appRouter = createTRPCRouter({\n  example: exampleRouter,\n  auth: authRouter,\n});\n\n// export type definition of API\nexport type AppRouter = typeof appRouter;\n"
  },
  {
    "path": "src/server/api/routers/auth.ts",
    "content": "import { createTRPCRouter, privateProcedure } from \"~/server/api/trpc\";\n\nexport const authRouter = createTRPCRouter({\n  getProfile: privateProcedure.query(({ ctx }) => {\n    return ctx.db.profiles.findFirstOrThrow({\n      where: {\n        id: ctx.user.id,\n      },\n    });\n  }),\n});\n"
  },
  {
    "path": "src/server/api/routers/example.ts",
    "content": "import { z } from \"zod\";\n\nimport { createTRPCRouter, publicProcedure } from \"~/server/api/trpc\";\n\nexport const exampleRouter = createTRPCRouter({\n  hello: publicProcedure\n    .input(z.object({ text: z.string() }))\n    .query(({ input }) => {\n      return {\n        greeting: `Hello ${input.text}`,\n      };\n    }),\n});\n"
  },
  {
    "path": "src/server/api/trpc.ts",
    "content": "/**\n * YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:\n * 1. You want to modify request context (see Part 1).\n * 2. You want to create a new middleware or type of procedure (see Part 3).\n *\n * TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will\n * need to use are documented accordingly near the end.\n */\nimport { TRPCError, initTRPC } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { db } from \"~/server/db\";\nimport { getUserAsAdmin } from \"../supabase/supabaseClient\";\n\n/**\n * This is the actual context you will use in your router. It will be used to process every request\n * that goes through your tRPC endpoint.\n *\n * @see https://trpc.io/docs/context\n */\n\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const headers = opts.headers;\n  const authToken = headers.get(\"authorization\");\n\n  const { user } = authToken ? await getUserAsAdmin(authToken) : { user: null };\n\n  return {\n    ...opts,\n    db,\n    user,\n  };\n};\n/**\n * 2. INITIALIZATION\n *\n * This is where the tRPC API is initialized, connecting the context and transformer. We also parse\n * ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation\n * errors on the backend.\n */\n\nconst t = initTRPC.context<typeof createTRPCContext>().create({\n  transformer: superjson,\n  errorFormatter({ shape, error }) {\n    return {\n      ...shape,\n      data: {\n        ...shape.data,\n        zodError:\n          error.cause instanceof ZodError ? error.cause.flatten() : null,\n      },\n    };\n  },\n});\n\n/**\n * 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)\n *\n * These are the pieces you use to build your tRPC API. You should import these a lot in the\n * \"/src/server/api/routers\" directory.\n */\n\n/**\n * This is how you create new routers and sub-routers in your tRPC API.\n *\n * @see https://trpc.io/docs/router\n */\nexport const createTRPCRouter = t.router;\n\n/**\n * Public (unauthenticated) procedure\n *\n * This is the base piece you use to build new queries and mutations on your tRPC API. It does not\n * guarantee that a user querying is authorized, but you can still access user session data if they\n * are logged in.\n */\nexport const publicProcedure = t.procedure;\n\nconst enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {\n  if (!ctx.user) {\n    throw new TRPCError({\n      code: \"UNAUTHORIZED\",\n    });\n  }\n\n  return next({\n    ctx: {\n      user: ctx.user,\n    },\n  });\n});\n\nexport const privateProcedure = t.procedure.use(enforceUserIsAuthed);\n"
  },
  {
    "path": "src/server/db.ts",
    "content": "import { PrismaClient } from \"@prisma/client\";\n\nimport { env } from \"~/env.mjs\";\n\nconst globalForPrisma = globalThis as unknown as {\n  prisma: PrismaClient | undefined;\n};\n\nexport const db =\n  globalForPrisma.prisma ??\n  new PrismaClient({\n    log:\n      env.NODE_ENV === \"development\" ? [\"query\", \"error\", \"warn\"] : [\"error\"],\n  });\n\nif (env.NODE_ENV !== \"production\") globalForPrisma.prisma = db;\n"
  },
  {
    "path": "src/server/supabase/supabaseClient.ts",
    "content": "import { createClient } from \"@supabase/supabase-js\";\n\nimport { type Database } from \"./supabaseTypes\";\n\nimport { env } from \"~/env.mjs\";\n\nexport const getServiceSupabase = () =>\n  createClient<Database>(\n    env.NEXT_PUBLIC_SUPABASE_URL,\n    env.SUPABASE_SERVICE_KEY,\n    {\n      auth: {\n        autoRefreshToken: false,\n        persistSession: false,\n      },\n    },\n  );\n\nexport const clientSupabase = createClient<Database>(\n  env.NEXT_PUBLIC_SUPABASE_URL,\n  env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n);\n\nexport const supabase = () =>\n  typeof window === \"undefined\" ? getServiceSupabase() : clientSupabase;\n\nexport const getUserAsAdmin = async (token: string) => {\n  const { data, error } = await getServiceSupabase().auth.getUser(token);\n\n  if (error) {\n    console.error(error);\n    throw error;\n  }\n\n  return data;\n};\n"
  },
  {
    "path": "src/server/supabase/supabaseTypes.ts",
    "content": "export type Json =\n  | string\n  | number\n  | boolean\n  | null\n  | { [key: string]: Json | undefined }\n  | Json[];\n\nexport interface Database {\n  graphql_public: {\n    Tables: {\n      [_ in never]: never;\n    };\n    Views: {\n      [_ in never]: never;\n    };\n    Functions: {\n      graphql: {\n        Args: {\n          operationName?: string;\n          query?: string;\n          variables?: Json;\n          extensions?: Json;\n        };\n        Returns: Json;\n      };\n    };\n    Enums: {\n      [_ in never]: never;\n    };\n    CompositeTypes: {\n      [_ in never]: never;\n    };\n  };\n  public: {\n    Tables: {\n      profiles: {\n        Row: {\n          avatar_url: string | null;\n          email: string | null;\n          full_name: string | null;\n          id: string;\n          updated_at: string | null;\n        };\n        Insert: {\n          avatar_url?: string | null;\n          email?: string | null;\n          full_name?: string | null;\n          id: string;\n          updated_at?: string | null;\n        };\n        Update: {\n          avatar_url?: string | null;\n          email?: string | null;\n          full_name?: string | null;\n          id?: string;\n          updated_at?: string | null;\n        };\n        Relationships: [\n          {\n            foreignKeyName: \"profiles_id_fkey\";\n            columns: [\"id\"];\n            referencedRelation: \"users\";\n            referencedColumns: [\"id\"];\n          },\n        ];\n      };\n    };\n    Views: {\n      [_ in never]: never;\n    };\n    Functions: {\n      [_ in never]: never;\n    };\n    Enums: {\n      [_ in never]: never;\n    };\n    CompositeTypes: {\n      [_ in never]: never;\n    };\n  };\n  storage: {\n    Tables: {\n      buckets: {\n        Row: {\n          allowed_mime_types: string[] | null;\n          avif_autodetection: boolean | null;\n          created_at: string | null;\n          file_size_limit: number | null;\n          id: string;\n          name: string;\n          owner: string | null;\n          public: boolean | null;\n          updated_at: string | null;\n        };\n        Insert: {\n          allowed_mime_types?: string[] | null;\n          avif_autodetection?: boolean | null;\n          created_at?: string | null;\n          file_size_limit?: number | null;\n          id: string;\n          name: string;\n          owner?: string | null;\n          public?: boolean | null;\n          updated_at?: string | null;\n        };\n        Update: {\n          allowed_mime_types?: string[] | null;\n          avif_autodetection?: boolean | null;\n          created_at?: string | null;\n          file_size_limit?: number | null;\n          id?: string;\n          name?: string;\n          owner?: string | null;\n          public?: boolean | null;\n          updated_at?: string | null;\n        };\n        Relationships: [\n          {\n            foreignKeyName: \"buckets_owner_fkey\";\n            columns: [\"owner\"];\n            referencedRelation: \"users\";\n            referencedColumns: [\"id\"];\n          },\n        ];\n      };\n      migrations: {\n        Row: {\n          executed_at: string | null;\n          hash: string;\n          id: number;\n          name: string;\n        };\n        Insert: {\n          executed_at?: string | null;\n          hash: string;\n          id: number;\n          name: string;\n        };\n        Update: {\n          executed_at?: string | null;\n          hash?: string;\n          id?: number;\n          name?: string;\n        };\n        Relationships: [];\n      };\n      objects: {\n        Row: {\n          bucket_id: string | null;\n          created_at: string | null;\n          id: string;\n          last_accessed_at: string | null;\n          metadata: Json | null;\n          name: string | null;\n          owner: string | null;\n          path_tokens: string[] | null;\n          updated_at: string | null;\n          version: string | null;\n        };\n        Insert: {\n          bucket_id?: string | null;\n          created_at?: string | null;\n          id?: string;\n          last_accessed_at?: string | null;\n          metadata?: Json | null;\n          name?: string | null;\n          owner?: string | null;\n          path_tokens?: string[] | null;\n          updated_at?: string | null;\n          version?: string | null;\n        };\n        Update: {\n          bucket_id?: string | null;\n          created_at?: string | null;\n          id?: string;\n          last_accessed_at?: string | null;\n          metadata?: Json | null;\n          name?: string | null;\n          owner?: string | null;\n          path_tokens?: string[] | null;\n          updated_at?: string | null;\n          version?: string | null;\n        };\n        Relationships: [\n          {\n            foreignKeyName: \"objects_bucketId_fkey\";\n            columns: [\"bucket_id\"];\n            referencedRelation: \"buckets\";\n            referencedColumns: [\"id\"];\n          },\n        ];\n      };\n    };\n    Views: {\n      [_ in never]: never;\n    };\n    Functions: {\n      can_insert_object: {\n        Args: {\n          bucketid: string;\n          name: string;\n          owner: string;\n          metadata: Json;\n        };\n        Returns: undefined;\n      };\n      extension: {\n        Args: {\n          name: string;\n        };\n        Returns: string;\n      };\n      filename: {\n        Args: {\n          name: string;\n        };\n        Returns: string;\n      };\n      foldername: {\n        Args: {\n          name: string;\n        };\n        Returns: unknown;\n      };\n      get_size_by_bucket: {\n        Args: Record<PropertyKey, never>;\n        Returns: {\n          size: number;\n          bucket_id: string;\n        }[];\n      };\n      search: {\n        Args: {\n          prefix: string;\n          bucketname: string;\n          limits?: number;\n          levels?: number;\n          offsets?: number;\n          search?: string;\n          sortcolumn?: string;\n          sortorder?: string;\n        };\n        Returns: {\n          name: string;\n          id: string;\n          updated_at: string;\n          created_at: string;\n          last_accessed_at: string;\n          metadata: Json;\n        }[];\n      };\n    };\n    Enums: {\n      [_ in never]: never;\n    };\n    CompositeTypes: {\n      [_ in never]: never;\n    };\n  };\n}\n"
  },
  {
    "path": "src/styles/globals.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  :root {\n    --background: 0 0% 100%;\n    --foreground: 222.2 84% 4.9%;\n    --card: 0 0% 100%;\n    --card-foreground: 222.2 84% 4.9%;\n    --popover: 0 0% 100%;\n    --popover-foreground: 222.2 84% 4.9%;\n    --primary: 222.2 47.4% 11.2%;\n    --primary-foreground: 210 40% 98%;\n    --secondary: 210 40% 96.1%;\n    --secondary-foreground: 222.2 47.4% 11.2%;\n    --muted: 210 40% 96.1%;\n    --muted-foreground: 215.4 16.3% 46.9%;\n    --accent: 210 40% 96.1%;\n    --accent-foreground: 222.2 47.4% 11.2%;\n    --destructive: 0 84.2% 60.2%;\n    --destructive-foreground: 210 40% 98%;\n    --border: 214.3 31.8% 91.4%;\n    --input: 214.3 31.8% 91.4%;\n    --ring: 222.2 84% 4.9%;\n    --radius: 0.5rem;\n  }\n\n  .dark {\n    --background: 222.2 84% 4.9%;\n    --foreground: 210 40% 98%;\n    --card: 222.2 84% 4.9%;\n    --card-foreground: 210 40% 98%;\n    --popover: 222.2 84% 4.9%;\n    --popover-foreground: 210 40% 98%;\n    --primary: 210 40% 98%;\n    --primary-foreground: 222.2 47.4% 11.2%;\n    --secondary: 217.2 32.6% 17.5%;\n    --secondary-foreground: 210 40% 98%;\n    --muted: 217.2 32.6% 17.5%;\n    --muted-foreground: 215 20.2% 65.1%;\n    --accent: 217.2 32.6% 17.5%;\n    --accent-foreground: 210 40% 98%;\n    --destructive: 0 62.8% 30.6%;\n    --destructive-foreground: 210 40% 98%;\n    --border: 217.2 32.6% 17.5%;\n    --input: 217.2 32.6% 17.5%;\n    --ring: 212.7 26.8% 83.9;\n  }\n}\n\n@layer base {\n  * {\n    @apply border-border;\n  }\n  body {\n    @apply bg-background text-foreground;\n  }\n}\n"
  },
  {
    "path": "src/trpc/react.tsx",
    "content": "\"use client\";\n\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { loggerLink, unstable_httpBatchStreamLink } from \"@trpc/client\";\nimport { createTRPCReact } from \"@trpc/react-query\";\nimport { useState } from \"react\";\n\nimport { type AppRouter } from \"~/server/api/root\";\nimport { getUrl, transformer } from \"./shared\";\nimport { supabase } from \"~/server/supabase/supabaseClient\";\n\nexport const api = createTRPCReact<AppRouter>({\n  overrides: {\n    useMutation: {\n      /**\n       * This function is called whenever a `.useMutation` succeeds\n       **/\n      async onSuccess(opts) {\n        /**\n         * @note that order here matters:\n         * The order here allows route changes in `onSuccess` without\n         * having a flash of content change whilst redirecting.\n         **/\n        // Calls the `onSuccess` defined in the `useQuery()`-options:\n        await opts.originalFn();\n        // Invalidate all queries in the react-query cache:\n        await opts.queryClient.invalidateQueries();\n      },\n    },\n  },\n});\n\nexport function TRPCReactProvider(props: {\n  children: React.ReactNode;\n  headers: Headers;\n}) {\n  const [queryClient] = useState(() => new QueryClient());\n\n  const [trpcClient] = useState(() =>\n    api.createClient({\n      transformer,\n\n      links: [\n        loggerLink({\n          enabled: (op) =>\n            process.env.NODE_ENV === \"development\" ||\n            (op.direction === \"down\" && op.result instanceof Error),\n        }),\n        unstable_httpBatchStreamLink({\n          url: getUrl(),\n          async headers() {\n            const heads = new Map(props.headers);\n            const { data } = await supabase().auth.getSession();\n\n            if (data.session) {\n              heads.set(\"authorization\", data.session.access_token);\n            }\n\n            heads.set(\"x-trpc-source\", \"react\");\n\n            return Object.fromEntries(heads);\n          },\n        }),\n      ],\n    }),\n  );\n\n  return (\n    <QueryClientProvider client={queryClient}>\n      <api.Provider client={trpcClient} queryClient={queryClient}>\n        {props.children}\n      </api.Provider>\n    </QueryClientProvider>\n  );\n}\n"
  },
  {
    "path": "src/trpc/server.ts",
    "content": "import {\n  createTRPCProxyClient,\n  loggerLink,\n  TRPCClientError,\n} from \"@trpc/client\";\nimport { cookies, headers } from \"next/headers\";\n\nimport { appRouter } from \"~/server/api/root\";\nimport { transformer } from \"./shared\";\nimport { cache } from \"react\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport { observable } from \"@trpc/server/observable\";\nimport { callProcedure } from \"@trpc/server\";\nimport { type TRPCErrorResponse } from \"@trpc/server/rpc\";\n\n/**\n * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when\n * handling a tRPC call from a React Server Component.\n */\nconst createContext = cache(() => {\n  const heads = new Headers(headers());\n  const ckies = cookies();\n  const mappedCookies = new Map(ckies);\n  const accessToken = mappedCookies.get(\"access-token\")?.value;\n\n  if (accessToken) {\n    heads.set(\"authorization\", accessToken);\n  }\n\n  heads.set(\"x-trpc-source\", \"rsc\");\n  heads.set(\"cookie\", ckies.toString());\n\n  return createTRPCContext({\n    headers: heads,\n  });\n});\n\nexport const api = createTRPCProxyClient<typeof appRouter>({\n  transformer,\n  links: [\n    loggerLink({\n      enabled: (op) =>\n        process.env.NODE_ENV === \"development\" ||\n        (op.direction === \"down\" && op.result instanceof Error),\n    }),\n    /**\n     * Custom RSC link that invokes procedures directly in the server component Don't be too afraid\n     * about the complexity here, it's just wrapping `callProcedure` with an observable to make it a\n     * valid ending link for tRPC.\n     */\n    () =>\n      ({ op }) =>\n        observable((observer) => {\n          createContext()\n            .then((ctx) => {\n              return callProcedure({\n                procedures: appRouter._def.procedures,\n                path: op.path,\n                rawInput: op.input,\n                ctx,\n                type: op.type,\n              });\n            })\n            .then((data) => {\n              observer.next({ result: { data } });\n              observer.complete();\n            })\n            .catch((cause: TRPCErrorResponse) => {\n              observer.error(TRPCClientError.from(cause));\n            });\n        }),\n  ],\n});\n"
  },
  {
    "path": "src/trpc/shared.ts",
    "content": "import { type inferRouterInputs, type inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nimport { type AppRouter } from \"~/server/api/root\";\n\nexport const transformer = superjson;\n\nfunction getBaseUrl() {\n  if (typeof window !== \"undefined\") return \"\";\n  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;\n\n  return `http://localhost:${process.env.PORT ?? 3000}`;\n}\n\nexport function getUrl() {\n  return getBaseUrl() + \"/api/trpc\";\n}\n\n/**\n * Inference helper for inputs.\n *\n * @example type HelloInput = RouterInputs['example']['hello']\n */\nexport type RouterInputs = inferRouterInputs<AppRouter>;\n\n/**\n * Inference helper for outputs.\n *\n * @example type HelloOutput = RouterOutputs['example']['hello']\n */\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n"
  },
  {
    "path": "src/utils/auth.ts",
    "content": "import { cache } from \"react\";\nimport { cookies } from \"next/headers\";\nimport { supabase } from \"~/server/supabase/supabaseClient\";\n\nexport const getServerUser = cache(async () => {\n  const ckies = cookies();\n  const mappedCookies = new Map(ckies);\n  const accessToken = mappedCookies.get(\"access-token\")?.value;\n  const refreshToken = mappedCookies.get(\"refresh-token\")?.value;\n\n  if (!accessToken || !refreshToken) {\n    return {\n      user: null,\n      session: null,\n    };\n  }\n\n  const { error, data } = await supabase().auth.setSession({\n    access_token: accessToken,\n    refresh_token: refreshToken,\n  });\n\n  if (error) {\n    return {\n      user: null,\n      session: null,\n    };\n  }\n\n  return data;\n});\n"
  },
  {
    "path": "src/utils/cn.ts",
    "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
  },
  {
    "path": "src/utils/getQueryClient.ts",
    "content": "import { QueryClient } from \"@tanstack/react-query\";\nimport { cache } from \"react\";\n\nexport const getServerQueryClient = cache(() => new QueryClient());\n"
  },
  {
    "path": "supabase/.gitignore",
    "content": "# Supabase\n.branches\n.temp\n"
  },
  {
    "path": "supabase/config.toml",
    "content": "# A string used to distinguish different Supabase projects on the same host. Defaults to the working\n# directory name when running `supabase init`.\nproject_id = \"APP_NAME\"\n\n[api]\n# Port to use for the API URL.\nport = 54321\n# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API\n# endpoints. public and storage are always included.\nschemas = [\"public\", \"storage\", \"graphql_public\"]\n# Extra schemas to add to the search_path of every request. public is always included.\nextra_search_path = [\"public\", \"extensions\"]\n# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size\n# for accidental or malicious requests.\nmax_rows = 1000\n\n[db]\n# Port to use for the local database URL.\nport = 54322\n# The database major version to use. This has to be the same as your remote database's. Run `SHOW\n# server_version;` on the remote database to check.\nmajor_version = 15\n\n[studio]\n# Port to use for Supabase Studio.\nport = 54323\n\n# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they\n# are monitored, and you can view the emails that would have been sent from the web interface.\n[inbucket]\n# Port to use for the email testing server web interface.\nport = 54324\nsmtp_port = 54325\npop3_port = 54326\n\n[storage]\n# The maximum file size allowed (e.g. \"5MB\", \"500KB\").\nfile_size_limit = \"50MiB\"\n\n[auth]\n# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used\n# in emails.\nsite_url = \"http://localhost:3000\"\n# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.\nadditional_redirect_urls = [\"https://localhost:3000\"]\n# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 seconds (one\n# week).\njwt_expiry = 3600\n# Allow/disallow new user signups to your project.\nenable_signup = true\n\n[auth.email]\n# Allow/disallow new user signups via email to your project.\nenable_signup = true\n# If enabled, a user will be required to confirm any email change on both the old, and new email\n# addresses. If disabled, only the new email is required to confirm.\ndouble_confirm_changes = true\n# If enabled, users need to confirm their email address before signing in.\nenable_confirmations = false\n\n# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,\n# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`,\n# `twitter`, `slack`, `spotify`, `workos`, `zoom`.\n[auth.external.apple]\nenabled = false\nclient_id = \"\"\nsecret = \"\"\n# Overrides the default auth redirectUrl.\nredirect_uri = \"\"\n# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,\n# or any other third-party OIDC providers.\nurl = \"\"\n\n[analytics]\nenabled = false\nport = 54327\nvector_port = 54328\n# Setup BigQuery project to enable log viewer on local development stack.\n# See: https://supabase.com/docs/guides/getting-started/local-development#enabling-local-logging\ngcp_project_id = \"\"\ngcp_project_number = \"\"\ngcp_jwt_path = \"supabase/gcloud.json\"\n"
  },
  {
    "path": "supabase/functions/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"denoland.vscode-deno\"]\n}\n"
  },
  {
    "path": "supabase/functions/.vscode/settings.json",
    "content": "{\n  \"deno.enable\": true,\n  \"deno.lint\": true,\n  \"editor.defaultFormatter\": \"denoland.vscode-deno\"\n}\n"
  },
  {
    "path": "supabase/migrations/20231004185846_initial_profiles.sql",
    "content": "create table \"public\".\"profiles\" (\n    \"id\" uuid not null,\n    \"updated_at\" timestamp with time zone,\n    \"email\" text,\n    \"full_name\" text,\n    \"avatar_url\" text\n);\n\n\nalter table \"public\".\"profiles\" enable row level security;\n\nCREATE UNIQUE INDEX profiles_pkey ON public.profiles USING btree (id);\n\nCREATE UNIQUE INDEX profiles_email_key ON public.profiles USING btree (email);\n\nalter table \"public\".\"profiles\" add constraint \"profiles_pkey\" PRIMARY KEY using index \"profiles_pkey\";\n\nalter table \"public\".\"profiles\" add constraint \"profiles_id_fkey\" FOREIGN KEY (id) REFERENCES auth.users(id) ON DELETE CASCADE not valid;\n\nalter table \"public\".\"profiles\" validate constraint \"profiles_id_fkey\";\n\nalter table \"public\".\"profiles\" add constraint \"profiles_email_key\" UNIQUE using index \"profiles_email_key\";\n\nset check_function_bodies = off;\n\nCREATE OR REPLACE FUNCTION public.handle_new_user()\n RETURNS trigger\n LANGUAGE plpgsql\n SECURITY DEFINER\nAS $function$\nbegin\n  insert into public.profiles (id, full_name, email)\n  values (new.id, new.raw_user_meta_data->>'full_name', new.email);\n  return new;\nend;\n$function$\n;\ncreate trigger on_auth_user_created\n  after insert on auth.users\n  for each row execute procedure public.handle_new_user();\n  \ncreate policy \"Public profiles are viewable by everyone.\"\non \"public\".\"profiles\"\nas permissive\nfor select\nto public\nusing (true);\n\n\ncreate policy \"Users can insert their own profile.\"\non \"public\".\"profiles\"\nas permissive\nfor insert\nto public\nwith check ((auth.uid() = id));\n\n\ncreate policy \"Users can update own profile.\"\non \"public\".\"profiles\"\nas permissive\nfor update\nto public\nusing ((auth.uid() = id));\n\n\n\n"
  },
  {
    "path": "supabase/seed.sql",
    "content": ""
  },
  {
    "path": "tailwind.config.ts",
    "content": "import { type Config } from \"tailwindcss\";\n\nexport default {\n  darkMode: [\"class\"],\n  content: [\"src/**/*.{ts,tsx}\"],\n  theme: {\n    container: {\n      center: true,\n      padding: \"2rem\",\n      screens: {\n        \"2xl\": \"1400px\",\n      },\n    },\n    extend: {\n      colors: {\n        border: \"hsl(var(--border))\",\n        input: \"hsl(var(--input))\",\n        ring: \"hsl(var(--ring))\",\n        background: \"hsl(var(--background))\",\n        foreground: \"hsl(var(--foreground))\",\n        primary: {\n          DEFAULT: \"hsl(var(--primary))\",\n          foreground: \"hsl(var(--primary-foreground))\",\n        },\n        secondary: {\n          DEFAULT: \"hsl(var(--secondary))\",\n          foreground: \"hsl(var(--secondary-foreground))\",\n        },\n        destructive: {\n          DEFAULT: \"hsl(var(--destructive))\",\n          foreground: \"hsl(var(--destructive-foreground))\",\n        },\n        muted: {\n          DEFAULT: \"hsl(var(--muted))\",\n          foreground: \"hsl(var(--muted-foreground))\",\n        },\n        accent: {\n          DEFAULT: \"hsl(var(--accent))\",\n          foreground: \"hsl(var(--accent-foreground))\",\n        },\n        popover: {\n          DEFAULT: \"hsl(var(--popover))\",\n          foreground: \"hsl(var(--popover-foreground))\",\n        },\n        card: {\n          DEFAULT: \"hsl(var(--card))\",\n          foreground: \"hsl(var(--card-foreground))\",\n        },\n      },\n      borderRadius: {\n        lg: \"var(--radius)\",\n        md: \"calc(var(--radius) - 2px)\",\n        sm: \"calc(var(--radius) - 4px)\",\n      },\n      keyframes: {\n        \"accordion-down\": {\n          from: { height: \"0\" },\n          to: { height: \"var(--radix-accordion-content-height)\" },\n        },\n        \"accordion-up\": {\n          from: { height: \"var(--radix-accordion-content-height)\" },\n          to: { height: \"0\" },\n        },\n      },\n      animation: {\n        \"accordion-down\": \"accordion-down 0.2s ease-out\",\n        \"accordion-up\": \"accordion-up 0.2s ease-out\",\n      },\n    },\n  },\n  plugins: [require(\"tailwindcss-animate\")],\n} satisfies Config;\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"noUncheckedIndexedAccess\": true,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"~/*\": [\"./src/*\"]\n    },\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ]\n  },\n  \"include\": [\n    \".eslintrc.cjs\",\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \"**/*.cjs\",\n    \"**/*.mjs\",\n    \".next/types/**/*.ts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  }
]