[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/beige-clouds-behave.md",
    "content": "---\n\"create-t3-app\": patch\n---\n\nfix #1903 #2157 #2163\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@2.1.1/schema.json\",\n  \"changelog\": [\n    \"@changesets/changelog-github\",\n    { \"repo\": \"t3-oss/create-t3-app\" }\n  ],\n  \"commit\": false,\n  \"fixed\": [],\n  \"linked\": [],\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": [\"@ct3a/www\"],\n  \"changedFilePatterns\": [\"src/**\", \"template/**\"]\n}\n"
  },
  {
    "path": ".changeset/curly-zoos-add.md",
    "content": "---\n\"create-t3-app\": minor\n---\n\nFixes Biome formatter during the initial installation process\n"
  },
  {
    "path": ".changeset/quick-snakes-give.md",
    "content": "---\n\"create-t3-app\": patch\n---\n\nfix(security): bump react and next ([BLOG](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components#update-instructions))\n"
  },
  {
    "path": ".changeset/tender-humans-hide.md",
    "content": "---\n\"create-t3-app\": patch\n---\n\nfix(security): bump react ([CVE-2025-55182](https://github.com/facebook/react/security/advisories/GHSA-fv66-9v8q-g76r))\n"
  },
  {
    "path": ".codesandbox/tasks.json",
    "content": "{\n  // These tasks will run in order when initializing your CodeSandbox project.\n  \"setupTasks\": [\n    {\n      \"name\": \"Install Dependencies\",\n      \"command\": \"pnpm install\"\n    }\n  ],\n\n  // These tasks can be run from CodeSandbox. Running one will open a log in the app.\n  \"tasks\": {\n    \"typecheck\": {\n      \"name\": \"typecheck\",\n      \"command\": \"pnpm typecheck\",\n      \"runAtStart\": false\n    },\n    \"build:cli\": {\n      \"name\": \"build:cli\",\n      \"command\": \"pnpm build:cli\",\n      \"runAtStart\": false\n    },\n    \"build:www\": {\n      \"name\": \"build:www\",\n      \"command\": \"pnpm build:www\",\n      \"runAtStart\": false\n    },\n    \"build\": {\n      \"name\": \"build\",\n      \"command\": \"pnpm build\",\n      \"runAtStart\": false\n    },\n    \"start:cli\": {\n      \"name\": \"start:cli\",\n      \"command\": \"pnpm start:cli\",\n      \"runAtStart\": false\n    },\n    \"start:www\": {\n      \"name\": \"start:www\",\n      \"command\": \"pnpm start:www\",\n      \"runAtStart\": false\n    },\n    \"dev:cli\": {\n      \"name\": \"dev:cli\",\n      \"command\": \"pnpm dev:cli\",\n      \"runAtStart\": false\n    },\n    \"dev:www\": {\n      \"name\": \"dev:www\",\n      \"command\": \"pnpm dev:www\",\n      \"runAtStart\": true\n    },\n    \"clean\": {\n      \"name\": \"clean\",\n      \"command\": \"pnpm clean\",\n      \"runAtStart\": false\n    },\n    \"lint\": {\n      \"name\": \"lint\",\n      \"command\": \"pnpm lint\",\n      \"runAtStart\": false\n    },\n    \"format\": {\n      \"name\": \"format\",\n      \"command\": \"pnpm format\",\n      \"runAtStart\": false\n    },\n    \"format:check\": {\n      \"name\": \"format:check\",\n      \"command\": \"pnpm format:check\",\n      \"runAtStart\": false\n    }\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "# mdx\n*.mdx linguist-detectable=false"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners\n\n* @juliusmarminge @nexxeln @t3dotgg @c-ehrlich\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: 🐞 Bug Report\ndescription: Create a bug report to help us improve\ntitle: \"bug: \"\nlabels: [\"🐞❔ unconfirmed bug\"]\nbody:\n  - type: textarea\n    attributes:\n      label: Provide environment information\n      description: |\n        Run this command in your project root and paste the results:\n        ```bash\n        npx envinfo --system --binaries\n        ```\n        If the issue is regarding a scaffolded app, please include the version used to scaffold that app which you can find in the `package.json` under `ct3aMetadata.initVersion`.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Describe the bug\n      description: A clear and concise description of the bug, as well as what you expected to happen when encountering it.\n    validations:\n      required: true\n  - type: input\n    attributes:\n      label: Reproduction repo\n      description: If applicable, please provide a link to a reproduction repo or a Stackblitz / CodeSandbox project. Your issue may be closed if this is not provided and we are unable to reproduce the issue. If your bug is a documentaion issue, link the appropriate page.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: To reproduce\n      description: Describe how to reproduce your bug. Steps, code snippets, reproduction repos etc.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Additional information\n      description: Add any other information related to the bug here, screenshots if applicable.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Ask a question\n    url: https://t3.gg/discord\n    about: Ask questions and discuss with other community members\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: 🧑‍💻 Feature Request\ndescription: Suggest an idea for this project\ntitle: \"feat: \"\nlabels: [\"🌟 enhancement\"]\nbody:\n  - type: textarea\n    attributes:\n      label: Is your feature request related to a problem? Please describe.\n      description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Describe the solution you'd like to see\n      description: A clear and concise description of what you want to happen.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Describe alternate solutions\n      description: A clear and concise description of any alternative solutions or features you've considered.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Additional information\n      description: Add any other information related to the feature here. If your feature request is related to any issues or discussions, link them here.\n"
  },
  {
    "path": ".github/actions/setup/action.yml",
    "content": "name: \"Setup and install\"\ndescription: \"Common setup steps for Actions\"\n\nruns:\n  using: composite\n  steps:\n    - uses: pnpm/action-setup@v3\n    - uses: actions/setup-node@v4\n      with:\n        node-version: 20\n        cache: \"pnpm\"\n\n    - shell: bash\n      run: pnpm install\n"
  },
  {
    "path": ".github/changeset-version.js",
    "content": "// ORIGINALLY FROM CLOUDFLARE WRANGLER:\n// https://github.com/cloudflare/wrangler2/blob/main/.github/changeset-version.js\n\nimport { exec } from \"child_process\";\n// This script is used by the `release.yml` workflow to update the version of the packages being released.\n// The standard step is only to run `changeset version` but this does not update the package-lock.json file.\n// So we also run `npm install`, which does this update.\n// This is a workaround until this is handled automatically by `changeset version`.\n// See https://github.com/changesets/changesets/issues/421.\nexec(\"npx changeset version\");\nexec(\"npm install\");\n"
  },
  {
    "path": ".github/labeler.yml",
    "content": "\"📌 area: cli\":\n  - any: [\"cli/**/*\"]\n\n\"📌 area: t3-app\":\n  - any: [\"cli/template/**/*\"]\n\n\"📚 documentation\":\n  - any: [\"www/**/*\"]\n  - any: [\"**/*.md\"]\n\n\"📌 area: ci\":\n  - any: [\".github/**/*\"]\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "Closes #<issue>\n\n## ✅ Checklist\n\n- [ ] I have followed every step in the [contributing guide](https://github.com/t3-oss/create-t3-app/blob/main/CONTRIBUTING.md) (updated 2022-10-06).\n- [ ] The PR title follows the convention we established [conventional-commit](https://www.conventionalcommits.org/en/v1.0.0/)\n- [ ] I performed a functional test on my final commit\n\n---\n\n## Changelog\n\n_[Short description of what has changed]_\n\n---\n\n## Screenshots\n\n_[Screenshots]_\n\n💯\n"
  },
  {
    "path": ".github/scripts/generate-matrix.js",
    "content": "// Define all possible values\nconst options = {\n  trpc: ['true', 'false'],\n  tailwind: ['true', 'false'],\n  nextAuth: ['true', 'false'],\n  betterAuth: ['true', 'false'],\n  prisma: ['true', 'false'],\n  drizzle: ['true', 'false'],\n  appRouter: ['true', 'false'],\n  dbType: ['planetscale', 'sqlite', 'mysql', 'postgres']\n};\n\n// Generate all combinations\nfunction generateCombinations(opts) {\n  const keys = Object.keys(opts);\n  const combinations = [];\n\n  function recurse(index, current) {\n    if (index === keys.length) {\n      combinations.push({...current});\n      return;\n    }\n\n    const key = keys[index];\n    for (const value of opts[key]) {\n      current[key] = value;\n      recurse(index + 1, current);\n    }\n  }\n\n  recurse(0, {});\n  return combinations;\n}\n\n// Filter valid combinations based on current validation logic\nfunction isValid(combo) {\n  const { prisma, drizzle, nextAuth, betterAuth, dbType } = combo;\n\n  // Not both auth true\n  if (nextAuth === 'true' && betterAuth === 'true') return false;\n\n  // Not both db true\n  if (prisma === 'true' && drizzle === 'true') return false;\n\n  // If no db selected, only allow sqlite\n  if (prisma === 'false' && drizzle === 'false' && dbType !== 'sqlite') return false;\n\n  return true;\n}\n\nconst allCombos = generateCombinations(options);\nconst validCombos = allCombos.filter(isValid);\n\nconsole.log(`matrix=${JSON.stringify({include: validCombos})}`);\n"
  },
  {
    "path": ".github/version-script-beta.js",
    "content": "// ORIGINALLY FROM CLOUDFLARE WRANGLER:\n// https://github.com/cloudflare/wrangler2/blob/main/.github/version-script.js\nimport fs from \"fs\";\nimport { exec } from \"child_process\";\n\nconst pkgJsonPath = \"cli/package.json\";\ntry {\n  const pkg = JSON.parse(fs.readFileSync(pkgJsonPath));\n  exec(\"git rev-parse --short HEAD\", (err, stdout) => {\n    if (err) {\n      console.log(err);\n      process.exit(1);\n    }\n    const [major, minor, patch] = pkg.version.split(\".\").map(Number);\n    pkg.version = `${major}.${minor}.${patch + 1}-beta.${stdout.trim()}`;\n    fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, \"\\t\") + \"\\n\");\n  });\n} catch (error) {\n  console.error(error);\n  process.exit(1);\n}\n"
  },
  {
    "path": ".github/version-script-next.js",
    "content": "// ORIGINALLY FROM CLOUDFLARE WRANGLER:\n// https://github.com/cloudflare/wrangler2/blob/main/.github/version-script.js\nimport fs from \"fs\";\nimport { exec } from \"child_process\";\n\nconst pkgJsonPath = \"cli/package.json\";\ntry {\n  const pkg = JSON.parse(fs.readFileSync(pkgJsonPath));\n  exec(\"git rev-parse --short HEAD\", (err, stdout) => {\n    if (err) {\n      console.log(err);\n      process.exit(1);\n    }\n    const [major, minor, patch] = pkg.version.split(\".\").map(Number);\n    pkg.version = `${major}.${minor}.${patch + 1}-next.${stdout.trim()}`;\n    fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, \"\\t\") + \"\\n\");\n  });\n} catch (error) {\n  console.error(error);\n  process.exit(1);\n}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "# this workflow will run on every pr to make sure the project is following the guidelines\n\n# after labeler, run other actions with strict permissions\nname: CI\n\non:\n  pull_request:\n    branches: [\"*\"]\n  merge_group:\n\nenv:\n  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    name: Run ESLint\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - run: pnpm turbo run lint\n      - run: pnpm manypkg check\n\n  check-changeset:\n    runs-on: ubuntu-latest\n    name: Check Changeset\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - name: Check and Validate Changes in /cli\n        run: |\n          git fetch origin main:main\n          changes=$(git diff --name-only main...${{ github.sha }} | grep '^cli/' || true)\n          if [[ -n \"$changes\" ]]; then\n            echo \"Changes detected in /cli: $changes\"\n            pnpm changeset status --since origin/main\n            exit_status=$?\n            if [[ $exit_status -eq 0 ]]; then\n              echo \"Changeset validation succeeded.\"\n            else\n              echo \"Changeset validation failed.\"\n            fi\n          else\n            echo \"No changes detected in /cli\"\n          fi\n\n  prettier:\n    runs-on: ubuntu-latest\n    name: Run Prettier\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - run: pnpm format:check\n\n  tsc:\n    runs-on: ubuntu-latest\n    name: Run Typechecker\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - run: pnpm typecheck\n\n  build-www:\n    runs-on: ubuntu-latest\n    name: Build and Check Astro\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - run: pnpm run --filter=www check\n      - run: pnpm turbo --filter=www build\n        # env:\n        #   PUBLIC_GITHUB_TOKEN: ${{ secrets.PUBLIC_GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/e2e.yml",
    "content": "# this workflow will run on every pr to make sure the project is following the guidelines\n\n# after labeler, run other actions with strict permissions\nname: E2E Tests\n\non:\n  pull_request:\n    branches:\n      - \"*\"\n    paths:\n      - \"cli/**/*\"\n  merge_group:\n\nenv:\n  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}\n\njobs:\n  generate-matrix:\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.generate.outputs.matrix }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Generate valid matrix combinations\n        id: generate\n        run: node .github/scripts/generate-matrix.js >> $GITHUB_OUTPUT\n\n  build-t3-app:\n    needs: generate-matrix\n    runs-on: ubuntu-latest\n    # if: |\n    #   contains(github.event.pull_request.labels.*.name, '📌 area: cli') ||\n    #   contains(github.event.pull_request.labels.*.name, '📌 area: t3-app')\n    strategy:\n      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}\n\n    name: \"Build and Start T3 App ${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.betterAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }}\"\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - uses: ./.github/actions/setup\n\n      - run: pnpm turbo --filter=create-t3-app build\n\n      # has to be scaffolded outside the CLI project so that no lint/tsconfig are leaking\n      # through. this way it ensures that it is the app's configs that are being used\n      # FIXME: this is a bit hacky, would rather have --packages=trpc,tailwind,... but not sure how to setup the matrix for that\n      - run: cd cli && pnpm start ../../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.betterAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} --noGit --CI --trpc=${{ matrix.trpc }} --tailwind=${{ matrix.tailwind }} --nextAuth=${{ matrix.nextAuth }} --betterAuth=${{ matrix.betterAuth }} --prisma=${{ matrix.prisma }} --drizzle=${{ matrix.drizzle }} --appRouter=${{ matrix.appRouter }} --dbProvider=${{ matrix.dbType }}\n        # can't use default mysql string cause t3-env blocks that\n\n      - run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.betterAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} && pnpm build\n        env:\n          AUTH_SECRET: foo\n          AUTH_DISCORD_ID: bar\n          AUTH_DISCORD_SECRET: baz\n          SKIP_ENV_VALIDATION: true\n\n  check-well-formatted:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        eslint: [\"true\", \"false\"]\n        biome: [\"true\", \"false\"]\n\n    name: \"Build and Start T3 App\"\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Check valid matrix\n        id: matrix-valid\n        run: |\n          echo \"continue=${{ (matrix.eslint == 'false' || matrix.biome == 'false') && (matrix.biome == 'true' || matrix.eslint == 'true') }}\" >> $GITHUB_OUTPUT\n\n      - uses: ./.github/actions/setup\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' }}\n\n      - run: pnpm turbo --filter=create-t3-app build\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' }}\n\n      - run: cd cli && pnpm start ../../ci-format-${{ matrix.eslint }}-${{ matrix.biome }} --noGit --CI --trpc --tailwind --nextAuth  --drizzle --appRouter --dbProvider=postgres --eslint=${{ matrix.eslint }} --biome=${{ matrix.biome }}\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' }}\n\n      - run: cd ../ci-format-${{ matrix.eslint }}-${{ matrix.biome }} && pnpm build\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' }}\n        env:\n          AUTH_SECRET: foo\n          AUTH_DISCORD_ID: bar\n          AUTH_DISCORD_SECRET: baz\n          SKIP_ENV_VALIDATION: true\n\n      # Run biome check\n      - run: cd ../ci-format-${{ matrix.eslint }}-${{ matrix.biome }} && pnpm check\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' && matrix.biome == 'true' }}\n\n      # Check linting and formatting with eslint and prettier\n      - run: cd ../ci-format-${{ matrix.eslint }}-${{ matrix.biome }} && pnpm lint && pnpm format:check\n        if: ${{ steps.matrix-valid.outputs.continue == 'true' && matrix.eslint == 'true' }}\n        env:\n          AUTH_SECRET: foo\n          AUTH_DISCORD_ID: bar\n          AUTH_DISCORD_SECRET: baz\n          SKIP_ENV_VALIDATION: true\n\n  build-t3-app-with-bun:\n    runs-on: ubuntu-latest\n\n    name: \"Build and Start T3 App with Bun\"\n    steps:\n      - uses: actions/checkout@v3\n        with:\n          fetch-depth: 0\n\n      # First install everything and build the CLI with Node\n      - uses: ./.github/actions/setup\n      - run: pnpm turbo --filter=create-t3-app build\n\n      # Then, run the CLI and build the generated app with Bun\n      # Let's just build a full app with Bun, we don't need the matrix here\n      - uses: oven-sh/setup-bun@v1\n        with:\n          bun-version: latest\n\n      - run: cd cli && bun run dist/index.js ../../ci-bun --default\n\n      - name: We should have a Bun lockfile\n        run: |\n          if [ ! -f \"../ci-bun/bun.lock\" ]; then\n            echo \"Bun lockfile not found\"\n            exit 1\n          fi\n\n      # FIXME: This doesn't actually run the build script using bun, since Next.js doesn't support it yet.\n      # But you should still be able to use `bun` as a package manager for any Next.js app.\n      # If/When Next.js supports it, we should be able to run `bun --bun run build` here to override any Node binaries.\n      # See: https://bun.sh/docs/cli/bunx#shebangs\n      - run: cd ../ci-bun && bun run build\n        # - run: cd ../ci-bun && bun --bun run build\n        env:\n          AUTH_SECRET: foo\n          AUTH_DISCORD_ID: bar\n          AUTH_DISCORD_SECRET: baz\n          DATABASE_URL: mysql://root:root@localhost:3306/test # can't use url from example env cause we block that in t3-env\n"
  },
  {
    "path": ".github/workflows/pr-labeler.yml",
    "content": "# this workflow will run on every pr to make sure the project is following the guidelines\n\n# run labeler with elevated permissions before other actions\n\nname: PR Checks\n\non:\n  pull_request_target:\n    branches: [\"*\"]\n    types: [\"opened\", \"edited\", \"synchronize\"]\n\njobs:\n  lint-pr-title:\n    runs-on: ubuntu-latest\n    name: Validate PR Title\n    steps:\n      - uses: amannn/action-semantic-pull-request@v5\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  labeler:\n    name: Label PR\n    permissions:\n      contents: read\n      pull-requests: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/labeler@v5\n        with:\n          repo-token: \"${{ secrets.GITHUB_TOKEN }}\"\n          sync-labels: true\n"
  },
  {
    "path": ".github/workflows/prerelease-comment.yml",
    "content": "name: Write Beta Release comment\n\non:\n  workflow_run:\n    workflows: [\"Release - Beta\"]\n    types:\n      - completed\n\njobs:\n  comment:\n    if: |\n      github.repository_owner == 't3-oss' &&\n      ${{ github.event.workflow_run.conclusion == 'success' }}\n    runs-on: ubuntu-latest\n    name: Write comment to the PR\n    steps:\n      - name: \"Comment on PR\"\n        uses: actions/github-script@v7\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              run_id: context.payload.workflow_run.id,\n            });\n\n            for (const artifact of allArtifacts.data.artifacts) {\n              // Extract the PR number and package version from the artifact name\n              const match = /^npm-package-create-t3-app@(.*?)-pr-(\\d+)/.exec(artifact.name);\n              \n              if (match) {\n                require(\"fs\").appendFileSync(\n                  process.env.GITHUB_ENV,\n                  `\\nBETA_PACKAGE_VERSION=${match[1]}` +\n                  `\\nWORKFLOW_RUN_PR=${match[2]}` +\n                  `\\nWORKFLOW_RUN_ID=${context.payload.workflow_run.id}`\n                );\n                break;\n              }\n            }\n\n      - name: \"Comment on PR with Link\"\n        uses: marocchino/sticky-pull-request-comment@v2\n        with:\n          number: ${{ env.WORKFLOW_RUN_PR }}\n          message: |\n            A new create-t3-app prerelease is available for testing. You can install this latest build in your project with:\n\n            ```sh\n            pnpm create t3-app@${{ env.BETA_PACKAGE_VERSION }}\n            ```\n\n      - name: \"Remove the autorelease label once published\"\n        uses: actions/github-script@v7\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            github.rest.issues.removeLabel({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: ${{ env.WORKFLOW_RUN_PR }},\n              name: '🚀 autorelease',\n            });\n"
  },
  {
    "path": ".github/workflows/prerelease.yml",
    "content": "# Originally inspired by Cloudflare Wrangler\n# https://github.com/cloudflare/wrangler2/blob/main/.github/workflows/prereleases.yml\n\nname: Release - Beta\n\non:\n  pull_request:\n    types: [labeled]\n    branches:\n      - main\njobs:\n  prerelease:\n    if: |\n      github.repository_owner == 't3-oss' &&\n      contains(github.event.pull_request.labels.*.name, '🚀 autorelease')\n    name: Build & Publish a beta release to NPM\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - name: Modify package.json version\n        run: node .github/version-script-beta.js\n\n      - name: Authenticate to NPM\n        run: echo \"//registry.npmjs.org/:_authToken=${{ secrets.NPM_ACCESS_TOKEN }}\" > cli/.npmrc\n\n      - name: Publish Beta to NPM\n        run: pnpm pub:beta\n        env:\n          NPM_PUBLISH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}\n\n      - name: get-npm-version\n        id: package-version\n        uses: martinbeentjes/npm-get-version-action@main\n        with:\n          path: cli\n\n      - name: Upload packaged artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: npm-package-create-t3-app@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name\n          path: cli/dist/index.js\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "# Originally inspired by Cloudflare Wrangler\n# https://github.com/cloudflare/wrangler2/blob/main/.github/workflows/release.yml\n\nname: Release\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  release:\n    if: ${{ github.repository_owner == 't3-oss' }}\n    permissions:\n      contents: write # to create release (changesets/action)\n      id-token: write # OpenID Connect token needed for provenance\n      pull-requests: write # to create pull request (changesets/action)\n    name: Create a PR for release workflow\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - uses: ./.github/actions/setup\n\n      - name: Check for errors\n        run: pnpm check\n\n      - name: Build the package\n        run: pnpm build:cli\n\n      - name: Create Version PR or Publish to NPM\n        id: changesets\n        uses: changesets/action@v1\n        with:\n          commit: \"chore(release): version packages\"\n          title: \"chore(release): version packages\"\n          version: node .github/changeset-version.js\n          publish: npx changeset publish\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_CONFIG_PROVENANCE: true\n          NPM_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}\n          NODE_ENV: \"production\"\n"
  },
  {
    "path": ".github/workflows/translations.yml",
    "content": "name: \"Notify codeowners about changes in docs\"\n\non:\n  pull_request_target:\n    types: [opened, edited, synchronize]\n    branches:\n      - \"*\"\n    paths:\n      - \"www/src/pages/**\"\n      - \"!www/src/pages/en/**\"\n\njobs:\n  notify-codeowners:\n    if: |\n      github.repository_owner == 't3-oss'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Parse changed files and write to env\n        uses: actions/github-script@v7\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const changedFiles = (await github.rest.pulls.listFiles({\n              owner: \"t3-oss\",\n              repo: \"create-t3-app\",\n              pull_number: context.payload.number,\n            })).data.map(file => file.filename);\n\n            const changedLanguages = [\n              ...new Set(\n                changedFiles\n                  .filter((file) => file.startsWith(\"www/src/pages/\"))\n                  .map((file) => file.split(\"/\")[3])\n                  .filter((file) => file !== \"en\"),\n              ),\n            ];\n\n            const CODEOWNERS = {\n              ar: [\"a4addel\", \"Sboonny\"],\n              fr: [\"Defranos\", \"joachimjusth\", \"vdeva\"],\n              ja: [\"t6adev\", \"uehaj\"],\n              no: [\"estubmo\", \"josephayman\"],\n              pl: [\"matibox\", \"Infiplaya\", \"PiotrekPKP\"],\n              pt: [\"minsk-dev\", \"Sn0wye\", \"victoriaquasar\", \"MattFerreira18\", \"gilhrpenner\"],\n              ru: [\"AmadeusTwi\", \"ronanru\", \"JohnBakhmat\"],\n              uk: [\"pqoqubbw\"],\n              \"zh-hans\": [\"fernandoxu\", \"escwxyz\"],\n            };\n\n            console.log(\"Changed languages:\", changedLanguages)\n\n            const formattedString = changedLanguages\n              .map(\n                (lang) =>\n                  `${lang.toUpperCase()}: ${(CODEOWNERS[lang] || []).map((user) => `@${user}`).join(\", \")}`,\n              )\n              .join(\"  |  \"); // cause we can't linebreak in env vars\n\n            console.log(\"Formatted string:\", formattedString)\n\n            require(\"fs\").appendFileSync(\n              process.env.GITHUB_ENV,\n              `\\nCODEOWNERS=${formattedString}`,\n            );\n\n      - name: Write comment on the PR tagging codeowners\n        uses: marocchino/sticky-pull-request-comment@v2\n        with:\n          number: ${{ env.WORKFLOW_RUN_PR }}\n          message: |\n            Hey t3-oss/translators! \n\n            This PR contains changes to your language. Please review the changes ❤️.\n\n            ${{ env.CODEOWNERS }}\n"
  },
  {
    "path": ".gitignore",
    "content": "### STANDARD GIT IGNORE FILE ###\n\n# DEPENDENCIES\nnode_modules/\n/.pnp\n.pnp.js\npackage-lock.json\nyarn.lock\n\n# TESTING\n/coverage\n*.lcov\n.nyc_output\n\n# BUILD\nbuild/\npublic/build/\ndist/\ngenerated/\n.astro\n\n# ENV FILES\n.env\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\n# LOGS\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# MISC\n.idea\n.cache/\n.next/\nnext-env.d.ts\n.nuxt/\ntmp/\ntemp/\n.docusaurus\n*.tsbuildinfo\n\n# MAC\n._*\n.DS_Store\nThumbs.db\n\n.turbo\n.vercel\n\n# Emacs backup files\n\\#*\n.\\#*\n\n# TYPESCRIPT\n*.tsbuildinfo\n"
  },
  {
    "path": ".gitpod.yml",
    "content": "tasks:\n  - init: pnpm install\nvscode:\n  extensions:\n    - astro-build.astro-vscode\n    - bradlc.vscode-tailwindcss"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"esbenp.prettier-vscode\",\n    \"dbaeumer.vscode-eslint\",\n    \"astro-build.astro-vscode\",\n    \"bradlc.vscode-tailwindcss\",\n    \"unifiedjs.vscode-mdx\",\n    \"yoavbls.pretty-ts-errors\"\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"workbench.colorCustomizations\": {\n    \"titleBar.activeBackground\": \"#1f0d49\",\n    \"titleBar.activeForeground\": \"#e2e8f0\",\n    \"titleBar.inactiveBackground\": \"#181239\",\n    \"titleBar.inactiveForeground\": \"#b1b6bd\"\n  },\n\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\"\n  },\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n  \"editor.formatOnSave\": true,\n  \"editor.rulers\": [100],\n  \"editor.tabSize\": 2,\n  \"editor.quickSuggestions\": {\n    \"strings\": true\n  },\n\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"astro\",\n    \"typescript\",\n    \"typescriptreact\"\n  ],\n  \"eslint.workingDirectories\": [\"cli\", \"upgrade\", \"www\"],\n\n  \"eslint.rules.customizations\": [{ \"rule\": \"*\", \"severity\": \"warn\" }],\n  \"typescript.tsdk\": \"node_modules/typescript/lib\",\n  \"prettier.documentSelectors\": [\n    \"**/*.{cjs,mjs,ts,tsx,astro,md,mdx,json,yaml,yml}\"\n  ],\n  \"mdx.experimentalLanguageServer\": true,\n  \"[astro]\": {\n    \"editor.defaultFormatter\": \"astro-build.astro-vscode\"\n  },\n  \"[prisma]\": {\n    \"editor.defaultFormatter\": \"Prisma.prisma\"\n  },\n  \"[javascript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[typescript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[typescriptreact]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  }\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution Guidelines\n\nWhen contributing to `create-t3-app`, whether on GitHub or in other community spaces:\n\n- Be respectful, civil, and open-minded.\n- Before opening a new pull request, try searching through the [issue tracker](https://github.com/t3-oss/create-t3-app/issues) for known issues or fixes.\n- If you want to make code changes based on your personal opinion(s), make sure you open an issue first describing the changes you want to make, and open a pull request only when your suggestions get approved by maintainers.\n\n## How to Contribute\n\n### Prerequisites\n\nIn order to not waste your time implementing a change that has already been declined, or is generally not needed, start by [opening an issue](https://github.com/t3-oss/create-t3-app/issues/new/choose) describing the problem you would like to solve.\n\n### Contributing via Codesandbox\n\nYou can contribute to this documentation on codesandbox which will automatically run all the setup command for you. [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/github/t3-oss/create-t3-app).\n\n### Setup your environment locally\n\n_Some commands will assume you have the Github CLI installed, if you haven't, consider [installing it](https://github.com/cli/cli#installation), but you can always use the Web UI if you prefer that instead._\n\nIn order to contribute to this project, you will need to fork the repository:\n\n```bash\ngh repo fork t3-oss/create-t3-app\n```\n\nthen, clone it to your local machine:\n\n```bash\ngh repo clone <your-github-name>/create-t3-app\n```\n\nThis project uses [pnpm](https://pnpm.io) as its package manager. Install it if you haven't already:\n\n```bash\nnpm install -g pnpm\n```\n\nThen, install the project's dependencies:\n\n```bash\npnpm install\n```\n\n### Implement your changes\n\nThis project is a [Turborepo](https://turborepo.org/) monorepo. The code for the CLI is in the `cli` directory, and the docs is in the `www` directory. Now you're all setup and can start implementing your changes.\n\nHere are some useful scripts for when you are developing:\n\n| Command          | Description                                             |\n| ---------------- | ------------------------------------------------------- |\n| `pnpm dev:cli`   | Builds and starts the CLI in watch-mode                 |\n| `pnpm dev:www`   | Starts the development server for the docs with HMR     |\n| `pnpm build:cli` | Builds the CLI                                          |\n| `pnpm build:www` | Builds the docs                                         |\n| `pnpm build`     | Builds CLI and docs                                     |\n| `pnpm format`    | Formats the code                                        |\n| `pnpm lint`      | Lints the code                                          |\n| `pnpm lint:fix`  | Lints the code and fixes any errors                     |\n| `pnpm check`     | Checks your code for typeerrors, formatting and linting |\n\nWhen making commits, make sure to follow the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) guidelines, i.e. prepending the message with `feat:`, `fix:`, `chore:`, `docs:`, etc... You can use `git status` to double check which files have not yet been staged for commit:\n\n```bash\ngit add <file> && git commit -m \"feat/fix/chore/docs: commit message\"\n```\n\n### When you're done\n\nCheck that your code follows the project's style guidelines by running:\n\n```bash\npnpm check\n```\n\nPlease also make a manual, functional test of your changes.\n\nIf your change should appear in the changelog, i.e. it changes some behavior of either the CLI or the outputted application, it must be captured by `changeset` which is done by running\n\n```bash\npnpm changeset\n```\n\nand filling out the form with the appropriate information. Then, add the generated changeset to git:\n\n```bash\ngit add .changeset/*.md && git commit -m \"chore: add changeset\"\n```\n\nWhen all that's done, it's time to file a pull request to upstream:\n\n```bash\ngh pr create --web\n```\n\nand fill out the title and body appropriately. Again, make sure to follow the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) guidelines for your title.\n\n## Translations\n\nFor more information on how to help with translation, please see the [contributing guidelines for our docs](https://github.com/t3-oss/create-t3-app/blob/main/www/TRANSLATIONS.md).\n\n## Credits\n\nThis documented was inspired by the contributing guidelines for [cloudflare/wrangler2](https://github.com/cloudflare/wrangler2/blob/main/CONTRIBUTING.md).\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 Shoubhit Dash\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "cli/.yarnrc.yml",
    "content": "packageExtensions:\n  chalk@5.0.1:\n    dependencies:\n      \"#ansi-styles\": npm:ansi-styles@6.1.0\n      \"#supports-color\": npm:supports-color@9.2.2\n"
  },
  {
    "path": "cli/CHANGELOG.md",
    "content": "# Changelog\n\n## 7.38.1\n\n### Patch Changes\n\n- [#2010](https://github.com/t3-oss/create-t3-app/pull/2010) [`12fccae15d08bc11168fe6b462d978a6787b5c7c`](https://github.com/t3-oss/create-t3-app/commit/12fccae15d08bc11168fe6b462d978a6787b5c7c) Thanks [@swyckoff](https://github.com/swyckoff)! - Added an import for crypto in the cli envVars.ts to support older node versions.\n\n## 7.38.0\n\n### Minor Changes\n\n- [#2000](https://github.com/t3-oss/create-t3-app/pull/2000) [`41de302b5a76966741d1dc270ba5da27064f82e8`](https://github.com/t3-oss/create-t3-app/commit/41de302b5a76966741d1dc270ba5da27064f82e8) Thanks [@ronanru](https://github.com/ronanru)! - update to next.js 15 and next-auth v5\n\n- [#2002](https://github.com/t3-oss/create-t3-app/pull/2002) [`54b66484692b76d325f59dc233eb27e0aee59af2`](https://github.com/t3-oss/create-t3-app/commit/54b66484692b76d325f59dc233eb27e0aee59af2) Thanks [@devotoare](https://github.com/devotoare)! - Change drizzle with PostgresQL to use identity columns\n\n### Patch Changes\n\n- [#1969](https://github.com/t3-oss/create-t3-app/pull/1969) [`e08dbe307b4e37c7cc7e0cbf6243c008771ef4f8`](https://github.com/t3-oss/create-t3-app/commit/e08dbe307b4e37c7cc7e0cbf6243c008771ef4f8) Thanks [@Guria](https://github.com/Guria)! - fix issue with prefetch protected procedure in auth templates\n\n- [#1997](https://github.com/t3-oss/create-t3-app/pull/1997) [`fe85a233c62af607e8a39bf5ca1b2358d43c6587`](https://github.com/t3-oss/create-t3-app/commit/fe85a233c62af607e8a39bf5ca1b2358d43c6587) Thanks [@programming-with-ia](https://github.com/programming-with-ia)! - Add more scripts in `package.json`\n\n- [#1975](https://github.com/t3-oss/create-t3-app/pull/1975) [`78cb06f99f15f4f4f90b57e3545f1dc0b222eaf3`](https://github.com/t3-oss/create-t3-app/commit/78cb06f99f15f4f4f90b57e3545f1dc0b222eaf3) Thanks [@0pilatos0](https://github.com/0pilatos0)! - Resolved issue where database startup script did not check for docker daemon being up and running\n\n## 7.37.0\n\n### Minor Changes\n\n- [#1936](https://github.com/t3-oss/create-t3-app/pull/1936) [`2d1878e53767e35ab4b22a37622fbf0d5fdb4da7`](https://github.com/t3-oss/create-t3-app/commit/2d1878e53767e35ab4b22a37622fbf0d5fdb4da7) Thanks [@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)! - upgrade to typescript eslint v8\n\n- [#1936](https://github.com/t3-oss/create-t3-app/pull/1936) [`2d1878e53767e35ab4b22a37622fbf0d5fdb4da7`](https://github.com/t3-oss/create-t3-app/commit/2d1878e53767e35ab4b22a37622fbf0d5fdb4da7) Thanks [@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)! - upgrade to drizzle-orm@0.33 and corresponding drizzle-kit version\n\n### Patch Changes\n\n- [#1954](https://github.com/t3-oss/create-t3-app/pull/1954) [`f9f96d069af87d4372dc917e3625409859e4e615`](https://github.com/t3-oss/create-t3-app/commit/f9f96d069af87d4372dc917e3625409859e4e615) Thanks [@ronanru](https://github.com/ronanru)! - fix typo\n\n## 7.36.2\n\n### Patch Changes\n\n- [#1945](https://github.com/t3-oss/create-t3-app/pull/1945) [`9eea9fb5f6d26d42944a660bfcee5f7fb33438ad`](https://github.com/t3-oss/create-t3-app/commit/9eea9fb5f6d26d42944a660bfcee5f7fb33438ad) Thanks [@datasalaryman](https://github.com/datasalaryman)! - resolve client error during getLatest trpc call\n\n- [#1948](https://github.com/t3-oss/create-t3-app/pull/1948) [`3a1b94d29a3addc783e2d6645c2e88a5b7273174`](https://github.com/t3-oss/create-t3-app/commit/3a1b94d29a3addc783e2d6645c2e88a5b7273174) Thanks [@keyding](https://github.com/keyding)! - Update seed.ts in prisma in documentation\n\n- [#1940](https://github.com/t3-oss/create-t3-app/pull/1940) [`46a4e2d144da8b184bf39444b19e0b1bd00bab2b`](https://github.com/t3-oss/create-t3-app/commit/46a4e2d144da8b184bf39444b19e0b1bd00bab2b) Thanks [@KrishanGoyal1](https://github.com/KrishanGoyal1)! - changed default password error message for `start-database` script\n\n## 7.36.1\n\n### Patch Changes\n\n- [#1937](https://github.com/t3-oss/create-t3-app/pull/1937) [`5a0cbc53afb8597d6da2bc6d184ea1427e741cec`](https://github.com/t3-oss/create-t3-app/commit/5a0cbc53afb8597d6da2bc6d184ea1427e741cec) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: dependency bumps\n\n## 7.36.0\n\n### Minor Changes\n\n- [#1932](https://github.com/t3-oss/create-t3-app/pull/1932) [`42a485a29370fbfe4f03e5f756d97c0fee0b09e8`](https://github.com/t3-oss/create-t3-app/commit/42a485a29370fbfe4f03e5f756d97c0fee0b09e8) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add trpc rsc prefetching\n\n### Patch Changes\n\n- [#1934](https://github.com/t3-oss/create-t3-app/pull/1934) [`1cfbb117c892905ea956a597aa6d48e9984b1190`](https://github.com/t3-oss/create-t3-app/commit/1cfbb117c892905ea956a597aa6d48e9984b1190) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - remove duplicate `<main>` tags\n\n- [#1931](https://github.com/t3-oss/create-t3-app/pull/1931) [`a1a4b8707b95b82e755733b2853ac595bb9d4829`](https://github.com/t3-oss/create-t3-app/commit/a1a4b8707b95b82e755733b2853ac595bb9d4829) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: unify drizlze schema and fix sqlite timestamps\n\n## 7.35.0\n\n### Minor Changes\n\n- [#1905](https://github.com/t3-oss/create-t3-app/pull/1905) [`b22e2e10d005689faa7b1db771a217b59c88635f`](https://github.com/t3-oss/create-t3-app/commit/b22e2e10d005689faa7b1db771a217b59c88635f) Thanks [@jessedelira](https://github.com/jessedelira)! - Add .idea to .gitignore\n\n### Patch Changes\n\n- [#1909](https://github.com/t3-oss/create-t3-app/pull/1909) [`f69fa29733d3bd0d6e5043d1200e250a938b6335`](https://github.com/t3-oss/create-t3-app/commit/f69fa29733d3bd0d6e5043d1200e250a938b6335) Thanks [@TheDevilOnLine](https://github.com/TheDevilOnLine)! - fix: Added $defaultFn to the user table's id field when using Drizzle to fix #1906\n\n## 7.34.0\n\n### Minor Changes\n\n- [#1893](https://github.com/t3-oss/create-t3-app/pull/1893) [`1925236bcfcafc6c490319ab5f07b2a698e88ef5`](https://github.com/t3-oss/create-t3-app/commit/1925236bcfcafc6c490319ab5f07b2a698e88ef5) Thanks [@brandon93s](https://github.com/brandon93s)! - Add `db:generate` and `db:migrate` scripts to drizzle and prisma installers\n\n### Patch Changes\n\n- [#1891](https://github.com/t3-oss/create-t3-app/pull/1891) [`4236f0dfa969ff0d8b7ce2a60b5595c43ced9043`](https://github.com/t3-oss/create-t3-app/commit/4236f0dfa969ff0d8b7ce2a60b5595c43ced9043) Thanks [@thecmdrunner](https://github.com/thecmdrunner)! - Apply drizzle rules for `ctx.db` object in tRPC context\n\n## 7.33.1\n\n### Patch Changes\n\n- [#1884](https://github.com/t3-oss/create-t3-app/pull/1884) [`f148deb`](https://github.com/t3-oss/create-t3-app/commit/f148debf74e16b61dae89c684fbc9ac1d97ac2c8) Thanks [@Irere123](https://github.com/Irere123)! - fix: remove deprecated push command in drizzle package.json scripts (…\n  )\n\n## 7.33.0\n\n### Minor Changes\n\n- [#1821](https://github.com/t3-oss/create-t3-app/pull/1821) [`4de1927`](https://github.com/t3-oss/create-t3-app/commit/4de1927489aa2d0cf61313ea1543f85268c0e645) Thanks [@kakeWasTaken](https://github.com/kakeWasTaken)! - change default font from Inter to Geist Sans\n\n### Patch Changes\n\n- [#1881](https://github.com/t3-oss/create-t3-app/pull/1881) [`9e5e7d0`](https://github.com/t3-oss/create-t3-app/commit/9e5e7d0c4342542fec18fdc97552b494fe31f5a3) Thanks [@gcjbr](https://github.com/gcjbr)! - chore: update `drizzle-kit` to `0.21.0`\n\n## 7.32.1\n\n### Patch Changes\n\n- [#1867](https://github.com/t3-oss/create-t3-app/pull/1867) [`304a67f`](https://github.com/t3-oss/create-t3-app/commit/304a67f5bde05116b143c86588546af02e86cfda) Thanks [@xelacast](https://github.com/xelacast)! - Parsed --dbprovider flag correctly and added related error message\n\n- [#1860](https://github.com/t3-oss/create-t3-app/pull/1860) [`b5ced34`](https://github.com/t3-oss/create-t3-app/commit/b5ced343f8a7fbc889a113ec05bef6c5e550cd55) Thanks [@victor-falcon](https://github.com/victor-falcon)! - Load PORT in start-database script\n\n- [#1871](https://github.com/t3-oss/create-t3-app/pull/1871) [`f29a69f`](https://github.com/t3-oss/create-t3-app/commit/f29a69fcc300db539fe0cfa9f52858551e89b869) Thanks [@xelacast](https://github.com/xelacast)! - Fixed project creation of . bug in ./start-database.sh\n\n- [#1858](https://github.com/t3-oss/create-t3-app/pull/1858) [`29348b6`](https://github.com/t3-oss/create-t3-app/commit/29348b6b4f11d7f19915be6639e3c5aaa27b8907) Thanks [@lcabraja](https://github.com/lcabraja)! - Added drizzle's db.sqlite location to .gitignore\n\n## 7.32.0\n\n### Minor Changes\n\n- [#1842](https://github.com/t3-oss/create-t3-app/pull/1842) [`088a773`](https://github.com/t3-oss/create-t3-app/commit/088a773103a03e0ec34cbe22329ead33cd80c5ff) Thanks [@nick22985](https://github.com/nick22985)! - Infers tRPC input & output types to the client for app router\n\n- [#1841](https://github.com/t3-oss/create-t3-app/pull/1841) [`41bd524`](https://github.com/t3-oss/create-t3-app/commit/41bd5240276f1029633cde588b0ca08301c4e78c) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - mark app router as stable\n\n### Patch Changes\n\n- [#1838](https://github.com/t3-oss/create-t3-app/pull/1838) [`ff886b3`](https://github.com/t3-oss/create-t3-app/commit/ff886b3fed4b193b8fc85882a71c7e8085457cf0) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - bump zod and t3-env\n\n## 7.31.0\n\n### Minor Changes\n\n- [#1830](https://github.com/t3-oss/create-t3-app/pull/1830) [`3257d0a`](https://github.com/t3-oss/create-t3-app/commit/3257d0a2fe73847b501bdf36f09053638b4a41a4) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: replace better-sqlite3 with libsql\n\n### Patch Changes\n\n- [`ab5fa95`](https://github.com/t3-oss/create-t3-app/commit/ab5fa95afce2a0feb8567aed6bb02beeef1401e5) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: pin zod version\n\n- [#1835](https://github.com/t3-oss/create-t3-app/pull/1835) [`f66e30a`](https://github.com/t3-oss/create-t3-app/commit/f66e30a0c84eb4f74182d79b23e3c5e900788e10) Thanks [@Inshiku-Han](https://github.com/Inshiku-Han)! - Only install @trpc/next when router style is page router\n\n## 7.30.2\n\n### Patch Changes\n\n- [#1817](https://github.com/t3-oss/create-t3-app/pull/1817) [`d49300a`](https://github.com/t3-oss/create-t3-app/commit/d49300a4230835f6a771ed1a6b759c61c8902d7e) Thanks [@kxzazz](https://github.com/kxzazz)! - fix: `start-database.sh` is marked optional\n\n- [#1823](https://github.com/t3-oss/create-t3-app/pull/1823) [`f5c5db9`](https://github.com/t3-oss/create-t3-app/commit/f5c5db99dbd86010369b26e55dd65973ccd0db05) Thanks [@t3dotgg](https://github.com/t3dotgg)! - chore: update next to 14.2.1\n\n## 7.30.1\n\n### Patch Changes\n\n- [#1802](https://github.com/t3-oss/create-t3-app/pull/1802) [`41380d1`](https://github.com/t3-oss/create-t3-app/commit/41380d1cbf29418c3d60a2dcefd3eaf3f7e7bc28) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix: non planetscale env.js refers to YOUR_MYSQL_URL_HERE\n\n- [#1808](https://github.com/t3-oss/create-t3-app/pull/1808) [`fedd7b3`](https://github.com/t3-oss/create-t3-app/commit/fedd7b3926540fdf3137f327cac917237a438943) Thanks [@thecmdrunner](https://github.com/thecmdrunner)! - Apply drizzle-orm lint rules for `db` keyword only\n\n## 7.30.0\n\n### Minor Changes\n\n- [#1741](https://github.com/t3-oss/create-t3-app/pull/1741) [`5de586d`](https://github.com/t3-oss/create-t3-app/commit/5de586da1933064c9eef84ddae47d795e71afc53) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: use trpc 11\n\n## 7.29.0\n\n### Minor Changes\n\n- [#1785](https://github.com/t3-oss/create-t3-app/pull/1785) [`57dc6ab`](https://github.com/t3-oss/create-t3-app/commit/57dc6ab0625d7cd56bf8f6b5c4d3b844421ffe48) Thanks [@thecmdrunner](https://github.com/thecmdrunner)! - Include ESLlint rules for `drizzle-orm`.\n\n- [#1794](https://github.com/t3-oss/create-t3-app/pull/1794) [`3cca996`](https://github.com/t3-oss/create-t3-app/commit/3cca9965739d29cc010e586406d40fff471a9bed) Thanks [@thecmdrunner](https://github.com/thecmdrunner)! - Use portable shebangs in scripts for nix systems\n\n## 7.28.0\n\n### Minor Changes\n\n- [#1777](https://github.com/t3-oss/create-t3-app/pull/1777) [`640a0e0`](https://github.com/t3-oss/create-t3-app/commit/640a0e086d1515f4f88315d3295b44296fe7bbd0) Thanks [@limegorilla](https://github.com/limegorilla)! - Warning about planetscale's serverless driver now only shown if using mySQL\n\n### Patch Changes\n\n- [#1778](https://github.com/t3-oss/create-t3-app/pull/1778) [`01badfb`](https://github.com/t3-oss/create-t3-app/commit/01badfb38caec5d0d211d7f93c6e288d55f2a751) Thanks [@DerTimonius](https://github.com/DerTimonius)! - fix: add missing default font in pagesDir\n\n- [#1766](https://github.com/t3-oss/create-t3-app/pull/1766) [`d7695df`](https://github.com/t3-oss/create-t3-app/commit/d7695df89a77ea5add1d703b63b9aeda5b5ef0c5) Thanks [@fuegoio](https://github.com/fuegoio)! - fix: cache database connection during development to prevent `Too many connections` due to HMR\n\n## 7.27.0\n\n### Minor Changes\n\n- [#1773](https://github.com/t3-oss/create-t3-app/pull/1773) [`8f29eb9`](https://github.com/t3-oss/create-t3-app/commit/8f29eb990ccbc36c018ce596d2de0205b3c7edac) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat(prisma): support correct typings when using `.extends()`\n\n### Patch Changes\n\n- [#1774](https://github.com/t3-oss/create-t3-app/pull/1774) [`0418663`](https://github.com/t3-oss/create-t3-app/commit/0418663ec6cc370ed1e067f1ef68f0d5ca41af53) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: update drizzle-orm\n\n- [#1763](https://github.com/t3-oss/create-t3-app/pull/1763) [`836fccf`](https://github.com/t3-oss/create-t3-app/commit/836fccf22dc224e283a764649c16090e4ba42b18) Thanks [@skullface](https://github.com/skullface)! - fix: correct casing of “PlanetScale”\n\n- [#1764](https://github.com/t3-oss/create-t3-app/pull/1764) [`79e361c`](https://github.com/t3-oss/create-t3-app/commit/79e361cfd8ad0740a353c7712cad8d38cbc8ee7b) Thanks [@vlxm](https://github.com/vlxm)! - fix: fix password substitution in start-database scripts\n\n- [#1769](https://github.com/t3-oss/create-t3-app/pull/1769) [`c944c49`](https://github.com/t3-oss/create-t3-app/commit/c944c490522a3fb921d564ab55eecd8c535142c3) Thanks [@jhamill34](https://github.com/jhamill34)! - fix: generated comments in env file\n\n- [#1772](https://github.com/t3-oss/create-t3-app/pull/1772) [`c3c4710`](https://github.com/t3-oss/create-t3-app/commit/c3c4710b2e7e6245c0afae45e1a5119d91cb9578) Thanks [@mladenovic-13](https://github.com/mladenovic-13)! - fix: use singleton pattern for client-side QueryClient to support `useSuspenseQuery` when there is no parent `<Suspense>`-element\n\n- [#1748](https://github.com/t3-oss/create-t3-app/pull/1748) [`17c2a5e`](https://github.com/t3-oss/create-t3-app/commit/17c2a5eb52a7faff7ea9e1d1a6270c2216235ff2) Thanks [@aaronmallen](https://github.com/aaronmallen)! - add missing `pg` dev dependency when using postgres drizzle option, required for `drizzle-studio`\n\n## 7.26.0\n\n### Minor Changes\n\n- [#1622](https://github.com/t3-oss/create-t3-app/pull/1622) [`06b1bca`](https://github.com/t3-oss/create-t3-app/commit/06b1bcafe8751a0fc3cfb7992dfb12cb88bf0234) Thanks [@ronanru](https://github.com/ronanru)! - add more db options\n\n## 7.25.2\n\n### Patch Changes\n\n- [#1723](https://github.com/t3-oss/create-t3-app/pull/1723) [`c116281`](https://github.com/t3-oss/create-t3-app/commit/c116281f3626ae5f05191037789d7338a8fa2e5c) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: don't pass cookies to CC\n\n- [#1728](https://github.com/t3-oss/create-t3-app/pull/1728) [`06ec5b3`](https://github.com/t3-oss/create-t3-app/commit/06ec5b37784c305d18a775b64d34cecb5de45bf2) Thanks [@Nsttt](https://github.com/Nsttt)! - fix missuse of binary expressions\n\n## 7.25.1\n\n### Patch Changes\n\n- [#1713](https://github.com/t3-oss/create-t3-app/pull/1713) [`e34b082`](https://github.com/t3-oss/create-t3-app/commit/e34b08245cc3c1288f90b289577e7c18b37acb1c) Thanks [@daikiejp](https://github.com/daikiejp)! - remove unused @types/inquirer\n\n- [#1703](https://github.com/t3-oss/create-t3-app/pull/1703) [`b6ccded`](https://github.com/t3-oss/create-t3-app/commit/b6ccdedd11b22b64e7bb6f1c55997362fa2915a4) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - update eslint setup for next 14.0.4\n\n- [#1714](https://github.com/t3-oss/create-t3-app/pull/1714) [`ba352ef`](https://github.com/t3-oss/create-t3-app/commit/ba352ef73823eb6413cf251bd7111db6fcb3a585) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: update drizzle dep to remove invalid expo peerDep\n\n- [#1707](https://github.com/t3-oss/create-t3-app/pull/1707) [`26efe48`](https://github.com/t3-oss/create-t3-app/commit/26efe482bdcb309796a2bf207c50ebc844233106) Thanks [@esize](https://github.com/esize)! - chore: update drizzle-orm and drizzle-kit\n\n- [#1708](https://github.com/t3-oss/create-t3-app/pull/1708) [`8f379b4`](https://github.com/t3-oss/create-t3-app/commit/8f379b4df75e56b98973aabcc2097b62be80d0c7) Thanks [@KATT](https://github.com/KATT)! - chore: drop `t.middleware()`\n\n## 7.25.0\n\n### Minor Changes\n\n- [#1702](https://github.com/t3-oss/create-t3-app/pull/1702) [`62fa8dc`](https://github.com/t3-oss/create-t3-app/commit/62fa8dcad2e0d3d6bad04bb6167d7580a754049c) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - update drizzle-kit and change connectionString to uri\n\n### Patch Changes\n\n- [#1690](https://github.com/t3-oss/create-t3-app/pull/1690) [`6efb99a`](https://github.com/t3-oss/create-t3-app/commit/6efb99a94f29d28243fa7c625b099995e84e4db2) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix typo in env.mjs\n\n## 7.24.2\n\n### Patch Changes\n\n- [#1687](https://github.com/t3-oss/create-t3-app/pull/1687) [`6461090`](https://github.com/t3-oss/create-t3-app/commit/6461090a029dd2094065493e513a289a1b414673) Thanks [@sinasab](https://github.com/sinasab)! - chore: reuse existing AppRouter type #1687\n\n## 7.24.1\n\n### Patch Changes\n\n- [#1673](https://github.com/t3-oss/create-t3-app/pull/1673) [`b80188e`](https://github.com/t3-oss/create-t3-app/commit/b80188eaecc64e564909ed7ee566790f5e56e59f) Thanks [@ahkhanjani](https://github.com/ahkhanjani)! - fix: Use the correct types for `prettier-plugin-tailwindcss`\n\n## 7.24.0\n\n### Minor Changes\n\n- [#1670](https://github.com/t3-oss/create-t3-app/pull/1670) [`32e0747`](https://github.com/t3-oss/create-t3-app/commit/32e0747a027be16cc36ad5bead062eea696e4012) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: trpc server caller without http\n\n### Patch Changes\n\n- [#1661](https://github.com/t3-oss/create-t3-app/pull/1661) [`ef8f99f`](https://github.com/t3-oss/create-t3-app/commit/ef8f99f65443e48284bc54699eeddc9d10c43a8c) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - update sharp\n\n- [#1667](https://github.com/t3-oss/create-t3-app/pull/1667) [`43cc10b`](https://github.com/t3-oss/create-t3-app/commit/43cc10b0e4ddd6c1b3eb175309df3aebe0571285) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump some deps\n\n- [#1666](https://github.com/t3-oss/create-t3-app/pull/1666) [`3317a41`](https://github.com/t3-oss/create-t3-app/commit/3317a41546728509543d8fc44a8fe715b04f09e8) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - refactor: use `type: module` for more modern setup\n\n- [#1664](https://github.com/t3-oss/create-t3-app/pull/1664) [`66213b0`](https://github.com/t3-oss/create-t3-app/commit/66213b04cf03fd7d4d0602bbb34a3de2ab703daa) Thanks [@piousdeer](https://github.com/piousdeer)! - chore: replace a `2` with `\"error\"` in eslint config\n\n## 7.23.2\n\n### Patch Changes\n\n- [#1651](https://github.com/t3-oss/create-t3-app/pull/1651) [`4834ec3`](https://github.com/t3-oss/create-t3-app/commit/4834ec3cd16c8dba4be1bcd2a9b162c37a0bc7d2) Thanks [@mattpocock](https://github.com/mattpocock)! - tidy up and modernize tsconfig\n\n## 7.23.1\n\n### Patch Changes\n\n- [#1644](https://github.com/t3-oss/create-t3-app/pull/1644) [`e6649f1`](https://github.com/t3-oss/create-t3-app/commit/e6649f18963086b2d016815e60cc9915711a85d8) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: only forward required cookie header\n\n## 7.23.0\n\n### Minor Changes\n\n- [#1628](https://github.com/t3-oss/create-t3-app/pull/1628) [`57a82d2`](https://github.com/t3-oss/create-t3-app/commit/57a82d2f4c1a34068280a1f01c1f2618af260650) Thanks [@CarlosZiegler](https://github.com/CarlosZiegler)! - Update Next to use last version (14.0.0)\n\n## 7.22.0\n\n### Minor Changes\n\n- [#1567](https://github.com/t3-oss/create-t3-app/pull/1567) [`e71bedd`](https://github.com/t3-oss/create-t3-app/commit/e71bedde0d6944fa7719a5f97cd27a1503156faa) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add app router option\n\n- [#1595](https://github.com/t3-oss/create-t3-app/pull/1595) [`d7824e0`](https://github.com/t3-oss/create-t3-app/commit/d7824e0e2523703662b731945229e2fae88708ae) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - show callout when scaffolding with app router\n\n## 7.21.0\n\n### Minor Changes\n\n- [#1584](https://github.com/t3-oss/create-t3-app/pull/1584) [`9614d84`](https://github.com/t3-oss/create-t3-app/commit/9614d8424d810278facf012fb99d1da51d2238e6) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - bump deps and add `emptyStringAsUndefined` option for `t3-env`\n\n## 7.20.2\n\n### Patch Changes\n\n- [#1564](https://github.com/t3-oss/create-t3-app/pull/1564) [`58ee08e`](https://github.com/t3-oss/create-t3-app/commit/58ee08e850d985b5ef1b7e5bf0cc164cfaff3f3f) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: block drizzle apps when the example database url hasn't been changed yet\n\n## 7.20.1\n\n### Patch Changes\n\n- [#1561](https://github.com/t3-oss/create-t3-app/pull/1561) [`b8507dc`](https://github.com/t3-oss/create-t3-app/commit/b8507dc64ee91b8423de2ab6145cb3e7d8072528) Thanks [@Nsttt](https://github.com/Nsttt)! - Add packageManager field in package.json at app creation\n\n## 7.20.0\n\n### Minor Changes\n\n- [#1461](https://github.com/t3-oss/create-t3-app/pull/1461) [`8034db0`](https://github.com/t3-oss/create-t3-app/commit/8034db042b9ed12f5ba01c1f779c5ee77d78afc4) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add drizzle\n\n  This release adds a new option to use [`drizzle-orm`](https://orm.drizzle.team/docs/overview) as an alternative to Prisma.\n\n  To make the different ORM options as similar as possible, some minor changes has also been made to the Prisma installer:\n\n  - a new script `db:push` has been added and is included in both ORM options.\n  - the prisma client has been renamed to `db` in the trpc context - you now access your database client like\n    ```ts\n    examples: publicProcedure.query((opts) => {\n       // prisma\n       opts.ctx.db.example.findMany()\n       // drizzle\n       opts.ctx.db.query.example.findMany()\n    }),\n    ```\n\n  You cannot choose the two options in the same app.\n\n### Patch Changes\n\n- [#1461](https://github.com/t3-oss/create-t3-app/pull/1461) [`8034db0`](https://github.com/t3-oss/create-t3-app/commit/8034db042b9ed12f5ba01c1f779c5ee77d78afc4) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - refactor: swap inquirer for clack\n\n## 7.19.0\n\n### Minor Changes\n\n- [#1375](https://github.com/t3-oss/create-t3-app/pull/1375) [`d781f08`](https://github.com/t3-oss/create-t3-app/commit/d781f0861ba05aee6b3d460fc53e126868409fb5) Thanks [@Zeko369](https://github.com/Zeko369)! - feat: detect and support usage of Bun as package manager\n\n## 7.18.0\n\n### Minor Changes\n\n- [#1532](https://github.com/t3-oss/create-t3-app/pull/1532) [`941a0fc`](https://github.com/t3-oss/create-t3-app/commit/941a0fc79bcfb24c894525c93aab87c2860b2ad4) Thanks [@spicybackend](https://github.com/spicybackend)! - chore(deps): upgrade Prisma to v5.1.1, bump patch versions of other dependencies\n\n- [#1507](https://github.com/t3-oss/create-t3-app/pull/1507) [`fe5755c`](https://github.com/t3-oss/create-t3-app/commit/fe5755c2d575ce27e8e9c86e6fc79e7903af0390) Thanks [@LevinUncu](https://github.com/LevinUncu)! - If the project is not in a Git repo, the next steps will show git init instead of git commit -m \"initial commit\".\n\n## 7.17.0\n\n### Minor Changes\n\n- [#1523](https://github.com/t3-oss/create-t3-app/pull/1523) [`c441a9e`](https://github.com/t3-oss/create-t3-app/commit/c441a9ecfaeb61866a76379712b297fc6c2c36b3) Thanks [@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)! - reduced stylistic linting\n\n## 7.16.0\n\n### Minor Changes\n\n- [#1476](https://github.com/t3-oss/create-t3-app/pull/1476) [`f3fd50f`](https://github.com/t3-oss/create-t3-app/commit/f3fd50fbd5dfd705507b1a2b53e8e6fd39b2dadb) Thanks [@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)! - Upgraded typescript-eslint to v6, with reworked ESLint configurations\n\n- [#1508](https://github.com/t3-oss/create-t3-app/pull/1508) [`e9c862e`](https://github.com/t3-oss/create-t3-app/commit/e9c862e7e114214139f05572d62af45d87d3fc1c) Thanks [@Sn0wye](https://github.com/Sn0wye)! - chore(deps): bump prisma to v5.0.0\n\n## 7.15.0\n\n### Minor Changes\n\n- [#1484](https://github.com/t3-oss/create-t3-app/pull/1484) [`23a9d60`](https://github.com/t3-oss/create-t3-app/commit/23a9d60cd013c40d76ab96d0340425e1e3d8efa2) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - reminder to git commit after creating an application with the CLI\n\n### Patch Changes\n\n- [#1493](https://github.com/t3-oss/create-t3-app/pull/1493) [`a230d9f`](https://github.com/t3-oss/create-t3-app/commit/a230d9f7bb3a78669f2003ae9084c868f06639b7) Thanks [@dcottr](https://github.com/dcottr)! - Remove trailing newlines in generated app that aren't allowed by the generated prettier config\n\n## 7.14.1\n\n### Patch Changes\n\n- [#1479](https://github.com/t3-oss/create-t3-app/pull/1479) [`bb7324c`](https://github.com/t3-oss/create-t3-app/commit/bb7324c9503995949c61c0a5abe736c38f07b815) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - use custom error class for IsTTYError\n\n## 7.14.0\n\n### Minor Changes\n\n- [#1466](https://github.com/t3-oss/create-t3-app/pull/1466) [`e8b68d9`](https://github.com/t3-oss/create-t3-app/commit/e8b68d92af093361bf73eed7eacd7ed6848500c3) Thanks [@brunoeduardodev](https://github.com/brunoeduardodev)! - Ignore trailing slashes when prompting the app name.\n\n## 7.13.2\n\n### Patch Changes\n\n- [#1469](https://github.com/t3-oss/create-t3-app/pull/1469) [`547f504`](https://github.com/t3-oss/create-t3-app/commit/547f504b91c3da9b6419ea7f9f43d03e6c243839) Thanks [@ericshively](https://github.com/ericshively)! - Replace React.FC with basic function syntax\n\n## 7.13.1\n\n### Patch Changes\n\n- [#1436](https://github.com/t3-oss/create-t3-app/pull/1436) [`b0facee`](https://github.com/t3-oss/create-t3-app/commit/b0facee2736e3e0afc909c3d80b38499174fd84c) Thanks [@harrismcc](https://github.com/harrismcc)! - When using NextAuth but not Prisma, the session user's id is now set to `token.sub` instead of `user.id` because `user` is undefined when not using database sessions.\n\n- [#1433](https://github.com/t3-oss/create-t3-app/pull/1433) [`7fbe991`](https://github.com/t3-oss/create-t3-app/commit/7fbe991175f4da02184e0e43a5439515d1ef7439) Thanks [@FinnDore](https://github.com/FinnDore)! - fix: SKIP_ENV_VALIDATION not skipping env validation\n\n## 7.13.0\n\n### Minor Changes\n\n- [#1397](https://github.com/t3-oss/create-t3-app/pull/1397) [`be9a834`](https://github.com/t3-oss/create-t3-app/commit/be9a83483339f8bb799be7a3d69cf67e64882daf) Thanks [@brieyla1](https://github.com/brieyla1)! - feat: Added JsonProtocol as the Default Prisma Engine for Serverless speedups\n\n  modified:\n\n      - cli/template/extras/prisma/schema/base.prisma\n\n      - cli/template/extras/prisma/schema/with-auth.prisma\n\n  Description: This pull request proposes the enabling of the JsonProtocol by default. The rationale for this change is based on the performance improvements provided by the JsonProtocol without compromising stability, even though it is still a preview feature. Empirical evidence gathered from large-scale projects, with 100+ Prisma calls, demonstrates the significant time reductions enabled by this optimization, particularly in serverless environments such as Vercel. Another point worth adding is that most projects using nextJS create-t3-app will be deployed on serverless platforms such as vercel, where the real impact is.\n\n## 7.12.3\n\n### Patch Changes\n\n- [#1404](https://github.com/t3-oss/create-t3-app/pull/1404) [`48dd89a`](https://github.com/t3-oss/create-t3-app/commit/48dd89adb33ff9625dba82f6e149cf111f02e488) Thanks [@michalbundyra](https://github.com/michalbundyra)! - update nextjs dependency to ^13.4.1\n\n## 7.12.2\n\n### Patch Changes\n\n- [#1401](https://github.com/t3-oss/create-t3-app/pull/1401) [`b1a35dd`](https://github.com/t3-oss/create-t3-app/commit/b1a35dd66c5c9abab13daebfee93c08b67317272) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - temporarily pin next to fix vercel build error\n\n## 7.12.1\n\n### Patch Changes\n\n- [#1377](https://github.com/t3-oss/create-t3-app/pull/1377) [`00018ff`](https://github.com/t3-oss/create-t3-app/commit/00018ff0cbe5904f0bb37b8cb0a64814ca5f9410) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - move env validation logic out to a separate package\n\n- [#1385](https://github.com/t3-oss/create-t3-app/pull/1385) [`ac12abb`](https://github.com/t3-oss/create-t3-app/commit/ac12abb92a77d251b2c4bc72caceb422ab4ca706) Thanks [@iAverages](https://github.com/iAverages)! - Fixed issue with creating git repository with git versions below 2.28\n  Fixed bug with check to use --inital-branch set in git v2.28\n\n## 7.12.0\n\n### Minor Changes\n\n- [#1370](https://github.com/t3-oss/create-t3-app/pull/1370) [`18bc6a7`](https://github.com/t3-oss/create-t3-app/commit/18bc6a73a77b0b48191792ddfd0c296b58cc8221) Thanks [@chungweileong94](https://github.com/chungweileong94)! - Enforce `NEXT_PUBLIC_` env key on client\n\n## 7.11.0\n\n### Minor Changes\n\n- [#1358](https://github.com/t3-oss/create-t3-app/pull/1358) [`1a8a97e`](https://github.com/t3-oss/create-t3-app/commit/1a8a97e42b8991596fc70e50dd6870c987a59075) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - improve boolean coercion of `SKIP_ENV_VALIDATION` environment variable\n\n  If defined, \"0\" and \"false\" are now considered falsey values, all other values are considered truthy.\n\n### Patch Changes\n\n- [#1352](https://github.com/t3-oss/create-t3-app/pull/1352) [`c48b38f`](https://github.com/t3-oss/create-t3-app/commit/c48b38f522b81097e2f0e883ede053dbac620c12) Thanks [@Tungetyt](https://github.com/Tungetyt)! - refactor: make destructuring consistent\n\n## 7.10.3\n\n### Patch Changes\n\n- [#1330](https://github.com/t3-oss/create-t3-app/pull/1330) [`85997e0`](https://github.com/t3-oss/create-t3-app/commit/85997e0cc26a2ae6fbcd08458734bd6335ba467a) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: create a new object for the session callback\n\n## 7.10.2\n\n### Patch Changes\n\n- [#1329](https://github.com/t3-oss/create-t3-app/pull/1329) [`5429989`](https://github.com/t3-oss/create-t3-app/commit/54299895517d3c406637efec8f0512cf1ba2da5a) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - temporarily pin next-auth version\n\n- [#1321](https://github.com/t3-oss/create-t3-app/pull/1321) [`7fcb41c`](https://github.com/t3-oss/create-t3-app/commit/7fcb41c95d24567040b72409a576d8c694f910a1) Thanks [@JingLi1998](https://github.com/JingLi1998)! - Update the type for global prisma instance\n\n## 7.10.1\n\n### Patch Changes\n\n- [#1312](https://github.com/t3-oss/create-t3-app/pull/1312) [`2fb3a51`](https://github.com/t3-oss/create-t3-app/commit/2fb3a51b8b91cf2eb992a3af49ff52588f1e9c95) Thanks [@FinnDore](https://github.com/FinnDore)! - feat: bumped tailwind from 3.2.7 -> 3.3.0\n\n## 7.10.0\n\n### Minor Changes\n\n- [#1295](https://github.com/t3-oss/create-t3-app/pull/1295) [`d0a8143`](https://github.com/t3-oss/create-t3-app/commit/d0a8143587c935819790521533e7cfa0862d300c) Thanks [@iAverages](https://github.com/iAverages)! - Replace Git Bash check with Mintty check\n\n### Patch Changes\n\n- [#1304](https://github.com/t3-oss/create-t3-app/pull/1304) [`2cb41e6`](https://github.com/t3-oss/create-t3-app/commit/2cb41e676f01d4e8bfb8c7fc41bf0d5c4a1c0689) Thanks [@PiotrekPKP](https://github.com/PiotrekPKP)! - fix: replace trpc links\n\n## 7.9.0\n\n### Minor Changes\n\n- [#1284](https://github.com/t3-oss/create-t3-app/pull/1284) [`a2af1a2`](https://github.com/t3-oss/create-t3-app/commit/a2af1a2b7d4fd3005f8efe0e297b871d6b1747ff) Thanks [@michalbundyra](https://github.com/michalbundyra)! - chore: bump typescript - 5.0.2\n\n## 7.8.0\n\n### Minor Changes\n\n- [#1273](https://github.com/t3-oss/create-t3-app/pull/1273) [`10a5e0b`](https://github.com/t3-oss/create-t3-app/commit/10a5e0b2fe91b887526960515c6422791a77c724) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add errorformatter for zod errors\n\n### Patch Changes\n\n- [#1263](https://github.com/t3-oss/create-t3-app/pull/1263) [`8dc6e33`](https://github.com/t3-oss/create-t3-app/commit/8dc6e33ea149851de97f84e8d8388accdd5547d9) Thanks [@mkreuzmayr](https://github.com/mkreuzmayr)! - search for tsconfig relative to eslintrc\n\n- [#1279](https://github.com/t3-oss/create-t3-app/pull/1279) [`ae5cd40`](https://github.com/t3-oss/create-t3-app/commit/ae5cd405c9d5bb672e3971c496d437a7a05b3f8f) Thanks [@arielconti10](https://github.com/arielconti10)! - fix: remove //@ts-check comment in next.config\n\n## 7.7.0\n\n### Minor Changes\n\n- [#1268](https://github.com/t3-oss/create-t3-app/pull/1268) [`db394ed`](https://github.com/t3-oss/create-t3-app/commit/db394edf396288dd754f5743ae2fe26a39c70ef5) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - ignore unused vars that begin with underscore\n\n## 7.6.0\n\n### Minor Changes\n\n- [#1255](https://github.com/t3-oss/create-t3-app/pull/1255) [`601cbb2`](https://github.com/t3-oss/create-t3-app/commit/601cbb23075cd33170c5b3ea2b1b0dbb0f2d5716) Thanks [@justasam](https://github.com/justasam)! - Add import alias validation\n\n## 7.5.9\n\n### Patch Changes\n\n- [#1252](https://github.com/t3-oss/create-t3-app/pull/1252) [`d8be181`](https://github.com/t3-oss/create-t3-app/commit/d8be181fd71dafba8c4c1358fea38b70bca8171a) Thanks [@ggrochow](https://github.com/ggrochow)! - Rename \\_eslint.cjs before intializing git repo to ensure .eslint.cjs is added by default\n\n## 7.5.8\n\n### Patch Changes\n\n- [#1249](https://github.com/t3-oss/create-t3-app/pull/1249) [`2432d76`](https://github.com/t3-oss/create-t3-app/commit/2432d76acb337e215743e712d12969b141b22879) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump nextjs\n\n## 7.5.7\n\n### Patch Changes\n\n- [#1232](https://github.com/t3-oss/create-t3-app/pull/1232) [`9c82f86`](https://github.com/t3-oss/create-t3-app/commit/9c82f862f5f5227c48e355a8fc31f83d88b0baeb) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: bind configs to variables before exporting to make sure typeerrors are reported\n\n## 7.5.6\n\n### Patch Changes\n\n- [#1222](https://github.com/t3-oss/create-t3-app/pull/1222) [`7baa339`](https://github.com/t3-oss/create-t3-app/commit/7baa339b36b40760443083e0a378d8fe04dddb40) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: detect and handle git bash environment\n\n## 7.5.5\n\n### Patch Changes\n\n- [#1218](https://github.com/t3-oss/create-t3-app/pull/1218) [`4f8d41a`](https://github.com/t3-oss/create-t3-app/commit/4f8d41ae2f41bef197cab13a332034e0ddffc955) Thanks [@bai](https://github.com/bai)! - feat: change eslint config to use `.cjs` format and typecheck it\n\n- [#1217](https://github.com/t3-oss/create-t3-app/pull/1217) [`55c87af`](https://github.com/t3-oss/create-t3-app/commit/55c87af37f64fbf778a5091b9cca75f9c9546468) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: add autofix to eslint type rule\n\n## 7.5.4\n\n### Patch Changes\n\n- [#1191](https://github.com/t3-oss/create-t3-app/pull/1191) [`aabb9a4`](https://github.com/t3-oss/create-t3-app/commit/aabb9a41aa8acce4b3b02e2341b83cd78b802924) Thanks [@bai](https://github.com/bai)! - Use ~/\\* import alias\n\n## 7.5.3\n\n### Patch Changes\n\n- [#1213](https://github.com/t3-oss/create-t3-app/pull/1213) [`ab3c7cb`](https://github.com/t3-oss/create-t3-app/commit/ab3c7cb4d4e78ab646a645bc28b4fe3496ba7831) Thanks [@michalbundyra](https://github.com/michalbundyra)! - fix: update comment regarding schema definition of env vars\n\n## 7.5.2\n\n### Patch Changes\n\n- [#1189](https://github.com/t3-oss/create-t3-app/pull/1189) [`bf12635`](https://github.com/t3-oss/create-t3-app/commit/bf1263576866116a904f3d1fa741c5496a535cb9) Thanks [@p13lgst](https://github.com/p13lgst)! - fix: remove ts-ignores on env.mjs\n\n## 7.5.1\n\n### Patch Changes\n\n- [#1187](https://github.com/t3-oss/create-t3-app/pull/1187) [`e111fb5`](https://github.com/t3-oss/create-t3-app/commit/e111fb5cb816de9b2d87bdf4ffcf84f446fd2023) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - remove old env files\n\n## 7.5.0\n\n### Minor Changes\n\n- [#1092](https://github.com/t3-oss/create-t3-app/pull/1092) [`aa44574`](https://github.com/t3-oss/create-t3-app/commit/aa44574680bf380cf4cf7f255fb547e5d9ced7d7) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - single env file\n\n### Patch Changes\n\n- [#1171](https://github.com/t3-oss/create-t3-app/pull/1171) [`efe8b7f`](https://github.com/t3-oss/create-t3-app/commit/efe8b7f54cf0fe5448dc52118745668ae4913547) Thanks [@esotuvaka](https://github.com/esotuvaka)! - fix: swap `@ts-check` comments to `checkJs: true` in scaffolded app's tsconfig\n\n## 7.4.1\n\n### Patch Changes\n\n- [#1155](https://github.com/t3-oss/create-t3-app/pull/1155) [`90955a5`](https://github.com/t3-oss/create-t3-app/commit/90955a50390eee8a23e1c1b35e10c860e4341fed) Thanks [@christopher-kapic](https://github.com/christopher-kapic)! - Change unstable_getServerSession to match the updated getServerSession from next-auth (introduced in next-auth 4.19.0)\n\n## 7.4.0\n\n### Minor Changes\n\n- [#1136](https://github.com/t3-oss/create-t3-app/pull/1136) [`715f6e8`](https://github.com/t3-oss/create-t3-app/commit/715f6e8e795685c054145149acff427a1b46172f) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: colocate auth config/dts/session-getter into a single file\n\n- [#1134](https://github.com/t3-oss/create-t3-app/pull/1134) [`4cb2e4e`](https://github.com/t3-oss/create-t3-app/commit/4cb2e4e5020f93636889499bf71029ce7fcb5fce) Thanks [@PiotrekPKP](https://github.com/PiotrekPKP)! - feat: added package installation progress\n\n### Patch Changes\n\n- [#1131](https://github.com/t3-oss/create-t3-app/pull/1131) [`ab0790e`](https://github.com/t3-oss/create-t3-app/commit/ab0790e95194291cab65dee458982a2b637a4d15) Thanks [@bastibuck](https://github.com/bastibuck)! - fix: fix types of serverEnv and clientEnv\n\n- [#1140](https://github.com/t3-oss/create-t3-app/pull/1140) [`fc445bf`](https://github.com/t3-oss/create-t3-app/commit/fc445bfaa72e2de2880fb286cee71ff2b26a72a6) Thanks [@Zamiell](https://github.com/Zamiell)! - chore: add descriptive comments and format .env prettier\n\n## 7.3.2\n\n### Patch Changes\n\n- [#1097](https://github.com/t3-oss/create-t3-app/pull/1097) [`2ed36cd`](https://github.com/t3-oss/create-t3-app/commit/2ed36cd624cba2032ba70c465cd47c49a962bb0d) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: bump nextjs and add a note about appDir+i18n being incompat\n\n## 7.3.1\n\n### Patch Changes\n\n- [#1084](https://github.com/t3-oss/create-t3-app/pull/1084) [`7490a34`](https://github.com/t3-oss/create-t3-app/commit/7490a34a3f46d8e912f996843d27ae5933f26164) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix: undo env changes\n\n## 7.3.0\n\n### Minor Changes\n\n- [#1071](https://github.com/t3-oss/create-t3-app/pull/1071) [`34d6c5b`](https://github.com/t3-oss/create-t3-app/commit/34d6c5b0431ea7baa922a27768d0c82b05c12bdc) Thanks [@ JacobADevore](https://github.com/JacobADevore)! - feat: automatically destructure env objects\n\n## 7.2.0\n\n### Minor Changes\n\n- [#1021](https://github.com/t3-oss/create-t3-app/pull/1021) [`78dfdc9`](https://github.com/t3-oss/create-t3-app/commit/78dfdc9b480ea19ac90270827653400e31300e6e) Thanks [@iduuck](https://github.com/iduuck)! - construct `serverEnv`, like we do with `clientEnv` #1000\n\n### Patch Changes\n\n- [#1060](https://github.com/t3-oss/create-t3-app/pull/1060) [`a8cc106`](https://github.com/t3-oss/create-t3-app/commit/a8cc106c3ef507e275f38c09a5d6a7a14336c254) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: cleanup context type in `initTRPC`\n\n## 7.1.0\n\n### Minor Changes\n\n- [#1036](https://github.com/t3-oss/create-t3-app/pull/1036) [`c5ca65e`](https://github.com/t3-oss/create-t3-app/commit/c5ca65e03e2a9d1c3c7f6844eb678402b0fa8993) Thanks [@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)! - use typescript-eslint's recommended-required-type-checking\n\n## 7.0.2\n\n### Patch Changes\n\n- [#1056](https://github.com/t3-oss/create-t3-app/pull/1056) [`c6704fb`](https://github.com/t3-oss/create-t3-app/commit/c6704fbeef1473e77ad62543770f1804645389a8) Thanks [@prashantrahul141](https://github.com/prashantrahul141)! - fix: update `package.json->name` before installing dependencies.\n\n## 7.0.1\n\n### Patch Changes\n\n- [#1043](https://github.com/t3-oss/create-t3-app/pull/1043) [`6fe7e1e`](https://github.com/t3-oss/create-t3-app/commit/6fe7e1e1025f46ea8fe6cc82bee7a68e96864078) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix(cli): exit with error code when aborting installation\n  fix(cli): don't log when scaffolding in current directory and it's empty\n\n## 7.0.0\n\n### Major Changes\n\n- [#934](https://github.com/t3-oss/create-t3-app/pull/934) [`c20ec70`](https://github.com/t3-oss/create-t3-app/commit/c20ec705a6d3d3005da24d072cc9be04370ab822) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat!: implement new folder structure\n\n  create-t3-app has decided to switch out the folder structure of the generated t3-app to, what is to us, a more minimal, logical and easier to understand structure.\n\n## 6.12.0\n\n### Minor Changes\n\n- [#1031](https://github.com/t3-oss/create-t3-app/pull/1031) [`61ba991`](https://github.com/t3-oss/create-t3-app/commit/61ba991ea92f5eb3e971d34769df0ba470310990) Thanks [@complexengine](https://github.com/complexengine)! - The CLI now stages the files on project initialization.\n\n## 6.11.6\n\n### Patch Changes\n\n- [#1024](https://github.com/t3-oss/create-t3-app/pull/1024) [`fcf59b0`](https://github.com/t3-oss/create-t3-app/commit/fcf59b077d80fdf0728ab7a4ea12a4b3b5521da3) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: allow dot name in name prompt\n\n## 6.11.5\n\n### Patch Changes\n\n- [#1010](https://github.com/t3-oss/create-t3-app/pull/1010) [`9eddbab`](https://github.com/t3-oss/create-t3-app/commit/9eddbabb9e045b2a8a668ec1389218020360b305) Thanks [@maxmellen](https://github.com/maxmellen)! - chore(create-t3-app): add @types/prettier package to tailwind installer and bump prettier versions\n\n## 6.11.4\n\n### Patch Changes\n\n- [#981](https://github.com/t3-oss/create-t3-app/pull/981) [`ac32b6d`](https://github.com/t3-oss/create-t3-app/commit/ac32b6d09df6d7b3620a41ace8cd2612bd909cc8) Thanks [@balazsorban44](https://github.com/balazsorban44)! - fix(cli): prompt TS first\n\n## 6.11.3\n\n### Patch Changes\n\n- [#939](https://github.com/t3-oss/create-t3-app/pull/939) [`77cfb4b`](https://github.com/t3-oss/create-t3-app/commit/77cfb4bd156ca3d97cbb70cf51ec8e12a632bd64) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - use next-auth 4.18.3 and undo hotfix\n\n- [#932](https://github.com/t3-oss/create-t3-app/pull/932) [`c04a35a`](https://github.com/t3-oss/create-t3-app/commit/c04a35a2b215c8537cf7f0d9ff9760c831720514) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix next-auth error\n\n## 6.11.2\n\n### Patch Changes\n\n- [#917](https://github.com/t3-oss/create-t3-app/pull/917) [`eb55d19`](https://github.com/t3-oss/create-t3-app/commit/eb55d19ae0204f6e61fb65b82057b93ed485e880) Thanks [@sharkby7e](https://github.com/sharkby7e)! - feat: add blank target to base template\n\n## 6.11.1\n\n### Patch Changes\n\n- [#914](https://github.com/t3-oss/create-t3-app/pull/914) [`1037d14`](https://github.com/t3-oss/create-t3-app/commit/1037d1472764080a5641d657cac75adec2bbd3f1) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - temporarily pin next-auth\n\n## 6.11.0\n\n### Minor Changes\n\n- [#901](https://github.com/t3-oss/create-t3-app/pull/901) [`9b6ae5c`](https://github.com/t3-oss/create-t3-app/commit/9b6ae5cc1c8fe85becd367d36b61828b06a0a6a9) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - include env files in all apps\n\n### Patch Changes\n\n- [#895](https://github.com/t3-oss/create-t3-app/pull/895) [`91362db`](https://github.com/t3-oss/create-t3-app/commit/91362db87a50fe7f09807aa9950acc5c60ba80dc) Thanks [@Mvmo](https://github.com/Mvmo)! - When initializing a new git repo the git config value 'init.defaultBranch' will be used as the branch name\n\n- [#897](https://github.com/t3-oss/create-t3-app/pull/897) [`272b954`](https://github.com/t3-oss/create-t3-app/commit/272b9547f42f70df3c24dc9d438a7cd88a244773) Thanks [@AyanavaKarmakar](https://github.com/AyanavaKarmakar)! - fix(cli): fix wrong prompt when setting up project name\n\n## 6.10.3\n\n### Patch Changes\n\n- [#869](https://github.com/t3-oss/create-t3-app/pull/869) [`cd93b98`](https://github.com/t3-oss/create-t3-app/commit/cd93b98d00e559721da0674b81978a00870e68ff) Thanks [@meech-ward](https://github.com/meech-ward)! - docs: add notes about env vars\n\n- [#878](https://github.com/t3-oss/create-t3-app/pull/878) [`9abaf80`](https://github.com/t3-oss/create-t3-app/commit/9abaf80d20620e3399c3a1ae51e06a41e2990e28) Thanks [@AyanavaKarmakar](https://github.com/AyanavaKarmakar)! - feat: update scaffolded README.md\n\n- [#845](https://github.com/t3-oss/create-t3-app/pull/845) [`c387187`](https://github.com/t3-oss/create-t3-app/commit/c38718768661944807daee92b21aae2789649ecb) Thanks [@GabrielPedroza](https://github.com/gabrielpedroza)! - fix: typo in env-schema comments\n\n## 6.10.2\n\n### Patch Changes\n\n- [#834](https://github.com/t3-oss/create-t3-app/pull/834) [`3ace6c8`](https://github.com/t3-oss/create-t3-app/commit/3ace6c8149b01d68c1503c6b3087f2a8e5ebc865) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - use trpc 10.0.0\n\n## 6.10.1\n\n### Patch Changes\n\n- [#784](https://github.com/t3-oss/create-t3-app/pull/784) [`f10ce0e`](https://github.com/t3-oss/create-t3-app/commit/f10ce0e9badd3ad6ed45b8dca272bdfc5fbfbff6) Thanks [@AyanavaKarmakar](https://github.com/AyanavaKarmakar)! - fix(t3-app): fix broken links\n\n- [#786](https://github.com/t3-oss/create-t3-app/pull/786) [`4d70f04`](https://github.com/t3-oss/create-t3-app/commit/4d70f048955cd75aa67f0ba91fd5cec5d0311d08) Thanks [@skuridin](https://github.com/skuridin)! - Add next-env.d.ts to .gitignore\n\n- [#800](https://github.com/t3-oss/create-t3-app/pull/800) [`d5d5a2f`](https://github.com/t3-oss/create-t3-app/commit/d5d5a2f7503cf9d7c3bfab4609aeb6a0188d6af1) Thanks [@HatulaPro](https://github.com/HatulaPro)! - fix: removing redundant optional chaining in templates\n\n## 6.10.0\n\n### Minor Changes\n\n- [#711](https://github.com/t3-oss/create-t3-app/pull/711) [`da760c7`](https://github.com/t3-oss/create-t3-app/commit/da760c7d4b96fb783ca1621aed933d63f0d51d4e) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - create new index pages\n\n### Patch Changes\n\n- [#754](https://github.com/t3-oss/create-t3-app/pull/754) [`b6cdcb3`](https://github.com/t3-oss/create-t3-app/commit/b6cdcb3f21feeec6153601d420177b0ada490f2e) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - fix: rename example env file\n\n## 6.9.0\n\n### Minor Changes\n\n- [#727](https://github.com/t3-oss/create-t3-app/pull/727) [`57cb2b5`](https://github.com/t3-oss/create-t3-app/commit/57cb2b5881c31182acc6918cf86330dda26d0586) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: add warning message when not using latest\n\n## 6.8.1\n\n### Patch Changes\n\n- [#717](https://github.com/t3-oss/create-t3-app/pull/717) [`7f8e706`](https://github.com/t3-oss/create-t3-app/commit/7f8e70643c3de0ba8c457833a54c4700bd974816) Thanks [@robotkutya](https://github.com/robotkutya)! - feat: update NEXTAUTH_SECRET validator and set a default\n\n- [#719](https://github.com/t3-oss/create-t3-app/pull/719) [`b359802`](https://github.com/t3-oss/create-t3-app/commit/b359802f128297f0048ae587453031d05e49b566) Thanks [@AyanavaKarmakar](https://github.com/AyanavaKarmakar)! - fix: update NEXTAUTH_SECRET validator to be optional in dev\n\n## 6.8.0\n\n### Minor Changes\n\n- [#673](https://github.com/t3-oss/create-t3-app/pull/673) [`44a107b`](https://github.com/t3-oss/create-t3-app/commit/44a107b8d5345023bafc8a773322e5ee39ba8580) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - remove node 18 and next 13 checks\n\n### Patch Changes\n\n- [#684](https://github.com/t3-oss/create-t3-app/pull/684) [`a707c4b`](https://github.com/t3-oss/create-t3-app/commit/a707c4ba9ffedb8991fc14976e352ff83f4502ac) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: version bumps\n\n## 6.7.0\n\n### Minor Changes\n\n- [#667](https://github.com/t3-oss/create-t3-app/pull/667) [`fde5b76`](https://github.com/t3-oss/create-t3-app/commit/fde5b7628860b305c95f70f5cc42ae3c37ad59a9) Thanks [@Pegasust](https://github.com/Pegasust)! - Add documentation on how to generate NEXTAUTH_SECRET in .env file for clarity\n\n- [#675](https://github.com/t3-oss/create-t3-app/pull/675) [`5d20745`](https://github.com/t3-oss/create-t3-app/commit/5d207453497c327b5c54cd3a55c824d59b80effe) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - only try to get secret message if there is a user\n\n### Patch Changes\n\n- [#676](https://github.com/t3-oss/create-t3-app/pull/676) [`a497e47`](https://github.com/t3-oss/create-t3-app/commit/a497e4765b17e686482ef5b5701766b2299ea0b2) Thanks [@nexxeln](https://github.com/nexxeln)! - update next to 13.0.1\n\n- [#654](https://github.com/t3-oss/create-t3-app/pull/654) [`3dfc27d`](https://github.com/t3-oss/create-t3-app/commit/3dfc27d7edc8dfedee6ed06e9b381cbd791ae0e7) Thanks [@nexxeln](https://github.com/nexxeln)! - Make experimental flags booleans and not require the name to be \"double passed\"\n\n## 6.6.0\n\n### Minor Changes\n\n- [#657](https://github.com/t3-oss/create-t3-app/pull/657) [`f1673eb`](https://github.com/t3-oss/create-t3-app/commit/f1673ebbf58033746b9a020b7f0b72d976988f84) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: update dependency Next.js to 13\n\n## 6.5.2\n\n### Patch Changes\n\n- [#649](https://github.com/t3-oss/create-t3-app/pull/649) [`6a21032`](https://github.com/t3-oss/create-t3-app/commit/6a210329136d089d61d41acaf99519223003f606) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - chore: version bumps\n\n## 6.5.1\n\n### Patch Changes\n\n- [#642](https://github.com/t3-oss/create-t3-app/pull/642) [`9639419`](https://github.com/t3-oss/create-t3-app/commit/9639419f1f24f8c3f5418680d9d8a214e16c8cd6) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - get next-auth to work with node 18\n\n## 6.5.0\n\n### Minor Changes\n\n- [#623](https://github.com/t3-oss/create-t3-app/pull/623) [`cf99211`](https://github.com/t3-oss/create-t3-app/commit/cf992110e7d7e741e56561a728ee0f2dee6fc614) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - consistent cli text color\n\n### Patch Changes\n\n- [#619](https://github.com/t3-oss/create-t3-app/pull/619) [`1122720`](https://github.com/t3-oss/create-t3-app/commit/112272083e6130209bfbac0cd350e985dcd9f19f) Thanks [@nexxeln](https://github.com/nexxeln)! - Added `createdAt` and `updatedAt` fields to the Example model in the Prisma schema.\n\n- [#621](https://github.com/t3-oss/create-t3-app/pull/621) [`1cc6735`](https://github.com/t3-oss/create-t3-app/commit/1cc67350c626db3c67f012a84d1a73a7a0f03a91) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix git spinner\n\n## 6.4.0\n\n### Minor Changes\n\n- [#613](https://github.com/t3-oss/create-t3-app/pull/613) [`135ee5b`](https://github.com/t3-oss/create-t3-app/commit/135ee5b469c575e3fa0d7729a9a545811cc9cf74) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - add inference helper for v10\n\n### Patch Changes\n\n- [#611](https://github.com/t3-oss/create-t3-app/pull/611) [`78a0da3`](https://github.com/t3-oss/create-t3-app/commit/78a0da3d08b9e4468fecbae29cccde7ec43801ab) Thanks [@nexxeln](https://github.com/nexxeln)! - fix(cli): make `installDependencies` step async to make loader spin\n\n## 6.3.0\n\n### Minor Changes\n\n- [#606](https://github.com/t3-oss/create-t3-app/pull/606) [`7f73518`](https://github.com/t3-oss/create-t3-app/commit/7f73518b488b0391f19c8d4d31f583e2be71195a) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - rename index.ts to \\_app.ts\n\n## 6.2.1\n\n### Patch Changes\n\n- [#602](https://github.com/t3-oss/create-t3-app/pull/602) [`9f86e39`](https://github.com/t3-oss/create-t3-app/commit/9f86e391fded7bb196ac40b83ac633d996bf035f) Thanks [@nexxeln](https://github.com/nexxeln)! - feat(template): add prettier.Config type to prettier config and resolve prettier-plugin-tailwindcss import\n\n## 6.2.0\n\n### Minor Changes\n\n- [#581](https://github.com/t3-oss/create-t3-app/pull/581) [`dd0e172`](https://github.com/t3-oss/create-t3-app/commit/dd0e172579d0436f5bdb5d29b721dd55362f620e) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - export helper procedures for trpc instead of the `t`-object\n\n## 6.1.2\n\n### Patch Changes\n\n- [#593](https://github.com/t3-oss/create-t3-app/pull/593) [`c8e2753`](https://github.com/t3-oss/create-t3-app/commit/c8e2753b916d15f3ce1103e7fa89dbd046150474) Thanks [@nexxeln](https://github.com/nexxeln)! - chore(template): remove the mention of @next in template readme\n\n## 6.1.1\n\n### Patch Changes\n\n- [#591](https://github.com/t3-oss/create-t3-app/pull/591) [`c90a695`](https://github.com/t3-oss/create-t3-app/commit/c90a6957de7a644e1669762c7a0d19bfbd300715) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - bump next-auth dependency to ^4.12\n\n## 6.1.0\n\n### Minor Changes\n\n- [#582](https://github.com/t3-oss/create-t3-app/pull/582) [`e562ee8`](https://github.com/t3-oss/create-t3-app/commit/e562ee89401307d92177573a9ead1b45373b63c7) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - move prettier from base to tailwind installer\n\n- [#587](https://github.com/t3-oss/create-t3-app/pull/587) [`8c0267f`](https://github.com/t3-oss/create-t3-app/commit/8c0267f98bb7c71e0d90644a9f6af97f1599c723) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - Add .env-example to scaffolded app\n\n## 6.0.1\n\n### Patch Changes\n\n- [#578](https://github.com/t3-oss/create-t3-app/pull/578) [`befc7f4`](https://github.com/t3-oss/create-t3-app/commit/befc7f4f74faeb1538cb6cad6191a1849bf34987) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - upgrade trpc to beta.15 and typescript to 4.8.4\n\n## 6.0.0\n\n### Major Changes\n\n- [#575](https://github.com/t3-oss/create-t3-app/pull/575) [`75fcb49`](https://github.com/t3-oss/create-t3-app/commit/75fcb49f338fbf783a1b157332a803f7c51048c6) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - upgrades trpc to v10 and improves cli performance by making it synchronous\n\n### Minor Changes\n\n- [#575](https://github.com/t3-oss/create-t3-app/pull/575) [`75fcb49`](https://github.com/t3-oss/create-t3-app/commit/75fcb49f338fbf783a1b157332a803f7c51048c6) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - enable vercel_url to pass default env-schema\n\n## 5.15.0\n\n### Minor Changes\n\n- [#533](https://github.com/t3-oss/create-t3-app/pull/533) [`a3a168a`](https://github.com/t3-oss/create-t3-app/commit/a3a168a5a2c54a51e841b2fce5786ec94d72b0fb) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - Tailor .env to only include relevant keys\n\n## 5.14.1\n\n### Patch Changes\n\n- [#510](https://github.com/t3-oss/create-t3-app/pull/510) [`39d766d`](https://github.com/t3-oss/create-t3-app/commit/39d766d3b384c3420c6c058c27be775e961a9319) Thanks [@EkkoKo](https://github.com/EkkoKo)! - fix: resolve target area of `Documentation` links in TechnologyCard\n\n## 5.14.0\n\n### Minor Changes\n\n- [#517](https://github.com/t3-oss/create-t3-app/pull/517) [`2b434bb`](https://github.com/t3-oss/create-t3-app/commit/2b434bb181dc346f299591ddf5465d3175df5c07) Thanks [@gabrielelpidio](https://github.com/gabrielelpidio)! - Add prettier and prettier-plugin-tailwindcss\n\n## 5.13.1\n\n### Patch Changes\n\n- [#506](https://github.com/t3-oss/create-t3-app/pull/506) [`f371ef8`](https://github.com/t3-oss/create-t3-app/commit/f371ef8f0b64205cbbfb5dc6f3416da01a673a71) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - temp fix for next-auth peer deps issue\n\n## 5.13.0\n\n### Minor Changes\n\n- [#485](https://github.com/t3-oss/create-t3-app/pull/485) [`ecc7642`](https://github.com/t3-oss/create-t3-app/commit/ecc764264eff0cf5062fee4f7e4bd9f75975ef41) Thanks [@nexxeln](https://github.com/nexxeln)! - bump next to 12.3.1 and fix AppType\n\n## 5.12.0\n\n### Minor Changes\n\n- [#446](https://github.com/t3-oss/create-t3-app/pull/446) [`6f63ec6`](https://github.com/t3-oss/create-t3-app/commit/6f63ec65201a077e534ec89c4ef18bfa07a30331) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - feat: better cli text when scaffolding in '.'\n\n## 5.11.0\n\n### Minor Changes\n\n- [#430](https://github.com/t3-oss/create-t3-app/pull/430) [`306777a`](https://github.com/t3-oss/create-t3-app/commit/306777a5513c365dfb3525c1484459236734a289) Thanks [@benmarg](https://github.com/benmarg)! - feat: direct developer to add schema from .env to schema.mjs for zod validation\n\n### Patch Changes\n\n- [#416](https://github.com/t3-oss/create-t3-app/pull/416) [`14b6d4a`](https://github.com/t3-oss/create-t3-app/commit/14b6d4a0764f57ece45749724c5b12a85544733e) Thanks [@xpressivecode](https://github.com/xpressivecode)! - fix(template): missing ctx when using ssr with trpc\n\n## 5.10.3\n\n### Patch Changes\n\n- [#419](https://github.com/t3-oss/create-t3-app/pull/419) [`554de8f`](https://github.com/t3-oss/create-t3-app/commit/554de8f2838a8d539d81bcb520f121a7e14e3c84) Thanks [@sor4chi](https://github.com/sor4chi)! - Remove unnecessary singlequote in tailwind classname\n\n## 5.10.2\n\n### Patch Changes\n\n- [#387](https://github.com/t3-oss/create-t3-app/pull/387) [`0f8f59c`](https://github.com/t3-oss/create-t3-app/commit/0f8f59c30155ddf4f6be90f3713ff5d5379f0cbb) Thanks [@Vallerem](https://github.com/Vallerem)! - feat: add basic i18n configuration in next.config\n\n## 5.10.1\n\n### Patch Changes\n\n- [#396](https://github.com/t3-oss/create-t3-app/pull/396) [`30f3db6`](https://github.com/t3-oss/create-t3-app/commit/30f3db64c3a81475488c712fa16682076ba3f18b) Thanks [@rhenriquez28](https://github.com/rhenriquez28)! - fixing ssr by forwarding client's headers\n\n## 5.10.0\n\n### Minor Changes\n\n- [#388](https://github.com/t3-oss/create-t3-app/pull/388) [`86d053c`](https://github.com/t3-oss/create-t3-app/commit/86d053c440ed3c5d5101faf8d73574b6d24bf99e) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - feat: non-tw index.tsx with styling\n\n* [#381](https://github.com/t3-oss/create-t3-app/pull/381) [`773b27e`](https://github.com/t3-oss/create-t3-app/commit/773b27e1399970992e232975830d327100316e74) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - feat: include all cards on all index.tsx files\n\n- [#383](https://github.com/t3-oss/create-t3-app/pull/383) [`e05bc3d`](https://github.com/t3-oss/create-t3-app/commit/e05bc3da9867fcf8d8262b4e8dd976565650cf8f) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - add safeguards for overwriting git repos\n\n* [#375](https://github.com/t3-oss/create-t3-app/pull/375) [`296c79b`](https://github.com/t3-oss/create-t3-app/commit/296c79b9617142d727a12e9a5c4250f68f437d9d) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - feat: add option to continue and overwrite on existing directory\n\n  for reference see: https://github.com/t3-oss/create-t3-app/issues/230\n\n### Patch Changes\n\n- [#394](https://github.com/t3-oss/create-t3-app/pull/394) [`52e9db7`](https://github.com/t3-oss/create-t3-app/commit/52e9db7be8eacbb1e0bb2196647f646f8af617ea) Thanks [@nadilas](https://github.com/nadilas)! - Extending the warning message for invalid client environment variables by including the reason\n\n## 5.9.0\n\n### Minor Changes\n\n- [#366](https://github.com/t3-oss/create-t3-app/pull/366) [`1f43f83`](https://github.com/t3-oss/create-t3-app/commit/1f43f83261c0e6f91b6af0fb39f579845889b724) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - Thanks [@hnqg](https://github.com/hnqg) for the initial PR. add wrapper function for unstable_getServerSession\n\n## 5.8.5\n\n### Patch Changes\n\n- [#357](https://github.com/t3-oss/create-t3-app/pull/357) [`b032074`](https://github.com/t3-oss/create-t3-app/commit/b03207434484d7ec3411b2d7c062a22cf425badc) Thanks [@virtuoushub](https://github.com/virtuoushub)! - chore: Sort package.json when in noInstallMode\n\n* [#365](https://github.com/t3-oss/create-t3-app/pull/365) [`b3ce004`](https://github.com/t3-oss/create-t3-app/commit/b3ce004affb9474e53e845e8507f676e3a771de0) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - revert prisma cleint teardown from #353\n\n## 5.8.4\n\n### Patch Changes\n\n- [#353](https://github.com/t3-oss/create-t3-app/pull/353) [`7a20de9`](https://github.com/t3-oss/create-t3-app/commit/7a20de9f19dfd9ae64143da112a4e3e1bfe30f52) Thanks [@Gejsi](https://github.com/Gejsi)! - Added loggers during development\n\n## 5.8.3\n\n### Patch Changes\n\n- [#345](https://github.com/t3-oss/create-t3-app/pull/345) [`8ee2ea0`](https://github.com/t3-oss/create-t3-app/commit/8ee2ea0c6ca4e49f2bb9b0f5c988471947c8a7ff) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - Include `cjs` and `mjs` files in tsconfig. Thanks @timfee for reporting!\n\n## 5.8.2\n\n### Patch Changes\n\n- [#330](https://github.com/t3-oss/create-t3-app/pull/330) [`5ba03fd`](https://github.com/t3-oss/create-t3-app/commit/5ba03fdf801265668c7bb89b757840ef1f8410f8) Thanks [@nexxeln](https://github.com/nexxeln)! - use auth instead of question while merging the router\n\n## 5.8.1\n\n### Patch Changes\n\n- [#335](https://github.com/t3-oss/create-t3-app/pull/335) [`5745ad7`](https://github.com/t3-oss/create-t3-app/commit/5745ad796ed5647a7103bfb91e16f981152bcbe5) Thanks [@julianread](https://github.com/julianread)! - Fix invalid typeof window comparison to undefined\n\n* [#334](https://github.com/t3-oss/create-t3-app/pull/334) [`a107f14`](https://github.com/t3-oss/create-t3-app/commit/a107f14c5981a233d118252a57066bdf1938b96c) Thanks [@c-ehrlich](https://github.com/c-ehrlich)! - fix: build fails on trpc, trpc+next\n\n## 5.8.0\n\n### Minor Changes\n\n- [#324](https://github.com/t3-oss/create-t3-app/pull/324) [`fb5498c`](https://github.com/t3-oss/create-t3-app/commit/fb5498ceda6d3c528c2fe4e9a5ba4adf3dd36b10) Thanks [@juliusmarminge](https://github.com/juliusmarminge)! - feat: wrap createContext with helper function to make it independent of req/res\n\n## 5.7.0\n\n### Minor Changes\n\n- 7a76c95: feat(app): add lint config for typescript\n\n## [5.6.0](https://github.com/t3-oss/create-t3-app/compare/v5.5.0...v5.6.0) (2022-08-11)\n\n### Features\n\n- Include ct3a version as metadata in generated app ([#305](https://github.com/t3-oss/create-t3-app/issues/305)) ([0be4a97](https://github.com/t3-oss/create-t3-app/commit/0be4a97fdf1c7bfab78d7be2051c2b21e665c491))\n\n### Bug Fixes\n\n- change ! reversion to equality in env validation ([#293](https://github.com/t3-oss/create-t3-app/issues/293)) ([7822c43](https://github.com/t3-oss/create-t3-app/commit/7822c433df18011f0cc6748e2c499c0e4283386c))\n- parse path returned from process.cwd() before using it ([#303](https://github.com/t3-oss/create-t3-app/issues/303)) ([b55f196](https://github.com/t3-oss/create-t3-app/commit/b55f196d0146c5c3969de4c25e7732046aad6284))\n\n## [5.5.0](https://github.com/t3-oss/create-t3-app/compare/v5.4.0...v5.5.0) (2022-08-07)\n\n### Features\n\n- make session.user.id non-nullable ([#282](https://github.com/t3-oss/create-t3-app/issues/282)) ([6a81f03](https://github.com/t3-oss/create-t3-app/commit/6a81f03bfafdf77c1c82b7972a97e3e54d77935c))\n\n## [5.4.0](https://github.com/t3-oss/create-t3-app/compare/v5.3.0...v5.4.0) (2022-08-02)\n\n### Features\n\n- add deployment strategy to generated README ([#258](https://github.com/t3-oss/create-t3-app/issues/258)) ([c7d4dce](https://github.com/t3-oss/create-t3-app/commit/c7d4dce182b1c306dc2a41d42483994c336843f4))\n- set appName to directory on 'npx create-t3-app .' ([#273](https://github.com/t3-oss/create-t3-app/issues/273)) ([2179f2d](https://github.com/t3-oss/create-t3-app/commit/2179f2d38f74de0e3fda5661f5125d049eb4d238))\n\n### Bug Fixes\n\n- height on small screens ([#256](https://github.com/t3-oss/create-t3-app/issues/256)) ([fe86915](https://github.com/t3-oss/create-t3-app/commit/fe86915ced72dc979e5fe68bd56b038d9c714928))\n- missing next-auth types ([#255](https://github.com/t3-oss/create-t3-app/issues/255)) ([ed42629](https://github.com/t3-oss/create-t3-app/commit/ed42629be5fb9be72abd40bbe784f2bda99eec99)), closes [#254](https://github.com/t3-oss/create-t3-app/issues/254)\n- **prisma:** make db changes for next-auth on mysql obvious ([#275](https://github.com/t3-oss/create-t3-app/issues/275)) ([e9507c8](https://github.com/t3-oss/create-t3-app/commit/e9507c887e135f3e44357c618689f5cdb2f13c43))\n\n## [5.3.0](https://github.com/t3-oss/create-t3-app/compare/v5.2.1...v5.3.0) (2022-07-25)\n\n### Features\n\n- add typesafe client side env variables ([#209](https://github.com/t3-oss/create-t3-app/issues/209)) ([d4cf879](https://github.com/t3-oss/create-t3-app/commit/d4cf879df811ded012a5f7cb3d91ff0bb95d87ac))\n- improved logo typography ([#238](https://github.com/t3-oss/create-t3-app/issues/238)) ([48c6720](https://github.com/t3-oss/create-t3-app/commit/48c67207da48c901822e214a00285c99bb785fd8))\n- updating tailwind and postcss config's to use .cjs ([#242](https://github.com/t3-oss/create-t3-app/issues/242)) ([5b97367](https://github.com/t3-oss/create-t3-app/commit/5b973670cae729c9e93b6c3c6f0b3e5b48dda904))\n\n### Bug Fixes\n\n- added JSDoc type to clientEnv in all env-schema ([#240](https://github.com/t3-oss/create-t3-app/issues/240)) ([9cb5ebb](https://github.com/t3-oss/create-t3-app/commit/9cb5ebbb2a0147ce15726c7e1a6c6be4065bc2dc))\n- clarify some comments and rename some files in env ([#245](https://github.com/t3-oss/create-t3-app/issues/245)) ([2048783](https://github.com/t3-oss/create-t3-app/commit/2048783bd26f7f0522357a3ab1e74e6f560a221c))\n- remove semicolon in \\_app.tsx with next-auth to avoid early return ([1be7713](https://github.com/t3-oss/create-t3-app/commit/1be771393628631b818b46d3f3bf1ca41ad99dce))\n- title being offset when using yarn/pnpm ([c881f00](https://github.com/t3-oss/create-t3-app/commit/c881f00430f606040a448eecc41e779ab0c728a7))\n\n### [5.2.1](https://github.com/t3-oss/create-t3-app/compare/v5.2.0...v5.2.1) (2022-07-19)\n\n### Bug Fixes\n\n- update url in auth prisma schema ([97c9e27](https://github.com/t3-oss/create-t3-app/commit/97c9e279bf7465a47f29add10c8a6d4c9b7339a5))\n\n## [5.2.0](https://github.com/t3-oss/create-t3-app/compare/v5.1.1...v5.2.0) (2022-07-19)\n\n### Features\n\n- add db.sqlite-journal to gitignore ([#221](https://github.com/t3-oss/create-t3-app/issues/221)) ([0604d21](https://github.com/t3-oss/create-t3-app/commit/0604d217f0dfe3d165013395c1a801e6bc32a17c))\n\n### Bug Fixes\n\n- handle pkg with version in noInstall mode ([#220](https://github.com/t3-oss/create-t3-app/issues/220)) ([5737beb](https://github.com/t3-oss/create-t3-app/commit/5737bebaab3ff6f955bf825274e25419a91642d6))\n- missing DATABASE_URL ([#222](https://github.com/t3-oss/create-t3-app/issues/222)) ([b6164d8](https://github.com/t3-oss/create-t3-app/commit/b6164d8944330564e9911e47f36d82620986c8c5))\n- typo - rename 'varibles' to 'variables' ([#223](https://github.com/t3-oss/create-t3-app/issues/223)) ([fc6519f](https://github.com/t3-oss/create-t3-app/commit/fc6519f66d067e4e348c7f4c00f6287dc5c40c3d))\n- typo in readme ([9390400](https://github.com/t3-oss/create-t3-app/commit/9390400b8720240c650e5dbde7ca0718b7835757))\n\n### [5.1.1](https://github.com/t3-oss/create-t3-app/compare/v5.1.0...v5.1.1) (2022-07-18)\n\n### Bug Fixes\n\n- add missing trpc import ([37b6283](https://github.com/t3-oss/create-t3-app/commit/37b6283bb56e44092fc9ef2d65c84e5298e51d22))\n\n## [5.1.0](https://github.com/t3-oss/create-t3-app/compare/v5.0.0...v5.1.0) (2022-07-18)\n\n### Features\n\n- add trpc inference helpers ([1fcec81](https://github.com/t3-oss/create-t3-app/commit/1fcec81a74372ce5cfaf6503d63f16d5e2b12e3c))\n- migrate env + next config to esm ([#205](https://github.com/t3-oss/create-t3-app/issues/205)) ([59f8ad4](https://github.com/t3-oss/create-t3-app/commit/59f8ad4f2104aa1f11508b55da75c333dce03625))\n\n### Bug Fixes\n\n- **#218:** lock react-query to v3 ([15ea5f1](https://github.com/t3-oss/create-t3-app/commit/15ea5f1dc8b86430a720f2eaeb6ccdfaab629892)), closes [#218](https://github.com/t3-oss/create-t3-app/issues/218)\n- move gitignore rename call ([#215](https://github.com/t3-oss/create-t3-app/issues/215)) ([7111033](https://github.com/t3-oss/create-t3-app/commit/7111033d75c858041f06d69e95c51e40515457fc))\n\n## 5.0.0 (2022-07-16)\n\n### Features\n\n- add check for yarn 3 ([#173](https://github.com/t3-oss/create-t3-app/issues/173)) ([cd846e1](https://github.com/t3-oss/create-t3-app/commit/cd846e16123a6bb11549276030224ec4ff1223df))\n- add ci for pull requests ([0e7cdc8](https://github.com/t3-oss/create-t3-app/commit/0e7cdc8bd307e17e95bd1874af2d0eb43211530e))\n- add commitlint ([#126](https://github.com/t3-oss/create-t3-app/issues/126)) ([3672aa3](https://github.com/t3-oss/create-t3-app/commit/3672aa3f4482ef592022cd94f1300b81e3fa7429))\n- add CONTRIBUTING.md for newcomers ([99f8220](https://github.com/t3-oss/create-t3-app/commit/99f8220f83a6363e5aab6c0ec33260eb059c9643))\n- add db.sqlite to gitignore ([#201](https://github.com/t3-oss/create-t3-app/issues/201)) ([90371c7](https://github.com/t3-oss/create-t3-app/commit/90371c7f88258b4b3e9a2689c09f67a9e439b189))\n- add environment variables validation ([#147](https://github.com/t3-oss/create-t3-app/issues/147)) ([0f0b56d](https://github.com/t3-oss/create-t3-app/commit/0f0b56d2604c1ba9dccd8d2a5213f0d2a640cd68))\n- add git prompt ([#130](https://github.com/t3-oss/create-t3-app/issues/130)) ([e5be271](https://github.com/t3-oss/create-t3-app/commit/e5be271612db741e3a692cd780ef84455faa115c))\n- add inferQueryResponse helper for tRPC ([748800f](https://github.com/t3-oss/create-t3-app/commit/748800f060031da58ce2b45bd65e4fd83266ce5c))\n- add main as initial branch ([7b94005](https://github.com/t3-oss/create-t3-app/commit/7b94005fd515d140176e639a487ab5035a290125))\n- add next-auth config to env-example [#108](https://github.com/t3-oss/create-t3-app/issues/108) ([c3ab997](https://github.com/t3-oss/create-t3-app/commit/c3ab997f149ee3635d2d33a67650e95e04877d5b))\n- add noInstall flag and prompt ([#133](https://github.com/t3-oss/create-t3-app/issues/133)) ([7ff0fca](https://github.com/t3-oss/create-t3-app/commit/7ff0fcacc3b94a4fd15d0db25e2efc09131d73c9))\n- add standard-version ([#125](https://github.com/t3-oss/create-t3-app/issues/125)) ([0fc6b47](https://github.com/t3-oss/create-t3-app/commit/0fc6b479c99c76ab830a81d011ba0e4ef90ce849))\n- add tRPC inference helper docs commment on utils ([3e784cb](https://github.com/t3-oss/create-t3-app/commit/3e784cbf3f9b4f6eeb4441a881ebbd028f311957))\n- added windows build support ([29acbf8](https://github.com/t3-oss/create-t3-app/commit/29acbf816c69f980454568946fba1afea6be114c))\n- better ui for templates ([e2e8c7e](https://github.com/t3-oss/create-t3-app/commit/e2e8c7eeeab576d730cd1c7e397497460c1787e0))\n- better validation and add path support ([#135](https://github.com/t3-oss/create-t3-app/issues/135)) ([e50cb8a](https://github.com/t3-oss/create-t3-app/commit/e50cb8a3e13126de628d098e00650a52753681f3))\n- check if dir is empty ([71bbdba](https://github.com/t3-oss/create-t3-app/commit/71bbdbae564d6e7df4b08645db59a8364b891b99))\n- make the ui symmetric ([19df71e](https://github.com/t3-oss/create-t3-app/commit/19df71ec53fd64e60b27ecd055cd9f0c6acc4a63))\n\n### Bug Fixes\n\n- add newline at the end of the file ([64eee1c](https://github.com/t3-oss/create-t3-app/commit/64eee1c8058aa5d2ec29fc1903ee63819fa8fc9d))\n- add scripts for CI ([539f3fd](https://github.com/t3-oss/create-t3-app/commit/539f3fdc44e1d96e5429f21afbb74f71bf4d963d))\n- add semantic elements and update tw classes on tw pages ([#151](https://github.com/t3-oss/create-t3-app/issues/151)) ([61d6819](https://github.com/t3-oss/create-t3-app/commit/61d6819f14ac5b65c779081c91ca894f724f7b16))\n- bumped package.json for beta-release ([3fe35f1](https://github.com/t3-oss/create-t3-app/commit/3fe35f14313da611cb16e26141e06d1afb5efb78))\n- change comment in .env to discord ([d992713](https://github.com/t3-oss/create-t3-app/commit/d992713cad08c08267a0f018fa8582b569a554db))\n- **cli:** use correct spelling, fix short choices ([7776aa9](https://github.com/t3-oss/create-t3-app/commit/7776aa9fc03293f27d9e27808cd03810f96ccc33))\n- conditionally run envVars installer ([#196](https://github.com/t3-oss/create-t3-app/issues/196)) ([f5f4f62](https://github.com/t3-oss/create-t3-app/commit/f5f4f6275c1a967f6de2e7c6d40d9a7731a3830b))\n- docs wrong format ([3d2dbb0](https://github.com/t3-oss/create-t3-app/commit/3d2dbb06cadb42d24f134ce09edc5a371d79aff9))\n- dont prompt for typesafe env-vars ([2faee56](https://github.com/t3-oss/create-t3-app/commit/2faee56720c39d770ebe05d15e3fb2aaacaf704e))\n- eslint warning (import/no-anonymous-default-export) ([a1cce55](https://github.com/t3-oss/create-t3-app/commit/a1cce5546a8fd6efb79c65a2f2b52d4c597dafd0))\n- fixed some typos ([#131](https://github.com/t3-oss/create-t3-app/issues/131)) ([a86466e](https://github.com/t3-oss/create-t3-app/commit/a86466eb0bc1ef51a1c8ba1b96938dc1bd7dfbbb))\n- format contributing.md ([4111476](https://github.com/t3-oss/create-t3-app/commit/41114766582ca33fb2a3fd0b566e609a6dd3e861))\n- handle git projects correctly ([3ed897f](https://github.com/t3-oss/create-t3-app/commit/3ed897ff49c06f6d70d49aee31d5c3741fced96e))\n- incompatible git version ([#127](https://github.com/t3-oss/create-t3-app/issues/127)) ([34f44f8](https://github.com/t3-oss/create-t3-app/commit/34f44f817df52b317afea5b8d55c87eea487833f))\n- invalid pnpm action version ([2a1f6e3](https://github.com/t3-oss/create-t3-app/commit/2a1f6e32aedb8f86ee7ca403e481be8e474b76b2))\n- language prompt short answer should both be ts ([#142](https://github.com/t3-oss/create-t3-app/issues/142)) ([5e4f80d](https://github.com/t3-oss/create-t3-app/commit/5e4f80d7aa930f16add3bb2273a23f5829548f49))\n- **markup:** multiple h1 replaced to h2 ([6bf9040](https://github.com/t3-oss/create-t3-app/commit/6bf90407b9a9774348a77927d37c47f3ded5552a))\n- **prompts:** show correct package manager in prompts ([#153](https://github.com/t3-oss/create-t3-app/issues/153)) ([fe66ae9](https://github.com/t3-oss/create-t3-app/commit/fe66ae9f60cbe6a2e429be406a1cd548c51e7bbd))\n- properly display the welcome title when installing with Yarn ([#160](https://github.com/t3-oss/create-t3-app/issues/160)) ([a5b9d53](https://github.com/t3-oss/create-t3-app/commit/a5b9d534e6395e494dcfab8419e71bf201b7326b))\n- provide cwd inside git init exec call ([9679492](https://github.com/t3-oss/create-t3-app/commit/9679492ebd9175973c99d647cf11a4f1b979a505))\n- reapply style fixes on tw pages ([#189](https://github.com/t3-oss/create-t3-app/issues/189)) ([af1067b](https://github.com/t3-oss/create-t3-app/commit/af1067b196205b0dd70a44571c62012d9667987e)), closes [#178](https://github.com/t3-oss/create-t3-app/issues/178)\n- remove changeset from repo ([#134](https://github.com/t3-oss/create-t3-app/issues/134)) ([d58b380](https://github.com/t3-oss/create-t3-app/commit/d58b380ed4310021a771e05037a6054176c14b91))\n- remove duplicated types ([#138](https://github.com/t3-oss/create-t3-app/issues/138)) ([e4c8e33](https://github.com/t3-oss/create-t3-app/commit/e4c8e336fff94bd125cac06f4bfa4d5eb365dd54))\n- remove unncesary import on auth router ([abdc61f](https://github.com/t3-oss/create-t3-app/commit/abdc61ffc18dd4f1e82f3fc02cd87a2144d0cc03))\n- run prettier ([9961645](https://github.com/t3-oss/create-t3-app/commit/99616456d54abde5b458d57add1132dcb2b68256))\n- standardize log messages ([83a13b9](https://github.com/t3-oss/create-t3-app/commit/83a13b9963f83317a62e3eeaed14dd5e2cb45344))\n- **template:** converting to use tech props and remove tw from template ([#183](https://github.com/t3-oss/create-t3-app/issues/183)) ([b2d542a](https://github.com/t3-oss/create-t3-app/commit/b2d542a44eed0aa699fe91e52f25f6ac68a0021c))\n- **templates:** h1 restored ([e51e03d](https://github.com/t3-oss/create-t3-app/commit/e51e03d93a899674bef839ddb215a36e62397e26))\n- type entrire app and not just the props ([908630e](https://github.com/t3-oss/create-t3-app/commit/908630e5cc14789b88a0ddf6dd097fb14eb9068a))\n- typo in \"Javascript\" ([#136](https://github.com/t3-oss/create-t3-app/issues/136)) ([6873a7a](https://github.com/t3-oss/create-t3-app/commit/6873a7a5ff17c6efda1b78fe73597ec43821552c))\n- update templates ([4418f1d](https://github.com/t3-oss/create-t3-app/commit/4418f1db06a29050293f0d4dd16a1347d34c6cf9))\n- use components for the tech within the splash screen ([#178](https://github.com/t3-oss/create-t3-app/issues/178)) ([c436382](https://github.com/t3-oss/create-t3-app/commit/c4363821664fe95b4301d46b3e2d34fbeb14952d))\n- with-tw removed unused styles and added motion saftey ([#148](https://github.com/t3-oss/create-t3-app/issues/148)) ([598ed0e](https://github.com/t3-oss/create-t3-app/commit/598ed0eda73e5218658ff7d574e28ecc25a4e2cb))\n\n## 4.4.1\n\n### Patch Changes\n\n- changed ui for template\n\n## 4.4.0\n\n### Minor Changes\n\n- improve ui examples of template app\n\n## 4.3.5\n\n### Patch Changes\n\n- add warning for old git versions\n\n## 4.3.4\n\n### Patch Changes\n\n- improve template styling\n\n## 4.3.3\n\n### Patch Changes\n\n- Add description for packages in the template\n\n## 4.3.2\n\n### Patch Changes\n\n- Redesign pages\n\n## 4.3.0\n\n### Minor Changes\n\n- added Next-Auth protected routes when using tRPC\n\n## 4.2.12\n\n### Patch Changes\n\n- upgrade next to 12.2.0\n\n## 4.2.11\n\n### Patch Changes\n\n- modified the title to print a colorful ascii art\n\n## 4.2.10\n\n### Patch Changes\n\n- add warning about next-auth when using Node 18\n\n## 4.2.9\n\n### Patch Changes\n\n- fix resolved path to package root\n\n## 4.2.8\n\n### Patch Changes\n\n- diable version flag\n\n## 4.2.2\n\n### Patch Changes\n\n- fix esm issues\n\n## 4.2.1\n\n### Patch Changes\n\n- trying to fix esm error\n\n## 4.2.0\n\n### Minor Changes\n\n- a548f22: added cli args, esm support\n\n## 4.1.1\n\n### Patch Changes\n\n- Updated package to full ESM support\n\n## 4.1.0\n\n### Minor Changes\n\n- Create-t3-app now accepts args!\n\n  When calling create-t3-app, you can specify the app name and directory directly from the cli.\n\n  Additonal options are visable by passing -h or --help into the command line\n\n## 4.0.8\n\n### Patch Changes\n\n- added loading spinners\n\n## 4.0.7\n\n### Patch Changes\n\n- added tsup as build tool\n\n## 4.0.6\n\n### Patch Changes\n\n- Added dev tooling.\n"
  },
  {
    "path": "cli/README.md",
    "content": "<p align=\"center\">\n  <picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/t3-oss/create-t3-app/99286f37324330ecdf75132fae1f246440a88035/www/public/images/t3-light.svg\">\n  <img src=\"https://raw.githubusercontent.com/t3-oss/create-t3-app/99286f37324330ecdf75132fae1f246440a88035/www/public/images/t3-dark.svg\" width=\"130\" alt=\"Logo for T3\">\n</picture>\n</p>\n\n<h1 align=\"center\">\n  create-t3-app\n</h1>\n\n<p align=\"center\">\n  Interactive CLI to start a full-stack, typesafe Next.js app.\n</p>\n\n<p align=\"center\">\n  Get started with the <a rel=\"noopener noreferrer\" target=\"_blank\" href=\"https://init.tips\">T3 Stack</a> by running <code>npm create t3-app@latest</code>\n</p>\n\n<div align=\"center\">\n\n[![PRs-Welcome][contribute-image]][contribute-url] [![Discord](https://img.shields.io/discord/966627436387266600?color=%235865F2&label=Discord&logo=discord&logoColor=%23fff)](https://t3.gg/discord) [![NPM version][npm-image]][npm-url]\n[![Downloads][downloads-image]][npm-url]\n\n</div>\n\n<a href=\"http://www.youtube.com/watch?v=PbjHxIuHduU\" target=\"_blank\">\n  <p align=\"center\">\n    <img src=\"https://t3.gg/random/T3%20Stack%20V4.png\" alt=\"Video thumbnail of Theo with an indecipherable expression on his face\" width=\"320\" />\n  </p>\n</a>\n\n<a href=\"http://www.youtube.com/watch?v=PbjHxIuHduU\" target=\"_blank\">\n  <p align=\"center\">Watch Theo's overview on Youtube here</p>\n</a>\n\n## Table of contents\n\n- <a href=\"#about\">The T3 Stack</a>\n- <a href=\"#axioms\">T3 Axioms</a>\n- <a href=\"#getting-started\">Getting Started</a>\n- <a href=\"#community\">Community</a>\n- <a href=\"#contributors\">Contributors</a>\n\n<h2 id=\"about\">The T3 Stack</h2>\n\nThe _\"T3 Stack\"_ is a web development stack made by [Theo](https://twitter.com/t3dotgg) focused on **simplicity**, **modularity**, and **full-stack typesafety**. It consists of:\n\n- [Next.js](https://nextjs.org)\n- [tRPC](https://trpc.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [TypeScript](https://typescriptlang.org)\n- [Prisma](https://prisma.io)\n- [Drizzle](https://orm.drizzle.team)\n- [NextAuth.js](https://next-auth.js.org)\n\n### So... what is `create-t3-app`? A template?\n\nKind of? `create-t3-app` is a CLI built by seasoned T3 Stack devs to streamline the setup of a modular T3 Stack app. This means each piece is optional, and the \"template\" is generated based on your specific needs.\n\nAfter countless projects and many years on this tech, we have lots of opinions and insights. We’ve done our best to encode them into this CLI.\n\nThis is **NOT** an all-inclusive template. We **expect** you to bring your own libraries that solve the needs of **YOUR** application. While we don’t want to prescribe solutions to more specific problems like state management and deployment, we [do have some recommendations listed here](https://create.t3.gg/en/other-recs).\n\n<h2 id=\"axioms\">T3 Axioms</h2>\n\nWe'll be frank - this is an _opinionated project_. We share a handful of core beliefs around building and we treat them as the basis for our decisions.\n\n### 1. Solve Problems\n\nIt's easy to fall into the trap of \"adding everything\" - we explicitly _don't_ want to do that. Everything added to `create-t3-app` should solve a _specific_ problem that exists within the core technologies included. This means we **won't** add things like state libraries (`zustand`, `redux`) but we **will** add things like NextAuth.js and integrate Prisma and tRPC for you.\n\n### 2. Bleed Responsibly\n\nWe love our bleeding edge tech. The amount of speed and, honestly, _fun_ that comes out of new shit is really cool. We think it's important to **bleed responsibly**, using riskier tech in the less risky parts. This means we **wouldn't** ⛔️ bet on risky new database tech (SQL is great!). But we **happily** ✅ bet on tRPC since it's just functions that are trivial to move off.\n\n### 3. Typesafety Isn't Optional\n\nThe stated goal of `create-t3-app` is to provide the quickest way to start a new full-stack, typesafe web application. We take typesafety seriously in these parts as it improves our productivity and helps us ship fewer bugs. Any decision that compromises the typesafe nature of `create-t3-app` is a decision that should be made in a different project.\n\n<h2 id=\"getting-started\">Getting Started</h2>\n\nTo scaffold an app using `create-t3-app`, run any of the following four commands and answer the command prompt questions:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nFor more advanced usage, check out the [CLI docs](https://create.t3.gg/en/installation).\n\n<h2 id=\"community\">Community</h2>\n\nFor help, discussion about best practices, or any other conversation that would benefit create-t3-app:\n\n[Join the T3 Discord Server](https://t3.gg/discord)\n\n<h2 id=\"contributors\">Contributors</h2>\n\nWe 💖 contributors! Feel free to contribute to this project but **please read the [Contributing Guidelines](CONTRIBUTING.md) before opening an issue or PR** so you understand the branching strategy and local development environment. We also welcome you to join our [Discord](https://discord.gg/tEAQjDseSX) community for either support or contributing guidance.\n\n<a href=\"https://github.com/t3-oss/create-t3-app/graphs/contributors\">\n  <p align=\"center\">\n    <img width=\"720\" src=\"https://contrib.rocks/image?repo=t3-oss/create-t3-app\" alt=\"A table of avatars from the project's contributors\" />\n  </p>\n</a>\n\n<p align=\"center\">\n  Made with <a rel=\"noopener noreferrer\" target=\"_blank\" href=\"https://contrib.rocks\">contrib.rocks</a>\n</p>\n\n<p align=\"center\">\n  <a rel=\"noopener noreferrer\" target=\"_blank\" href=\"https://vercel.com/?utm_source=t3-oss&utm_campaign=oss\">\n    <img height=\"34px\" src=\"https://www.datocms-assets.com/31049/1618983297-powered-by-vercel.svg\" alt=\"Powered by vercel\">\n  </a>\n</p>\n\n[downloads-image]: https://img.shields.io/npm/dm/create-t3-app?color=364fc7&logoColor=364fc7\n[npm-url]: https://www.npmjs.com/package/create-t3-app\n[npm-image]: https://img.shields.io/npm/v/create-t3-app?color=0b7285&logoColor=0b7285\n[contribute-url]: https://github.com/t3-oss/create-t3-app/blob/main/CONTRIBUTING.md\n[contribute-image]: https://img.shields.io/badge/PRs-welcome-blue.svg\n"
  },
  {
    "path": "cli/eslint.config.js",
    "content": "// @ts-check\nimport tseslint from \"typescript-eslint\";\n// import isaacscript from \"eslint-plugin-isaacscript\";\nimport importPlugin from \"eslint-plugin-import-x\";\n\nexport default tseslint.config(\n  { ignores: [\"dist\", \"*.config.*\"] },\n  {\n    files: [\"**/*.{ts,tsx}\"],\n    plugins: {\n      // isaacscript, // REENABLE\n      \"import-x\": importPlugin,\n    },\n    extends: [\n      ...tseslint.configs.recommended,\n    ],\n    rules: {\n      \"@typescript-eslint/no-unused-vars\": [\n        \"error\",\n        { argsIgnorePattern: \"^_\", destructuredArrayIgnorePattern: \"^_\" },\n      ],\n      \"@typescript-eslint/consistent-type-imports\": [\n        \"error\",\n        { prefer: \"type-imports\", fixStyle: \"inline-type-imports\" },\n      ],\n      \"import-x/consistent-type-specifier-style\": [\"error\", \"prefer-inline\"],\n\n      // // For educational purposes we format our comments/jsdoc nicely\n      // \"isaacscript/complete-sentences-jsdoc\": \"warn\",\n      // \"isaacscript/format-jsdoc-comments\": \"warn\",\n\n      // These lint rules don't make sense for us but are enabled in the preset configs\n      \"@typescript-eslint/no-confusing-void-expression\": \"off\",\n      \"@typescript-eslint/restrict-template-expressions\": \"off\",\n\n      // This rule doesn't seem to be working properly\n      \"@typescript-eslint/prefer-nullish-coalescing\": \"off\",\n    },\n  },\n  {\n    files: [\"src/**/*.{ts,tsx}\"],\n    extends: [\n      ...tseslint.configs.recommendedTypeChecked,\n      ...tseslint.configs.stylisticTypeChecked,\n    ],\n    rules: {\n      \"@typescript-eslint/no-explicit-any\": \"error\",\n    },\n  },\n  {\n    // Template files don't have reliable type information\n    files: [\"./template/**/*.{ts,tsx}\"],\n    extends: [tseslint.configs.disableTypeChecked],\n  },\n  {\n    linterOptions: {\n      reportUnusedDisableDirectives: true,\n    },\n    languageOptions: {\n      sourceType: \"module\",\n      parserOptions: {\n        project: [\n          \"./tsconfig.eslint.json\",\n        ],\n        // projectService: {\n        //   defaultProject: \"tsconfig.eslint.json\",\n        // },\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n);\n"
  },
  {
    "path": "cli/package.json",
    "content": "{\n  \"name\": \"create-t3-app\",\n  \"version\": \"7.40.0\",\n  \"description\": \"Create web application with the t3 stack\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/t3-oss/create-t3-app.git\",\n    \"directory\": \"cli\"\n  },\n  \"keywords\": [\n    \"create-t3-app\",\n    \"init.tips\",\n    \"next.js\",\n    \"t3-stack\",\n    \"tailwind\",\n    \"tRPC\",\n    \"typescript\"\n  ],\n  \"type\": \"module\",\n  \"exports\": \"./dist/index.js\",\n  \"bin\": {\n    \"create-t3-app\": \"./dist/index.js\"\n  },\n  \"files\": [\n    \"dist\",\n    \"template\",\n    \"README.md\",\n    \"LICENSE\",\n    \"CHANGELOG.md\",\n    \".yarnrc.yml\",\n    \"package.json\"\n  ],\n  \"engines\": {\n    \"node\": \">=18.17.0\"\n  },\n  \"scripts\": {\n    \"typecheck\": \"tsc\",\n    \"build\": \"tsup\",\n    \"dev\": \"tsup --watch\",\n    \"clean\": \"rm -rf dist .turbo node_modules\",\n    \"start\": \"node dist/index.js\",\n    \"lint\": \"eslint\",\n    \"lint:fix\": \"pnpm lint --fix\",\n    \"format\": \"prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write\",\n    \"format:check\": \"prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --check\",\n    \"release\": \"changeset version\",\n    \"pub:beta\": \"pnpm build && npm publish --tag beta\",\n    \"pub:next\": \"pnpm build && npm publish --tag next\",\n    \"pub:release\": \"pnpm build && npm publish\"\n  },\n  \"dependencies\": {\n    \"@clack/core\": \"^0.3.4\",\n    \"@clack/prompts\": \"^0.6.3\",\n    \"@ianvs/prettier-plugin-sort-imports\": \"^4.2.1\",\n    \"chalk\": \"5.2.0\",\n    \"commander\": \"^10.0.1\",\n    \"execa\": \"^7.2.0\",\n    \"fs-extra\": \"^11.2.0\",\n    \"gradient-string\": \"^2.0.2\",\n    \"ora\": \"6.3.1\",\n    \"sort-package-json\": \"^2.10.0\"\n  },\n  \"devDependencies\": {\n    \"@auth/drizzle-adapter\": \"^1.1.0\",\n    \"@auth/prisma-adapter\": \"^1.6.0\",\n    \"@libsql/client\": \"^0.14.0\",\n    \"@planetscale/database\": \"^1.19.0\",\n    \"@prisma/adapter-planetscale\": \"^6.6.0\",\n    \"@prisma/client\": \"^6.6.0\",\n    \"@t3-oss/env-nextjs\": \"^0.12.0\",\n    \"@tailwindcss/postcss\": \"^4.0.15\",\n    \"@tanstack/react-query\": \"^5.69.0\",\n    \"@trpc/client\": \"11.0.0\",\n    \"@trpc/next\": \"11.0.0\",\n    \"@trpc/react-query\": \"11.0.0\",\n    \"@trpc/server\": \"11.0.0\",\n    \"@types/fs-extra\": \"^11.0.4\",\n    \"@types/gradient-string\": \"^1.1.6\",\n    \"@types/node\": \"^24.10.1\",\n    \"better-auth\": \"^1.3\",\n    \"drizzle-kit\": \"^0.30.5\",\n    \"drizzle-orm\": \"^0.41.0\",\n    \"mysql2\": \"^3.11.0\",\n    \"next\": \"^15.5.9\",\n    \"next-auth\": \"^4.24.7\",\n    \"postgres\": \"^3.4.4\",\n    \"prettier\": \"^3.5.3\",\n    \"prettier-plugin-tailwindcss\": \"^0.6.11\",\n    \"prisma\": \"^6.6.0\",\n    \"react\": \"^19.2.3\",\n    \"react-dom\": \"^19.2.3\",\n    \"superjson\": \"^2.2.1\",\n    \"tailwindcss\": \"^4.0.15\",\n    \"tsup\": \"^6.7.0\",\n    \"type-fest\": \"^3.13.1\",\n    \"typescript\": \"^5.8.2\",\n    \"zod\": \"^3.24.2\"\n  }\n}\n"
  },
  {
    "path": "cli/prettier.config.mjs",
    "content": "import baseConfig from \"../prettier.config.mjs\";\n\n/**\n * @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions &\n *       import(\"@ianvs/prettier-plugin-sort-imports\").PluginConfig}\n */\nconst config = {\n  ...baseConfig,\n  arrowParens: \"always\",\n  plugins: [\n    \"@ianvs/prettier-plugin-sort-imports\",\n    \"prettier-plugin-tailwindcss\",\n  ],\n  tailwindConfig: \"./template/extras/config/tailwind.config.ts\",\n  trailingComma: \"es5\",\n  importOrder: [\"<THIRD_PARTY_MODULES>\", \"\", \"^~/\", \"^[.][.]/\", \"^[.]/\"],\n  importOrderParserPlugins: [\"typescript\", \"jsx\", \"decorators-legacy\"],\n  importOrderTypeScriptVersion: \"4.4.0\",\n};\n\nexport default config;\n"
  },
  {
    "path": "cli/src/cli/index.ts",
    "content": "import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\n\nimport { CREATE_T3_APP, DEFAULT_APP_NAME } from \"~/consts.js\";\nimport {\n  databaseProviders,\n  type AvailablePackages,\n  type DatabaseProvider,\n} from \"~/installers/index.js\";\nimport { getVersion } from \"~/utils/getT3Version.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\nimport { IsTTYError } from \"~/utils/isTTYError.js\";\nimport { logger } from \"~/utils/logger.js\";\nimport { validateAppName } from \"~/utils/validateAppName.js\";\nimport { validateImportAlias } from \"~/utils/validateImportAlias.js\";\n\ninterface CliFlags {\n  noGit: boolean;\n  noInstall: boolean;\n  default: boolean;\n  importAlias: string;\n\n  /** @internal Used in CI. */\n  CI: boolean;\n  /** @internal Used in CI. */\n  tailwind: boolean;\n  /** @internal Used in CI. */\n  trpc: boolean;\n  /** @internal Used in CI. */\n  prisma: boolean;\n  /** @internal Used in CI. */\n  drizzle: boolean;\n  /** @internal Used in CI. */\n  nextAuth: boolean;\n  /** @internal Used in CI. */\n  betterAuth: boolean;\n  /** @internal Used in CI. */\n  appRouter: boolean;\n  /** @internal Used in CI. */\n  dbProvider: DatabaseProvider;\n  /** @internal Used in CI */\n  eslint: boolean;\n  /** @internal Used in CI */\n  biome: boolean;\n}\n\ninterface CliResults {\n  appName: string;\n  packages: AvailablePackages[];\n  flags: CliFlags;\n  databaseProvider: DatabaseProvider;\n}\n\nconst defaultOptions: CliResults = {\n  appName: DEFAULT_APP_NAME,\n  packages: [\"nextAuth\", \"prisma\", \"tailwind\", \"trpc\", \"eslint\"],\n  flags: {\n    noGit: false,\n    noInstall: false,\n    default: false,\n    CI: false,\n    tailwind: false,\n    trpc: false,\n    prisma: false,\n    drizzle: false,\n    nextAuth: false,\n    betterAuth: false,\n    importAlias: \"~/\",\n    appRouter: false,\n    dbProvider: \"sqlite\",\n    eslint: false,\n    biome: false,\n  },\n  databaseProvider: \"sqlite\",\n};\n\nexport const runCli = async (): Promise<CliResults> => {\n  const cliResults = defaultOptions;\n\n  const program = new Command()\n    .name(CREATE_T3_APP)\n    .description(\"A CLI for creating web applications with the t3 stack\")\n    .argument(\n      \"[dir]\",\n      \"The name of the application, as well as the name of the directory to create\"\n    )\n    .option(\n      \"--noGit\",\n      \"Explicitly tell the CLI to not initialize a new git repo in the project\",\n      false\n    )\n    .option(\n      \"--noInstall\",\n      \"Explicitly tell the CLI to not run the package manager's install command\",\n      false\n    )\n    .option(\n      \"-y, --default\",\n      \"Bypass the CLI and use all default options to bootstrap a new t3-app\",\n      false\n    )\n    /** START CI-FLAGS */\n    /**\n     * @experimental Used for CI E2E tests. If any of the following option-flags are provided, we\n     *               skip prompting.\n     */\n    .option(\"--CI\", \"Boolean value if we're running in CI\", false)\n    /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--tailwind [boolean]\",\n      \"Experimental: Boolean value if we should install Tailwind CSS. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--nextAuth [boolean]\",\n      \"Experimental: Boolean value if we should install NextAuth.js. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--betterAuth [boolean]\",\n      \"Experimental: Boolean value if we should install BetterAuth. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--prisma [boolean]\",\n      \"Experimental: Boolean value if we should install Prisma. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--drizzle [boolean]\",\n      \"Experimental: Boolean value if we should install Drizzle. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"--trpc [boolean]\",\n      \"Experimental: Boolean value if we should install tRPC. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */\n    .option(\n      \"-i, --import-alias [alias]\",\n      \"Explicitly tell the CLI to use a custom import alias\",\n      defaultOptions.flags.importAlias\n    )\n    .option(\n      \"--dbProvider [provider]\",\n      `Choose a database provider to use. Possible values: ${databaseProviders.join(\n        \", \"\n      )}`,\n      defaultOptions.flags.dbProvider\n    )\n    .option(\n      \"--appRouter [boolean]\",\n      \"Explicitly tell the CLI to use the new Next.js app router\",\n      (value) => !!value && value !== \"false\"\n    )\n    .option(\n      \"--eslint [boolean]\",\n      \"Experimental: Boolean value if we should install eslint and prettier. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    .option(\n      \"--biome [boolean]\",\n      \"Experimental: Boolean value if we should install biome. Must be used in conjunction with `--CI`.\",\n      (value) => !!value && value !== \"false\"\n    )\n    /** END CI-FLAGS */\n    .version(getVersion(), \"-v, --version\", \"Display the version number\")\n    .addHelpText(\n      \"afterAll\",\n      `\\n The t3 stack was inspired by ${chalk\n        .hex(\"#E8DCFF\")\n        .bold(\n          \"@t3dotgg\"\n        )} and has been used to build awesome fullstack applications like ${chalk\n        .hex(\"#E24A8D\")\n        .underline(\"https://ping.gg\")} \\n`\n    )\n    .parse(process.argv);\n\n  // FIXME: TEMPORARY WARNING WHEN USING YARN 3. SEE ISSUE #57\n  if (process.env.npm_config_user_agent?.startsWith(\"yarn/3\")) {\n    logger.warn(`  WARNING: It looks like you are using Yarn 3. This is currently not supported,\n  and likely to result in a crash. Please run create-t3-app with another\n  package manager such as pnpm, npm, or Yarn Classic.\n  See: https://github.com/t3-oss/create-t3-app/issues/57`);\n  }\n\n  // Needs to be separated outside the if statement to correctly infer the type as string | undefined\n  const cliProvidedName = program.args[0];\n  if (cliProvidedName) {\n    cliResults.appName = cliProvidedName;\n  }\n\n  cliResults.flags = program.opts();\n\n  /** @internal Used for CI E2E tests. */\n  if (cliResults.flags.CI) {\n    cliResults.packages = [];\n    if (cliResults.flags.trpc) cliResults.packages.push(\"trpc\");\n    if (cliResults.flags.tailwind) cliResults.packages.push(\"tailwind\");\n    if (cliResults.flags.prisma) cliResults.packages.push(\"prisma\");\n    if (cliResults.flags.drizzle) cliResults.packages.push(\"drizzle\");\n    if (cliResults.flags.nextAuth) cliResults.packages.push(\"nextAuth\");\n    if (cliResults.flags.betterAuth) cliResults.packages.push(\"betterAuth\");\n    if (cliResults.flags.eslint) cliResults.packages.push(\"eslint\");\n    if (cliResults.flags.biome) cliResults.packages.push(\"biome\");\n    if (cliResults.flags.prisma && cliResults.flags.drizzle) {\n      // We test a matrix of all possible combination of packages in CI. Checking for impossible\n      // combinations here and exiting gracefully is easier than changing the CI matrix to exclude\n      // invalid combinations. We are using an \"OK\" exit code so CI continues with the next combination.\n      logger.warn(\"Incompatible combination Prisma + Drizzle. Exiting.\");\n      process.exit(0);\n    }\n    if (cliResults.flags.biome && cliResults.flags.eslint) {\n      logger.warn(\"Incompatible combination Biome + ESLint. Exiting.\");\n      process.exit(0);\n    }\n    if (cliResults.flags.nextAuth && cliResults.flags.betterAuth) {\n      logger.warn(\"Incompatible combination NextAuth + BetterAuth. Exiting.\");\n      process.exit(0);\n    }\n    if (databaseProviders.includes(cliResults.flags.dbProvider) === false) {\n      logger.warn(\n        `Incompatible database provided. Use: ${databaseProviders.join(\", \")}. Exiting.`\n      );\n      process.exit(0);\n    }\n\n    cliResults.databaseProvider =\n      cliResults.packages.includes(\"drizzle\") ||\n      cliResults.packages.includes(\"prisma\")\n        ? cliResults.flags.dbProvider\n        : \"sqlite\";\n\n    return cliResults;\n  }\n\n  if (cliResults.flags.default) {\n    return cliResults;\n  }\n\n  // Explained below why this is in a try/catch block\n  try {\n    if (process.env.TERM_PROGRAM?.toLowerCase().includes(\"mintty\")) {\n      logger.warn(`  WARNING: It looks like you are using MinTTY, which is non-interactive. This is most likely because you are\n  using Git Bash. If that's that case, please use Git Bash from another terminal, such as Windows Terminal. Alternatively, you\n  can provide the arguments from the CLI directly: https://create.t3.gg/en/installation#experimental-usage to skip the prompts.`);\n\n      throw new IsTTYError(\"Non-interactive environment\");\n    }\n\n    // if --CI flag is set, we are running in CI mode and should not prompt the user\n\n    const pkgManager = getUserPkgManager();\n\n    const project = await p.group(\n      {\n        ...(!cliProvidedName && {\n          name: () =>\n            p.text({\n              message: \"What will your project be called?\",\n              defaultValue: cliProvidedName,\n              validate: validateAppName,\n            }),\n        }),\n        language: () => {\n          return p.select({\n            message: \"Will you be using TypeScript or JavaScript?\",\n            options: [\n              { value: \"typescript\", label: \"TypeScript\" },\n              { value: \"javascript\", label: \"JavaScript\" },\n            ],\n            initialValue: \"typescript\",\n          });\n        },\n        _: ({ results }) =>\n          results.language === \"javascript\"\n            ? p.note(chalk.redBright(\"Wrong answer, using TypeScript instead\"))\n            : undefined,\n        styling: () => {\n          return p.confirm({\n            message: \"Will you be using Tailwind CSS for styling?\",\n          });\n        },\n        trpc: () => {\n          return p.confirm({\n            message: \"Would you like to use tRPC?\",\n          });\n        },\n        authentication: () => {\n          return p.select({\n            message: \"What authentication provider would you like to use?\",\n            options: [\n              { value: \"none\", label: \"None\" },\n              { value: \"next-auth\", label: \"NextAuth.js\" },\n              { value: \"better-auth\", label: \"BetterAuth\" },\n              // Maybe later\n              // { value: \"clerk\", label: \"Clerk\" },\n            ],\n            initialValue: \"none\",\n          });\n        },\n        database: () => {\n          return p.select({\n            message: \"What database ORM would you like to use?\",\n            options: [\n              { value: \"none\", label: \"None\" },\n              { value: \"prisma\", label: \"Prisma\" },\n              { value: \"drizzle\", label: \"Drizzle\" },\n            ],\n            initialValue: \"none\",\n          });\n        },\n        appRouter: () => {\n          return p.confirm({\n            message: \"Would you like to use Next.js App Router?\",\n            initialValue: true,\n          });\n        },\n        databaseProvider: ({ results }) => {\n          if (results.database === \"none\") return;\n          return p.select({\n            message: \"What database provider would you like to use?\",\n            options: [\n              { value: \"sqlite\", label: \"SQLite (LibSQL)\" },\n              { value: \"mysql\", label: \"MySQL\" },\n              { value: \"postgres\", label: \"PostgreSQL\" },\n              { value: \"planetscale\", label: \"PlanetScale\" },\n            ],\n            initialValue: \"sqlite\",\n          });\n        },\n        linter: () => {\n          return p.select({\n            message:\n              \"Would you like to use ESLint and Prettier or Biome for linting and formatting?\",\n            options: [\n              { value: \"eslint\", label: \"ESLint/Prettier\" },\n              { value: \"biome\", label: \"Biome\" },\n            ],\n            initialValue: \"eslint\",\n          });\n        },\n        ...(!cliResults.flags.noGit && {\n          git: () => {\n            return p.confirm({\n              message:\n                \"Should we initialize a Git repository and stage the changes?\",\n              initialValue: !defaultOptions.flags.noGit,\n            });\n          },\n        }),\n        ...(!cliResults.flags.noInstall && {\n          install: () => {\n            return p.confirm({\n              message:\n                `Should we run '${pkgManager}` +\n                (pkgManager === \"yarn\" ? `'?` : ` install' for you?`),\n              initialValue: !defaultOptions.flags.noInstall,\n            });\n          },\n        }),\n        importAlias: () => {\n          return p.text({\n            message: \"What import alias would you like to use?\",\n            defaultValue: defaultOptions.flags.importAlias,\n            placeholder: defaultOptions.flags.importAlias,\n            validate: validateImportAlias,\n          });\n        },\n      },\n      {\n        onCancel() {\n          process.exit(1);\n        },\n      }\n    );\n\n    const packages: AvailablePackages[] = [];\n    if (project.styling) packages.push(\"tailwind\");\n    if (project.trpc) packages.push(\"trpc\");\n    if (project.authentication === \"next-auth\") packages.push(\"nextAuth\");\n    if (project.authentication === \"better-auth\") packages.push(\"betterAuth\");\n    if (project.database === \"prisma\") packages.push(\"prisma\");\n    if (project.database === \"drizzle\") packages.push(\"drizzle\");\n    if (project.linter === \"eslint\") packages.push(\"eslint\");\n    if (project.linter === \"biome\") packages.push(\"biome\");\n\n    return {\n      appName: project.name ?? cliResults.appName,\n      packages,\n      databaseProvider:\n        (project.databaseProvider as DatabaseProvider) || \"sqlite\",\n      flags: {\n        ...cliResults.flags,\n        appRouter: project.appRouter ?? cliResults.flags.appRouter,\n        noGit: !project.git || cliResults.flags.noGit,\n        noInstall: !project.install || cliResults.flags.noInstall,\n        importAlias: project.importAlias ?? cliResults.flags.importAlias,\n      },\n    };\n  } catch (err) {\n    // If the user is not calling create-t3-app from an interactive terminal, inquirer will throw an IsTTYError\n    // If this happens, we catch the error, tell the user what has happened, and then continue to run the program with a default t3 app\n    if (err instanceof IsTTYError) {\n      logger.warn(`\n  ${CREATE_T3_APP} needs an interactive terminal to provide options`);\n\n      const shouldContinue = await p.confirm({\n        message: `Continue scaffolding a default T3 app?`,\n        initialValue: true,\n      });\n\n      if (!shouldContinue) {\n        logger.info(\"Exiting...\");\n        process.exit(0);\n      }\n\n      logger.info(`Bootstrapping a default T3 app in ./${cliResults.appName}`);\n    } else {\n      throw err;\n    }\n  }\n\n  return cliResults;\n};\n"
  },
  {
    "path": "cli/src/consts.ts",
    "content": "import path from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// With the move to TSUP as a build tool, this keeps path routes in other files (installers, loaders, etc) in check more easily.\n// Path is in relation to a single index.js file inside ./dist\nconst __filename = fileURLToPath(import.meta.url);\nconst distPath = path.dirname(__filename);\nexport const PKG_ROOT = path.join(distPath, \"../\");\n\n//export const PKG_ROOT = path.dirname(require.main.filename);\n\nexport const TITLE_TEXT = `   ___ ___ ___   __ _____ ___   _____ ____    __   ___ ___\n  / __| _ \\\\ __| /  \\\\_   _| __| |_   _|__ /   /  \\\\ | _ \\\\ _ \\\\\n | (__|   / _| / /\\\\ \\\\| | | _|    | |  |_ \\\\  / /\\\\ \\\\|  _/  _/\n  \\\\___|_|_\\\\___|_/‾‾\\\\_\\\\_| |___|   |_| |___/ /_/‾‾\\\\_\\\\_| |_|\n`;\nexport const DEFAULT_APP_NAME = \"my-t3-app\";\nexport const CREATE_T3_APP = \"create-t3-app\";\n"
  },
  {
    "path": "cli/src/helpers/createProject.ts",
    "content": "import fs from \"fs\";\nimport path from \"path\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { installPackages } from \"~/helpers/installPackages.js\";\nimport { scaffoldProject } from \"~/helpers/scaffoldProject.js\";\nimport {\n  selectAppFile,\n  selectIndexFile,\n  selectLayoutFile,\n  selectPageFile,\n} from \"~/helpers/selectBoilerplate.js\";\nimport {\n  type DatabaseProvider,\n  type PkgInstallerMap,\n} from \"~/installers/index.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\n\ninterface CreateProjectOptions {\n  projectName: string;\n  packages: PkgInstallerMap;\n  scopedAppName: string;\n  noInstall: boolean;\n  importAlias: string;\n  appRouter: boolean;\n  databaseProvider: DatabaseProvider;\n}\n\nexport const createProject = async ({\n  projectName,\n  scopedAppName,\n  packages,\n  noInstall,\n  appRouter,\n  databaseProvider,\n}: CreateProjectOptions) => {\n  const pkgManager = getUserPkgManager();\n  const projectDir = path.resolve(process.cwd(), projectName);\n\n  // Bootstraps the base Next.js application\n  await scaffoldProject({\n    projectName,\n    projectDir,\n    pkgManager,\n    scopedAppName,\n    noInstall,\n    appRouter,\n    databaseProvider,\n  });\n\n  // Install the selected packages\n  installPackages({\n    projectName,\n    scopedAppName,\n    projectDir,\n    pkgManager,\n    packages,\n    noInstall,\n    appRouter,\n    databaseProvider,\n  });\n\n  // Select necessary _app,index / layout,page files\n  if (appRouter) {\n    // Replace next.config\n    fs.copyFileSync(\n      path.join(PKG_ROOT, \"template/extras/config/next-config-appdir.js\"),\n      path.join(projectDir, \"next.config.js\")\n    );\n\n    selectLayoutFile({ projectDir, packages });\n    selectPageFile({ projectDir, packages });\n  } else {\n    selectAppFile({ projectDir, packages });\n    selectIndexFile({ projectDir, packages });\n  }\n\n  // If no tailwind, select use css modules\n  if (!packages.tailwind.inUse) {\n    const indexModuleCss = path.join(\n      PKG_ROOT,\n      \"template/extras/src/index.module.css\"\n    );\n    const indexModuleCssDest = path.join(\n      projectDir,\n      \"src\",\n      appRouter ? \"app\" : \"pages\",\n      \"index.module.css\"\n    );\n    fs.copyFileSync(indexModuleCss, indexModuleCssDest);\n  }\n\n  return projectDir;\n};\n"
  },
  {
    "path": "cli/src/helpers/format.ts",
    "content": "import chalk from \"chalk\";\nimport { execa } from \"execa\";\nimport ora from \"ora\";\n\nimport { type PackageManager } from \"~/utils/getUserPkgManager.js\";\nimport { logger } from \"~/utils/logger.js\";\n\n// Runs format and lint command to ensure created repository is tidy upon creation\nexport const formatProject = async ({\n  pkgManager,\n  projectDir,\n  eslint,\n  biome,\n}: {\n  pkgManager: PackageManager;\n  projectDir: string;\n  eslint: boolean;\n  biome: boolean;\n}) => {\n  logger.info(`Formatting project with ${eslint ? \"prettier\" : \"biome\"}...`);\n  const spinner = ora(\"Running format command\\n\").start();\n\n  if (eslint) {\n    await execa(pkgManager, [\"run\", \"format:write\"], {\n      cwd: projectDir,\n    });\n  } else if (biome) {\n    await execa(pkgManager, [\"run\", \"check:unsafe\"], {\n      cwd: projectDir,\n    });\n  }\n  spinner.succeed(`${chalk.green(\"Successfully formatted project\")}`);\n};\n"
  },
  {
    "path": "cli/src/helpers/git.ts",
    "content": "import { execSync } from \"child_process\";\nimport path from \"path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { execa } from \"execa\";\nimport fs from \"fs-extra\";\nimport ora from \"ora\";\n\nimport { logger } from \"~/utils/logger.js\";\n\nconst isGitInstalled = (dir: string): boolean => {\n  try {\n    execSync(\"git --version\", { cwd: dir });\n    return true;\n  } catch {\n    return false;\n  }\n};\n\n/** @returns Whether or not the provided directory has a `.git` subdirectory in it. */\nexport const isRootGitRepo = (dir: string): boolean => {\n  return fs.existsSync(path.join(dir, \".git\"));\n};\n\n/** @returns Whether or not this directory or a parent directory has a `.git` directory. */\nexport const isInsideGitRepo = async (dir: string): Promise<boolean> => {\n  try {\n    // If this command succeeds, we're inside a git repo\n    await execa(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n      cwd: dir,\n      stdout: \"ignore\",\n    });\n    return true;\n  } catch {\n    // Else, it will throw a git-error and we return false\n    return false;\n  }\n};\n\nconst getGitVersion = () => {\n  const stdout = execSync(\"git --version\").toString().trim();\n  const gitVersionTag = stdout.split(\" \")[2];\n  const major = gitVersionTag?.split(\".\")[0];\n  const minor = gitVersionTag?.split(\".\")[1];\n  return { major: Number(major), minor: Number(minor) };\n};\n\n/** @returns The git config value of \"init.defaultBranch\". If it is not set, returns \"main\". */\nconst getDefaultBranch = () => {\n  const stdout = execSync(\"git config --global init.defaultBranch || echo main\")\n    .toString()\n    .trim();\n\n  return stdout;\n};\n\n// This initializes the Git-repository for the project\nexport const initializeGit = async (projectDir: string) => {\n  logger.info(\"Initializing Git...\");\n\n  if (!isGitInstalled(projectDir)) {\n    logger.warn(\"Git is not installed. Skipping Git initialization.\");\n    return;\n  }\n\n  const spinner = ora(\"Creating a new git repo...\\n\").start();\n\n  const isRoot = isRootGitRepo(projectDir);\n  const isInside = await isInsideGitRepo(projectDir);\n  const dirName = path.parse(projectDir).name; // skip full path for logging\n\n  if (isInside && isRoot) {\n    // Dir is a root git repo\n    spinner.stop();\n    const overwriteGit = await p.confirm({\n      message: `${chalk.redBright.bold(\n        \"Warning:\"\n      )} Git is already initialized in \"${dirName}\". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,\n      initialValue: false,\n    });\n\n    if (!overwriteGit) {\n      spinner.info(\"Skipping Git initialization.\");\n      return;\n    }\n    // Deleting the .git folder\n    fs.removeSync(path.join(projectDir, \".git\"));\n  } else if (isInside && !isRoot) {\n    // Dir is inside a git worktree\n    spinner.stop();\n    const initializeChildGitRepo = await p.confirm({\n      message: `${chalk.redBright.bold(\n        \"Warning:\"\n      )} \"${dirName}\" is already in a git worktree. Would you still like to initialize a new git repository in this directory?`,\n      initialValue: false,\n    });\n    if (!initializeChildGitRepo) {\n      spinner.info(\"Skipping Git initialization.\");\n      return;\n    }\n  }\n\n  // We're good to go, initializing the git repo\n  try {\n    const branchName = getDefaultBranch();\n\n    // --initial-branch flag was added in git v2.28.0\n    const { major, minor } = getGitVersion();\n    if (major < 2 || (major == 2 && minor < 28)) {\n      await execa(\"git\", [\"init\"], { cwd: projectDir });\n      // symbolic-ref is used here due to refs/heads/master not existing\n      // It is only created after the first commit\n      // https://superuser.com/a/1419674\n      await execa(\"git\", [\"symbolic-ref\", \"HEAD\", `refs/heads/${branchName}`], {\n        cwd: projectDir,\n      });\n    } else {\n      await execa(\"git\", [\"init\", `--initial-branch=${branchName}`], {\n        cwd: projectDir,\n      });\n    }\n    await execa(\"git\", [\"add\", \".\"], { cwd: projectDir });\n    spinner.succeed(\n      `${chalk.green(\"Successfully initialized and staged\")} ${chalk.green.bold(\n        \"git\"\n      )}\\n`\n    );\n  } catch {\n    // Safeguard, should be unreachable\n    spinner.fail(\n      `${chalk.bold.red(\n        \"Failed:\"\n      )} could not initialize git. Update git to the latest version!\\n`\n    );\n  }\n};\n"
  },
  {
    "path": "cli/src/helpers/installDependencies.ts",
    "content": "import chalk from \"chalk\";\nimport { execa, type StdioOption } from \"execa\";\nimport ora, { type Ora } from \"ora\";\n\nimport {\n  getUserPkgManager,\n  type PackageManager,\n} from \"~/utils/getUserPkgManager.js\";\nimport { logger } from \"~/utils/logger.js\";\n\nconst execWithSpinner = async (\n  projectDir: string,\n  pkgManager: PackageManager,\n  options: {\n    args?: string[];\n    stdout?: StdioOption;\n    onDataHandle?: (spinner: Ora) => (data: Buffer) => void;\n  }\n) => {\n  const { onDataHandle, args = [\"install\"], stdout = \"pipe\" } = options;\n\n  const spinner = ora(`Running ${pkgManager} install...`).start();\n  const subprocess = execa(pkgManager, args, { cwd: projectDir, stdout });\n\n  await new Promise<void>((res, rej) => {\n    if (onDataHandle) {\n      subprocess.stdout?.on(\"data\", onDataHandle(spinner));\n    }\n\n    void subprocess.on(\"error\", (e) => rej(e));\n    void subprocess.on(\"close\", () => res());\n  });\n\n  return spinner;\n};\n\nconst runInstallCommand = async (\n  pkgManager: PackageManager,\n  projectDir: string\n): Promise<Ora | null> => {\n  switch (pkgManager) {\n    // When using npm, inherit the stderr stream so that the progress bar is shown\n    case \"npm\":\n      await execa(pkgManager, [\"install\"], {\n        cwd: projectDir,\n        stderr: \"inherit\",\n      });\n\n      return null;\n    // When using yarn or pnpm, use the stdout stream and ora spinner to show the progress\n    case \"pnpm\":\n      return execWithSpinner(projectDir, pkgManager, {\n        onDataHandle: (spinner) => (data) => {\n          const text = data.toString();\n\n          if (text.includes(\"Progress\")) {\n            spinner.text = text.includes(\"|\")\n              ? (text.split(\" | \")[1] ?? \"\")\n              : text;\n          }\n        },\n      });\n    case \"yarn\":\n      return execWithSpinner(projectDir, pkgManager, {\n        onDataHandle: (spinner) => (data) => {\n          spinner.text = data.toString();\n        },\n      });\n    // When using bun, the stdout stream is ignored and the spinner is shown\n    case \"bun\":\n      return execWithSpinner(projectDir, pkgManager, { stdout: \"ignore\" });\n  }\n};\n\nexport const installDependencies = async ({\n  projectDir,\n}: {\n  projectDir: string;\n}) => {\n  logger.info(\"Installing dependencies...\");\n  const pkgManager = getUserPkgManager();\n\n  const installSpinner = await runInstallCommand(pkgManager, projectDir);\n\n  // If the spinner was used to show the progress, use succeed method on it\n  // If not, use the succeed on a new spinner\n  (installSpinner ?? ora()).succeed(\n    chalk.green(\"Successfully installed dependencies!\\n\")\n  );\n};\n"
  },
  {
    "path": "cli/src/helpers/installPackages.ts",
    "content": "import chalk from \"chalk\";\nimport ora from \"ora\";\n\nimport {\n  type InstallerOptions,\n  type PkgInstallerMap,\n} from \"~/installers/index.js\";\nimport { logger } from \"~/utils/logger.js\";\n\ntype InstallPackagesOptions = InstallerOptions & {\n  packages: PkgInstallerMap;\n};\n// This runs the installer for all the packages that the user has selected\nexport const installPackages = (options: InstallPackagesOptions) => {\n  const { packages } = options;\n  logger.info(\"Adding boilerplate...\");\n\n  for (const [name, pkgOpts] of Object.entries(packages)) {\n    if (pkgOpts.inUse) {\n      const spinner = ora(`Boilerplating ${name}...`).start();\n      pkgOpts.installer(options);\n      spinner.succeed(\n        chalk.green(\n          `Successfully setup boilerplate for ${chalk.green.bold(name)}`\n        )\n      );\n    }\n  }\n\n  logger.info(\"\");\n};\n"
  },
  {
    "path": "cli/src/helpers/logNextSteps.ts",
    "content": "import { DEFAULT_APP_NAME } from \"~/consts.js\";\nimport { type InstallerOptions } from \"~/installers/index.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\nimport { logger } from \"~/utils/logger.js\";\nimport { isInsideGitRepo, isRootGitRepo } from \"./git.js\";\n\n// This logs the next steps that the user should take in order to advance the project\nexport const logNextSteps = async ({\n  projectName = DEFAULT_APP_NAME,\n  packages,\n  noInstall,\n  projectDir,\n  databaseProvider,\n}: Pick<\n  InstallerOptions,\n  | \"projectName\"\n  | \"packages\"\n  | \"noInstall\"\n  | \"projectDir\"\n  | \"appRouter\"\n  | \"databaseProvider\"\n>) => {\n  const pkgManager = getUserPkgManager();\n\n  logger.info(\"Next steps:\");\n  if (projectName !== \".\") {\n    logger.info(`  cd ${projectName}`);\n  }\n  if (noInstall) {\n    // To reflect yarn's default behavior of installing packages when no additional args provided\n    if (pkgManager === \"yarn\") {\n      logger.info(`  ${pkgManager}`);\n    } else {\n      logger.info(`  ${pkgManager} install`);\n    }\n  }\n\n  if ([\"postgres\", \"mysql\"].includes(databaseProvider)) {\n    logger.info(\"  Start up a database, if needed using './start-database.sh'\");\n  }\n\n  if (packages?.prisma.inUse || packages?.drizzle.inUse) {\n    if ([\"npm\", \"bun\"].includes(pkgManager)) {\n      logger.info(`  ${pkgManager} run db:push`);\n    } else {\n      logger.info(`  ${pkgManager} db:push`);\n    }\n  }\n\n  if (packages?.nextAuth.inUse) {\n    logger.info(\n      `  Fill in your .env with necessary values. See https://create.t3.gg/en/usage/first-steps for more info.`\n    );\n  }\n\n  if ([\"npm\", \"bun\"].includes(pkgManager)) {\n    logger.info(`  ${pkgManager} run dev`);\n  } else {\n    logger.info(`  ${pkgManager} dev`);\n  }\n\n  if (!(await isInsideGitRepo(projectDir)) && !isRootGitRepo(projectDir)) {\n    logger.info(`  git init`);\n  }\n  logger.info(`  git commit -m \"initial commit\"`);\n};\n"
  },
  {
    "path": "cli/src/helpers/scaffoldProject.ts",
    "content": "import path from \"path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport ora from \"ora\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type InstallerOptions } from \"~/installers/index.js\";\nimport { logger } from \"~/utils/logger.js\";\n\n// This bootstraps the base Next.js application\nexport const scaffoldProject = async ({\n  projectName,\n  projectDir,\n  pkgManager,\n  noInstall,\n}: InstallerOptions) => {\n  const srcDir = path.join(PKG_ROOT, \"template/base\");\n\n  if (!noInstall) {\n    logger.info(`\\nUsing: ${chalk.cyan.bold(pkgManager)}\\n`);\n  } else {\n    logger.info(\"\");\n  }\n\n  const spinner = ora(`Scaffolding in: ${projectDir}...\\n`).start();\n\n  if (fs.existsSync(projectDir)) {\n    if (fs.readdirSync(projectDir).length === 0) {\n      if (projectName !== \".\")\n        spinner.info(\n          `${chalk.cyan.bold(projectName)} exists but is empty, continuing...\\n`\n        );\n    } else {\n      spinner.stopAndPersist();\n      const overwriteDir = await p.select({\n        message: `${chalk.redBright.bold(\"Warning:\")} ${chalk.cyan.bold(\n          projectName\n        )} already exists and isn't empty. How would you like to proceed?`,\n        options: [\n          {\n            label: \"Abort installation (recommended)\",\n            value: \"abort\",\n          },\n          {\n            label: \"Clear the directory and continue installation\",\n            value: \"clear\",\n          },\n          {\n            label: \"Continue installation and overwrite conflicting files\",\n            value: \"overwrite\",\n          },\n        ],\n        initialValue: \"abort\",\n      });\n\n      if (p.isCancel(overwriteDir) || overwriteDir === \"abort\") {\n        spinner.fail(\"Aborting installation...\");\n        process.exit(1);\n      }\n\n      const confirmOverwriteDir = await p.confirm({\n        message: `Are you sure you want to ${\n          overwriteDir === \"clear\"\n            ? \"clear the directory\"\n            : \"overwrite conflicting files\"\n        }?`,\n        initialValue: false,\n      });\n\n      if (p.isCancel(confirmOverwriteDir) || !confirmOverwriteDir) {\n        spinner.fail(\"Aborting installation...\");\n        process.exit(1);\n      }\n\n      if (overwriteDir === \"clear\") {\n        spinner.info(\n          `Emptying ${chalk.cyan.bold(projectName)} and creating t3 app..\\n`\n        );\n        fs.emptyDirSync(projectDir);\n      }\n    }\n  }\n\n  spinner.start();\n\n  fs.copySync(srcDir, projectDir);\n  fs.renameSync(\n    path.join(projectDir, \"_gitignore\"),\n    path.join(projectDir, \".gitignore\")\n  );\n\n  const scaffoldedName =\n    projectName === \".\" ? \"App\" : chalk.cyan.bold(projectName);\n\n  spinner.succeed(\n    `${scaffoldedName} ${chalk.green(\"scaffolded successfully!\")}\\n`\n  );\n};\n"
  },
  {
    "path": "cli/src/helpers/selectBoilerplate.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type InstallerOptions } from \"~/installers/index.js\";\n\ntype SelectBoilerplateProps = Required<\n  Pick<InstallerOptions, \"packages\" | \"projectDir\">\n>;\n// This generates the _app.tsx file that is used to render the app\nexport const selectAppFile = ({\n  projectDir,\n  packages,\n}: SelectBoilerplateProps) => {\n  const appFileDir = path.join(PKG_ROOT, \"template/extras/src/pages/_app\");\n\n  const usingTw = packages.tailwind.inUse;\n  const usingTRPC = packages.trpc.inUse;\n  const usingAuth = packages?.nextAuth.inUse ?? packages?.betterAuth.inUse;\n  const usingBetterAuth = packages?.betterAuth.inUse;\n\n  let appFile = \"base.tsx\";\n  if (usingTRPC && usingTw && usingBetterAuth) {\n    appFile = \"with-better-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingBetterAuth) {\n    appFile = \"with-better-auth-trpc.tsx\";\n  } else if (usingTRPC && usingTw && usingAuth) {\n    appFile = \"with-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingAuth) {\n    appFile = \"with-auth-trpc.tsx\";\n  } else if (usingTRPC && usingTw) {\n    appFile = \"with-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw) {\n    appFile = \"with-trpc.tsx\";\n  } else if (!usingTRPC && usingTw) {\n    appFile = \"with-tw.tsx\";\n  } else if (usingAuth && usingTw) {\n    appFile = \"with-auth-tw.tsx\";\n  } else if (usingAuth && !usingTw) {\n    appFile = \"with-auth.tsx\";\n  }\n\n  const appSrc = path.join(appFileDir, appFile);\n  const appDest = path.join(projectDir, \"src/pages/_app.tsx\");\n  fs.copySync(appSrc, appDest);\n};\n\n// Similar to _app, but for app router\nexport const selectLayoutFile = ({\n  projectDir,\n  packages,\n}: SelectBoilerplateProps) => {\n  const layoutFileDir = path.join(PKG_ROOT, \"template/extras/src/app/layout\");\n\n  const usingTw = packages.tailwind.inUse;\n  const usingTRPC = packages.trpc.inUse;\n  let layoutFile = \"base.tsx\";\n  if (usingTRPC && usingTw) {\n    layoutFile = \"with-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw) {\n    layoutFile = \"with-trpc.tsx\";\n  } else if (!usingTRPC && usingTw) {\n    layoutFile = \"with-tw.tsx\";\n  }\n\n  const appSrc = path.join(layoutFileDir, layoutFile);\n  const appDest = path.join(projectDir, \"src/app/layout.tsx\");\n  fs.copySync(appSrc, appDest);\n};\n\n// This selects the proper index.tsx to be used that showcases the chosen tech\nexport const selectIndexFile = ({\n  projectDir,\n  packages,\n}: SelectBoilerplateProps) => {\n  const indexFileDir = path.join(PKG_ROOT, \"template/extras/src/pages/index\");\n\n  const usingTRPC = packages.trpc.inUse;\n  const usingTw = packages.tailwind.inUse;\n  const usingBetterAuth = packages?.betterAuth.inUse;\n  const usingNextAuth = packages?.nextAuth.inUse;\n  const usingAuth = usingNextAuth || usingBetterAuth;\n\n  let indexFile = \"base.tsx\";\n  if (usingTRPC && usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-trpc.tsx\";\n  } else if (!usingTRPC && usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-tw.tsx\";\n  } else if (!usingTRPC && !usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth.tsx\";\n  } else if (usingTRPC && usingTw && usingAuth) {\n    indexFile = \"with-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingAuth) {\n    indexFile = \"with-auth-trpc.tsx\";\n  } else if (usingTRPC && usingTw) {\n    indexFile = \"with-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw) {\n    indexFile = \"with-trpc.tsx\";\n  } else if (!usingTRPC && usingTw) {\n    indexFile = \"with-tw.tsx\";\n  }\n\n  const indexSrc = path.join(indexFileDir, indexFile);\n  const indexDest = path.join(projectDir, \"src/pages/index.tsx\");\n  fs.copySync(indexSrc, indexDest);\n};\n\n// Similar to index, but for app router\nexport const selectPageFile = ({\n  projectDir,\n  packages,\n}: SelectBoilerplateProps) => {\n  const indexFileDir = path.join(PKG_ROOT, \"template/extras/src/app/page\");\n\n  const usingTRPC = packages.trpc.inUse;\n  const usingTw = packages.tailwind.inUse;\n  const usingAuth = packages?.nextAuth.inUse;\n  const usingBetterAuth = packages?.betterAuth.inUse;\n\n  let indexFile = \"base.tsx\";\n  if (usingTRPC && usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-trpc.tsx\";\n  } else if (!usingTRPC && usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth-tw.tsx\";\n  } else if (!usingTRPC && !usingTw && usingBetterAuth) {\n    indexFile = \"with-better-auth.tsx\";\n  } else if (usingTRPC && usingTw && usingAuth) {\n    indexFile = \"with-auth-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw && usingAuth) {\n    indexFile = \"with-auth-trpc.tsx\";\n  } else if (usingTRPC && usingTw) {\n    indexFile = \"with-trpc-tw.tsx\";\n  } else if (usingTRPC && !usingTw) {\n    indexFile = \"with-trpc.tsx\";\n  } else if (!usingTRPC && usingTw) {\n    indexFile = \"with-tw.tsx\";\n  }\n\n  const indexSrc = path.join(indexFileDir, indexFile);\n  const indexDest = path.join(projectDir, \"src/app/page.tsx\");\n  fs.copySync(indexSrc, indexDest);\n};\n"
  },
  {
    "path": "cli/src/helpers/setImportAlias.ts",
    "content": "import fs from \"fs\";\nimport path from \"path\";\n\nfunction replaceTextInFiles(\n  directoryPath: string,\n  search: string,\n  replacement: string\n): void {\n  const files = fs.readdirSync(directoryPath);\n\n  files.forEach((file) => {\n    const filePath = path.join(directoryPath, file);\n    if (fs.statSync(filePath).isDirectory()) {\n      replaceTextInFiles(filePath, search, replacement);\n    } else {\n      const data = fs.readFileSync(filePath, \"utf8\");\n      const updatedData = data.replace(new RegExp(search, \"g\"), replacement);\n      fs.writeFileSync(filePath, updatedData, \"utf8\");\n    }\n  });\n}\n\nexport const setImportAlias = (projectDir: string, importAlias: string) => {\n  const normalizedImportAlias = importAlias\n    .replace(/\\*/g, \"\") // remove any wildcards (~/* -> ~/)\n    .replace(/[^/]$/, \"$&/\"); // ensure trailing slash (@ -> ~/)\n\n  // update import alias in any files if not using the default\n  replaceTextInFiles(projectDir, `~/`, normalizedImportAlias);\n};\n"
  },
  {
    "path": "cli/src/index.ts",
    "content": "#!/usr/bin/env node\nimport path from \"path\";\nimport { execa } from \"execa\";\nimport fs from \"fs-extra\";\nimport { type PackageJson } from \"type-fest\";\n\nimport { runCli } from \"~/cli/index.js\";\nimport { createProject } from \"~/helpers/createProject.js\";\nimport { initializeGit } from \"~/helpers/git.js\";\nimport { logNextSteps } from \"~/helpers/logNextSteps.js\";\nimport { setImportAlias } from \"~/helpers/setImportAlias.js\";\nimport { buildPkgInstallerMap } from \"~/installers/index.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\nimport { logger } from \"~/utils/logger.js\";\nimport { parseNameAndPath } from \"~/utils/parseNameAndPath.js\";\nimport { renderTitle } from \"~/utils/renderTitle.js\";\nimport { formatProject } from \"./helpers/format.js\";\nimport { installDependencies } from \"./helpers/installDependencies.js\";\nimport { getVersion } from \"./utils/getT3Version.js\";\nimport {\n  getNpmVersion,\n  renderVersionWarning,\n} from \"./utils/renderVersionWarning.js\";\n\ntype CT3APackageJSON = PackageJson & {\n  ct3aMetadata?: {\n    initVersion: string;\n  };\n};\n\nconst main = async () => {\n  const npmVersion = await getNpmVersion();\n  const pkgManager = getUserPkgManager();\n  renderTitle();\n  if (npmVersion) {\n    renderVersionWarning(npmVersion);\n  }\n\n  const {\n    appName,\n    packages,\n    flags: { noGit, noInstall, importAlias, appRouter },\n    databaseProvider,\n  } = await runCli();\n\n  const usePackages = buildPkgInstallerMap(packages, databaseProvider);\n\n  // e.g. dir/@mono/app returns [\"@mono/app\", \"dir/app\"]\n  const [scopedAppName, appDir] = parseNameAndPath(appName);\n\n  const projectDir = await createProject({\n    projectName: appDir,\n    scopedAppName,\n    packages: usePackages,\n    databaseProvider,\n    importAlias,\n    noInstall,\n    appRouter,\n  });\n\n  // Write name to package.json\n  const pkgJson = fs.readJSONSync(\n    path.join(projectDir, \"package.json\")\n  ) as CT3APackageJSON;\n  pkgJson.name = scopedAppName;\n  pkgJson.ct3aMetadata = { initVersion: getVersion() };\n\n  // ? Bun doesn't support this field (yet)\n  if (pkgManager !== \"bun\") {\n    const { stdout } = await execa(pkgManager, [\"-v\"], {\n      cwd: projectDir,\n    });\n    pkgJson.packageManager = `${pkgManager}@${stdout.trim()}`;\n  }\n\n  fs.writeJSONSync(path.join(projectDir, \"package.json\"), pkgJson, {\n    spaces: 2,\n  });\n\n  // update import alias in any generated files if not using the default\n  if (importAlias !== \"~/\") {\n    setImportAlias(projectDir, importAlias);\n  }\n\n  if (!noInstall) {\n    await installDependencies({ projectDir });\n\n    if (usePackages.prisma.inUse) {\n      logger.info(\"Generating Prisma client...\");\n      await execa(\"npx\", [\"prisma\", \"generate\"], { cwd: projectDir });\n      logger.info(\"Successfully generated Prisma client!\");\n    }\n\n    await formatProject({\n      pkgManager,\n      projectDir,\n      eslint: packages.includes(\"eslint\"),\n      biome: packages.includes(\"biome\"),\n    });\n  }\n\n  if (!noGit) {\n    await initializeGit(projectDir);\n  }\n\n  await logNextSteps({\n    projectName: appDir,\n    packages: usePackages,\n    appRouter,\n    noInstall,\n    projectDir,\n    databaseProvider,\n  });\n\n  process.exit(0);\n};\n\nmain().catch((err) => {\n  logger.error(\"Aborting installation...\");\n  if (err instanceof Error) {\n    logger.error(err);\n  } else {\n    logger.error(\n      \"An unknown error has occurred. Please open an issue on github with the below:\"\n    );\n    console.log(err);\n  }\n  process.exit(1);\n});\n"
  },
  {
    "path": "cli/src/installers/betterAuth.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type AvailableDependencies } from \"~/installers/dependencyVersionMap.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\n\nexport const betterAuthInstaller: Installer = ({\n  projectDir,\n  packages,\n  databaseProvider,\n  appRouter,\n}) => {\n  const usingPrisma = packages?.prisma.inUse;\n  const usingDrizzle = packages?.drizzle.inUse;\n\n  const deps: AvailableDependencies[] = [\"better-auth\"];\n  if (usingPrisma) deps.push(\"@auth/prisma-adapter\");\n  if (usingDrizzle) deps.push(\"@auth/drizzle-adapter\");\n\n  addPackageDependency({\n    projectDir,\n    dependencies: deps,\n    devMode: false,\n  });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const isAppRouter = appRouter ?? true; // Default to app router if not specified\n\n  const apiHandlerFile = isAppRouter\n    ? \"src/app/api/auth/[...all]/route.ts\"\n    : \"src/pages/api/auth/[...all].ts\";\n\n  const apiHandlerSrc = path.join(extrasDir, apiHandlerFile);\n  const apiHandlerDest = path.join(projectDir, apiHandlerFile);\n\n  const authConfigSrc = path.join(\n    extrasDir,\n    \"src/server/better-auth/config\",\n    usingPrisma\n      ? \"with-prisma.ts\"\n      : usingDrizzle\n        ? \"with-drizzle.ts\"\n        : \"base.ts\"\n  );\n  const authConfigDest = path.join(\n    projectDir,\n    \"src/server/better-auth/config.ts\"\n  );\n\n  const authIndexSrc = path.join(extrasDir, \"src/server/better-auth/index.ts\");\n  const authIndexDest = path.join(\n    projectDir,\n    \"src/server/better-auth/index.ts\"\n  );\n\n  // Better Auth client and server helpers\n  const betterAuthClientSrc = path.join(\n    extrasDir,\n    \"src/server/better-auth/client.ts\"\n  );\n  const betterAuthClientDest = path.join(\n    projectDir,\n    \"src/server/better-auth/client.ts\"\n  );\n  const betterAuthServerSrc = path.join(\n    extrasDir,\n    \"src/server/better-auth/server.ts\"\n  );\n  const betterAuthServerDest = path.join(\n    projectDir,\n    \"src/server/better-auth/server.ts\"\n  );\n\n  fs.copySync(apiHandlerSrc, apiHandlerDest);\n  fs.copySync(authConfigSrc, authConfigDest);\n  fs.copySync(authIndexSrc, authIndexDest);\n  fs.copySync(betterAuthClientSrc, betterAuthClientDest);\n  fs.copySync(betterAuthServerSrc, betterAuthServerDest);\n\n  // Update Better Auth adapter provider according to selected DB\n  try {\n    if (fs.pathExistsSync(authConfigDest)) {\n      const content = fs.readFileSync(authConfigDest, \"utf8\");\n\n      // Map CLI database provider to adapter provider strings\n      const providerForDrizzle = (db: string) => {\n        switch (db) {\n          case \"postgres\":\n            return \"pg\";\n          case \"mysql\":\n          case \"planetscale\":\n            return \"mysql\";\n          case \"sqlite\":\n            return \"sqlite\";\n          default:\n            return \"pg\";\n        }\n      };\n\n      const providerForPrisma = (db: string) => {\n        switch (db) {\n          case \"postgres\":\n            return \"postgresql\";\n          case \"mysql\":\n          case \"planetscale\":\n            return \"mysql\";\n          case \"sqlite\":\n            return \"sqlite\";\n          default:\n            return \"postgresql\";\n        }\n      };\n\n      const providerValue = usingPrisma\n        ? providerForPrisma(databaseProvider)\n        : usingDrizzle\n          ? providerForDrizzle(databaseProvider)\n          : undefined;\n\n      if (providerValue) {\n        const updated = content.replace(\n          /(provider:\\s*\")[^\"]+(\"\\s*,?)/,\n          `$1${providerValue}$2`\n        );\n        fs.writeFileSync(authConfigDest, updated, \"utf8\");\n      }\n    }\n  } catch {\n    // Non-fatal: leave default provider from template\n  }\n};\n"
  },
  {
    "path": "cli/src/installers/biome.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\nimport { addPackageScript } from \"~/utils/addPackageScript.js\";\n\nexport const biomeInstaller: Installer = ({ projectDir }) => {\n  addPackageDependency({\n    projectDir,\n    dependencies: [\"@biomejs/biome\"],\n    devMode: true,\n  });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n  const biomeConfigSrc = path.join(extrasDir, \"config/biome.jsonc\");\n  const biomeConfigDest = path.join(projectDir, \"biome.jsonc\");\n\n  fs.copySync(biomeConfigSrc, biomeConfigDest);\n\n  addPackageScript({\n    projectDir,\n    scripts: {\n      \"check:unsafe\": \"biome check --write --unsafe .\",\n      \"check:write\": \"biome check --write .\",\n      check: \"biome check .\",\n    },\n  });\n};\n"
  },
  {
    "path": "cli/src/installers/dbContainer.ts",
    "content": "import fs from \"fs\";\nimport path from \"path\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { parseNameAndPath } from \"~/utils/parseNameAndPath.js\";\n\n// Sanitizes a project name to ensure it adheres to Docker container naming conventions.\nconst sanitizeName = (name: string): string => {\n  return name\n    .replace(/[^a-zA-Z0-9_.-]/g, \"_\") // Replace invalid characters with underscores\n    .toLowerCase(); // Convert to lowercase for consistency\n};\n\nexport const dbContainerInstaller: Installer = ({\n  projectDir,\n  databaseProvider,\n  projectName,\n}) => {\n  const scriptSrc = path.join(\n    PKG_ROOT,\n    `template/extras/start-database/${databaseProvider}.sh`\n  );\n  const scriptText = fs.readFileSync(scriptSrc, \"utf-8\");\n  const scriptDest = path.join(projectDir, \"start-database.sh\");\n  // for configuration with postgresql and mysql when project is created with '.' project name\n  const [projectNameParsed] =\n    projectName === \".\" ? parseNameAndPath(projectDir) : [projectName];\n\n  // Sanitize the project name for Docker container usage\n  const sanitizedProjectName = sanitizeName(projectNameParsed);\n\n  fs.writeFileSync(\n    scriptDest,\n    scriptText.replaceAll(\"project1\", sanitizedProjectName)\n  );\n  fs.chmodSync(scriptDest, \"755\");\n};\n"
  },
  {
    "path": "cli/src/installers/dependencyVersionMap.ts",
    "content": "/*\n * This maps the necessary packages to a version.\n * This improves performance significantly over fetching it from the npm registry.\n */\nexport const dependencyVersionMap = {\n  // NextAuth.js\n  \"next-auth\": \"5.0.0-beta.25\",\n  \"@auth/prisma-adapter\": \"^2.7.2\",\n  \"@auth/drizzle-adapter\": \"^1.7.2\",\n\n  // Better-Auth\n  \"better-auth\": \"^1.3\",\n\n  // Prisma\n  prisma: \"^6.6.0\",\n  \"@prisma/client\": \"^6.6.0\",\n  \"@prisma/adapter-planetscale\": \"^6.6.0\",\n\n  // Drizzle\n  \"drizzle-kit\": \"^0.30.5\",\n  \"drizzle-orm\": \"^0.41.0\",\n  mysql2: \"^3.11.0\",\n  \"@planetscale/database\": \"^1.19.0\",\n  postgres: \"^3.4.4\",\n  \"@libsql/client\": \"^0.14.0\",\n\n  // TailwindCSS\n  tailwindcss: \"^4.0.15\",\n  postcss: \"^8.5.3\",\n  \"@tailwindcss/postcss\": \"^4.0.15\",\n\n  // tRPC\n  \"@trpc/client\": \"^11.0.0\",\n  \"@trpc/server\": \"^11.0.0\",\n  \"@trpc/react-query\": \"^11.0.0\",\n  \"@trpc/next\": \"^11.0.0\",\n  \"@tanstack/react-query\": \"^5.69.0\",\n  superjson: \"^2.2.1\",\n  \"server-only\": \"^0.0.1\",\n\n  // biome\n  \"@biomejs/biome\": \"^2.2.5\",\n\n  // eslint / prettier\n  prettier: \"^3.5.3\",\n  \"@eslint/eslintrc\": \"^3.3.1\",\n  \"prettier-plugin-tailwindcss\": \"^0.6.11\",\n  eslint: \"^9.23.0\",\n  \"eslint-config-next\": \"^15.2.3\",\n  \"eslint-plugin-drizzle\": \"^0.2.3\",\n  \"typescript-eslint\": \"^8.27.0\",\n} as const;\nexport type AvailableDependencies = keyof typeof dependencyVersionMap;\n"
  },
  {
    "path": "cli/src/installers/drizzle.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\nimport { addPackageScript } from \"~/utils/addPackageScript.js\";\n\nexport const drizzleInstaller: Installer = ({\n  projectDir,\n  packages,\n  scopedAppName,\n  databaseProvider,\n}) => {\n  addPackageDependency({\n    projectDir,\n    dependencies: [\"drizzle-kit\"],\n    devMode: true,\n  });\n  addPackageDependency({\n    projectDir,\n    dependencies: [\n      \"drizzle-orm\",\n      (\n        {\n          planetscale: \"@planetscale/database\",\n          mysql: \"mysql2\",\n          postgres: \"postgres\",\n          sqlite: \"@libsql/client\",\n        } as const\n      )[databaseProvider],\n    ],\n    devMode: false,\n  });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const configFile = path.join(\n    extrasDir,\n    `config/drizzle-config-${\n      databaseProvider === \"planetscale\" ? \"mysql\" : databaseProvider\n    }.ts`\n  );\n  const configDest = path.join(projectDir, \"drizzle.config.ts\");\n\n  const schemaBaseName = packages?.betterAuth.inUse\n    ? \"with-better-auth\"\n    : packages?.nextAuth.inUse\n      ? \"with-auth\"\n      : \"base\";\n  const schemaSrc = path.join(\n    extrasDir,\n    \"src/server/db/schema-drizzle\",\n    `${schemaBaseName}-${databaseProvider}.ts`\n  );\n  const schemaDest = path.join(projectDir, \"src/server/db/schema.ts\");\n\n  // Replace placeholder table prefix with project name\n  let schemaContent = fs.readFileSync(schemaSrc, \"utf-8\");\n  schemaContent = schemaContent.replace(\n    \"project1_${name}\",\n    `${scopedAppName}_\\${name}`\n  );\n\n  let configContent = fs.readFileSync(configFile, \"utf-8\");\n\n  configContent = configContent.replace(\"project1_*\", `${scopedAppName}_*`);\n\n  const clientSrc = path.join(\n    extrasDir,\n    `src/server/db/index-drizzle/with-${databaseProvider}.ts`\n  );\n  const clientDest = path.join(projectDir, \"src/server/db/index.ts\");\n\n  addPackageScript({\n    projectDir,\n    scripts: {\n      \"db:push\": \"drizzle-kit push\",\n      \"db:studio\": \"drizzle-kit studio\",\n      \"db:generate\": \"drizzle-kit generate\",\n      \"db:migrate\": \"drizzle-kit migrate\",\n    },\n  });\n\n  fs.copySync(configFile, configDest);\n  fs.mkdirSync(path.dirname(schemaDest), { recursive: true });\n  fs.writeFileSync(schemaDest, schemaContent);\n  fs.writeFileSync(configDest, configContent);\n  fs.copySync(clientSrc, clientDest);\n};\n"
  },
  {
    "path": "cli/src/installers/envVars.ts",
    "content": "import crypto from \"node:crypto\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type DatabaseProvider, type Installer } from \"~/installers/index.js\";\n\nexport const envVariablesInstaller: Installer = ({\n  projectDir,\n  packages,\n  databaseProvider,\n  scopedAppName,\n}) => {\n  const usingNextAuth = packages?.nextAuth.inUse;\n  const usingBetterAuth = packages?.betterAuth.inUse;\n  const usingPrisma = packages?.prisma.inUse;\n  const usingDrizzle = packages?.drizzle.inUse;\n\n  const usingDb = usingPrisma === true || usingDrizzle === true;\n  const usingPlanetScale = databaseProvider === \"planetscale\";\n\n  const envContent = getEnvContent(\n    !!usingNextAuth,\n    !!usingBetterAuth,\n    !!usingPrisma,\n    !!usingDrizzle,\n    databaseProvider,\n    scopedAppName\n  );\n\n  let envFile = \"\";\n  if (usingDb) {\n    if (usingPlanetScale) {\n      if (usingBetterAuth) envFile = \"with-better-auth-db-planetscale.js\";\n      else if (usingNextAuth) envFile = \"with-auth-db-planetscale.js\";\n      else envFile = \"with-db-planetscale.js\";\n    } else {\n      if (usingBetterAuth) envFile = \"with-better-auth-db.js\";\n      else if (usingNextAuth) envFile = \"with-auth-db.js\";\n      else envFile = \"with-db.js\";\n    }\n  } else {\n    if (usingBetterAuth) envFile = \"with-better-auth.js\";\n    else if (usingNextAuth) envFile = \"with-auth.js\";\n  }\n\n  if (envFile !== \"\") {\n    const envSchemaSrc = path.join(\n      PKG_ROOT,\n      \"template/extras/src/env\",\n      envFile\n    );\n    const envSchemaDest = path.join(projectDir, \"src/env.js\");\n    fs.copyFileSync(envSchemaSrc, envSchemaDest);\n  }\n\n  const envDest = path.join(projectDir, \".env\");\n  const envExampleDest = path.join(projectDir, \".env.example\");\n\n  const _exampleEnvContent = exampleEnvContent + envContent;\n\n  // Generate an auth secret and put in .env, not .env.example\n  const secret = Buffer.from(\n    crypto.getRandomValues(new Uint8Array(32))\n  ).toString(\"base64\");\n  const _envContent = envContent\n    .replace(\n      'AUTH_SECRET=\"\"',\n      `AUTH_SECRET=\"${secret}\" # Generated by create-t3-app.`\n    )\n    .replace(\n      'BETTER_AUTH_SECRET=\"\"',\n      `BETTER_AUTH_SECRET=\"${secret}\" # Generated by create-t3-app.`\n    );\n\n  fs.writeFileSync(envDest, _envContent, \"utf-8\");\n  fs.writeFileSync(envExampleDest, _exampleEnvContent, \"utf-8\");\n};\n\nconst getEnvContent = (\n  usingNextAuth: boolean,\n  usingBetterAuth: boolean,\n  usingPrisma: boolean,\n  usingDrizzle: boolean,\n  databaseProvider: DatabaseProvider,\n  scopedAppName: string\n) => {\n  let content = `\n# When adding additional environment variables, the schema in \"/src/env.js\"\n# should be updated accordingly.\n`\n    .trim()\n    .concat(\"\\n\");\n\n  if (usingNextAuth)\n    content += `\n# Next Auth\n# You can generate a new secret on the command line with:\n# npx auth secret\n# https://next-auth.js.org/configuration/options#secret\nAUTH_SECRET=\"\"\n\n# Next Auth Discord Provider\nAUTH_DISCORD_ID=\"\"\nAUTH_DISCORD_SECRET=\"\"\n`;\n\n  if (usingBetterAuth)\n    content += `\n# Better Auth\n# Secret used by Better Auth\nBETTER_AUTH_SECRET=\"\"\n\n# Better Auth GitHub OAuth\nBETTER_AUTH_GITHUB_CLIENT_ID=\"\"\nBETTER_AUTH_GITHUB_CLIENT_SECRET=\"\"\n`;\n\n  if (usingPrisma)\n    content += `\n# Prisma\n# https://www.prisma.io/docs/reference/database-reference/connection-urls#env\n`;\n\n  if (usingDrizzle) content += \"\\n# Drizzle\\n\";\n\n  if (usingPrisma || usingDrizzle) {\n    if (databaseProvider === \"planetscale\") {\n      if (usingDrizzle) {\n        content += `# Get the Database URL from the \"prisma\" dropdown selector in PlanetScale.\n# Change the query params at the end of the URL to \"?ssl={\"rejectUnauthorized\":true}\"\nDATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?ssl={\"rejectUnauthorized\":true}'`;\n      } else {\n        content += `# Get the Database URL from the \"prisma\" dropdown selector in PlanetScale.\nDATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?sslaccept=strict'`;\n      }\n    } else if (databaseProvider === \"mysql\") {\n      content += `DATABASE_URL=\"mysql://root:password@localhost:3306/${scopedAppName}\"`;\n    } else if (databaseProvider === \"postgres\") {\n      content += `DATABASE_URL=\"postgresql://postgres:password@localhost:5432/${scopedAppName}\"`;\n    } else if (databaseProvider === \"sqlite\") {\n      content += 'DATABASE_URL=\"file:./db.sqlite\"';\n    }\n    content += \"\\n\";\n  }\n\n  if (!usingNextAuth && !usingBetterAuth && !usingPrisma && !usingDrizzle)\n    content += `\n# Example:\n# SERVERVAR=\"foo\"\n# NEXT_PUBLIC_CLIENTVAR=\"bar\"\n`;\n\n  return content;\n};\n\nconst exampleEnvContent = `\n# Since the \".env\" file is gitignored, you can use the \".env.example\" file to\n# build a new \".env\" file when you clone the repo. Keep this file up-to-date\n# when you add new variables to \\`.env\\`.\n\n# This file will be committed to version control, so make sure not to have any\n# secrets in it. If you are cloning this repo, create a copy of this file named\n# \".env\" and populate it with your secrets.\n`\n  .trim()\n  .concat(\"\\n\\n\");\n"
  },
  {
    "path": "cli/src/installers/eslint.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\nimport { addPackageScript } from \"~/utils/addPackageScript.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\nimport { type AvailableDependencies } from \"./dependencyVersionMap.js\";\n\n// Also installs prettier\nexport const dynamicEslintInstaller: Installer = ({ projectDir, packages }) => {\n  const devPackages: AvailableDependencies[] = [\n    \"prettier\",\n    \"eslint\",\n    \"eslint-config-next\",\n    \"typescript-eslint\",\n    \"@eslint/eslintrc\",\n  ];\n\n  if (packages?.tailwind.inUse) {\n    devPackages.push(\"prettier-plugin-tailwindcss\");\n  }\n  if (packages?.drizzle.inUse) {\n    devPackages.push(\"eslint-plugin-drizzle\");\n  }\n\n  addPackageDependency({\n    projectDir,\n    dependencies: devPackages,\n    devMode: true,\n  });\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  // Prettier\n  let prettierSrc: string;\n  if (packages?.tailwind.inUse) {\n    prettierSrc = path.join(extrasDir, \"config/_tailwind.prettier.config.js\");\n  } else {\n    prettierSrc = path.join(extrasDir, \"config/_prettier.config.js\");\n  }\n  const prettierDest = path.join(projectDir, \"prettier.config.js\");\n\n  fs.copySync(prettierSrc, prettierDest);\n\n  // pnpm\n  const pkgManager = getUserPkgManager();\n  if (pkgManager === \"pnpm\") {\n    const pnpmSrc = path.join(extrasDir, \"pnpm/_npmrc\");\n    fs.copySync(pnpmSrc, path.join(projectDir, \".npmrc\"));\n  }\n\n  addPackageScript({\n    projectDir,\n    scripts: {\n      lint: \"next lint\",\n      \"lint:fix\": \"next lint --fix\",\n      check: \"next lint && tsc --noEmit\",\n      \"format:write\": 'prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache',\n      \"format:check\": 'prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache',\n    },\n  });\n\n  // eslint\n  const usingDrizzle = !!packages?.drizzle?.inUse;\n  const eslintConfigSrc = path.join(\n    extrasDir,\n    usingDrizzle ? \"config/_eslint.drizzle.js\" : \"config/_eslint.base.js\"\n  );\n  const eslintConfigDest = path.join(projectDir, \"eslint.config.js\");\n\n  fs.copySync(eslintConfigSrc, eslintConfigDest);\n};\n"
  },
  {
    "path": "cli/src/installers/index.ts",
    "content": "import { envVariablesInstaller } from \"~/installers/envVars.js\";\nimport { nextAuthInstaller } from \"~/installers/nextAuth.js\";\nimport { prismaInstaller } from \"~/installers/prisma.js\";\nimport { tailwindInstaller } from \"~/installers/tailwind.js\";\nimport { trpcInstaller } from \"~/installers/trpc.js\";\nimport { type PackageManager } from \"~/utils/getUserPkgManager.js\";\nimport { betterAuthInstaller } from \"./betterAuth.js\";\nimport { biomeInstaller } from \"./biome.js\";\nimport { dbContainerInstaller } from \"./dbContainer.js\";\nimport { drizzleInstaller } from \"./drizzle.js\";\nimport { dynamicEslintInstaller } from \"./eslint.js\";\n\n// Turning this into a const allows the list to be iterated over for programmatically creating prompt options\n// Should increase extensibility in the future\nexport const availablePackages = [\n  \"nextAuth\",\n  \"betterAuth\",\n  \"prisma\",\n  \"drizzle\",\n  \"tailwind\",\n  \"trpc\",\n  \"envVariables\",\n  \"eslint\",\n  \"biome\",\n  \"dbContainer\",\n] as const;\nexport type AvailablePackages = (typeof availablePackages)[number];\n\nexport const databaseProviders = [\n  \"mysql\",\n  \"postgres\",\n  \"sqlite\",\n  \"planetscale\",\n] as const;\nexport type DatabaseProvider = (typeof databaseProviders)[number];\n\nexport interface InstallerOptions {\n  projectDir: string;\n  pkgManager: PackageManager;\n  noInstall: boolean;\n  packages?: PkgInstallerMap;\n  appRouter?: boolean;\n  projectName: string;\n  scopedAppName: string;\n  databaseProvider: DatabaseProvider;\n}\n\nexport type Installer = (opts: InstallerOptions) => void;\n\nexport type PkgInstallerMap = Record<\n  AvailablePackages,\n  {\n    inUse: boolean;\n    installer: Installer;\n  }\n>;\n\nexport const buildPkgInstallerMap = (\n  packages: AvailablePackages[],\n  databaseProvider: DatabaseProvider\n): PkgInstallerMap => ({\n  nextAuth: {\n    inUse: packages.includes(\"nextAuth\"),\n    installer: nextAuthInstaller,\n  },\n  betterAuth: {\n    inUse: packages.includes(\"betterAuth\"),\n    installer: betterAuthInstaller,\n  },\n  prisma: {\n    inUse: packages.includes(\"prisma\"),\n    installer: prismaInstaller,\n  },\n  drizzle: {\n    inUse: packages.includes(\"drizzle\"),\n    installer: drizzleInstaller,\n  },\n  tailwind: {\n    inUse: packages.includes(\"tailwind\"),\n    installer: tailwindInstaller,\n  },\n  trpc: {\n    inUse: packages.includes(\"trpc\"),\n    installer: trpcInstaller,\n  },\n  dbContainer: {\n    inUse: [\"mysql\", \"postgres\"].includes(databaseProvider),\n    installer: dbContainerInstaller,\n  },\n  envVariables: {\n    inUse: true,\n    installer: envVariablesInstaller,\n  },\n  eslint: {\n    inUse: packages.includes(\"eslint\"),\n    installer: dynamicEslintInstaller,\n  },\n  biome: {\n    inUse: packages.includes(\"biome\"),\n    installer: biomeInstaller,\n  },\n});\n"
  },
  {
    "path": "cli/src/installers/nextAuth.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type AvailableDependencies } from \"~/installers/dependencyVersionMap.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\n\nexport const nextAuthInstaller: Installer = ({ projectDir, packages }) => {\n  const usingPrisma = packages?.prisma.inUse;\n  const usingDrizzle = packages?.drizzle.inUse;\n\n  const deps: AvailableDependencies[] = [\"next-auth\"];\n  if (usingPrisma) deps.push(\"@auth/prisma-adapter\");\n  if (usingDrizzle) deps.push(\"@auth/drizzle-adapter\");\n\n  addPackageDependency({\n    projectDir,\n    dependencies: deps,\n    devMode: false,\n  });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const apiHandlerFile = \"src/app/api/auth/[...nextauth]/route.ts\";\n\n  const apiHandlerSrc = path.join(extrasDir, apiHandlerFile);\n  const apiHandlerDest = path.join(projectDir, apiHandlerFile);\n\n  const authConfigSrc = path.join(\n    extrasDir,\n    \"src/server/auth/config\",\n    usingPrisma\n      ? \"with-prisma.ts\"\n      : usingDrizzle\n        ? \"with-drizzle.ts\"\n        : \"base.ts\"\n  );\n  const authConfigDest = path.join(projectDir, \"src/server/auth/config.ts\");\n\n  const authIndexSrc = path.join(extrasDir, \"src/server/auth/index.ts\");\n  const authIndexDest = path.join(projectDir, \"src/server/auth/index.ts\");\n\n  fs.copySync(apiHandlerSrc, apiHandlerDest);\n  fs.copySync(authConfigSrc, authConfigDest);\n  fs.copySync(authIndexSrc, authIndexDest);\n};\n"
  },
  {
    "path": "cli/src/installers/prisma.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\nimport { addPackageScript } from \"~/utils/addPackageScript.js\";\n\nexport const prismaInstaller: Installer = ({\n  projectDir,\n  packages,\n  databaseProvider,\n}) => {\n  addPackageDependency({\n    projectDir,\n    dependencies: [\"prisma\"],\n    devMode: true,\n  });\n  addPackageDependency({\n    projectDir,\n    dependencies: [\"@prisma/client\"],\n    devMode: false,\n  });\n  if (databaseProvider === \"planetscale\")\n    addPackageDependency({\n      projectDir,\n      dependencies: [\"@prisma/adapter-planetscale\", \"@planetscale/database\"],\n      devMode: false,\n    });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const schemaBaseName = packages?.betterAuth.inUse\n    ? \"with-better-auth\"\n    : packages?.nextAuth.inUse\n      ? \"with-auth\"\n      : \"base\";\n  const schemaSrc = path.join(\n    extrasDir,\n    \"prisma/schema\",\n    `${schemaBaseName}${\n      databaseProvider === \"planetscale\" ? \"-planetscale\" : \"\"\n    }.prisma`\n  );\n  let schemaText = fs.readFileSync(schemaSrc, \"utf-8\");\n  if (databaseProvider !== \"sqlite\") {\n    schemaText = schemaText.replace(\n      'provider = \"sqlite\"',\n      `provider = \"${\n        {\n          mysql: \"mysql\",\n          postgres: \"postgresql\",\n          planetscale: \"mysql\",\n        }[databaseProvider]\n      }\"`\n    );\n    if ([\"mysql\", \"planetscale\"].includes(databaseProvider)) {\n      schemaText = schemaText.replace(\"// @db.Text\", \"@db.Text\");\n    }\n  }\n  const schemaDest = path.join(projectDir, \"prisma/schema.prisma\");\n  fs.mkdirSync(path.dirname(schemaDest), { recursive: true });\n  fs.writeFileSync(schemaDest, schemaText);\n\n  const clientSrc = path.join(\n    extrasDir,\n    databaseProvider === \"planetscale\"\n      ? \"src/server/db/db-prisma-planetscale.ts\"\n      : \"src/server/db/db-prisma.ts\"\n  );\n  const clientDest = path.join(projectDir, \"src/server/db.ts\");\n\n  addPackageScript({\n    projectDir,\n    scripts: {\n      postinstall: \"prisma generate\",\n      \"db:push\": \"prisma db push\",\n      \"db:studio\": \"prisma studio\",\n      \"db:generate\": \"prisma migrate dev\",\n      \"db:migrate\": \"prisma migrate deploy\",\n    },\n  });\n\n  fs.copySync(clientSrc, clientDest);\n};\n"
  },
  {
    "path": "cli/src/installers/tailwind.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\n\nexport const tailwindInstaller: Installer = ({ projectDir }) => {\n  addPackageDependency({\n    projectDir,\n    dependencies: [\"tailwindcss\", \"postcss\", \"@tailwindcss/postcss\"],\n    devMode: true,\n  });\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const postcssCfgSrc = path.join(extrasDir, \"config/postcss.config.js\");\n  const postcssCfgDest = path.join(projectDir, \"postcss.config.js\");\n\n  const cssSrc = path.join(extrasDir, \"src/styles/globals.css\");\n  const cssDest = path.join(projectDir, \"src/styles/globals.css\");\n\n  fs.copySync(postcssCfgSrc, postcssCfgDest);\n  fs.copySync(cssSrc, cssDest);\n};\n"
  },
  {
    "path": "cli/src/installers/trpc.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\nimport { type Installer } from \"~/installers/index.js\";\nimport { addPackageDependency } from \"~/utils/addPackageDependency.js\";\n\nexport const trpcInstaller: Installer = ({\n  projectDir,\n  packages,\n  appRouter,\n}) => {\n  addPackageDependency({\n    projectDir,\n    dependencies: [\n      \"@tanstack/react-query\",\n      \"superjson\",\n      \"@trpc/server\",\n      \"@trpc/client\",\n      \"@trpc/react-query\",\n    ],\n    devMode: false,\n  });\n\n  const usingAuth = packages?.nextAuth.inUse;\n  const usingBetterAuth = packages?.betterAuth.inUse;\n  const usingPrisma = packages?.prisma.inUse;\n  const usingDrizzle = packages?.drizzle.inUse;\n  const usingDb = usingPrisma === true || usingDrizzle === true;\n\n  const extrasDir = path.join(PKG_ROOT, \"template/extras\");\n\n  const apiHandlerFile = \"src/pages/api/trpc/[trpc].ts\";\n  const routeHandlerFile = \"src/app/api/trpc/[trpc]/route.ts\";\n  const srcToUse = appRouter ? routeHandlerFile : apiHandlerFile;\n\n  const apiHandlerSrc = path.join(extrasDir, srcToUse);\n  const apiHandlerDest = path.join(projectDir, srcToUse);\n\n  const trpcFile = (() => {\n    if (usingBetterAuth && usingDb) return \"with-better-auth-db.ts\";\n    if (usingBetterAuth) return \"with-better-auth.ts\";\n    if (usingAuth && usingDb) return \"with-auth-db.ts\";\n    if (usingAuth) return \"with-auth.ts\";\n    if (usingDb) return \"with-db.ts\";\n    return \"base.ts\";\n  })();\n  const trpcSrc = path.join(\n    extrasDir,\n    \"src/server/api\",\n    appRouter ? \"trpc-app\" : \"trpc-pages\",\n    trpcFile\n  );\n  const trpcDest = path.join(projectDir, \"src/server/api/trpc.ts\");\n\n  const rootRouterSrc = path.join(extrasDir, \"src/server/api/root.ts\");\n  const rootRouterDest = path.join(projectDir, \"src/server/api/root.ts\");\n\n  const exampleRouterFile =\n    (usingAuth || usingBetterAuth) && usingPrisma\n      ? \"with-auth-prisma.ts\"\n      : (usingAuth || usingBetterAuth) && usingDrizzle\n        ? \"with-auth-drizzle.ts\"\n        : usingAuth || usingBetterAuth\n          ? \"with-auth.ts\"\n          : usingPrisma\n            ? \"with-prisma.ts\"\n            : usingDrizzle\n              ? \"with-drizzle.ts\"\n              : \"base.ts\";\n\n  const exampleRouterSrc = path.join(\n    extrasDir,\n    \"src/server/api/routers/post\",\n    exampleRouterFile\n  );\n  const exampleRouterDest = path.join(\n    projectDir,\n    \"src/server/api/routers/post.ts\"\n  );\n\n  const copySrcDest: [string, string][] = [\n    [apiHandlerSrc, apiHandlerDest],\n    [trpcSrc, trpcDest],\n    [rootRouterSrc, rootRouterDest],\n    [exampleRouterSrc, exampleRouterDest],\n  ];\n\n  if (appRouter) {\n    addPackageDependency({\n      dependencies: [\"server-only\"],\n      devMode: false,\n      projectDir,\n    });\n\n    const trpcDir = path.join(extrasDir, \"src/trpc\");\n    copySrcDest.push(\n      [\n        path.join(trpcDir, \"server.ts\"),\n        path.join(projectDir, \"src/trpc/server.ts\"),\n      ],\n      [\n        path.join(trpcDir, \"react.tsx\"),\n        path.join(projectDir, \"src/trpc/react.tsx\"),\n      ],\n      [\n        path.join(\n          extrasDir,\n          \"src/app/_components\",\n          packages?.tailwind.inUse ? \"post-tw.tsx\" : \"post.tsx\"\n        ),\n        path.join(projectDir, \"src/app/_components/post.tsx\"),\n      ],\n      [\n        path.join(extrasDir, \"src/trpc/query-client.ts\"),\n        path.join(projectDir, \"src/trpc/query-client.ts\"),\n      ]\n    );\n  } else {\n    addPackageDependency({\n      dependencies: [\"@trpc/next\"],\n      devMode: false,\n      projectDir,\n    });\n\n    const utilsSrc = path.join(extrasDir, \"src/utils/api.ts\");\n    const utilsDest = path.join(projectDir, \"src/utils/api.ts\");\n    copySrcDest.push([utilsSrc, utilsDest]);\n  }\n\n  copySrcDest.forEach(([src, dest]) => {\n    fs.copySync(src, dest);\n  });\n};\n"
  },
  {
    "path": "cli/src/utils/addPackageDependency.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\nimport sortPackageJson from \"sort-package-json\";\nimport { type PackageJson } from \"type-fest\";\n\nimport {\n  dependencyVersionMap,\n  type AvailableDependencies,\n} from \"~/installers/dependencyVersionMap.js\";\n\nexport const addPackageDependency = (opts: {\n  dependencies: AvailableDependencies[];\n  devMode: boolean;\n  projectDir: string;\n}) => {\n  const { dependencies, devMode, projectDir } = opts;\n\n  const pkgJson = fs.readJSONSync(\n    path.join(projectDir, \"package.json\")\n  ) as PackageJson;\n\n  dependencies.forEach((pkgName) => {\n    const version = dependencyVersionMap[pkgName];\n\n    if (devMode && pkgJson.devDependencies) {\n      pkgJson.devDependencies[pkgName] = version;\n    } else if (pkgJson.dependencies) {\n      pkgJson.dependencies[pkgName] = version;\n    }\n  });\n  const sortedPkgJson = sortPackageJson(pkgJson);\n\n  fs.writeJSONSync(path.join(projectDir, \"package.json\"), sortedPkgJson, {\n    spaces: 2,\n  });\n};\n"
  },
  {
    "path": "cli/src/utils/addPackageScript.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\nimport sortPackageJson from \"sort-package-json\";\nimport { type PackageJson } from \"type-fest\";\n\nexport const addPackageScript = (opts: {\n  scripts: Record<string, string>;\n  projectDir: string;\n}) => {\n  const { scripts, projectDir } = opts;\n\n  const packageJsonPath = path.join(projectDir, \"package.json\");\n  const packageJsonContent = fs.readJSONSync(packageJsonPath) as PackageJson;\n\n  packageJsonContent.scripts = {\n    ...packageJsonContent.scripts,\n    ...scripts,\n  };\n\n  const sortedPkgJson = sortPackageJson(packageJsonContent);\n\n  fs.writeJSONSync(packageJsonPath, sortedPkgJson, {\n    spaces: 2,\n  });\n};\n"
  },
  {
    "path": "cli/src/utils/getT3Version.ts",
    "content": "import path from \"path\";\nimport fs from \"fs-extra\";\nimport { type PackageJson } from \"type-fest\";\n\nimport { PKG_ROOT } from \"~/consts.js\";\n\nexport const getVersion = () => {\n  const packageJsonPath = path.join(PKG_ROOT, \"package.json\");\n\n  const packageJsonContent = fs.readJSONSync(packageJsonPath) as PackageJson;\n\n  return packageJsonContent.version ?? \"1.0.0\";\n};\n"
  },
  {
    "path": "cli/src/utils/getUserPkgManager.ts",
    "content": "export type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport const getUserPkgManager: () => PackageManager = () => {\n  // This environment variable is set by npm and yarn but pnpm seems less consistent\n  const userAgent = process.env.npm_config_user_agent;\n\n  if (userAgent) {\n    if (userAgent.startsWith(\"yarn\")) {\n      return \"yarn\";\n    } else if (userAgent.startsWith(\"pnpm\")) {\n      return \"pnpm\";\n    } else if (userAgent.startsWith(\"bun\")) {\n      return \"bun\";\n    } else {\n      return \"npm\";\n    }\n  } else {\n    // If no user agent is set, assume npm\n    return \"npm\";\n  }\n};\n"
  },
  {
    "path": "cli/src/utils/isTTYError.ts",
    "content": "export class IsTTYError extends Error {\n  constructor(msg: string) {\n    super(msg);\n  }\n}\n"
  },
  {
    "path": "cli/src/utils/logger.ts",
    "content": "import chalk from \"chalk\";\n\nexport const logger = {\n  error(...args: unknown[]) {\n    console.log(chalk.red(...args));\n  },\n  warn(...args: unknown[]) {\n    console.log(chalk.yellow(...args));\n  },\n  info(...args: unknown[]) {\n    console.log(chalk.cyan(...args));\n  },\n  success(...args: unknown[]) {\n    console.log(chalk.green(...args));\n  },\n};\n"
  },
  {
    "path": "cli/src/utils/parseNameAndPath.ts",
    "content": "import pathModule from \"path\";\n\nimport { removeTrailingSlash } from \"./removeTrailingSlash.js\";\n\n/**\n * Parses the appName and its path from the user input.\n *\n * Returns a tuple of of `[appName, path]`, where `appName` is the name put in the \"package.json\"\n * file and `path` is the path to the directory where the app will be created.\n *\n * If `appName` is \".\", the name of the directory will be used instead. Handles the case where the\n * input includes a scoped package name in which case that is being parsed as the name, but not\n * included as the path.\n *\n * For example:\n *\n * - dir/@mono/app => [\"@mono/app\", \"dir/app\"]\n * - dir/app => [\"app\", \"dir/app\"]\n */\nexport const parseNameAndPath = (rawInput: string) => {\n  const input = removeTrailingSlash(rawInput);\n\n  const paths = input.split(\"/\");\n\n  let appName = paths[paths.length - 1]!;\n\n  // If the user ran `npx create-t3-app .` or similar, the appName should be the current directory\n  if (appName === \".\") {\n    const parsedCwd = pathModule.resolve(process.cwd());\n    appName = pathModule.basename(parsedCwd);\n  }\n\n  // If the first part is a @, it's a scoped package\n  const indexOfDelimiter = paths.findIndex((p) => p.startsWith(\"@\"));\n  if (paths.findIndex((p) => p.startsWith(\"@\")) !== -1) {\n    appName = paths.slice(indexOfDelimiter).join(\"/\");\n  }\n\n  const path = paths.filter((p) => !p.startsWith(\"@\")).join(\"/\");\n\n  return [appName, path] as const;\n};\n"
  },
  {
    "path": "cli/src/utils/removeTrailingSlash.ts",
    "content": "export const removeTrailingSlash = (input: string) => {\n  if (input.length > 1 && input.endsWith(\"/\")) {\n    input = input.slice(0, -1);\n  }\n\n  return input;\n};\n"
  },
  {
    "path": "cli/src/utils/renderTitle.ts",
    "content": "import gradient from \"gradient-string\";\n\nimport { TITLE_TEXT } from \"~/consts.js\";\nimport { getUserPkgManager } from \"~/utils/getUserPkgManager.js\";\n\n// colors brought in from vscode poimandres theme\nconst poimandresTheme = {\n  blue: \"#add7ff\",\n  cyan: \"#89ddff\",\n  green: \"#5de4c7\",\n  magenta: \"#fae4fc\",\n  red: \"#d0679d\",\n  yellow: \"#fffac2\",\n};\n\nexport const renderTitle = () => {\n  const t3Gradient = gradient(Object.values(poimandresTheme));\n\n  // resolves weird behavior where the ascii is offset\n  const pkgManager = getUserPkgManager();\n  if (pkgManager === \"yarn\" || pkgManager === \"pnpm\") {\n    console.log(\"\");\n  }\n  console.log(t3Gradient.multiline(TITLE_TEXT));\n};\n"
  },
  {
    "path": "cli/src/utils/renderVersionWarning.ts",
    "content": "import { execSync } from \"child_process\";\nimport https from \"https\";\n\nimport { getVersion } from \"./getT3Version.js\";\nimport { logger } from \"./logger.js\";\n\nexport const renderVersionWarning = (npmVersion: string) => {\n  const currentVersion = getVersion();\n\n  //   console.log(\"current\", currentVersion);\n  //   console.log(\"npm\", npmVersion);\n\n  if (currentVersion.includes(\"beta\")) {\n    logger.warn(\"  You are using a beta version of create-t3-app.\");\n    logger.warn(\"  Please report any bugs you encounter.\");\n  } else if (currentVersion.includes(\"next\")) {\n    logger.warn(\n      \"  You are running create-t3-app with the @next tag which is no longer maintained.\"\n    );\n    logger.warn(\"  Please run the CLI with @latest instead.\");\n  } else if (currentVersion !== npmVersion) {\n    logger.warn(\"  You are using an outdated version of create-t3-app.\");\n    logger.warn(\n      \"  Your version:\",\n      currentVersion + \".\",\n      \"Latest version in the npm registry:\",\n      npmVersion\n    );\n    logger.warn(\"  Please run the CLI with @latest to get the latest updates.\");\n  }\n  console.log(\"\");\n};\n\n/**\n * Copyright (c) 2015-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the LICENSE file in the root\n * directory of this source tree.\n * https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/LICENSE\n */\ninterface DistTagsBody {\n  latest: string;\n}\n\nfunction checkForLatestVersion(): Promise<string> {\n  return new Promise((resolve, reject) => {\n    https\n      .get(\n        \"https://registry.npmjs.org/-/package/create-t3-app/dist-tags\",\n        (res) => {\n          if (res.statusCode === 200) {\n            let body = \"\";\n            res.on(\"data\", (data) => (body += data));\n            res.on(\"end\", () => {\n              resolve((JSON.parse(body) as DistTagsBody).latest);\n            });\n          } else {\n            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n            reject();\n          }\n        }\n      )\n      .on(\"error\", () => {\n        // logger.error(\"Unable to check for latest version.\");\n        // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n        reject();\n      });\n  });\n}\n\nexport const getNpmVersion = () =>\n  // `fetch` to the registry is faster than `npm view` so we try that first\n  checkForLatestVersion().catch(() => {\n    try {\n      return execSync(\"npm view create-t3-app version\").toString().trim();\n    } catch {\n      return null;\n    }\n  });\n"
  },
  {
    "path": "cli/src/utils/validateAppName.ts",
    "content": "import { removeTrailingSlash } from \"./removeTrailingSlash.js\";\n\nconst validationRegExp =\n  /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\n\n//Validate a string against allowed package.json names\nexport const validateAppName = (rawInput: string) => {\n  const input = removeTrailingSlash(rawInput);\n  const paths = input.split(\"/\");\n\n  // If the first part is a @, it's a scoped package\n  const indexOfDelimiter = paths.findIndex((p) => p.startsWith(\"@\"));\n\n  let appName = paths[paths.length - 1];\n  if (paths.findIndex((p) => p.startsWith(\"@\")) !== -1) {\n    appName = paths.slice(indexOfDelimiter).join(\"/\");\n  }\n\n  if (input === \".\" || validationRegExp.test(appName ?? \"\")) {\n    return;\n  } else {\n    return \"App name must consist of only lowercase alphanumeric characters, '-', and '_'\";\n  }\n};\n"
  },
  {
    "path": "cli/src/utils/validateImportAlias.ts",
    "content": "export const validateImportAlias = (input: string) => {\n  if (input.startsWith(\".\") || input.startsWith(\"/\")) {\n    return \"Import alias can't start with '.' or '/'\";\n  }\n  return;\n};\n"
  },
  {
    "path": "cli/template/base/README.md",
    "content": "# Create T3 App\n\nThis is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`.\n\n## What's next? How do I make an app with this?\n\nWe try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary.\n\nIf you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.\n\n- [Next.js](https://nextjs.org)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Drizzle](https://orm.drizzle.team)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\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 our 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": "cli/template/base/_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\ndb.sqlite\n/generated/\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\n# idea files\n.idea"
  },
  {
    "path": "cli/template/base/next.config.js",
    "content": "/**\n * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful\n * for Docker builds.\n */\nimport \"./src/env.js\";\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": "cli/template/base/package.json",
    "content": "{\n  \"name\": \"template\",\n  \"version\": \"0.1.0\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev --turbo\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"preview\": \"next build && next start\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"@t3-oss/env-nextjs\": \"^0.12.0\",\n    \"next\": \"^15.5.9\",\n    \"react\": \"^19.2.3\",\n    \"react-dom\": \"^19.2.3\",\n    \"zod\": \"^3.24.2\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.10.1\",\n    \"@types/react\": \"~19.1.0\",\n    \"@types/react-dom\": \"~19.1.0\",\n    \"typescript\": \"^5.8.2\"\n  }\n}\n"
  },
  {
    "path": "cli/template/base/src/env.js",
    "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    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\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_CLIENTVAR: z.string(),\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    NODE_ENV: process.env.NODE_ENV,\n    // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/base/src/styles/globals.css",
    "content": "html,\nbody {\n  padding: 0;\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,\n    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;\n}\n\na {\n  color: inherit;\n  text-decoration: none;\n}\n\n* {\n  box-sizing: border-box;\n}\n"
  },
  {
    "path": "cli/template/base/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Base Options: */\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"target\": \"es2022\",\n    \"allowJs\": true,\n    \"resolveJsonModule\": true,\n    \"moduleDetection\": \"force\",\n    \"isolatedModules\": true,\n    \"verbatimModuleSyntax\": true,\n\n    /* Strictness */\n    \"strict\": true,\n    \"noUncheckedIndexedAccess\": true,\n    \"checkJs\": true,\n\n    /* Bundled projects */\n    \"lib\": [\"dom\", \"dom.iterable\", \"ES2022\"],\n    \"noEmit\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"jsx\": \"preserve\",\n    \"plugins\": [{ \"name\": \"next\" }],\n    \"incremental\": true,\n\n    /* Path Aliases */\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"~/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \"**/*.cjs\",\n    \"**/*.js\",\n    \".next/types/**/*.ts\"\n  ],\n  \"exclude\": [\"node_modules\", \"generated\"]\n}\n"
  },
  {
    "path": "cli/template/extras/config/_eslint.base.js",
    "content": "import { FlatCompat } from \"@eslint/eslintrc\";\nimport tseslint from 'typescript-eslint';\n\nconst compat = new FlatCompat({\n  baseDirectory: import.meta.dirname,\n});\n\nexport default tseslint.config(\n  {\n\t\tignores: ['.next']\n\t},\n  ...compat.extends(\"next/core-web-vitals\"),\n  {\n    files: ['**/*.ts', '**/*.tsx'],\n\t\textends: [\n\t\t\t...tseslint.configs.recommended,\n\t\t\t...tseslint.configs.recommendedTypeChecked,\n\t\t\t...tseslint.configs.stylisticTypeChecked\n\t\t],\n      rules: {\n    \"@typescript-eslint/array-type\": \"off\",\n    \"@typescript-eslint/consistent-type-definitions\": \"off\",\n    \"@typescript-eslint/consistent-type-imports\": [\n      \"warn\",\n      { prefer: \"type-imports\", fixStyle: \"inline-type-imports\" },\n    ],\n    \"@typescript-eslint/no-unused-vars\": [\"warn\", { argsIgnorePattern: \"^_\" }],\n    \"@typescript-eslint/require-await\": \"off\",\n    \"@typescript-eslint/no-misused-promises\": [\n      \"error\",\n      { checksVoidReturn: { attributes: false } },\n    ],\n  },\n  },\n  {\n\t\tlinterOptions: {\n\t\t\treportUnusedDisableDirectives: true\n\t\t},\n\t\tlanguageOptions: {\n\t\t\tparserOptions: {\n\t\t\t\tprojectService: true\n\t\t\t}\n\t\t}\n\t}\n)\n"
  },
  {
    "path": "cli/template/extras/config/_eslint.drizzle.js",
    "content": "import { FlatCompat } from \"@eslint/eslintrc\";\nimport tseslint from 'typescript-eslint';\n// @ts-ignore -- no types for this plugin\nimport drizzle from \"eslint-plugin-drizzle\";\n\nconst compat = new FlatCompat({\n  baseDirectory: import.meta.dirname,\n});\n\nexport default tseslint.config(\n  {\n\t\tignores: ['.next']\n\t},\n  ...compat.extends(\"next/core-web-vitals\"),\n  {\n    files: ['**/*.ts', '**/*.tsx'],\n    plugins: {\n      drizzle,\n    },\n\t\textends: [\n\t\t\t...tseslint.configs.recommended,\n\t\t\t...tseslint.configs.recommendedTypeChecked,\n\t\t\t...tseslint.configs.stylisticTypeChecked\n\t\t],\n      rules: {\n    \"@typescript-eslint/array-type\": \"off\",\n    \"@typescript-eslint/consistent-type-definitions\": \"off\",\n    \"@typescript-eslint/consistent-type-imports\": [\n      \"warn\",\n      { prefer: \"type-imports\", fixStyle: \"inline-type-imports\" },\n    ],\n    \"@typescript-eslint/no-unused-vars\": [\"warn\", { argsIgnorePattern: \"^_\" }],\n    \"@typescript-eslint/require-await\": \"off\",\n    \"@typescript-eslint/no-misused-promises\": [\n      \"error\",\n      { checksVoidReturn: { attributes: false } },\n    ],\n    \"drizzle/enforce-delete-with-where\": [\n      \"error\",\n      { drizzleObjectName: [\"db\", \"ctx.db\"] },\n    ],\n    \"drizzle/enforce-update-with-where\": [\n      \"error\",\n      { drizzleObjectName: [\"db\", \"ctx.db\"] },\n    ],\n  },\n  },\n  {\n\t\tlinterOptions: {\n\t\t\treportUnusedDisableDirectives: true\n\t\t},\n\t\tlanguageOptions: {\n\t\t\tparserOptions: {\n\t\t\t\tprojectService: true\n\t\t\t}\n\t\t}\n\t}\n)\n"
  },
  {
    "path": "cli/template/extras/config/_prettier.config.js",
    "content": "/** @type {import('prettier').Config} */\nexport default {};\n"
  },
  {
    "path": "cli/template/extras/config/_tailwind.prettier.config.js",
    "content": "/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */\nexport default {\n  plugins: [\"prettier-plugin-tailwindcss\"],\n};\n"
  },
  {
    "path": "cli/template/extras/config/biome.jsonc",
    "content": "{\n  \"$schema\": \"./node_modules/@biomejs/biome/configuration_schema.json\",\n  \"root\": true,\n  \"vcs\": {\n    \"enabled\": true,\n    \"useIgnoreFile\": true,\n    \"clientKind\": \"git\",\n  },\n  \"assist\": {\n    \"enabled\": true,\n    \"actions\": {\n      \"recommended\": true,\n      \"source\": {\n        \"recommended\": true,\n        \"organizeImports\": \"on\",\n        \"useSortedAttributes\": \"on\",\n      },\n    },\n  },\n  \"formatter\": {\n    \"enabled\": true,\n  },\n  \"linter\": {\n    \"enabled\": true,\n    \"rules\": {\n      \"recommended\": true,\n      \"nursery\": {\n        \"useSortedClasses\": {\n          \"level\": \"warn\",\n          \"fix\": \"safe\",\n          \"options\": {\n            \"functions\": [\"clsx\", \"cva\", \"cn\"],\n          },\n        },\n      },\n    },\n  },\n  \"html\": {\n    \"formatter\": {\n      \"enabled\": true,\n    },\n  },\n  \"javascript\": {\n    \"assist\": {\n      \"enabled\": true,\n    },\n    \"formatter\": {\n      \"enabled\": true,\n    },\n    \"linter\": {\n      \"enabled\": true,\n    },\n  },\n  \"css\": {\n    \"assist\": {\n      \"enabled\": true,\n    },\n    \"formatter\": {\n      \"enabled\": true,\n    },\n    \"linter\": {\n      \"enabled\": true,\n    },\n    \"parser\": {\n      \"cssModules\": true,\n      \"tailwindDirectives\": true,\n    },\n  },\n}\n"
  },
  {
    "path": "cli/template/extras/config/drizzle-config-mysql.ts",
    "content": "import { type Config } from \"drizzle-kit\";\n\nimport { env } from \"~/env\";\n\nexport default {\n  schema: \"./src/server/db/schema.ts\",\n  dialect: \"mysql\",\n  dbCredentials: {\n    url: env.DATABASE_URL,\n  },\n  tablesFilter: [\"project1_*\"],\n} satisfies Config;\n"
  },
  {
    "path": "cli/template/extras/config/drizzle-config-postgres.ts",
    "content": "import { type Config } from \"drizzle-kit\";\n\nimport { env } from \"~/env\";\n\nexport default {\n  schema: \"./src/server/db/schema.ts\",\n  dialect: \"postgresql\",\n  dbCredentials: {\n    url: env.DATABASE_URL,\n  },\n  tablesFilter: [\"project1_*\"],\n} satisfies Config;\n"
  },
  {
    "path": "cli/template/extras/config/drizzle-config-sqlite.ts",
    "content": "import { type Config } from \"drizzle-kit\";\n\nimport { env } from \"~/env\";\n\nexport default {\n  schema: \"./src/server/db/schema.ts\",\n  dialect: \"sqlite\",\n  dbCredentials: {\n    url: env.DATABASE_URL,\n  },\n  tablesFilter: [\"project1_*\"],\n} satisfies Config;\n"
  },
  {
    "path": "cli/template/extras/config/next-config-appdir.js",
    "content": "/**\n * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful\n * for Docker builds.\n */\nimport \"./src/env.js\";\n\n/** @type {import(\"next\").NextConfig} */\nconst config = {};\n\nexport default config;\n"
  },
  {
    "path": "cli/template/extras/config/postcss.config.js",
    "content": "export default {\n  plugins: {\n    \"@tailwindcss/postcss\": {},\n  },\n};\n"
  },
  {
    "path": "cli/template/extras/pnpm/_npmrc",
    "content": "public-hoist-pattern[]=*eslint*\npublic-hoist-pattern[]=*prettier*"
  },
  {
    "path": "cli/template/extras/prisma/schema/base-planetscale.prisma",
    "content": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n    provider        = \"prisma-client-js\"\n    previewFeatures = [\"driverAdapters\"]\n    output          = \"../generated/prisma\"\n}\n\ndatasource db {\n    provider = \"mysql\"\n    url      = env(\"DATABASE_URL\")\n\n    // If you have enabled foreign key constraints for your database, remove this line.\n    relationMode = \"prisma\"\n}\n\nmodel Post {\n    id        Int      @id @default(autoincrement())\n    name      String\n    createdAt DateTime @default(now())\n    updatedAt DateTime @updatedAt\n\n    @@index([name])\n}\n"
  },
  {
    "path": "cli/template/extras/prisma/schema/base.prisma",
    "content": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n    provider = \"prisma-client-js\"\n    output   = \"../generated/prisma\"\n}\n\ndatasource db {\n    provider = \"sqlite\"\n    url      = env(\"DATABASE_URL\")\n}\n\nmodel Post {\n    id        Int      @id @default(autoincrement())\n    name      String\n    createdAt DateTime @default(now())\n    updatedAt DateTime @updatedAt\n\n    @@index([name])\n}\n"
  },
  {
    "path": "cli/template/extras/prisma/schema/with-auth-planetscale.prisma",
    "content": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n    provider = \"prisma-client-js\"\n    output   = \"../generated/prisma\"\n\n    previewFeatures = [\"driverAdapters\"]\n}\n\ndatasource db {\n    provider = \"mysql\"\n    url      = env(\"DATABASE_URL\")\n\n    // If you have enabled foreign key constraints for your database, remove this line.\n    relationMode = \"prisma\"\n}\n\nmodel Post {\n    id        Int      @id @default(autoincrement())\n    name      String\n    createdAt DateTime @default(now())\n    updatedAt DateTime @updatedAt\n\n    createdBy   User   @relation(fields: [createdById], references: [id])\n    createdById String\n\n    @@index([name])\n    @@index([createdById])\n}\n\n// Necessary for Next auth\nmodel Account {\n    id                String  @id @default(cuid())\n    userId            String\n    type              String\n    provider          String\n    providerAccountId String\n    refresh_token     String? @db.Text\n    access_token      String? @db.Text\n    expires_at        Int?\n    token_type        String?\n    scope             String?\n    id_token          String? @db.Text\n    session_state     String?\n    user              User    @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n    @@unique([provider, providerAccountId])\n    @@index([userId])\n}\n\nmodel Session {\n    id           String   @id @default(cuid())\n    sessionToken String   @unique\n    userId       String\n    expires      DateTime\n    user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n    @@index([userId])\n}\n\nmodel User {\n    id            String    @id @default(cuid())\n    name          String?\n    email         String?   @unique\n    emailVerified DateTime?\n    image         String?\n    accounts      Account[]\n    sessions      Session[]\n    posts         Post[]\n}\n\nmodel VerificationToken {\n    identifier String\n    token      String   @unique\n    expires    DateTime\n\n    @@unique([identifier, token])\n}\n"
  },
  {
    "path": "cli/template/extras/prisma/schema/with-auth.prisma",
    "content": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n    provider = \"prisma-client-js\"\n    output   = \"../generated/prisma\"\n}\n\ndatasource db {\n    provider = \"sqlite\"\n    // NOTE: When using mysql or sqlserver, uncomment the @db.Text annotations in model Account below\n    // Further reading:\n    // https://next-auth.js.org/adapters/prisma#create-the-prisma-schema\n    // https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#string\n    url      = env(\"DATABASE_URL\")\n}\n\nmodel Post {\n    id        Int      @id @default(autoincrement())\n    name      String\n    createdAt DateTime @default(now())\n    updatedAt DateTime @updatedAt\n\n    createdBy   User   @relation(fields: [createdById], references: [id])\n    createdById String\n\n    @@index([name])\n}\n\n// Necessary for Next auth\nmodel Account {\n    id                       String  @id @default(cuid())\n    userId                   String\n    type                     String\n    provider                 String\n    providerAccountId        String\n    refresh_token            String? // @db.Text\n    access_token             String? // @db.Text\n    expires_at               Int?\n    token_type               String?\n    scope                    String?\n    id_token                 String? // @db.Text\n    session_state            String?\n    user                     User    @relation(fields: [userId], references: [id], onDelete: Cascade)\n    refresh_token_expires_in Int?\n\n    @@unique([provider, providerAccountId])\n}\n\nmodel Session {\n    id           String   @id @default(cuid())\n    sessionToken String   @unique\n    userId       String\n    expires      DateTime\n    user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel User {\n    id            String    @id @default(cuid())\n    name          String?\n    email         String?   @unique\n    emailVerified DateTime?\n    image         String?\n    accounts      Account[]\n    sessions      Session[]\n    posts         Post[]\n}\n\nmodel VerificationToken {\n    identifier String\n    token      String   @unique\n    expires    DateTime\n\n    @@unique([identifier, token])\n}\n"
  },
  {
    "path": "cli/template/extras/prisma/schema/with-better-auth-planetscale.prisma",
    "content": "// Prisma schema for Better Auth\n// learn more: https://better-auth.com/docs/concepts/database\n\ngenerator client {\n  provider = \"prisma-client-js\"\n  output   = \"../generated/prisma\"\n}\n\n// NOTE: When using mysql or sqlserver, uncomment the  @db.Text annotations in model Account below\n// Further reading:\n// https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#string\n\ndatasource db {\n  provider     = \"mysql\"\n  relationMode = \"prisma\"\n  url          = env(\"DATABASE_URL\")\n}\n\nmodel Post {\n  id        String   @id @default(cuid())\n  name      String\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n\n  createdBy   User   @relation(fields: [createdById], references: [id])\n  createdById String\n\n  @@index([name])\n}\n\nmodel User {\n  id            String    @id\n  name          String    @db.Text\n  email         String\n  emailVerified Boolean   @default(false)\n  image         String?   @db.Text\n  createdAt     DateTime  @default(now())\n  updatedAt     DateTime  @default(now()) @updatedAt\n  sessions      Session[]\n  accounts      Account[]\n  posts         Post[]\n\n  @@unique([email])\n  @@map(\"user\")\n}\n\nmodel Session {\n  id        String   @id\n  expiresAt DateTime\n  token     String\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n  ipAddress String?  @db.Text\n  userAgent String?  @db.Text\n  userId    String\n  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n  @@unique([token])\n  @@map(\"session\")\n}\n\nmodel Account {\n  id                    String    @id\n  accountId             String    @db.Text\n  providerId            String    @db.Text\n  userId                String\n  user                  User      @relation(fields: [userId], references: [id], onDelete: Cascade)\n  accessToken           String?   @db.Text\n  refreshToken          String?   @db.Text\n  idToken               String?   @db.Text\n  accessTokenExpiresAt  DateTime?\n  refreshTokenExpiresAt DateTime?\n  scope                 String?   @db.Text\n  password              String?   @db.Text\n  createdAt             DateTime  @default(now())\n  updatedAt             DateTime  @updatedAt\n\n  @@map(\"account\")\n}\n\nmodel Verification {\n  id         String   @id\n  identifier String   @db.Text\n  value      String   @db.Text\n  expiresAt  DateTime\n  createdAt  DateTime @default(now())\n  updatedAt  DateTime @default(now()) @updatedAt\n\n  @@map(\"verification\")\n}\n"
  },
  {
    "path": "cli/template/extras/prisma/schema/with-better-auth.prisma",
    "content": "// Prisma schema for Better Auth\n// learn more: https://better-auth.com/docs/concepts/database\n\ngenerator client {\n  provider = \"prisma-client-js\"\n  output   = \"../generated/prisma\"\n}\n\n// NOTE: When using mysql or sqlserver, uncomment the //@db.Text annotations in model Account below\n// Further reading:\n// https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#string\n\ndatasource db {\n  provider = \"sqlite\"\n  url      = env(\"DATABASE_URL\")\n}\n\nmodel Post {\n  id        String   @id @default(cuid())\n  name      String\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n\n  createdBy   User   @relation(fields: [createdById], references: [id])\n  createdById String\n\n  @@index([name])\n}\n\nmodel User {\n  id            String    @id\n  name          String //@db.Text\n  email         String\n  emailVerified Boolean   @default(false)\n  image         String? //@db.Text\n  createdAt     DateTime  @default(now())\n  updatedAt     DateTime  @default(now()) @updatedAt\n  sessions      Session[]\n  accounts      Account[]\n  posts         Post[]\n\n  @@unique([email])\n  @@map(\"user\")\n}\n\nmodel Session {\n  id        String   @id\n  expiresAt DateTime\n  token     String\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n  ipAddress String? //@db.Text\n  userAgent String? //@db.Text\n  userId    String\n  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n  @@unique([token])\n  @@map(\"session\")\n}\n\nmodel Account {\n  id                    String    @id\n  accountId             String //@db.Text\n  providerId            String //@db.Text\n  userId                String\n  user                  User      @relation(fields: [userId], references: [id], onDelete: Cascade)\n  accessToken           String? //@db.Text\n  refreshToken          String? //@db.Text\n  idToken               String? //@db.Text\n  accessTokenExpiresAt  DateTime?\n  refreshTokenExpiresAt DateTime?\n  scope                 String? //@db.Text\n  password              String? //@db.Text\n  createdAt             DateTime  @default(now())\n  updatedAt             DateTime  @updatedAt\n\n  @@map(\"account\")\n}\n\nmodel Verification {\n  id         String   @id\n  identifier String //@db.Text\n  value      String //@db.Text\n  expiresAt  DateTime\n  createdAt  DateTime @default(now())\n  updatedAt  DateTime @default(now()) @updatedAt\n\n  @@map(\"verification\")\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/_components/post-tw.tsx",
    "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { api } from \"~/trpc/react\";\n\nexport function LatestPost() {\n  const [latestPost] = api.post.getLatest.useSuspenseQuery();\n\n  const utils = api.useUtils();\n  const [name, setName] = useState(\"\");\n  const createPost = api.post.create.useMutation({\n    onSuccess: async () => {\n      await utils.post.invalidate();\n      setName(\"\");\n    },\n  });\n\n  return (\n    <div className=\"w-full max-w-xs\">\n      {latestPost ? (\n        <p className=\"truncate\">Your most recent post: {latestPost.name}</p>\n      ) : (\n        <p>You have no posts yet.</p>\n      )}\n      <form\n        onSubmit={(e) => {\n          e.preventDefault();\n          createPost.mutate({ name });\n        }}\n        className=\"flex flex-col gap-2\"\n      >\n        <input\n          type=\"text\"\n          placeholder=\"Title\"\n          value={name}\n          onChange={(e) => setName(e.target.value)}\n          className=\"w-full rounded-full bg-white/10 px-4 py-2 text-white\"\n        />\n        <button\n          type=\"submit\"\n          className=\"rounded-full bg-white/10 px-10 py-3 font-semibold transition hover:bg-white/20\"\n          disabled={createPost.isPending}\n        >\n          {createPost.isPending ? \"Submitting...\" : \"Submit\"}\n        </button>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/_components/post.tsx",
    "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { api } from \"~/trpc/react\";\nimport styles from \"../index.module.css\";\n\nexport function LatestPost() {\n  const [latestPost] = api.post.getLatest.useSuspenseQuery();\n\n  const utils = api.useUtils();\n  const [name, setName] = useState(\"\");\n  const createPost = api.post.create.useMutation({\n    onSuccess: async () => {\n      await utils.post.invalidate();\n      setName(\"\");\n    },\n  });\n\n  return (\n    <div className={styles.showcaseContainer}>\n      {latestPost ? (\n        <p className={styles.showcaseText}>\n          Your most recent post: {latestPost.name}\n        </p>\n      ) : (\n        <p className={styles.showcaseText}>You have no posts yet.</p>\n      )}\n\n      <form\n        onSubmit={(e) => {\n          e.preventDefault();\n          createPost.mutate({ name });\n        }}\n        className={styles.form}\n      >\n        <input\n          type=\"text\"\n          placeholder=\"Title\"\n          value={name}\n          onChange={(e) => setName(e.target.value)}\n          className={styles.input}\n        />\n        <button\n          type=\"submit\"\n          className={styles.submitButton}\n          disabled={createPost.isPending}\n        >\n          {createPost.isPending ? \"Submitting...\" : \"Submit\"}\n        </button>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/api/auth/[...all]/route.ts",
    "content": "import { toNextJsHandler } from \"better-auth/next-js\";\n\nimport { auth } from \"~/server/better-auth\";\n\nexport const { GET, POST } = toNextJsHandler(auth.handler);\n"
  },
  {
    "path": "cli/template/extras/src/app/api/auth/[...nextauth]/route.ts",
    "content": "import { handlers } from \"~/server/auth\";\n\nexport const { GET, POST } = handlers;\n"
  },
  {
    "path": "cli/template/extras/src/app/api/trpc/[trpc]/route.ts",
    "content": "import { fetchRequestHandler } from \"@trpc/server/adapters/fetch\";\nimport { type NextRequest } from \"next/server\";\n\nimport { env } from \"~/env\";\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": "cli/template/extras/src/app/layout/base.tsx",
    "content": "import \"~/styles/globals.css\";\n\nimport { type Metadata } from \"next\";\nimport { Geist } from \"next/font/google\";\n\nexport const metadata: Metadata = {\n  title: \"Create T3 App\",\n  description: \"Generated by create-t3-app\",\n  icons: [{ rel: \"icon\", url: \"/favicon.ico\" }],\n};\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nexport default function RootLayout({\n  children,\n}: Readonly<{ children: React.ReactNode }>) {\n  return (\n    <html lang=\"en\">\n      <body className={geist.className}>{children}</body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/layout/with-trpc-tw.tsx",
    "content": "import \"~/styles/globals.css\";\n\nimport { type Metadata } from \"next\";\nimport { Geist } from \"next/font/google\";\n\nimport { TRPCReactProvider } from \"~/trpc/react\";\n\nexport const metadata: Metadata = {\n  title: \"Create T3 App\",\n  description: \"Generated by create-t3-app\",\n  icons: [{ rel: \"icon\", url: \"/favicon.ico\" }],\n};\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n  variable: \"--font-geist-sans\",\n});\n\nexport default function RootLayout({\n  children,\n}: Readonly<{ children: React.ReactNode }>) {\n  return (\n    <html lang=\"en\" className={`${geist.variable}`}>\n      <body>\n        <TRPCReactProvider>{children}</TRPCReactProvider>\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/layout/with-trpc.tsx",
    "content": "import \"~/styles/globals.css\";\n\nimport { type Metadata } from \"next\";\nimport { Geist } from \"next/font/google\";\n\nimport { TRPCReactProvider } from \"~/trpc/react\";\n\nexport const metadata: Metadata = {\n  title: \"Create T3 App\",\n  description: \"Generated by create-t3-app\",\n  icons: [{ rel: \"icon\", url: \"/favicon.ico\" }],\n};\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nexport default function RootLayout({\n  children,\n}: Readonly<{ children: React.ReactNode }>) {\n  return (\n    <html lang=\"en\">\n      <body className={geist.className}>\n        <TRPCReactProvider>{children}</TRPCReactProvider>\n      </body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/layout/with-tw.tsx",
    "content": "import \"~/styles/globals.css\";\n\nimport { type Metadata } from \"next\";\nimport { Geist } from \"next/font/google\";\n\nexport const metadata: Metadata = {\n  title: \"Create T3 App\",\n  description: \"Generated by create-t3-app\",\n  icons: [{ rel: \"icon\", url: \"/favicon.ico\" }],\n};\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n  variable: \"--font-geist-sans\",\n});\n\nexport default function RootLayout({\n  children,\n}: Readonly<{ children: React.ReactNode }>) {\n  return (\n    <html lang=\"en\" className={`${geist.variable}`}>\n      <body>{children}</body>\n    </html>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/base.tsx",
    "content": "import Link from \"next/link\";\n\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  return (\n    <main className={styles.main}>\n      <div className={styles.container}>\n        <h1 className={styles.title}>\n          Create <span className={styles.pinkSpan}>T3</span> App\n        </h1>\n        <div className={styles.cardRow}>\n          <Link\n            className={styles.card}\n            href=\"https://create.t3.gg/en/usage/first-steps\"\n            target=\"_blank\"\n          >\n            <h3 className={styles.cardTitle}>First Steps →</h3>\n            <div className={styles.cardText}>\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={styles.card}\n            href=\"https://create.t3.gg/en/introduction\"\n            target=\"_blank\"\n          >\n            <h3 className={styles.cardTitle}>Documentation →</h3>\n            <div className={styles.cardText}>\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>\n    </main>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-auth-trpc-tw.tsx",
    "content": "import Link from \"next/link\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { auth } from \"~/server/auth\";\nimport { api, HydrateClient } from \"~/trpc/server\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n  const session = await auth();\n\n  if (session?.user) {\n    void api.post.getLatest.prefetch();\n  }\n\n  return (\n    <HydrateClient>\n      <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white\">\n        <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16\">\n          <h1 className=\"text-5xl font-extrabold tracking-tight sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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 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 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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <p className=\"text-2xl text-white\">\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n\n            <div className=\"flex flex-col items-center justify-center gap-4\">\n              <p className=\"text-center text-2xl text-white\">\n                {session && <span>Logged in as {session.user?.name}</span>}\n              </p>\n              <Link\n                href={session ? \"/api/auth/signout\" : \"/api/auth/signin\"}\n                className=\"rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20\"\n              >\n                {session ? \"Sign out\" : \"Sign in\"}\n              </Link>\n            </div>\n          </div>\n\n          {session?.user && <LatestPost />}\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-auth-trpc.tsx",
    "content": "import Link from \"next/link\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { auth } from \"~/server/auth\";\nimport { api, HydrateClient } from \"~/trpc/server\";\nimport styles from \"./index.module.css\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n  const session = await auth();\n\n  if (session?.user) {\n    void api.post.getLatest.prefetch();\n  }\n\n  return (\n    <HydrateClient>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <p className={styles.showcaseText}>\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n\n            <div className={styles.authContainer}>\n              <p className={styles.showcaseText}>\n                {session && <span>Logged in as {session.user?.name}</span>}\n              </p>\n              <Link\n                href={session ? \"/api/auth/signout\" : \"/api/auth/signin\"}\n                className={styles.loginButton}\n              >\n                {session ? \"Sign out\" : \"Sign in\"}\n              </Link>\n            </div>\n          </div>\n\n          {session?.user && <LatestPost />}\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-better-auth-trpc-tw.tsx",
    "content": "import { headers } from \"next/headers\";\nimport Link from \"next/link\";\nimport { redirect } from \"next/navigation\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { auth } from \"~/server/better-auth\";\nimport { getSession } from \"~/server/better-auth/server\";\nimport { api, HydrateClient } from \"~/trpc/server\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n  const session = await getSession();\n\n  if (session) {\n    void api.post.getLatest.prefetch();\n  }\n\n  return (\n    <HydrateClient>\n      <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white\">\n        <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16\">\n          <h1 className=\"text-5xl font-extrabold tracking-tight sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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 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 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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <p className=\"text-2xl text-white\">\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n\n            <div className=\"flex flex-col items-center justify-center gap-4\">\n              <p className=\"text-center text-2xl text-white\">\n                {session && <span>Logged in as {session.user?.name}</span>}\n              </p>\n              {!session ? (\n                <form>\n                  <button\n                    type=\"submit\"\n                    className=\"rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20\"\n                    formAction={async () => {\n                      \"use server\";\n                      const res = await auth.api.signInSocial({\n                        body: {\n                          provider: \"github\",\n                          callbackURL: \"/\",\n                        },\n                      });\n                      if (!res.url) {\n                        throw new Error(\"No URL returned from signInSocial\");\n                      }\n                      redirect(res.url);\n                    }}\n                  >\n                    Sign in with Github\n                  </button>\n                </form>\n              ) : (\n                <form>\n                  <button\n                    type=\"submit\"\n                    className=\"rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20\"\n                    formAction={async () => {\n                      \"use server\";\n                      await auth.api.signOut({\n                        headers: await headers(),\n                      });\n                      redirect(\"/\");\n                    }}\n                  >\n                    Sign out\n                  </button>\n                </form>\n              )}\n            </div>\n          </div>\n\n          {session?.user && <LatestPost />}\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-better-auth-trpc.tsx",
    "content": "import { headers } from \"next/headers\";\nimport Link from \"next/link\";\nimport { redirect } from \"next/navigation\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { auth } from \"~/server/better-auth\";\nimport { getSession } from \"~/server/better-auth/server\";\nimport { api, HydrateClient } from \"~/trpc/server\";\nimport styles from \"./index.module.css\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n  const session = await getSession();\n\n  if (session?.user) {\n    void api.post.getLatest.prefetch();\n  }\n\n  return (\n    <HydrateClient>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <p className={styles.showcaseText}>\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n\n            <div className={styles.authContainer}>\n              <p className={styles.showcaseText}>\n                {session && <span>Logged in as {session.user?.name}</span>}\n              </p>\n              {!session ? (\n                <form>\n                  <button\n                    type=\"submit\"\n                    className={styles.loginButton}\n                    formAction={async () => {\n                      \"use server\";\n                      const res = await auth.api.signInSocial({\n                        body: {\n                          provider: \"github\",\n                          callbackURL: \"/\",\n                        },\n                      });\n                      if (!res.url)\n                        throw new Error(\"No URL returned from signInSocial\");\n                      redirect(res.url);\n                    }}\n                  >\n                    Sign in with Github\n                  </button>\n                </form>\n              ) : (\n                <form>\n                  <button\n                    type=\"submit\"\n                    className={styles.loginButton}\n                    formAction={async () => {\n                      \"use server\";\n                      await auth.api.signOut({ headers: await headers() });\n                      redirect(\"/\");\n                    }}\n                  >\n                    Sign out\n                  </button>\n                </form>\n              )}\n            </div>\n          </div>\n\n          {session?.user && <LatestPost />}\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-better-auth-tw.tsx",
    "content": "import { headers } from \"next/headers\";\nimport Link from \"next/link\";\nimport { redirect } from \"next/navigation\";\n\nimport { auth } from \"~/server/better-auth\";\nimport { getSession } from \"~/server/better-auth/server\";\n\nexport default async function Home() {\n  const session = await getSession();\n\n  return (\n    <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white\">\n      <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16\">\n        <h1 className=\"text-5xl font-extrabold tracking-tight sm:text-[5rem]\">\n          Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n        </h1>\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 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 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 flex-col items-center gap-2\">\n          <div className=\"flex flex-col items-center justify-center gap-4\">\n            <p className=\"text-center text-2xl text-white\">\n              {session && <span>Logged in as {session.user?.name}</span>}\n            </p>\n            {!session ? (\n              <form>\n                <button\n                  type=\"submit\"\n                  className=\"rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20\"\n                  formAction={async () => {\n                    \"use server\";\n                    const res = await auth.api.signInSocial({\n                      body: {\n                        provider: \"github\",\n                        callbackURL: \"/\",\n                      },\n                    });\n                    if (!res.url) {\n                      throw new Error(\"No URL returned from signInSocial\");\n                    }\n                    redirect(res.url);\n                  }}\n                >\n                  Sign in with Github\n                </button>\n              </form>\n            ) : (\n              <form>\n                <button\n                  type=\"submit\"\n                  className=\"rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20\"\n                  formAction={async () => {\n                    \"use server\";\n                    await auth.api.signOut({\n                      headers: await headers(),\n                    });\n                    redirect(\"/\");\n                  }}\n                >\n                  Sign out\n                </button>\n              </form>\n            )}\n          </div>\n        </div>\n      </div>\n    </main>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-better-auth.tsx",
    "content": "import { headers } from \"next/headers\";\nimport Link from \"next/link\";\nimport { redirect } from \"next/navigation\";\n\nimport { auth } from \"~/server/better-auth\";\nimport { getSession } from \"~/server/better-auth/server\";\nimport styles from \"./index.module.css\";\n\nexport default async function Home() {\n  const session = await getSession();\n\n  return (\n    <main className={styles.main}>\n      <div className={styles.container}>\n        <h1 className={styles.title}>\n          Create <span className={styles.pinkSpan}>T3</span> App\n        </h1>\n        <div className={styles.cardRow}>\n          <Link\n            className={styles.card}\n            href=\"https://create.t3.gg/en/usage/first-steps\"\n            target=\"_blank\"\n          >\n            <h3 className={styles.cardTitle}>First Steps →</h3>\n            <div className={styles.cardText}>\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={styles.card}\n            href=\"https://create.t3.gg/en/introduction\"\n            target=\"_blank\"\n          >\n            <h3 className={styles.cardTitle}>Documentation →</h3>\n            <div className={styles.cardText}>\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={styles.showcaseContainer}>\n          <div className={styles.authContainer}>\n            <p className={styles.showcaseText}>\n              {session && <span>Logged in as {session.user?.name}</span>}\n            </p>\n            {!session ? (\n              <form>\n                <button\n                  type=\"submit\"\n                  className={styles.loginButton}\n                  formAction={async () => {\n                    \"use server\";\n                    const res = await auth.api.signInSocial({\n                      body: {\n                        provider: \"github\",\n                        callbackURL: \"/\",\n                      },\n                    });\n                    if (!res.url)\n                      throw new Error(\"No URL returned from signInSocial\");\n                    redirect(res.url);\n                  }}\n                >\n                  Sign in with Github\n                </button>\n              </form>\n            ) : (\n              <form>\n                <button\n                  type=\"submit\"\n                  className={styles.loginButton}\n                  formAction={async () => {\n                    \"use server\";\n                    await auth.api.signOut({ headers: await headers() });\n                    redirect(\"/\");\n                  }}\n                >\n                  Sign out\n                </button>\n              </form>\n            )}\n          </div>\n        </div>\n      </div>\n    </main>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-trpc-tw.tsx",
    "content": "import Link from \"next/link\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { api, HydrateClient } from \"~/trpc/server\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n\n  void api.post.getLatest.prefetch();\n\n  return (\n    <HydrateClient>\n      <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white\">\n        <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16\">\n          <h1 className=\"text-5xl font-extrabold tracking-tight sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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 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 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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <p className=\"text-2xl text-white\">\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n          </div>\n\n          <LatestPost />\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-trpc.tsx",
    "content": "import Link from \"next/link\";\n\nimport { LatestPost } from \"~/app/_components/post\";\nimport { api, HydrateClient } from \"~/trpc/server\";\nimport styles from \"./index.module.css\";\n\nexport default async function Home() {\n  const hello = await api.post.hello({ text: \"from tRPC\" });\n\n  void api.post.getLatest.prefetch();\n\n  return (\n    <HydrateClient>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <p className={styles.showcaseText}>\n              {hello ? hello.greeting : \"Loading tRPC query...\"}\n            </p>\n          </div>\n\n          <LatestPost />\n        </div>\n      </main>\n    </HydrateClient>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/app/page/with-tw.tsx",
    "content": "import Link from \"next/link\";\n\nexport default function HomePage() {\n  return (\n    <main className=\"flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white\">\n      <div className=\"container flex flex-col items-center justify-center gap-12 px-4 py-16\">\n        <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n          Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n        </h1>\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>\n    </main>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/env/with-auth-db-planetscale.js",
    "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    AUTH_SECRET:\n      process.env.NODE_ENV === \"production\"\n        ? z.string()\n        : z.string().optional(),\n    AUTH_DISCORD_ID: z.string(),\n    AUTH_DISCORD_SECRET: z.string(),\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  },\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_CLIENTVAR: z.string(),\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    AUTH_SECRET: process.env.AUTH_SECRET,\n    AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,\n    AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,\n    DATABASE_URL: process.env.DATABASE_URL,\n    NODE_ENV: process.env.NODE_ENV,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-auth-db.js",
    "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    AUTH_SECRET:\n      process.env.NODE_ENV === \"production\"\n        ? z.string()\n        : z.string().optional(),\n    AUTH_DISCORD_ID: z.string(),\n    AUTH_DISCORD_SECRET: z.string(),\n    DATABASE_URL: z.string().url(),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"])\n      .default(\"development\"),\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_CLIENTVAR: z.string(),\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    AUTH_SECRET: process.env.AUTH_SECRET,\n    AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,\n    AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,\n    DATABASE_URL: process.env.DATABASE_URL,\n    NODE_ENV: process.env.NODE_ENV,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-auth.js",
    "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    AUTH_SECRET:\n      process.env.NODE_ENV === \"production\"\n        ? z.string()\n        : z.string().optional(),\n    AUTH_DISCORD_ID: z.string(),\n    AUTH_DISCORD_SECRET: z.string(),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"])\n      .default(\"development\"),\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_CLIENTVAR: z.string(),\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    AUTH_SECRET: process.env.AUTH_SECRET,\n    AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,\n    AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,\n    NODE_ENV: process.env.NODE_ENV,\n    // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-better-auth-db-planetscale.js",
    "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    BETTER_AUTH_SECRET:\n      process.env.NODE_ENV === \"production\"\n        ? z.string()\n        : z.string().optional(),\n    BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),\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  },\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_CLIENTVAR: z.string(),\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    BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,\n    BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,\n    DATABASE_URL: process.env.DATABASE_URL,\n    NODE_ENV: process.env.NODE_ENV,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-better-auth-db.js",
    "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    BETTER_AUTH_SECRET:\n      process.env.NODE_ENV === \"production\" ? z.string() : z.string().optional(),\n    BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),\n    DATABASE_URL: z.string().url(),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"]) \n      .default(\"development\"),\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_CLIENTVAR: z.string(),\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    BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,\n    BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,\n    DATABASE_URL: process.env.DATABASE_URL,\n    NODE_ENV: process.env.NODE_ENV,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-better-auth.js",
    "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    BETTER_AUTH_SECRET:\n      process.env.NODE_ENV === \"production\" ? z.string() : z.string().optional(),\n    BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"]) \n      .default(\"development\"),\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_CLIENTVAR: z.string(),\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    BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,\n    BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,\n    BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,\n    NODE_ENV: process.env.NODE_ENV,\n    // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-db-planetscale.js",
    "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  },\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_CLIENTVAR: z.string(),\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    // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/env/with-db.js",
    "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.string().url(),\n    NODE_ENV: z\n      .enum([\"development\", \"test\", \"production\"])\n      .default(\"development\"),\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_CLIENTVAR: z.string(),\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    // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\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   * Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and\n   * `SOME_VAR=''` will throw an error.\n   */\n  emptyStringAsUndefined: true,\n});\n"
  },
  {
    "path": "cli/template/extras/src/index.module.css",
    "content": ".main {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  min-height: 100vh;\n  background-image: linear-gradient(to bottom, #2e026d, #15162c);\n}\n\n.container {\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  gap: 3rem;\n  padding: 4rem 1rem;\n}\n\n@media (min-width: 640px) {\n  .container {\n    max-width: 640px;\n  }\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 768px;\n  }\n}\n\n@media (min-width: 1024px) {\n  .container {\n    max-width: 1024px;\n  }\n}\n\n@media (min-width: 1280px) {\n  .container {\n    max-width: 1280px;\n  }\n}\n\n@media (min-width: 1536px) {\n  .container {\n    max-width: 1536px;\n  }\n}\n\n.title {\n  font-size: 3rem;\n  line-height: 1;\n  font-weight: 800;\n  letter-spacing: -0.025em;\n  margin: 0;\n  color: white;\n}\n\n@media (min-width: 640px) {\n  .title {\n    font-size: 5rem;\n  }\n}\n\n.pinkSpan {\n  color: hsl(280 100% 70%);\n}\n\n.cardRow {\n  display: grid;\n  grid-template-columns: repeat(1, minmax(0, 1fr));\n  gap: 1rem;\n}\n\n@media (min-width: 640px) {\n  .cardRow {\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n  }\n}\n\n@media (min-width: 768px) {\n  .cardRow {\n    gap: 2rem;\n  }\n}\n\n.card {\n  max-width: 20rem;\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n  padding: 1rem;\n  border-radius: 0.75rem;\n  color: white;\n  background-color: rgb(255 255 255 / 0.1);\n}\n\n.card:hover {\n  background-color: rgb(255 255 255 / 0.2);\n  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);\n}\n\n.cardTitle {\n  font-size: 1.5rem;\n  line-height: 2rem;\n  font-weight: 700;\n  margin: 0;\n}\n\n.cardText {\n  font-size: 1.125rem;\n  line-height: 1.75rem;\n}\n\n.showcaseContainer {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  gap: 0.5rem;\n}\n\n.showcaseText {\n  color: white;\n  text-align: center;\n  font-size: 1.5rem;\n  line-height: 2rem;\n}\n\n.authContainer {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  gap: 1rem;\n}\n\n.loginButton {\n  border-radius: 9999px;\n  background-color: rgb(255 255 255 / 0.1);\n  padding: 0.75rem 2.5rem;\n  font-weight: 600;\n  color: white;\n  text-decoration-line: none;\n  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);\n}\n\n.loginButton:hover {\n  background-color: rgb(255 255 255 / 0.2);\n}\n\n.form {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.input {\n  width: 100%;\n  border-radius: 9999px;\n  padding: 0.5rem 1rem;\n  color: black;\n}\n\n.submitButton {\n  all: unset;\n  border-radius: 9999px;\n  background-color: rgb(255 255 255 / 0.1);\n  padding: 0.75rem 2.5rem;\n  font-weight: 600;\n  color: white;\n  text-align: center;\n  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);\n}\n\n.submitButton:hover {\n  background-color: rgb(255 255 255 / 0.2);\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/base.tsx",
    "content": "import { type AppType } from \"next/dist/shared/lib/utils\";\nimport { Geist } from \"next/font/google\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default MyApp;\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-auth-trpc-tw.tsx",
    "content": "import { type Session } from \"next-auth\";\nimport { SessionProvider } from \"next-auth/react\";\nimport { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType<{ session: Session | null }> = ({\n  Component,\n  pageProps: { session, ...pageProps },\n}) => {\n  return (\n    <SessionProvider session={session}>\n      <div className={geist.className}>\n        <Component {...pageProps} />\n      </div>\n    </SessionProvider>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-auth-trpc.tsx",
    "content": "import { type Session } from \"next-auth\";\nimport { SessionProvider } from \"next-auth/react\";\nimport { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType<{ session: Session | null }> = ({\n  Component,\n  pageProps: { session, ...pageProps },\n}) => {\n  return (\n    <SessionProvider session={session}>\n      <div className={geist.className}>\n        <Component {...pageProps} />\n      </div>\n    </SessionProvider>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-auth-tw.tsx",
    "content": "import { type Session } from \"next-auth\";\nimport { SessionProvider } from \"next-auth/react\";\nimport { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType<{ session: Session | null }> = ({\n  Component,\n  pageProps: { session, ...pageProps },\n}) => {\n  return (\n    <SessionProvider session={session}>\n      <div className={geist.className}>\n        <Component {...pageProps} />\n      </div>\n    </SessionProvider>\n  );\n};\n\nexport default MyApp;\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-auth.tsx",
    "content": "import { type Session } from \"next-auth\";\nimport { SessionProvider } from \"next-auth/react\";\nimport { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType<{ session: Session | null }> = ({\n  Component,\n  pageProps: { session, ...pageProps },\n}) => {\n  return (\n    <SessionProvider session={session}>\n      <div className={geist.className}>\n        <Component {...pageProps} />\n      </div>\n    </SessionProvider>\n  );\n};\n\nexport default MyApp;\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-better-auth-trpc-tw.tsx",
    "content": "import { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-better-auth-trpc.tsx",
    "content": "import { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-trpc-tw.tsx",
    "content": "import { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-trpc.tsx",
    "content": "import { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport { api } from \"~/utils/api\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default api.withTRPC(MyApp);\n"
  },
  {
    "path": "cli/template/extras/src/pages/_app/with-tw.tsx",
    "content": "import { type AppType } from \"next/app\";\nimport { Geist } from \"next/font/google\";\n\nimport \"~/styles/globals.css\";\n\nconst geist = Geist({\n  subsets: [\"latin\"],\n});\n\nconst MyApp: AppType = ({ Component, pageProps }) => {\n  return (\n    <div className={geist.className}>\n      <Component {...pageProps} />\n    </div>\n  );\n};\n\nexport default MyApp;\n"
  },
  {
    "path": "cli/template/extras/src/pages/api/auth/[...all].ts",
    "content": "import { toNodeHandler } from \"better-auth/node\";\n\nimport { auth } from \"~/server/better-auth\";\n\n// Disallow body parsing, we will parse it manually\nexport const config = { api: { bodyParser: false } };\n\nexport default toNodeHandler(auth.handler);\n"
  },
  {
    "path": "cli/template/extras/src/pages/api/trpc/[trpc].ts",
    "content": "import { createNextApiHandler } from \"@trpc/server/adapters/next\";\n\nimport { env } from \"~/env\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\n\n// export API handler\nexport default createNextApiHandler({\n  router: appRouter,\n  createContext: createTRPCContext,\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"
  },
  {
    "path": "cli/template/extras/src/pages/index/base.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-auth-trpc-tw.tsx",
    "content": "import { signIn, signOut, useSession } from \"next-auth/react\";\nimport Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { api } from \"~/utils/api\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\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          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <p className=\"text-2xl text-white\">\n              {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n            </p>\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData } = useSession();\n\n  const { data: secretMessage } = api.post.getSecretMessage.useQuery(\n    undefined, // no input\n    { enabled: sessionData?.user !== undefined }\n  );\n\n  return (\n    <div className=\"flex flex-col items-center justify-center gap-4\">\n      <p className=\"text-center text-2xl text-white\">\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n        {secretMessage && <span> - {secretMessage}</span>}\n      </p>\n      <button\n        type=\"button\"\n        className=\"rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20\"\n        onClick={sessionData ? () => void signOut() : () => void signIn()}\n      >\n        {sessionData ? \"Sign out\" : \"Sign in\"}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-auth-trpc.tsx",
    "content": "import { signIn, signOut, useSession } from \"next-auth/react\";\nimport Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { api } from \"~/utils/api\";\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <p className={styles.showcaseText}>\n              {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n            </p>\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData } = useSession();\n\n  const { data: secretMessage } = api.post.getSecretMessage.useQuery(\n    undefined, // no input\n    { enabled: sessionData?.user !== undefined }\n  );\n\n  return (\n    <div className={styles.authContainer}>\n      <p className={styles.showcaseText}>\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n        {secretMessage && <span> - {secretMessage}</span>}\n      </p>\n      <button\n        type=\"button\"\n        className={styles.loginButton}\n        onClick={sessionData ? () => void signOut() : () => void signIn()}\n      >\n        {sessionData ? \"Sign out\" : \"Sign in\"}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-better-auth-trpc-tw.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { authClient } from \"~/server/better-auth/client\";\nimport { api } from \"~/utils/api\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\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          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <p className=\"text-2xl text-white\">\n              {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n            </p>\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData, isPending } = authClient.useSession();\n\n  const { data: secretMessage } = api.post.getSecretMessage.useQuery(\n    undefined, // no input\n    { enabled: sessionData?.user !== undefined }\n  );\n\n  if (isPending) {\n    return <p className=\"text-2xl text-white\">Loading...</p>;\n  }\n\n  return (\n    <div className=\"flex flex-col items-center justify-center gap-4\">\n      <p className=\"text-center text-2xl text-white\">\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n        {secretMessage && <span> - {secretMessage}</span>}\n      </p>\n      {sessionData ? (\n        <button\n          type=\"button\"\n          className=\"rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20\"\n          onClick={async () => {\n            await authClient.signOut();\n          }}\n        >\n          Sign out\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          className=\"rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20\"\n          onClick={async () => {\n            await authClient.signIn.social({ provider: \"github\" });\n          }}\n        >\n          Sign in with GitHub\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-better-auth-trpc.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { authClient } from \"~/server/better-auth/client\";\nimport { api } from \"~/utils/api\";\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <p className={styles.showcaseText}>\n              {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n            </p>\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData, isPending } = authClient.useSession();\n\n  const { data: secretMessage } = api.post.getSecretMessage.useQuery(\n    undefined, // no input\n    { enabled: sessionData?.user !== undefined }\n  );\n\n  if (isPending) {\n    return <p className={styles.showcaseText}>Loading...</p>;\n  }\n\n  return (\n    <div className={styles.authContainer}>\n      <p className={styles.showcaseText}>\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n        {secretMessage && <span> - {secretMessage}</span>}\n      </p>\n      {sessionData ? (\n        <button\n          type=\"button\"\n          className={styles.loginButton}\n          onClick={async () => {\n            await authClient.signOut();\n          }}\n        >\n          Sign out\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          className={styles.loginButton}\n          onClick={async () => {\n            await authClient.signIn.social({ provider: \"github\" });\n          }}\n        >\n          Sign in with GitHub\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-better-auth-tw.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { authClient } from \"~/server/better-auth/client\";\n\nexport default function Home() {\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\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          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData, isPending } = authClient.useSession();\n\n  if (isPending) {\n    return <p className=\"text-2xl text-white\">Loading...</p>;\n  }\n\n  return (\n    <div className=\"flex flex-col items-center justify-center gap-4\">\n      <p className=\"text-center text-2xl text-white\">\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n      </p>\n      {sessionData ? (\n        <button\n          type=\"button\"\n          className=\"rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20\"\n          onClick={async () => {\n            await authClient.signOut();\n          }}\n        >\n          Sign out\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          className=\"rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20\"\n          onClick={async () => {\n            await authClient.signIn.social({ provider: \"github\" });\n          }}\n        >\n          Sign in with GitHub\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-better-auth.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { authClient } from \"~/server/better-auth/client\";\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <div className={styles.showcaseContainer}>\n            <AuthShowcase />\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n\nfunction AuthShowcase() {\n  const { data: sessionData, isPending } = authClient.useSession();\n\n  if (isPending) {\n    return <p className={styles.showcaseText}>Loading...</p>;\n  }\n\n  return (\n    <div className={styles.authContainer}>\n      <p className={styles.showcaseText}>\n        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}\n      </p>\n      {sessionData ? (\n        <button\n          type=\"button\"\n          className={styles.loginButton}\n          onClick={async () => {\n            await authClient.signOut();\n          }}\n        >\n          Sign out\n        </button>\n      ) : (\n        <button\n          type=\"button\"\n          className={styles.loginButton}\n          onClick={async () => {\n            await authClient.signIn.social({ provider: \"github\" });\n          }}\n        >\n          Sign in with GitHub\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-trpc-tw.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { api } from \"~/utils/api\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\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          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <p className=\"text-2xl text-white\">\n            {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n          </p>\n        </div>\n      </main>\n    </>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-trpc.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nimport { api } from \"~/utils/api\";\nimport styles from \"./index.module.css\";\n\nexport default function Home() {\n  const hello = api.post.hello.useQuery({ text: \"from tRPC\" });\n\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\n      <main className={styles.main}>\n        <div className={styles.container}>\n          <h1 className={styles.title}>\n            Create <span className={styles.pinkSpan}>T3</span> App\n          </h1>\n          <div className={styles.cardRow}>\n            <Link\n              className={styles.card}\n              href=\"https://create.t3.gg/en/usage/first-steps\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>First Steps →</h3>\n              <div className={styles.cardText}>\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={styles.card}\n              href=\"https://create.t3.gg/en/introduction\"\n              target=\"_blank\"\n            >\n              <h3 className={styles.cardTitle}>Documentation →</h3>\n              <div className={styles.cardText}>\n                Learn more about Create T3 App, the libraries it uses, and how\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n          <p className={styles.showcaseText}>\n            {hello.data ? hello.data.greeting : \"Loading tRPC query...\"}\n          </p>\n        </div>\n      </main>\n    </>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/pages/index/with-tw.tsx",
    "content": "import Head from \"next/head\";\nimport Link from \"next/link\";\n\nexport default function Home() {\n  return (\n    <>\n      <Head>\n        <title>Create T3 App</title>\n        <meta name=\"description\" content=\"Generated by create-t3-app\" />\n        <link rel=\"icon\" href=\"/favicon.ico\" />\n      </Head>\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          <h1 className=\"text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]\">\n            Create <span className=\"text-[hsl(280,100%,70%)]\">T3</span> App\n          </h1>\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\n                to deploy it.\n              </div>\n            </Link>\n          </div>\n        </div>\n      </main>\n    </>\n  );\n}\n"
  },
  {
    "path": "cli/template/extras/src/server/api/root.ts",
    "content": "import { postRouter } from \"~/server/api/routers/post\";\nimport { createCallerFactory, createTRPCRouter } from \"~/server/api/trpc\";\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  post: postRouter,\n});\n\n// export type definition of API\nexport type AppRouter = typeof appRouter;\n\n/**\n * Create a server-side caller for the tRPC API.\n * @example\n * const trpc = createCaller(createContext);\n * const res = await trpc.post.all();\n *       ^? Post[]\n */\nexport const createCaller = createCallerFactory(appRouter);\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/base.ts",
    "content": "import { z } from \"zod\";\n\nimport { createTRPCRouter, publicProcedure } from \"~/server/api/trpc\";\n\n// Mocked DB\ninterface Post {\n  id: number;\n  name: string;\n}\nconst posts: Post[] = [\n  {\n    id: 1,\n    name: \"Hello World\",\n  },\n];\n\nexport const postRouter = 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  create: publicProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ input }) => {\n      const post: Post = {\n        id: posts.length + 1,\n        name: input.name,\n      };\n      posts.push(post);\n      return post;\n    }),\n\n  getLatest: publicProcedure.query(() => {\n    return posts.at(-1) ?? null;\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/with-auth-drizzle.ts",
    "content": "import { z } from \"zod\";\n\nimport {\n  createTRPCRouter,\n  protectedProcedure,\n  publicProcedure,\n} from \"~/server/api/trpc\";\nimport { posts } from \"~/server/db/schema\";\n\nexport const postRouter = 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  create: protectedProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ ctx, input }) => {\n      await ctx.db.insert(posts).values({\n        name: input.name,\n        createdById: ctx.session.user.id,\n      });\n    }),\n\n  getLatest: protectedProcedure.query(async ({ ctx }) => {\n    const post = await ctx.db.query.posts.findFirst({\n      orderBy: (posts, { desc }) => [desc(posts.createdAt)],\n    });\n\n    return post ?? null;\n  }),\n\n  getSecretMessage: protectedProcedure.query(() => {\n    return \"you can now see this secret message!\";\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/with-auth-prisma.ts",
    "content": "import { z } from \"zod\";\n\nimport {\n  createTRPCRouter,\n  protectedProcedure,\n  publicProcedure,\n} from \"~/server/api/trpc\";\n\nexport const postRouter = 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  create: protectedProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ ctx, input }) => {\n      return ctx.db.post.create({\n        data: {\n          name: input.name,\n          createdBy: { connect: { id: ctx.session.user.id } },\n        },\n      });\n    }),\n\n  getLatest: protectedProcedure.query(async ({ ctx }) => {\n    const post = await ctx.db.post.findFirst({\n      orderBy: { createdAt: \"desc\" },\n      where: { createdBy: { id: ctx.session.user.id } },\n    });\n\n    return post ?? null;\n  }),\n\n  getSecretMessage: protectedProcedure.query(() => {\n    return \"you can now see this secret message!\";\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/with-auth.ts",
    "content": "import { z } from \"zod\";\n\nimport {\n  createTRPCRouter,\n  protectedProcedure,\n  publicProcedure,\n} from \"~/server/api/trpc\";\n\nlet post = {\n  id: 1,\n  name: \"Hello World\",\n};\n\nexport const postRouter = 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  create: protectedProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ input }) => {\n      post = { id: post.id + 1, name: input.name };\n      return post;\n    }),\n\n  getLatest: protectedProcedure.query(() => {\n    return post;\n  }),\n\n  getSecretMessage: protectedProcedure.query(() => {\n    return \"you can now see this secret message!\";\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/with-drizzle.ts",
    "content": "import { z } from \"zod\";\n\nimport { createTRPCRouter, publicProcedure } from \"~/server/api/trpc\";\nimport { posts } from \"~/server/db/schema\";\n\nexport const postRouter = 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  create: publicProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ ctx, input }) => {\n      await ctx.db.insert(posts).values({\n        name: input.name,\n      });\n    }),\n\n  getLatest: publicProcedure.query(async ({ ctx }) => {\n    const post = await ctx.db.query.posts.findFirst({\n      orderBy: (posts, { desc }) => [desc(posts.createdAt)],\n    });\n\n    return post ?? null;\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/routers/post/with-prisma.ts",
    "content": "import { z } from \"zod\";\n\nimport { createTRPCRouter, publicProcedure } from \"~/server/api/trpc\";\n\nexport const postRouter = 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  create: publicProcedure\n    .input(z.object({ name: z.string().min(1) }))\n    .mutation(async ({ ctx, input }) => {\n      return ctx.db.post.create({\n        data: {\n          name: input.name,\n        },\n      });\n    }),\n\n  getLatest: publicProcedure.query(async ({ ctx }) => {\n    const post = await ctx.db.post.findFirst({\n      orderBy: { createdAt: \"desc\" },\n    });\n\n    return post ?? null;\n  }),\n});\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/base.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 { initTRPC } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  return {\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/with-auth-db.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 */\n\nimport { initTRPC, TRPCError } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/auth\";\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth();\n\n  return {\n    db,\n    session,\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/with-auth.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 { initTRPC, TRPCError } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/auth\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth();\n\n  return {\n    session,\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/with-better-auth-db.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 */\n\nimport { initTRPC, TRPCError } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/better-auth\";\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth.api.getSession({\n    headers: opts.headers,\n  });\n  return {\n    db,\n    session,\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/with-better-auth.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 { initTRPC, TRPCError } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/better-auth\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth.api.getSession({\n    headers: opts.headers,\n  });\n  return {\n    session,\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-app/with-db.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 { initTRPC } from \"@trpc/server\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n *\n * This helper generates the \"internals\" for a tRPC context. The API handler and RSC clients each\n * wrap this and provides the required context.\n *\n * @see https://trpc.io/docs/server/context\n */\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  return {\n    db,\n    ...opts,\n  };\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 */\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/base.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 */\n\nimport { initTRPC } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ntype CreateContextOptions = Record<string, never>;\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = (_opts: CreateContextOptions) => {\n  return {};\n};\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 */\nexport const createTRPCContext = (_opts: CreateNextContextOptions) => {\n  return createInnerTRPCContext({});\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/with-auth-db.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 */\n\nimport { initTRPC, TRPCError } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\nimport { type Session } from \"next-auth\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/auth\";\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ninterface CreateContextOptions {\n  session: Session | null;\n}\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = (opts: CreateContextOptions) => {\n  return {\n    session: opts.session,\n    db,\n  };\n};\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 */\nexport const createTRPCContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n\n  // Get the session from the server using the getServerSession wrapper function\n  const session = await auth(req, res);\n\n  return createInnerTRPCContext({\n    session,\n  });\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/with-auth.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 { initTRPC, TRPCError } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\nimport { type Session } from \"next-auth\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/auth\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ninterface CreateContextOptions {\n  session: Session | null;\n}\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = ({ session }: CreateContextOptions) => {\n  return {\n    session,\n  };\n};\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 */\nexport const createTRPCContext = async ({\n  req,\n  res,\n}: CreateNextContextOptions) => {\n  // Get the session from the server using the getServerSession wrapper function\n  const session = await auth(req, res);\n\n  return createInnerTRPCContext({\n    session,\n  });\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/with-better-auth-db.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 */\n\nimport { initTRPC, TRPCError } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/better-auth\";\nimport { type Session } from \"~/server/better-auth/config\";\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ninterface CreateContextOptions {\n  session: Session | null;\n}\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = (opts: CreateContextOptions) => {\n  return {\n    session: opts.session,\n    db,\n  };\n};\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 */\nexport const createTRPCContext = async ({ req }: CreateNextContextOptions) => {\n  // Convert IncomingHttpHeaders to Headers object\n  const headers = new Headers();\n  for (const [key, value] of Object.entries(req.headers)) {\n    if (Array.isArray(value)) {\n      value.forEach((v) => headers.append(key, v));\n    } else if (value) {\n      headers.append(key, value);\n    }\n  }\n\n  const session = await auth.api.getSession({\n    headers,\n  });\n  return createInnerTRPCContext({\n    session,\n  });\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/with-better-auth.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 { initTRPC, TRPCError } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\n// import {  } from \"next-auth\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { auth } from \"~/server/better-auth\";\nimport { type Session } from \"~/server/better-auth/config\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ninterface CreateContextOptions {\n  session: Session | null;\n}\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = ({ session }: CreateContextOptions) => {\n  return {\n    session,\n  };\n};\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 */\nexport const createTRPCContext = async ({ req }: CreateNextContextOptions) => {\n  // Convert IncomingHttpHeaders to Headers object\n  const headers = new Headers();\n  for (const [key, value] of Object.entries(req.headers)) {\n    if (Array.isArray(value)) {\n      value.forEach((v) => headers.append(key, v));\n    } else if (value) {\n      headers.append(key, value);\n    }\n  }\n\n  const session = await auth.api.getSession({\n    headers,\n  });\n  return createInnerTRPCContext({\n    session,\n  });\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n\n/**\n * Protected (authenticated) procedure\n *\n * If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies\n * the session is valid and guarantees `ctx.session.user` is not null.\n *\n * @see https://trpc.io/docs/procedures\n */\nexport const protectedProcedure = t.procedure\n  .use(timingMiddleware)\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        // infers the `session` as non-nullable\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n"
  },
  {
    "path": "cli/template/extras/src/server/api/trpc-pages/with-db.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 { initTRPC } from \"@trpc/server\";\nimport { type CreateNextContextOptions } from \"@trpc/server/adapters/next\";\nimport superjson from \"superjson\";\nimport { ZodError } from \"zod\";\n\nimport { db } from \"~/server/db\";\n\n/**\n * 1. CONTEXT\n *\n * This section defines the \"contexts\" that are available in the backend API.\n *\n * These allow you to access things when processing a request, like the database, the session, etc.\n */\n\ntype CreateContextOptions = Record<string, never>;\n\n/**\n * This helper generates the \"internals\" for a tRPC context. If you need to use it, you can export\n * it from here.\n *\n * Examples of things you may need it for:\n * - testing, so we don't have to mock Next.js' req/res\n * - tRPC's `createSSGHelpers`, where we don't have req/res\n *\n * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts\n */\nconst createInnerTRPCContext = (_opts: CreateContextOptions) => {\n  return {\n    db,\n  };\n};\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 */\nexport const createTRPCContext = (_opts: CreateNextContextOptions) => {\n  return createInnerTRPCContext({});\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 * Create a server-side caller.\n *\n * @see https://trpc.io/docs/server/server-side-calls\n */\nexport const createCallerFactory = t.createCallerFactory;\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 * Middleware for timing procedure execution and adding an artificial delay in development.\n *\n * You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating\n * network latency that would occur in production but not in local development.\n */\nconst timingMiddleware = t.middleware(async ({ next, path }) => {\n  const start = Date.now();\n\n  if (t._config.isDev) {\n    // artificial delay in dev\n    const waitMs = Math.floor(Math.random() * 400) + 100;\n    await new Promise((resolve) => setTimeout(resolve, waitMs));\n  }\n\n  const result = await next();\n\n  const end = Date.now();\n  console.log(`[TRPC] ${path} took ${end - start}ms to execute`);\n\n  return result;\n});\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.use(timingMiddleware);\n"
  },
  {
    "path": "cli/template/extras/src/server/auth/config/base.ts",
    "content": "import { type DefaultSession, type NextAuthConfig } from \"next-auth\";\nimport DiscordProvider from \"next-auth/providers/discord\";\n\n/**\n * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`\n * object and keep type safety.\n *\n * @see https://next-auth.js.org/getting-started/typescript#module-augmentation\n */\ndeclare module \"next-auth\" {\n  interface Session extends DefaultSession {\n    user: {\n      id: string;\n      // ...other properties\n      // role: UserRole;\n    } & DefaultSession[\"user\"];\n  }\n\n  // interface User {\n  //   // ...other properties\n  //   // role: UserRole;\n  // }\n}\n\n/**\n * Options for NextAuth.js used to configure adapters, providers, callbacks, etc.\n *\n * @see https://next-auth.js.org/configuration/options\n */\nexport const authConfig = {\n  providers: [\n    DiscordProvider,\n    /**\n     * ...add more providers here.\n     *\n     * Most other providers require a bit more work than the Discord provider. For example, the\n     * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account\n     * model. Refer to the NextAuth.js docs for the provider you want to use. Example:\n     *\n     * @see https://next-auth.js.org/providers/github\n     */\n  ],\n  callbacks: {\n    session: ({ session, token }) => ({\n      ...session,\n      user: {\n        ...session.user,\n        id: token.sub,\n      },\n    }),\n  },\n} satisfies NextAuthConfig;\n"
  },
  {
    "path": "cli/template/extras/src/server/auth/config/with-drizzle.ts",
    "content": "import { DrizzleAdapter } from \"@auth/drizzle-adapter\";\nimport { type DefaultSession, type NextAuthConfig } from \"next-auth\";\nimport DiscordProvider from \"next-auth/providers/discord\";\n\nimport { db } from \"~/server/db\";\nimport {\n  accounts,\n  sessions,\n  users,\n  verificationTokens,\n} from \"~/server/db/schema\";\n\n/**\n * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`\n * object and keep type safety.\n *\n * @see https://next-auth.js.org/getting-started/typescript#module-augmentation\n */\ndeclare module \"next-auth\" {\n  interface Session extends DefaultSession {\n    user: {\n      id: string;\n      // ...other properties\n      // role: UserRole;\n    } & DefaultSession[\"user\"];\n  }\n\n  // interface User {\n  //   // ...other properties\n  //   // role: UserRole;\n  // }\n}\n\n/**\n * Options for NextAuth.js used to configure adapters, providers, callbacks, etc.\n *\n * @see https://next-auth.js.org/configuration/options\n */\nexport const authConfig = {\n  providers: [\n    DiscordProvider,\n    /**\n     * ...add more providers here.\n     *\n     * Most other providers require a bit more work than the Discord provider. For example, the\n     * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account\n     * model. Refer to the NextAuth.js docs for the provider you want to use. Example:\n     *\n     * @see https://next-auth.js.org/providers/github\n     */\n  ],\n  adapter: DrizzleAdapter(db, {\n    usersTable: users,\n    accountsTable: accounts,\n    sessionsTable: sessions,\n    verificationTokensTable: verificationTokens,\n  }),\n  callbacks: {\n    session: ({ session, user }) => ({\n      ...session,\n      user: {\n        ...session.user,\n        id: user.id,\n      },\n    }),\n  },\n} satisfies NextAuthConfig;\n"
  },
  {
    "path": "cli/template/extras/src/server/auth/config/with-prisma.ts",
    "content": "import { PrismaAdapter } from \"@auth/prisma-adapter\";\nimport { type DefaultSession, type NextAuthConfig } from \"next-auth\";\nimport DiscordProvider from \"next-auth/providers/discord\";\n\nimport { db } from \"~/server/db\";\n\n/**\n * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`\n * object and keep type safety.\n *\n * @see https://next-auth.js.org/getting-started/typescript#module-augmentation\n */\ndeclare module \"next-auth\" {\n  interface Session extends DefaultSession {\n    user: {\n      id: string;\n      // ...other properties\n      // role: UserRole;\n    } & DefaultSession[\"user\"];\n  }\n\n  // interface User {\n  //   // ...other properties\n  //   // role: UserRole;\n  // }\n}\n\n/**\n * Options for NextAuth.js used to configure adapters, providers, callbacks, etc.\n *\n * @see https://next-auth.js.org/configuration/options\n */\nexport const authConfig = {\n  providers: [\n    DiscordProvider,\n    /**\n     * ...add more providers here.\n     *\n     * Most other providers require a bit more work than the Discord provider. For example, the\n     * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account\n     * model. Refer to the NextAuth.js docs for the provider you want to use. Example:\n     *\n     * @see https://next-auth.js.org/providers/github\n     */\n  ],\n  adapter: PrismaAdapter(db),\n  callbacks: {\n    session: ({ session, user }) => ({\n      ...session,\n      user: {\n        ...session.user,\n        id: user.id,\n      },\n    }),\n  },\n} satisfies NextAuthConfig;\n"
  },
  {
    "path": "cli/template/extras/src/server/auth/index.ts",
    "content": "import NextAuth from \"next-auth\";\nimport { cache } from \"react\";\n\nimport { authConfig } from \"./config\";\n\nconst { auth: uncachedAuth, handlers, signIn, signOut } = NextAuth(authConfig);\n\nconst auth = cache(uncachedAuth);\n\nexport { auth, handlers, signIn, signOut };\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/client.ts",
    "content": "import { createAuthClient } from \"better-auth/react\";\n\nexport const authClient = createAuthClient();\n\nexport type Session = typeof authClient.$Infer.Session;\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/config/base.ts",
    "content": "import { betterAuth } from \"better-auth\";\nimport { nextCookies } from \"better-auth/next-js\";\n\nexport const auth = betterAuth({\n  emailAndPassword: {\n    enabled: true,\n  },\n  // Make sure nextCookies() is the last plugin in the array\n  plugins: [nextCookies()],\n});\n\nexport type Session = typeof auth.$Infer.Session;\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/config/with-drizzle.ts",
    "content": "import { betterAuth } from \"better-auth\";\nimport { drizzleAdapter } from \"better-auth/adapters/drizzle\";\nimport { nextCookies } from \"better-auth/next-js\";\n\nimport { env } from \"~/env\";\nimport { db } from \"~/server/db\";\n\nexport const auth = betterAuth({\n  database: drizzleAdapter(db, {\n    provider: \"pg\", // or \"pg\" or \"mysql\"\n  }),\n  emailAndPassword: {\n    enabled: true,\n  },\n  socialProviders: {\n    github: {\n      clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID,\n      clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET,\n      redirectURI: \"http://localhost:3000/api/auth/callback/github\",\n    },\n  },\n  // Make sure nextCookies() is the last plugin in the array\n  plugins: [nextCookies()],\n});\n\nexport type Session = typeof auth.$Infer.Session;\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/config/with-prisma.ts",
    "content": "import { betterAuth } from \"better-auth\";\nimport { prismaAdapter } from \"better-auth/adapters/prisma\";\nimport { nextCookies } from \"better-auth/next-js\";\n\nimport { env } from \"~/env\";\nimport { db } from \"~/server/db\";\n\nexport const auth = betterAuth({\n  database: prismaAdapter(db, {\n    provider: \"postgresql\", // or \"sqlite\" or \"mysql\"\n  }),\n  emailAndPassword: {\n    enabled: true,\n  },\n  socialProviders: {\n    github: {\n      clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID,\n      clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET,\n      redirectURI: \"http://localhost:3000/api/auth/callback/github\",\n    },\n  },\n  // Make sure nextCookies() is the last plugin in the array\n  plugins: [nextCookies()],\n});\n\nexport type Session = typeof auth.$Infer.Session;\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/index.ts",
    "content": "export { auth } from \"./config\";\n"
  },
  {
    "path": "cli/template/extras/src/server/better-auth/server.ts",
    "content": "import { auth } from \".\";\nimport { headers } from \"next/headers\";\nimport { cache } from \"react\";\n\nexport const getSession = cache(async () =>\n  auth.api.getSession({ headers: await headers() })\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/db-prisma-planetscale.ts",
    "content": "import { PrismaPlanetScale } from \"@prisma/adapter-planetscale\";\n\nimport { env } from \"~/env\";\nimport { PrismaClient } from \"../../generated/prisma\";\n\nconst createPrismaClient = () =>\n  new PrismaClient({\n    log:\n      env.NODE_ENV === \"development\" ? [\"query\", \"error\", \"warn\"] : [\"error\"],\n    adapter: new PrismaPlanetScale({ url: env.DATABASE_URL }),\n  });\n\nconst globalForPrisma = globalThis as unknown as {\n  prisma: ReturnType<typeof createPrismaClient> | undefined;\n};\n\nexport const db = globalForPrisma.prisma ?? createPrismaClient();\n\nif (env.NODE_ENV !== \"production\") globalForPrisma.prisma = db;\n"
  },
  {
    "path": "cli/template/extras/src/server/db/db-prisma.ts",
    "content": "import { env } from \"~/env\";\nimport { PrismaClient } from \"../../generated/prisma\";\n\nconst createPrismaClient = () =>\n  new PrismaClient({\n    log:\n      env.NODE_ENV === \"development\" ? [\"query\", \"error\", \"warn\"] : [\"error\"],\n  });\n\nconst globalForPrisma = globalThis as unknown as {\n  prisma: ReturnType<typeof createPrismaClient> | undefined;\n};\n\nexport const db = globalForPrisma.prisma ?? createPrismaClient();\n\nif (env.NODE_ENV !== \"production\") globalForPrisma.prisma = db;\n"
  },
  {
    "path": "cli/template/extras/src/server/db/index-drizzle/with-mysql.ts",
    "content": "import { drizzle } from \"drizzle-orm/mysql2\";\nimport { createPool, type Pool } from \"mysql2/promise\";\n\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\n\n/**\n * Cache the database connection in development. This avoids creating a new connection on every HMR\n * update.\n */\nconst globalForDb = globalThis as unknown as {\n  conn: Pool | undefined;\n};\n\nconst conn = globalForDb.conn ?? createPool({ uri: env.DATABASE_URL });\nif (env.NODE_ENV !== \"production\") globalForDb.conn = conn;\n\nexport const db = drizzle(conn, { schema, mode: \"default\" });\n"
  },
  {
    "path": "cli/template/extras/src/server/db/index-drizzle/with-planetscale.ts",
    "content": "import { Client } from \"@planetscale/database\";\nimport { drizzle } from \"drizzle-orm/planetscale-serverless\";\n\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\n\nexport const db = drizzle(new Client({ url: env.DATABASE_URL }), { schema });\n"
  },
  {
    "path": "cli/template/extras/src/server/db/index-drizzle/with-postgres.ts",
    "content": "import { drizzle } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\n\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\n\n/**\n * Cache the database connection in development. This avoids creating a new connection on every HMR\n * update.\n */\nconst globalForDb = globalThis as unknown as {\n  conn: postgres.Sql | undefined;\n};\n\nconst conn = globalForDb.conn ?? postgres(env.DATABASE_URL);\nif (env.NODE_ENV !== \"production\") globalForDb.conn = conn;\n\nexport const db = drizzle(conn, { schema });\n"
  },
  {
    "path": "cli/template/extras/src/server/db/index-drizzle/with-sqlite.ts",
    "content": "import { createClient, type Client } from \"@libsql/client\";\nimport { drizzle } from \"drizzle-orm/libsql\";\n\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\n\n/**\n * Cache the database connection in development. This avoids creating a new connection on every HMR\n * update.\n */\nconst globalForDb = globalThis as unknown as {\n  client: Client | undefined;\n};\n\nexport const client =\n  globalForDb.client ?? createClient({ url: env.DATABASE_URL });\nif (env.NODE_ENV !== \"production\") globalForDb.client = client;\n\nexport const db = drizzle(client, { schema });\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/base-mysql.ts",
    "content": "// Example model schema from the Drizzle docs\n// https://orm.drizzle.team/docs/sql-schema-declaration\n\nimport { index, mysqlTableCreator } from \"drizzle-orm/mysql-core\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [index(\"name_idx\").on(t.name)]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/base-planetscale.ts",
    "content": "// Example model schema from the Drizzle docs\n// https://orm.drizzle.team/docs/sql-schema-declaration\n\nimport { index, mysqlTableCreator } from \"drizzle-orm/mysql-core\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [index(\"name_idx\").on(t.name)]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/base-postgres.ts",
    "content": "// Example model schema from the Drizzle docs\n// https://orm.drizzle.team/docs/sql-schema-declaration\n\nimport { index, pgTableCreator } from \"drizzle-orm/pg-core\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = pgTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.integer().primaryKey().generatedByDefaultAsIdentity(),\n    name: d.varchar({ length: 256 }),\n    createdAt: d\n      .timestamp({ withTimezone: true })\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),\n  }),\n  (t) => [index(\"name_idx\").on(t.name)]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/base-sqlite.ts",
    "content": "// Example model schema from the Drizzle docs\n// https://orm.drizzle.team/docs/sql-schema-declaration\n\nimport { sql } from \"drizzle-orm\";\nimport { index, sqliteTableCreator } from \"drizzle-orm/sqlite-core\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = sqliteTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.integer({ mode: \"number\" }).primaryKey({ autoIncrement: true }),\n    name: d.text({ length: 256 }),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [index(\"name_idx\").on(t.name)]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-auth-mysql.ts",
    "content": "import { relations, sql } from \"drizzle-orm\";\nimport { index, mysqlTableCreator, primaryKey } from \"drizzle-orm/mysql-core\";\nimport { type AdapterAccount } from \"next-auth/adapters\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdById: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const users = createTable(\"user\", (d) => ({\n  id: d\n    .varchar({ length: 255 })\n    .notNull()\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  name: d.varchar({ length: 255 }),\n  email: d.varchar({ length: 255 }).notNull(),\n  emailVerified: d\n    .timestamp({\n      mode: \"date\",\n      fsp: 3,\n    })\n    .default(sql`CURRENT_TIMESTAMP(3)`),\n  image: d.varchar({ length: 255 }),\n}));\n\nexport const usersRelations = relations(users, ({ many }) => ({\n  accounts: many(accounts),\n  sessions: many(sessions),\n}));\n\nexport const accounts = createTable(\n  \"account\",\n  (d) => ({\n    userId: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    type: d.varchar({ length: 255 }).$type<AdapterAccount[\"type\"]>().notNull(),\n    provider: d.varchar({ length: 255 }).notNull(),\n    providerAccountId: d.varchar({ length: 255 }).notNull(),\n    refresh_token: d.text(),\n    access_token: d.text(),\n    expires_at: d.int(),\n    token_type: d.varchar({ length: 255 }),\n    scope: d.varchar({ length: 255 }),\n    id_token: d.text(),\n    session_state: d.varchar({ length: 255 }),\n  }),\n  (t) => [\n    primaryKey({\n      columns: [t.provider, t.providerAccountId],\n    }),\n    index(\"account_user_id_idx\").on(t.userId),\n  ]\n);\n\nexport const accountsRelations = relations(accounts, ({ one }) => ({\n  user: one(users, { fields: [accounts.userId], references: [users.id] }),\n}));\n\nexport const sessions = createTable(\n  \"session\",\n  (d) => ({\n    sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),\n    userId: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    expires: d.timestamp({ mode: \"date\" }).notNull(),\n  }),\n  (t) => [index(\"session_user_id_idx\").on(t.userId)]\n);\n\nexport const sessionsRelations = relations(sessions, ({ one }) => ({\n  user: one(users, { fields: [sessions.userId], references: [users.id] }),\n}));\n\nexport const verificationTokens = createTable(\n  \"verification_token\",\n  (d) => ({\n    identifier: d.varchar({ length: 255 }).notNull(),\n    token: d.varchar({ length: 255 }).notNull(),\n    expires: d.timestamp({ mode: \"date\" }).notNull(),\n  }),\n  (t) => [primaryKey({ columns: [t.identifier, t.token] })]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-auth-planetscale.ts",
    "content": "import { relations, sql } from \"drizzle-orm\";\nimport { index, mysqlTableCreator, primaryKey } from \"drizzle-orm/mysql-core\";\nimport { type AdapterAccount } from \"next-auth/adapters\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdById: d.varchar({ length: 255 }).notNull(),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const users = createTable(\"user\", (d) => ({\n  id: d\n    .varchar({ length: 255 })\n    .notNull()\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  name: d.varchar({ length: 255 }),\n  email: d.varchar({ length: 255 }).notNull(),\n  emailVerified: d\n    .timestamp({\n      mode: \"date\",\n      fsp: 3,\n    })\n    .default(sql`CURRENT_TIMESTAMP(3)`),\n  image: d.varchar({ length: 255 }),\n}));\n\nexport const usersRelations = relations(users, ({ many }) => ({\n  accounts: many(accounts),\n  sessions: many(sessions),\n}));\n\nexport const accounts = createTable(\n  \"account\",\n  (d) => ({\n    userId: d.varchar({ length: 255 }).notNull(),\n    type: d.varchar({ length: 255 }).$type<AdapterAccount[\"type\"]>().notNull(),\n    provider: d.varchar({ length: 255 }).notNull(),\n    providerAccountId: d.varchar({ length: 255 }).notNull(),\n    refresh_token: d.text(),\n    access_token: d.text(),\n    expires_at: d.int(),\n    token_type: d.varchar({ length: 255 }),\n    scope: d.varchar({ length: 255 }),\n    id_token: d.text(),\n    session_state: d.varchar({ length: 255 }),\n  }),\n  (account) => [\n    primaryKey({ columns: [account.provider, account.providerAccountId] }),\n    index(\"accounts_user_id_idx\").on(account.userId),\n  ]\n);\n\nexport const accountsRelations = relations(accounts, ({ one }) => ({\n  user: one(users, { fields: [accounts.userId], references: [users.id] }),\n}));\n\nexport const sessions = createTable(\n  \"session\",\n  (d) => ({\n    sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),\n    userId: d.varchar({ length: 255 }).notNull(),\n    expires: d.timestamp({ mode: \"date\" }).notNull(),\n  }),\n  (session) => [index(\"session_user_id_idx\").on(session.userId)]\n);\n\nexport const sessionsRelations = relations(sessions, ({ one }) => ({\n  user: one(users, { fields: [sessions.userId], references: [users.id] }),\n}));\n\nexport const verificationTokens = createTable(\n  \"verification_token\",\n  (d) => ({\n    identifier: d.varchar({ length: 255 }).notNull(),\n    token: d.varchar({ length: 255 }).notNull(),\n    expires: d.timestamp({ mode: \"date\" }).notNull(),\n  }),\n  (vt) => [primaryKey({ columns: [vt.identifier, vt.token] })]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-auth-postgres.ts",
    "content": "import { relations } from \"drizzle-orm\";\nimport { index, pgTableCreator, primaryKey } from \"drizzle-orm/pg-core\";\nimport { type AdapterAccount } from \"next-auth/adapters\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = pgTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.integer().primaryKey().generatedByDefaultAsIdentity(),\n    name: d.varchar({ length: 256 }),\n    createdById: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    createdAt: d\n      .timestamp({ withTimezone: true })\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const users = createTable(\"user\", (d) => ({\n  id: d\n    .varchar({ length: 255 })\n    .notNull()\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  name: d.varchar({ length: 255 }),\n  email: d.varchar({ length: 255 }).notNull(),\n  emailVerified: d\n    .timestamp({\n      mode: \"date\",\n      withTimezone: true,\n    })\n    .$defaultFn(() => /* @__PURE__ */ new Date()),\n  image: d.varchar({ length: 255 }),\n}));\n\nexport const usersRelations = relations(users, ({ many }) => ({\n  accounts: many(accounts),\n}));\n\nexport const accounts = createTable(\n  \"account\",\n  (d) => ({\n    userId: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    type: d.varchar({ length: 255 }).$type<AdapterAccount[\"type\"]>().notNull(),\n    provider: d.varchar({ length: 255 }).notNull(),\n    providerAccountId: d.varchar({ length: 255 }).notNull(),\n    refresh_token: d.text(),\n    access_token: d.text(),\n    expires_at: d.integer(),\n    token_type: d.varchar({ length: 255 }),\n    scope: d.varchar({ length: 255 }),\n    id_token: d.text(),\n    session_state: d.varchar({ length: 255 }),\n  }),\n  (t) => [\n    primaryKey({ columns: [t.provider, t.providerAccountId] }),\n    index(\"account_user_id_idx\").on(t.userId),\n  ]\n);\n\nexport const accountsRelations = relations(accounts, ({ one }) => ({\n  user: one(users, { fields: [accounts.userId], references: [users.id] }),\n}));\n\nexport const sessions = createTable(\n  \"session\",\n  (d) => ({\n    sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),\n    userId: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    expires: d.timestamp({ mode: \"date\", withTimezone: true }).notNull(),\n  }),\n  (t) => [index(\"t_user_id_idx\").on(t.userId)]\n);\n\nexport const sessionsRelations = relations(sessions, ({ one }) => ({\n  user: one(users, { fields: [sessions.userId], references: [users.id] }),\n}));\n\nexport const verificationTokens = createTable(\n  \"verification_token\",\n  (d) => ({\n    identifier: d.varchar({ length: 255 }).notNull(),\n    token: d.varchar({ length: 255 }).notNull(),\n    expires: d.timestamp({ mode: \"date\", withTimezone: true }).notNull(),\n  }),\n  (t) => [primaryKey({ columns: [t.identifier, t.token] })]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-auth-sqlite.ts",
    "content": "import { relations, sql } from \"drizzle-orm\";\nimport { index, primaryKey, sqliteTableCreator } from \"drizzle-orm/sqlite-core\";\nimport { type AdapterAccount } from \"next-auth/adapters\";\n\n/**\n * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same\n * database instance for multiple projects.\n *\n * @see https://orm.drizzle.team/docs/goodies#multi-project-schema\n */\nexport const createTable = sqliteTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.integer({ mode: \"number\" }).primaryKey({ autoIncrement: true }),\n    name: d.text({ length: 256 }),\n    createdById: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const users = createTable(\"user\", (d) => ({\n  id: d\n    .text({ length: 255 })\n    .notNull()\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  name: d.text({ length: 255 }),\n  email: d.text({ length: 255 }).notNull(),\n  emailVerified: d.integer({ mode: \"timestamp\" }).default(sql`(unixepoch())`),\n  image: d.text({ length: 255 }),\n}));\n\nexport const usersRelations = relations(users, ({ many }) => ({\n  accounts: many(accounts),\n}));\n\nexport const accounts = createTable(\n  \"account\",\n  (d) => ({\n    userId: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    type: d.text({ length: 255 }).$type<AdapterAccount[\"type\"]>().notNull(),\n    provider: d.text({ length: 255 }).notNull(),\n    providerAccountId: d.text({ length: 255 }).notNull(),\n    refresh_token: d.text(),\n    access_token: d.text(),\n    expires_at: d.integer(),\n    token_type: d.text({ length: 255 }),\n    scope: d.text({ length: 255 }),\n    id_token: d.text(),\n    session_state: d.text({ length: 255 }),\n  }),\n  (t) => [\n    primaryKey({\n      columns: [t.provider, t.providerAccountId],\n    }),\n    index(\"account_user_id_idx\").on(t.userId),\n  ]\n);\n\nexport const accountsRelations = relations(accounts, ({ one }) => ({\n  user: one(users, { fields: [accounts.userId], references: [users.id] }),\n}));\n\nexport const sessions = createTable(\n  \"session\",\n  (d) => ({\n    sessionToken: d.text({ length: 255 }).notNull().primaryKey(),\n    userId: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => users.id),\n    expires: d.integer({ mode: \"timestamp\" }).notNull(),\n  }),\n  (t) => [index(\"session_userId_idx\").on(t.userId)]\n);\n\nexport const sessionsRelations = relations(sessions, ({ one }) => ({\n  user: one(users, { fields: [sessions.userId], references: [users.id] }),\n}));\n\nexport const verificationTokens = createTable(\n  \"verification_token\",\n  (d) => ({\n    identifier: d.text({ length: 255 }).notNull(),\n    token: d.text({ length: 255 }).notNull(),\n    expires: d.integer({ mode: \"timestamp\" }).notNull(),\n  }),\n  (t) => [primaryKey({ columns: [t.identifier, t.token] })]\n);\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-better-auth-mysql.ts",
    "content": "import { relations } from \"drizzle-orm\";\nimport {\n  boolean,\n  index,\n  mysqlTable,\n  mysqlTableCreator,\n  text,\n  timestamp,\n  varchar,\n} from \"drizzle-orm/mysql-core\";\n\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdById: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const user = mysqlTable(\"user\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  name: text(\"name\").notNull(),\n  email: varchar(\"email\", { length: 255 }).notNull().unique(),\n  emailVerified: boolean(\"email_verified\")\n    .$defaultFn(() => false)\n    .notNull(),\n  image: text(\"image\"),\n  createdAt: timestamp(\"created_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n  updatedAt: timestamp(\"updated_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n});\n\nexport const session = mysqlTable(\"session\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  token: varchar(\"token\", { length: 255 }).notNull().unique(),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n  ipAddress: text(\"ip_address\"),\n  userAgent: text(\"user_agent\"),\n  userId: varchar(\"user_id\", { length: 36 })\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n});\n\nexport const account = mysqlTable(\"account\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  accountId: text(\"account_id\").notNull(),\n  providerId: text(\"provider_id\").notNull(),\n  userId: varchar(\"user_id\", { length: 36 })\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n  accessToken: text(\"access_token\"),\n  refreshToken: text(\"refresh_token\"),\n  idToken: text(\"id_token\"),\n  accessTokenExpiresAt: timestamp(\"access_token_expires_at\"),\n  refreshTokenExpiresAt: timestamp(\"refresh_token_expires_at\"),\n  scope: text(\"scope\"),\n  password: text(\"password\"),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n});\n\nexport const verification = mysqlTable(\"verification\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  identifier: text(\"identifier\").notNull(),\n  value: text(\"value\").notNull(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  createdAt: timestamp(\"created_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n  updatedAt: timestamp(\"updated_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n});\n\nexport const usersRelations = relations(user, ({ many }) => ({\n  accounts: many(account),\n  sessions: many(session),\n}));\n\nexport const accountsRelations = relations(account, ({ one }) => ({\n  user: one(user, { fields: [account.userId], references: [user.id] }),\n}));\n\nexport const sessionsRelations = relations(session, ({ one }) => ({\n  user: one(user, { fields: [session.userId], references: [user.id] }),\n}));\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-better-auth-planetscale.ts",
    "content": "import { relations } from \"drizzle-orm\";\nimport {\n  boolean,\n  index,\n  mysqlTable,\n  mysqlTableCreator,\n  text,\n  timestamp,\n  varchar,\n} from \"drizzle-orm/mysql-core\";\n\nexport const createTable = mysqlTableCreator((name) => `project1_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.bigint({ mode: \"number\" }).primaryKey().autoincrement(),\n    name: d.varchar({ length: 256 }),\n    createdById: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    createdAt: d\n      .timestamp()\n      .$defaultFn(() => /* @__PURE__ */ new Date())\n      .notNull(),\n    updatedAt: d.timestamp().onUpdateNow(),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const user = mysqlTable(\"user\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  name: text(\"name\").notNull(),\n  email: varchar(\"email\", { length: 255 }).notNull().unique(),\n  emailVerified: boolean(\"email_verified\")\n    .$defaultFn(() => false)\n    .notNull(),\n  image: text(\"image\"),\n  createdAt: timestamp(\"created_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n  updatedAt: timestamp(\"updated_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n});\n\nexport const session = mysqlTable(\"session\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  token: varchar(\"token\", { length: 255 }).notNull().unique(),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n  ipAddress: text(\"ip_address\"),\n  userAgent: text(\"user_agent\"),\n  userId: varchar(\"user_id\", { length: 36 })\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n});\n\nexport const account = mysqlTable(\"account\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  accountId: text(\"account_id\").notNull(),\n  providerId: text(\"provider_id\").notNull(),\n  userId: varchar(\"user_id\", { length: 36 })\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n  accessToken: text(\"access_token\"),\n  refreshToken: text(\"refresh_token\"),\n  idToken: text(\"id_token\"),\n  accessTokenExpiresAt: timestamp(\"access_token_expires_at\"),\n  refreshTokenExpiresAt: timestamp(\"refresh_token_expires_at\"),\n  scope: text(\"scope\"),\n  password: text(\"password\"),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n});\n\nexport const verification = mysqlTable(\"verification\", {\n  id: varchar(\"id\", { length: 36 }).primaryKey(),\n  identifier: text(\"identifier\").notNull(),\n  value: text(\"value\").notNull(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  createdAt: timestamp(\"created_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n  updatedAt: timestamp(\"updated_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n});\n\nexport const usersRelations = relations(user, ({ many }) => ({\n  accounts: many(account),\n  sessions: many(session),\n}));\n\nexport const accountsRelations = relations(account, ({ one }) => ({\n  user: one(user, { fields: [account.userId], references: [user.id] }),\n}));\n\nexport const sessionsRelations = relations(session, ({ one }) => ({\n  user: one(user, { fields: [session.userId], references: [user.id] }),\n}));\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-better-auth-postgres.ts",
    "content": "import { relations } from \"drizzle-orm\";\nimport {\n  boolean,\n  index,\n  pgTable,\n  pgTableCreator,\n  text,\n  timestamp,\n} from \"drizzle-orm/pg-core\";\n\nexport const createTable = pgTableCreator((name) => `pg-drizzle_${name}`);\n\nexport const posts = createTable(\n  \"post\",\n  (d) => ({\n    id: d.integer().primaryKey().generatedByDefaultAsIdentity(),\n    name: d.varchar({ length: 256 }),\n    createdById: d\n      .varchar({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    createdAt: d\n      .timestamp({ withTimezone: true })\n      .$defaultFn(() => new Date())\n      .notNull(),\n    updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\nexport const user = pgTable(\"user\", {\n  id: text(\"id\").primaryKey(),\n  name: text(\"name\").notNull(),\n  email: text(\"email\").notNull().unique(),\n  emailVerified: boolean(\"email_verified\")\n    .$defaultFn(() => false)\n    .notNull(),\n  image: text(\"image\"),\n  createdAt: timestamp(\"created_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n  updatedAt: timestamp(\"updated_at\")\n    .$defaultFn(() => /* @__PURE__ */ new Date())\n    .notNull(),\n});\n\nexport const session = pgTable(\"session\", {\n  id: text(\"id\").primaryKey(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  token: text(\"token\").notNull().unique(),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n  ipAddress: text(\"ip_address\"),\n  userAgent: text(\"user_agent\"),\n  userId: text(\"user_id\")\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n});\n\nexport const account = pgTable(\"account\", {\n  id: text(\"id\").primaryKey(),\n  accountId: text(\"account_id\").notNull(),\n  providerId: text(\"provider_id\").notNull(),\n  userId: text(\"user_id\")\n    .notNull()\n    .references(() => user.id, { onDelete: \"cascade\" }),\n  accessToken: text(\"access_token\"),\n  refreshToken: text(\"refresh_token\"),\n  idToken: text(\"id_token\"),\n  accessTokenExpiresAt: timestamp(\"access_token_expires_at\"),\n  refreshTokenExpiresAt: timestamp(\"refresh_token_expires_at\"),\n  scope: text(\"scope\"),\n  password: text(\"password\"),\n  createdAt: timestamp(\"created_at\").notNull(),\n  updatedAt: timestamp(\"updated_at\").notNull(),\n});\n\nexport const verification = pgTable(\"verification\", {\n  id: text(\"id\").primaryKey(),\n  identifier: text(\"identifier\").notNull(),\n  value: text(\"value\").notNull(),\n  expiresAt: timestamp(\"expires_at\").notNull(),\n  createdAt: timestamp(\"created_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n  updatedAt: timestamp(\"updated_at\").$defaultFn(\n    () => /* @__PURE__ */ new Date()\n  ),\n});\n\nexport const userRelations = relations(user, ({ many }) => ({\n  account: many(account),\n  session: many(session),\n}));\n\nexport const accountRelations = relations(account, ({ one }) => ({\n  user: one(user, { fields: [account.userId], references: [user.id] }),\n}));\n\nexport const sessionRelations = relations(session, ({ one }) => ({\n  user: one(user, { fields: [session.userId], references: [user.id] }),\n}));\n"
  },
  {
    "path": "cli/template/extras/src/server/db/schema-drizzle/with-better-auth-sqlite.ts",
    "content": "import { relations, sql } from \"drizzle-orm\";\nimport { index, sqliteTable } from \"drizzle-orm/sqlite-core\";\n\n/**\n * Multi-project schema prefix helper\n */\n\n// Posts example table\nexport const posts = sqliteTable(\n  \"post\",\n  (d) => ({\n    id: d.integer({ mode: \"number\" }).primaryKey({ autoIncrement: true }),\n    name: d.text({ length: 256 }),\n    createdById: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [\n    index(\"created_by_idx\").on(t.createdById),\n    index(\"name_idx\").on(t.name),\n  ]\n);\n\n// Better Auth core tables\nexport const user = sqliteTable(\"user\", (d) => ({\n  id: d\n    .text({ length: 255 })\n    .notNull()\n    .primaryKey()\n    .$defaultFn(() => crypto.randomUUID()),\n  name: d.text({ length: 255 }),\n  email: d.text({ length: 255 }).notNull().unique(),\n  emailVerified: d.integer({ mode: \"boolean\" }).default(false),\n  image: d.text({ length: 255 }),\n  createdAt: d\n    .integer({ mode: \"timestamp\" })\n    .default(sql`(unixepoch())`)\n    .notNull(),\n  updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n}));\n\nexport const userRelations = relations(user, ({ many }) => ({\n  account: many(account),\n  session: many(session),\n}));\n\nexport const account = sqliteTable(\n  \"account\",\n  (d) => ({\n    id: d\n      .text({ length: 255 })\n      .notNull()\n      .primaryKey()\n      .$defaultFn(() => crypto.randomUUID()),\n    userId: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    accountId: d.text({ length: 255 }).notNull(),\n    providerId: d.text({ length: 255 }).notNull(),\n    accessToken: d.text(),\n    refreshToken: d.text(),\n    accessTokenExpiresAt: d.integer({ mode: \"timestamp\" }),\n    refreshTokenExpiresAt: d.integer({ mode: \"timestamp\" }),\n    scope: d.text({ length: 255 }),\n    idToken: d.text(),\n    password: d.text(),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [index(\"account_user_id_idx\").on(t.userId)]\n);\n\nexport const accountRelations = relations(account, ({ one }) => ({\n  user: one(user, { fields: [account.userId], references: [user.id] }),\n}));\n\nexport const session = sqliteTable(\n  \"session\",\n  (d) => ({\n    id: d\n      .text({ length: 255 })\n      .notNull()\n      .primaryKey()\n      .$defaultFn(() => crypto.randomUUID()),\n    userId: d\n      .text({ length: 255 })\n      .notNull()\n      .references(() => user.id),\n    token: d.text({ length: 255 }).notNull().unique(),\n    expiresAt: d.integer({ mode: \"timestamp\" }).notNull(),\n    ipAddress: d.text({ length: 255 }),\n    userAgent: d.text({ length: 255 }),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [index(\"session_user_id_idx\").on(t.userId)]\n);\n\nexport const sessionRelations = relations(session, ({ one }) => ({\n  user: one(user, { fields: [session.userId], references: [user.id] }),\n}));\n\nexport const verification = sqliteTable(\n  \"verification\",\n  (d) => ({\n    id: d\n      .text({ length: 255 })\n      .notNull()\n      .primaryKey()\n      .$defaultFn(() => crypto.randomUUID()),\n    identifier: d.text({ length: 255 }).notNull(),\n    value: d.text({ length: 255 }).notNull(),\n    expiresAt: d.integer({ mode: \"timestamp\" }).notNull(),\n    createdAt: d\n      .integer({ mode: \"timestamp\" })\n      .default(sql`(unixepoch())`)\n      .notNull(),\n    updatedAt: d.integer({ mode: \"timestamp\" }).$onUpdate(() => new Date()),\n  }),\n  (t) => [index(\"verification_identifier_idx\").on(t.identifier)]\n);\n"
  },
  {
    "path": "cli/template/extras/src/styles/globals.css",
    "content": "@import \"tailwindcss\";\n\n@theme {\n  --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif,\n    \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n}\n"
  },
  {
    "path": "cli/template/extras/src/trpc/query-client.ts",
    "content": "import {\n  defaultShouldDehydrateQuery,\n  QueryClient,\n} from \"@tanstack/react-query\";\nimport SuperJSON from \"superjson\";\n\nexport const createQueryClient = () =>\n  new QueryClient({\n    defaultOptions: {\n      queries: {\n        // With SSR, we usually want to set some default staleTime\n        // above 0 to avoid refetching immediately on the client\n        staleTime: 30 * 1000,\n      },\n      dehydrate: {\n        serializeData: SuperJSON.serialize,\n        shouldDehydrateQuery: (query) =>\n          defaultShouldDehydrateQuery(query) ||\n          query.state.status === \"pending\",\n      },\n      hydrate: {\n        deserializeData: SuperJSON.deserialize,\n      },\n    },\n  });\n"
  },
  {
    "path": "cli/template/extras/src/trpc/react.tsx",
    "content": "\"use client\";\n\nimport { QueryClientProvider, type QueryClient } from \"@tanstack/react-query\";\nimport { httpBatchStreamLink, loggerLink } from \"@trpc/client\";\nimport { createTRPCReact } from \"@trpc/react-query\";\nimport { type inferRouterInputs, type inferRouterOutputs } from \"@trpc/server\";\nimport { useState } from \"react\";\nimport SuperJSON from \"superjson\";\n\nimport { type AppRouter } from \"~/server/api/root\";\nimport { createQueryClient } from \"./query-client\";\n\nlet clientQueryClientSingleton: QueryClient | undefined = undefined;\nconst getQueryClient = () => {\n  if (typeof window === \"undefined\") {\n    // Server: always make a new query client\n    return createQueryClient();\n  }\n  // Browser: use singleton pattern to keep the same query client\n  clientQueryClientSingleton ??= createQueryClient();\n\n  return clientQueryClientSingleton;\n};\n\nexport const api = createTRPCReact<AppRouter>();\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\nexport function TRPCReactProvider(props: { children: React.ReactNode }) {\n  const queryClient = getQueryClient();\n\n  const [trpcClient] = useState(() =>\n    api.createClient({\n      links: [\n        loggerLink({\n          enabled: (op) =>\n            process.env.NODE_ENV === \"development\" ||\n            (op.direction === \"down\" && op.result instanceof Error),\n        }),\n        httpBatchStreamLink({\n          transformer: SuperJSON,\n          url: getBaseUrl() + \"/api/trpc\",\n          headers: () => {\n            const headers = new Headers();\n            headers.set(\"x-trpc-source\", \"nextjs-react\");\n            return headers;\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\nfunction getBaseUrl() {\n  if (typeof window !== \"undefined\") return window.location.origin;\n  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;\n  return `http://localhost:${process.env.PORT ?? 3000}`;\n}\n"
  },
  {
    "path": "cli/template/extras/src/trpc/server.ts",
    "content": "import \"server-only\";\n\nimport { createHydrationHelpers } from \"@trpc/react-query/rsc\";\nimport { headers } from \"next/headers\";\nimport { cache } from \"react\";\n\nimport { createCaller, type AppRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport { createQueryClient } from \"./query-client\";\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(async () => {\n  const heads = new Headers(await headers());\n  heads.set(\"x-trpc-source\", \"rsc\");\n\n  return createTRPCContext({\n    headers: heads,\n  });\n});\n\nconst getQueryClient = cache(createQueryClient);\nconst caller = createCaller(createContext);\n\nexport const { trpc: api, HydrateClient } = createHydrationHelpers<AppRouter>(\n  caller,\n  getQueryClient\n);\n"
  },
  {
    "path": "cli/template/extras/src/utils/api.ts",
    "content": "/**\n * This is the client-side entrypoint for your tRPC API. It is used to create the `api` object which\n * contains the Next.js App-wrapper, as well as your type-safe React Query hooks.\n *\n * We also create a few inference helpers for input and output types.\n */\nimport { httpBatchLink, loggerLink } from \"@trpc/client\";\nimport { createTRPCNext } from \"@trpc/next\";\nimport { type inferRouterInputs, type inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nimport { type AppRouter } from \"~/server/api/root\";\n\nconst getBaseUrl = () => {\n  if (typeof window !== \"undefined\") return \"\"; // browser should use relative url\n  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url\n  return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost\n};\n\n/** A set of type-safe react-query hooks for your tRPC API. */\nexport const api = createTRPCNext<AppRouter>({\n  config() {\n    return {\n      /**\n       * Links used to determine request flow from client to server.\n       *\n       * @see https://trpc.io/docs/links\n       */\n      links: [\n        loggerLink({\n          enabled: (opts) =>\n            process.env.NODE_ENV === \"development\" ||\n            (opts.direction === \"down\" && opts.result instanceof Error),\n        }),\n        httpBatchLink({\n          /**\n           * Transformer used for data de-serialization from the server.\n           *\n           * @see https://trpc.io/docs/data-transformers\n           */\n          transformer: superjson,\n          url: `${getBaseUrl()}/api/trpc`,\n        }),\n      ],\n    };\n  },\n  /**\n   * Whether tRPC should await queries when server rendering pages.\n   *\n   * @see https://trpc.io/docs/nextjs#ssr-boolean-default-false\n   */\n  ssr: false,\n  transformer: superjson,\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": "cli/template/extras/start-database/mysql.sh",
    "content": "#!/usr/bin/env bash\n# Use this script to start a docker container for a local development database\n\n# TO RUN ON WINDOWS:\n# 1. Install WSL (Windows Subsystem for Linux) - https://learn.microsoft.com/en-us/windows/wsl/install\n# 2. Install Docker Desktop or Podman Deskop\n# - Docker Desktop for Windows - https://docs.docker.com/docker-for-windows/install/\n# - Podman Desktop - https://podman.io/getting-started/installation\n# 3. Open WSL - `wsl`\n# 4. Run this script - `./start-database.sh`\n\n# On Linux and macOS you can run this script directly - `./start-database.sh`\n\nset -a\nsource .env\n\nDB_PASSWORD=$(echo \"$DATABASE_URL\" | awk -F':' '{print $3}' | awk -F'@' '{print $1}')\nDB_PORT=$(echo \"$DATABASE_URL\" | awk -F':' '{print $4}' | awk -F'\\/' '{print $1}')\nDB_NAME=$(echo \"$DATABASE_URL\" | awk -F'/' '{print $4}')\nDB_CONTAINER_NAME=\"$DB_NAME-mysql\"\n\nif ! [ -x \"$(command -v docker)\" ] && ! [ -x \"$(command -v podman)\" ]; then\n  echo -e \"Docker or Podman is not installed. Please install docker or podman and try again.\\nDocker install guide: https://docs.docker.com/engine/install/\\nPodman install guide: https://podman.io/getting-started/installation\"\n  exit 1\nfi\n\n# determine which docker command to use\nif [ -x \"$(command -v docker)\" ]; then\n  DOCKER_CMD=\"docker\"\nelif [ -x \"$(command -v podman)\" ]; then\n  DOCKER_CMD=\"podman\"\nfi\n\nif ! $DOCKER_CMD info > /dev/null 2>&1; then\n  echo \"$DOCKER_CMD daemon is not running. Please start $DOCKER_CMD and try again.\"\n  exit 1\nfi\n\nif command -v nc >/dev/null 2>&1; then\n  if nc -z localhost \"$DB_PORT\" 2>/dev/null; then\n    echo \"Port $DB_PORT is already in use.\"\n    exit 1\n  fi\nelse\n  echo \"Warning: Unable to check if port $DB_PORT is already in use (netcat not installed)\"\n  read -p \"Do you want to continue anyway? [y/N]: \" -r REPLY\n  if ! [[ $REPLY =~ ^[Yy]$ ]]; then\n    echo \"Aborting.\"\n    exit 1\n  fi\nfi\n\nif [ \"$($DOCKER_CMD ps -q -f name=$DB_CONTAINER_NAME)\" ]; then\n  echo \"Database container '$DB_CONTAINER_NAME' already running\"\n  exit 0\nfi\n\nif [ \"$($DOCKER_CMD ps -q -a -f name=$DB_CONTAINER_NAME)\" ]; then\n  $DOCKER_CMD start \"$DB_CONTAINER_NAME\"\n  echo \"Existing database container '$DB_CONTAINER_NAME' started\"\n  exit 0\nfi\n\nif [ \"$DB_PASSWORD\" == \"password\" ]; then\n  echo \"You are using the default database password\"\n  read -p \"Should we generate a random password for you? [y/N]: \" -r REPLY\n  if ! [[ $REPLY =~ ^[Yy]$ ]]; then\n    echo \"Please change the default password in the .env file and try again\"\n    exit 1\n  fi\n  # Generate a random URL-safe password\n  DB_PASSWORD=$(openssl rand -base64 12 | tr '+/' '-_')\n  if [[ \"$(uname)\" == \"Darwin\" ]]; then\n    # macOS requires an empty string to be passed with the `i` flag\n    sed -i '' \"s#:password@#:$DB_PASSWORD@#\" .env\n  else\n    sed -i \"s#:password@#:$DB_PASSWORD@#\" .env\n  fi\nfi\n\n$DOCKER_CMD run -d \\\n  --name $DB_CONTAINER_NAME \\\n  -e MYSQL_ROOT_PASSWORD=\"$DB_PASSWORD\" \\\n  -e MYSQL_DATABASE=\"$DB_NAME\" \\\n  -p \"$DB_PORT\":3306 \\\n  docker.io/mysql && echo \"Database container '$DB_CONTAINER_NAME' was successfully created\"\n"
  },
  {
    "path": "cli/template/extras/start-database/postgres.sh",
    "content": "#!/usr/bin/env bash\n# Use this script to start a docker container for a local development database\n\n# TO RUN ON WINDOWS:\n# 1. Install WSL (Windows Subsystem for Linux) - https://learn.microsoft.com/en-us/windows/wsl/install\n# 2. Install Docker Desktop or Podman Deskop\n# - Docker Desktop for Windows - https://docs.docker.com/docker-for-windows/install/\n# - Podman Desktop - https://podman.io/getting-started/installation\n# 3. Open WSL - `wsl`\n# 4. Run this script - `./start-database.sh`\n\n# On Linux and macOS you can run this script directly - `./start-database.sh`\n\n# import env variables from .env\nset -a\nsource .env\n\nDB_PASSWORD=$(echo \"$DATABASE_URL\" | awk -F':' '{print $3}' | awk -F'@' '{print $1}')\nDB_PORT=$(echo \"$DATABASE_URL\" | awk -F':' '{print $4}' | awk -F'\\/' '{print $1}')\nDB_NAME=$(echo \"$DATABASE_URL\" | awk -F'/' '{print $4}')\nDB_CONTAINER_NAME=\"$DB_NAME-postgres\"\n\nif ! [ -x \"$(command -v docker)\" ] && ! [ -x \"$(command -v podman)\" ]; then\n  echo -e \"Docker or Podman is not installed. Please install docker or podman and try again.\\nDocker install guide: https://docs.docker.com/engine/install/\\nPodman install guide: https://podman.io/getting-started/installation\"\n  exit 1\nfi\n\n# determine which docker command to use\nif [ -x \"$(command -v docker)\" ]; then\n  DOCKER_CMD=\"docker\"\nelif [ -x \"$(command -v podman)\" ]; then\n  DOCKER_CMD=\"podman\"\nfi\n\nif ! $DOCKER_CMD info > /dev/null 2>&1; then\n  echo \"$DOCKER_CMD daemon is not running. Please start $DOCKER_CMD and try again.\"\n  exit 1\nfi\n\nif command -v nc >/dev/null 2>&1; then\n  if nc -z localhost \"$DB_PORT\" 2>/dev/null; then\n    echo \"Port $DB_PORT is already in use.\"\n    exit 1\n  fi\nelse\n  echo \"Warning: Unable to check if port $DB_PORT is already in use (netcat not installed)\"\n  read -p \"Do you want to continue anyway? [y/N]: \" -r REPLY\n  if ! [[ $REPLY =~ ^[Yy]$ ]]; then\n    echo \"Aborting.\"\n    exit 1\n  fi\nfi\n\nif [ \"$($DOCKER_CMD ps -q -f name=$DB_CONTAINER_NAME)\" ]; then\n  echo \"Database container '$DB_CONTAINER_NAME' already running\"\n  exit 0\nfi\n\nif [ \"$($DOCKER_CMD ps -q -a -f name=$DB_CONTAINER_NAME)\" ]; then\n  $DOCKER_CMD start \"$DB_CONTAINER_NAME\"\n  echo \"Existing database container '$DB_CONTAINER_NAME' started\"\n  exit 0\nfi\n\nif [ \"$DB_PASSWORD\" = \"password\" ]; then\n  echo \"You are using the default database password\"\n  read -p \"Should we generate a random password for you? [y/N]: \" -r REPLY\n  if ! [[ $REPLY =~ ^[Yy]$ ]]; then\n    echo \"Please change the default password in the .env file and try again\"\n    exit 1\n  fi\n  # Generate a random URL-safe password\n  DB_PASSWORD=$(openssl rand -base64 12 | tr '+/' '-_')\n  if [[ \"$(uname)\" == \"Darwin\" ]]; then\n    # macOS requires an empty string to be passed with the `i` flag\n    sed -i '' \"s#:password@#:$DB_PASSWORD@#\" .env\n  else\n    sed -i \"s#:password@#:$DB_PASSWORD@#\" .env\n  fi\nfi\n\n$DOCKER_CMD run -d \\\n  --name $DB_CONTAINER_NAME \\\n  -e POSTGRES_USER=\"postgres\" \\\n  -e POSTGRES_PASSWORD=\"$DB_PASSWORD\" \\\n  -e POSTGRES_DB=\"$DB_NAME\" \\\n  -p \"$DB_PORT\":5432 \\\n  docker.io/postgres && echo \"Database container '$DB_CONTAINER_NAME' was successfully created\"\n"
  },
  {
    "path": "cli/tsconfig.eslint.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"include\": [\"src\", \"template/**/*.ts\", \"template/**/*.tsx\"]\n}\n"
  },
  {
    "path": "cli/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"~/*\": [\"./src/*\"]\n    },\n    \"checkJs\": true\n  },\n  \"include\": [\"src\", \"tsup.config.ts\", \"../reset.d.ts\", \"prettier.config.mjs\"]\n}\n"
  },
  {
    "path": "cli/tsup.config.ts",
    "content": "import { defineConfig } from \"tsup\";\n\nconst isDev = process.env.npm_lifecycle_event === \"dev\";\n\nexport default defineConfig({\n  clean: true,\n  entry: [\"src/index.ts\"],\n  format: [\"esm\"],\n  minify: !isDev,\n  target: \"esnext\",\n  outDir: \"dist\",\n  onSuccess: isDev ? \"node dist/index.js\" : undefined,\n});\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@ct3a/root\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Quickest way to start a new web app with full stack typesafety\",\n  \"author\": \"Shoubhit Dash <shoubhit2005@gmail.com> (https://nexxel.dev)\",\n  \"maintainers\": [\n    \"Julius Marminge <julius0216@outlook.com> (https://jumr.dev)\"\n  ],\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/t3-oss/create-t3-app.git\"\n  },\n  \"keywords\": [\n    \"create-t3-app\",\n    \"init.tips\",\n    \"next.js\",\n    \"t3-stack\",\n    \"tailwind\",\n    \"tRPC\",\n    \"typescript\"\n  ],\n  \"engines\": {\n    \"node\": \">=20.0.0\"\n  },\n  \"packageManager\": \"pnpm@10.8.0\",\n  \"scripts\": {\n    \"typecheck\": \"turbo typecheck\",\n    \"build:cli\": \"turbo --filter=create-t3-app build\",\n    \"build:www\": \"turbo --filter=www build\",\n    \"build\": \"turbo build\",\n    \"start:cli\": \"turbo --filter=create-t3-app start\",\n    \"start:www\": \"turbo --filter=www start\",\n    \"dev:cli\": \"turbo --filter=create-t3-app dev\",\n    \"dev:www\": \"turbo --filter=www dev\",\n    \"clean\": \"turbo clean && rm -rf node_modules\",\n    \"lint\": \"turbo lint && manypkg check\",\n    \"lint:fix\": \"turbo lint:fix && manypkg fix\",\n    \"format\": \"turbo format && prettier --write '*.{cjs,json}' --ignore-unknown --no-error-on-unmatched-pattern\",\n    \"format:check\": \"turbo format:check && prettier --check '*.{cjs,json}' --ignore-unknown --no-error-on-unmatched-pattern\",\n    \"check\": \"turbo lint typecheck format:check && manypkg check\",\n    \"release\": \"changeset version\",\n    \"pub:beta\": \"cd cli && pnpm pub:beta\",\n    \"pub:release\": \"cd cli && pnpm pub:release\"\n  },\n  \"dependencies\": {\n    \"@changesets/changelog-github\": \"^0.4.8\",\n    \"@changesets/cli\": \"^2.27.3\",\n    \"@eslint/compat\": \"^1.2.7\",\n    \"@eslint/eslintrc\": \"^3.3.1\",\n    \"@ianvs/prettier-plugin-sort-imports\": \"^4.2.1\",\n    \"@manypkg/cli\": \"^0.20.0\",\n    \"@total-typescript/ts-reset\": \"^0.3.7\",\n    \"@types/node\": \"^24.10.1\",\n    \"eslint\": \"^9.23.0\",\n    \"eslint-plugin-import-x\": \"^4.9.1\",\n    \"eslint-plugin-isaacscript\": \"^4.0.0\",\n    \"eslint-plugin-react\": \"^7.37.4\",\n    \"eslint-plugin-react-hooks\": \"^5.2.0\",\n    \"prettier\": \"^3.5.3\",\n    \"turbo\": \"1.13.3-canary.3\",\n    \"typescript\": \"^5.8.2\",\n    \"typescript-eslint\": \"^8.27.0\"\n  }\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - cli\n  - www\n\nonlyBuiltDependencies:\n  - '@prisma/client'\n  - '@prisma/engines'\n  - esbuild\n  - prisma\n  - sharp\n"
  },
  {
    "path": "prettier.config.mjs",
    "content": "/**\n * @type {import('prettier').Config & import(\"@ianvs/prettier-plugin-sort-imports\").PluginConfig}\n */\nconst config = {\n  arrowParens: \"always\",\n  printWidth: 80,\n  singleQuote: false,\n  jsxSingleQuote: false,\n  semi: true,\n  trailingComma: \"all\",\n  tabWidth: 2,\n};\n\nexport default config;\n"
  },
  {
    "path": "reset.d.ts",
    "content": "import \"@total-typescript/ts-reset\";\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"include\": [\".eslintrc.cjs\", \"prettier.config.mjs\"],\n  \"compilerOptions\": {\n    /* LANGUAGE COMPILATION OPTIONS */\n    \"target\": \"ES2020\",\n    \"lib\": [\"DOM\", \"DOM.Iterable\", \"ES2021\"],\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"nodenext\",\n    \"resolveJsonModule\": true,\n    \"allowJs\": true,\n    \"checkJs\": true,\n\n    /* EMIT RULES */\n    \"outDir\": \"./dist\",\n    \"noEmit\": true, // TSUP takes care of emitting js for us, in a MUCH faster way\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"removeComments\": true,\n\n    /* TYPE CHECKING RULES */\n    \"strict\": true,\n    // \"noImplicitAny\": true, // Included in \"Strict\"\n    // \"noImplicitThis\": true, // Included in \"Strict\"\n    // \"strictBindCallApply\": true, // Included in \"Strict\"\n    // \"strictFunctionTypes\": true, // Included in \"Strict\"\n    // \"strictNullChecks\": true, // Included in \"Strict\"\n    // \"strictPropertyInitialization\": true, // Included in \"Strict\"\n    \"noFallthroughCasesInSwitch\": true,\n    \"noImplicitOverride\": true,\n    \"noImplicitReturns\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"useUnknownInCatchVariables\": true,\n    \"noUncheckedIndexedAccess\": true, // TLDR - Checking an indexed value (array[0]) now forces type <T | undefined> as there is no confirmation that index exists\n    // THE BELOW ARE EXTRA STRICT OPTIONS THAT SHOULD ONLY BY CONSIDERED IN VERY SAFE PROJECTS\n    // \"exactOptionalPropertyTypes\": true, // TLDR - Setting to undefined is not the same as a property not being defined at all\n    // \"noPropertyAccessFromIndexSignature\": true, // TLDR - Use dot notation for objects if youre sure it exists, use ['index'] notaion if unsure\n\n    /* OTHER OPTIONS */\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    // \"emitDecoratorMetadata\": true,\n    // \"experimentalDecorators\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true,\n    \"useDefineForClassFields\": true\n  }\n}\n"
  },
  {
    "path": "turbo.json",
    "content": "{\n  \"$schema\": \"https://turbo.build/schema.json\",\n  \"pipeline\": {\n    \"build\": {\n      \"outputs\": [\"dist/**\", \".vercel/output/**\", \".next/**\"],\n      \"dependsOn\": [\"^build\"]\n    },\n    \"dev\": {\n      \"cache\": false,\n      \"persistent\": true\n    },\n    \"start\": {\n      \"dependsOn\": [\"^build\"]\n    },\n    \"lint\": {\n      \"cache\": false\n    },\n    \"lint:fix\": {\n      \"cache\": false\n    },\n    \"format\": {\n      \"cache\": false\n    },\n    \"format:check\": {\n      \"cache\": false\n    },\n    \"clean\": {\n      \"cache\": false\n    },\n    \"typecheck\": {}\n  }\n}\n"
  },
  {
    "path": "www/.env.example",
    "content": "# For developers who would like the data to be pulled correctly,\n# generate these tokens from the provider and add them to a .gitignored .env file\n# You can run `pnpm dev` without them, and dummy data (or no data) will be used instead\n\n# Github - for grabbing star count in navbar, and commit history for docs pages\n# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token\nPUBLIC_GITHUB_TOKEN=\n\n# Twitter (API v2)- for grabbing Twitter card data\n# https://developer.twitter.com/en/docs/authentication/overview\nTWITTER_BEARER_TOKEN=\n\n# For enabling debug mode in satori (for OG images)\nDEBUG_OG="
  },
  {
    "path": "www/.gitignore",
    "content": "# build output\ndist/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n\n# environment variables\n.env\n.env.production\n!.env.example\n\n# macOS-specific files\n.DS_Store\n"
  },
  {
    "path": "www/README.md",
    "content": "# create-t3-app Documentation Site\n\nBased on the [Astro Starter Kit: Docs Site](https://github.com/withastro/astro/tree/latest/examples/docs). New to Astro?\n\n- Check out [their documentation](https://docs.astro.build).\n- Jump into their [Discord server](https://astro.build/chat).\n- Deploy a site to production with the guide, [Deploy an Astro Website](https://docs.astro.build/guides/deploy).\n\n## Outline\n\n- [Features](#features)\n- [Run Site Locally](#run-site-locally)\n- [Command Cheat Sheet](#command-cheat-sheet)\n- [Customize This Theme](#customize-this-theme)\n  - [Site Metadata](#site-metadata)\n  - [CSS Styling](#css-styling)\n  - [Page Metadata](#page-metadata)\n  - [Sidebar Navigation](#sidebar-navigation)\n  - [Multiple Languages Support](#multiple-languages-support)\n\n## Features\n\n- ✅ **Full Markdown support**\n- ✅ **Responsive mobile-friendly design**\n- ✅ **Sidebar navigation**\n- ✅ **Search (powered by Algolia)**\n- ✅ **Multi-language i18n**\n- ✅ **Automatic table of contents**\n- ✅ **Automatic list of contributors**\n- ✅ (and, best of all) **dark mode**\n\n## Run Site Locally\n\n```bash\ngit clone https://github.com/t3-oss/create-t3-app.git\ncd create-t3-app/www\npnpm i\npnpm dev\n```\n\n## Command Cheat Sheet\n\nAll commands are run from the root of the project, from a terminal.\n\n| Command                | Action                                           |\n| :--------------------- | :----------------------------------------------- |\n| `npm install`          | Installs dependencies                            |\n| `npm run dev`          | Starts local dev server at `localhost:3000`      |\n| `npm run build`        | Build your production site to `./dist/`          |\n| `npm run preview`      | Preview your build locally, before deploying     |\n| `npm run astro ...`    | Run CLI commands like `astro add`, `astro check` |\n| `npm run astro --help` | Get help using the Astro CLI                     |\n\n## Customize This Theme\n\n### Site Metadata\n\n`src/config.ts` contains several data objects that describe metadata about your site like title, description, default language, and Open Graph details. You can customize these to match your project.\n\n### CSS Styling\n\nThe theme's look and feel is controlled by a few key variables that you can customize yourself. You'll find them in the `public/theme.css` CSS file. If you've never worked with CSS variables before, give [MDN's guide on CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) a quick read.\n\nThis theme uses a \"cool blue\" accent color by default. To customize this for your project, change the `--theme-accent` variable to whatever color you'd like:\n\n```diff\n/* public/theme.css */\n\n:root {\n  color-scheme: light;\n-  --theme-accent: hsla(var(--color-blue), 1);\n+  --theme-accent: hsla(var(--color-red), 1);   /* or: hsla(#FF0000, 1); */\n```\n\n### Page Metadata\n\nAstro uses frontmatter in Markdown pages to choose layouts and pass properties to those layouts. If you are using the default layout, you can customize the page in many different ways to optimize SEO and other things.\n\n```markdown\n---\ntitle: Example title\ndescription: Really cool docs example that uses Astro\nlayout: ../../layouts/MainLayout.astro\n---\n\n# Page content...\n```\n\nThis uses the `title` and `description` properties to set the document title, meta title, meta description, and Open Graph description. See `src/components/HeadSEO.astro` for more SEO related properties.\n\n### Sidebar Navigation\n\nThe sidebar navigation is controlled by the `SIDEBAR` variable in your `src/config.ts` file. You can customize the sidebar by modifying this object. A default, starter navigation has already been created for you.\n\n```ts\n// src/config.ts\n\nexport const SIDEBAR = {\n  en: [\n    { text: \"Section Header\", header: true },\n    { text: \"Introduction\", link: \"en/introduction\" },\n    { text: \"Page 2\", link: \"en/page-2\" },\n    { text: \"Page 3\", link: \"en/page-3\" },\n\n    { text: \"Another Section\", header: true },\n    { text: \"Page 4\", link: \"en/page-4\" },\n  ],\n};\n```\n\nNote the top-level `en` key: This is needed for multi-language support. You can change it to whatever language you'd like, or add new languages as you go. More details on this below.\n\n### Multiple Languages Support\n\nThe Astro docs template supports multiple languages out of the box. The default theme only shows `en` docs. But you can enable multi-language support features. To add a second language to your project, you'll want to extend the layout, `src/pages/[lang]/...`:\n\n```diff\n 📂 src/pages\n ┣ 📂 en\n ┃ ┣ 📜 page-1.md\n ┃ ┣ 📜 page-2.md\n ┃ ┣ 📜 page-3.astro\n+ ┣ 📂 es\n+ ┃ ┣ 📜 page-1.md\n+ ┃ ┣ 📜 page-2.md\n+ ┃ ┣ 📜 page-3.astro\n```\n\nYou'll also need to add the new language name to the `KNOWN_LANGUAGES` map in your `src/config.ts` file. This will enable your new language switcher in the site header.\n\n```diff\n// src/config.ts\n\nexport const KNOWN_LANGUAGES = {\n  English: 'en',\n+  Spanish: 'es',\n};\n```\n\nLast step: you'll need to add a new entry to your sidebar, to create the table of contents for that language. While duplicating every page might not sound ideal to everyone, this extra control allows you to create entirely custom content for every language.\n\n> Make sure the sidebar `link` value points to the correct language!\n\n```diff\n// src/config.ts\n\nexport const SIDEBAR = {\n  en: [\n    { text: 'Section Header', header: true, },\n    { text: 'Introduction', link: 'en/introduction' },\n    // ...\n  ],\n+  es: [\n+    { text: 'Encabezado de sección', header: true, },\n+    { text: 'Introducción', link: 'es/introduction' },\n+    // ...\n+  ],\n};\n\n// ...\n```\n\nIf you plan to use Spanish as the default language, you just need to modify the redirect path in `src/pages/index.astro` (or you can remove the script and write a landing page in Spanish instead):\n\n```diff\n<script>\n- window.location.pathname = `/en/introduction`;\n+ window.location.pathname = `/es/introduction`;\n</script>\n```\n\nWhat if I don't plan to support multiple languages? Totally fine! Not all projects need (or can support) that. If that single language is not English, you can just replace `en` in directory layouts and configurations with the preferred language such as `es`.\n"
  },
  {
    "path": "www/TRANSLATIONS.md",
    "content": "# Contributing Guidelines for our docs\n\nAre you a native speaker of a language other than English? We'd love to have your help!\n\n## How to contribute\n\n(Read the [contribution guidelines](../CONTRIBUTING.md) first for general information about contributing to this project.)\n\n### Initial Translation\n\nIf the docs are not available in your language yet and you would like to translate them, you can do so by following these steps:\n\n1. Copy the `pages/en` directory to a new directory with the name of your language, e.g. `pages/de` for German. (If you're not sure what the language code is, you can find it [here](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).)\n\n2. File a draft PR to let others know you're working on it. This is to avoid duplicate work, and also allows for community feedback along the way.\n\n3. File by file, translate the content of the files.\n\n4. Update the `lang` attribute in the frontmatter of the files translated to your language. If there are any files you haven't translated yet, that's fine. Just leave the `lang: en` attribute in the frontmatter.\n\n5. If the language you are translating into is read right-to-left (for example, Arabic or Hebrew), also add `dir: rtl` to the frontmatter.\n\n6. Add your language to the `KNOWN_LANGUAGE` object in [config.ts](./src/config.ts). You'll now get some type errors on the `SIDEBAR` and `SIDEBAR_HEADER_MAP` objects in the same file. Follow the instructions in the comments and translate the requested entries.\n\n7. When you're done, mark the pull request as ready for review.\n\n### Reviewing\n\nWe aim to have 1-2 reviews on each PR before merging. This allows for some back and forth and ensures that the quality of the docs is high, and the tone is consistent.\n\nWe'd highly appreciate it if you knew someone who speaks the language you're translating into to review your PR. This can help speed up the process of getting your contribution merged.\n\n### Maintaining\n\nNaturally, the English docs will move faster than the translated ones. We've implemented a feature that alerts visitors if a translated version of a page is outdated. If you see that a page is outdated and you're able to update it, please do so!\n\nWe also have code owners for each language. Being a code owner means that you get notified when there is a PR that includes changes to the files of your language, so that you can review it.\n\nBecoming a code owner is open to anyone who has contributed to a language, either by writing translations themselves or by reviewing those of others. If would like to become a code owner, either add your GitHub username to your language in [translations.yml](https://github.com/t3-oss/create-t3-app/blob/next/.github/workflows/translations.yml) or let us know in the `create-t3-translation` channel on [Discord](https://create.t3.gg/discord).\n"
  },
  {
    "path": "www/astro.config.mjs",
    "content": "import mdx from \"@astrojs/mdx\";\nimport react from \"@astrojs/react\";\nimport sitemap from \"@astrojs/sitemap\";\nimport vercel from \"@astrojs/vercel\";\nimport { defineConfig } from \"astro/config\";\nimport rehypeAutolinkHeadings from \"rehype-autolink-headings\";\nimport rehypeExternalLinks from \"rehype-external-links\";\nimport rehypeSlug from \"rehype-slug\";\nimport remarkCodeTitles from \"remark-code-titles\";\n\n/** @link https://astro.build/config */\nexport default defineConfig({\n  site: `https://create.t3.gg/`,\n  output: \"server\",\n  adapter: vercel(),\n  markdown: {\n    remarkPlugins: [remarkCodeTitles],\n    rehypePlugins: [\n      [\n        rehypeExternalLinks,\n        {\n          target: \"_blank\",\n          rel: [\"noreferrer noopener\"],\n          content: {\n            type: \"text\",\n            value: \"↗\",\n          },\n        },\n      ],\n      rehypeSlug,\n      [\n        rehypeAutolinkHeadings,\n        {\n          properties: {\n            class: \"heading-link heading-link--hidden---effects\",\n            \"data-heading-link\": true,\n          },\n          behavior: \"wrap\",\n        },\n      ],\n    ],\n    shikiConfig: {\n      theme: \"rose-pine\",\n      wrap: true,\n    },\n  },\n  integrations: [react(), sitemap(), mdx()],\n  vite: {\n    optimizeDeps: {\n      exclude: [\"@resvg/resvg-js\"],\n    },\n  },\n});\n"
  },
  {
    "path": "www/package.json",
    "content": "{\n  \"name\": \"@ct3a/www\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"scripts\": {\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"astro dev\",\n    \"start\": \"astro dev\",\n    \"check\": \"astro check\",\n    \"clean\": \"rm -rf node_modules .turbo dist .eslintcache\",\n    \"format\": \"prettier '**/*.{cjs,mjs,ts,tsx,md,json,astro}' --ignore-path ../.gitignore --ignore-unknown --write\",\n    \"format:check\": \"prettier '**/*.{cjs,mjs,ts,tsx,md,json,astro}' --ignore-path ../.gitignore --ignore-unknown --check\",\n    \"build\": \"astro build\",\n    \"preview\": \"astro preview\",\n    \"astro\": \"astro\"\n  },\n  \"dependencies\": {\n    \"@algolia/client-search\": \"^5.21.0\",\n    \"@astrojs/check\": \"^0.9.4\",\n    \"@astrojs/mdx\": \"^4.2.1\",\n    \"@astrojs/sitemap\": \"^3.3.0\",\n    \"@astrojs/vercel\": \"^8.1.3\",\n    \"@docsearch/css\": \"^3.9.0\",\n    \"@docsearch/react\": \"^3.9.0\",\n    \"@fontsource-variable/inter\": \"^5.2.5\",\n    \"@headlessui/react\": \"^2.2.0\",\n    \"@ianvs/prettier-plugin-sort-imports\": \"^4.2.1\",\n    \"@resvg/resvg-js\": \"^2.6.2\",\n    \"@stackblitz/sdk\": \"^1.11.0\",\n    \"@vercel/analytics\": \"^1.5.0\",\n    \"clsx\": \"^2.1.1\",\n    \"embla-carousel\": \"^8.5.2\",\n    \"embla-carousel-autoplay\": \"^8.5.2\",\n    \"satori\": \"^0.12.1\",\n    \"sharp\": \"^0.33.5\",\n    \"tailwind-scrollbar\": \"^3.0.0\",\n    \"treeify\": \"^1.1.0\",\n    \"unist-util-visit\": \"^5.0.0\",\n    \"zod\": \"^3.24.2\"\n  },\n  \"devDependencies\": {\n    \"@astrojs/react\": \"^4.2.1\",\n    \"@astrojs/tailwind\": \"^6.0.1\",\n    \"@types/node\": \"^24.10.1\",\n    \"@types/react\": \"~19.1.0\",\n    \"@types/react-dom\": \"~19.1.0\",\n    \"@types/react-typist\": \"^2.0.6\",\n    \"@types/treeify\": \"^1.0.3\",\n    \"astro\": \"^5.5.4\",\n    \"prettier\": \"^3.5.3\",\n    \"prettier-plugin-astro\": \"^0.14.1\",\n    \"prettier-plugin-tailwindcss\": \"^0.6.11\",\n    \"react\": \"^19.2.3\",\n    \"react-dom\": \"^19.2.3\",\n    \"react-typist\": \"^2.0.5\",\n    \"rehype-autolink-headings\": \"^7.1.0\",\n    \"rehype-external-links\": \"^3.0.0\",\n    \"rehype-slug\": \"^6.0.0\",\n    \"remark-code-titles\": \"^0.1.2\",\n    \"tailwindcss\": \"npm:tailwindcss@^3\",\n    \"typescript\": \"^5.8.2\"\n  }\n}\n"
  },
  {
    "path": "www/postcss.config.cjs",
    "content": "const config = {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "www/prettier.config.mjs",
    "content": "import baseConfig from \"../prettier.config.mjs\";\n\n/**\n * @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions &\n *       import(\"@ianvs/prettier-plugin-sort-imports\").PluginConfig}\n */\nconst config = {\n  ...baseConfig,\n  plugins: [\n    \"@ianvs/prettier-plugin-sort-imports\",\n    \"prettier-plugin-astro\",\n    \"prettier-plugin-tailwindcss\", // MUST come last\n  ],\n  overrides: [\n    {\n      files: \"*.astro\",\n      options: {\n        parser: \"astro\",\n      },\n    },\n  ],\n  astroAllowShorthand: false,\n  tailwindConfig: \"./tailwind.config.ts\",\n  importOrder: [\"<THIRD_PARTY_MODULES>\", \"\", \"^~/\", \"^[.][.]/\", \"^[.]/\"],\n  importOrderParserPlugins: [\"typescript\", \"jsx\", \"decorators-legacy\"],\n  importOrderTypeScriptVersion: \"4.4.0\",\n};\n\nexport default config;\n"
  },
  {
    "path": "www/public/makeScrollableCodeFocusable.js",
    "content": "Array.from(document.getElementsByTagName(\"pre\")).forEach((element) => {\n  element.setAttribute(\"tabindex\", \"0\");\n});\n"
  },
  {
    "path": "www/public/robots.txt",
    "content": "# Algolia-Crawler-Verif: 013A1A14AB9EE32B\n\nUser-agent: *\nAllow: /\nSitemap: https://create.t3.gg/sitemap-index.xml\n"
  },
  {
    "path": "www/src/.vscode/settings.json",
    "content": "{\n  \"workbench.editor.wrapTabs\": false,\n  \"editor.wordWrap\": \"on\"\n}\n"
  },
  {
    "path": "www/src/components/accessibility/jumpToContent.astro",
    "content": "---\nimport Button from \"../landingPage/button.astro\";\n---\n\n<Button\n  href=\"#content\"\n  className=\"absolute -top-96 z-50 opacity-0 focus:top-0 focus:opacity-100 ltr:-left-96 ltr:focus:left-0 rtl:-right-96 rtl:focus:right-0\"\n>\n  Jump to content\n</Button>\n"
  },
  {
    "path": "www/src/components/branding/Asset.astro",
    "content": "---\nimport Button from \"../landingPage/button.astro\";\n\nexport interface Props {\n  title: string;\n  bg: \"white\" | \"black\";\n  description: string;\n  assets: {\n    svg: string | null;\n    png: string | null;\n  };\n  attribution?: boolean;\n}\n\nconst {\n  title,\n  bg,\n  description,\n  assets: { svg, png },\n  attribution = false,\n} = Astro.props;\n\nfunction getDownloadName(path: string) {\n  const lastIndex = path.lastIndexOf(\"/\");\n  return path.slice(lastIndex + 1, path.length - 4);\n}\n---\n\n<div class=\"flex w-80 flex-col overflow-hidden rounded\">\n  <div\n    class={`${\n      bg === \"white\" ? \"bg-white\" : \"bg-black\"\n    } p-4 w-full flex justify-center`}\n  >\n    <img src={svg ? svg : png} />\n  </div>\n  <div class=\"flex w-full flex-1 flex-col gap-4 bg-neutral p-4\">\n    <div class=\"flex flex-col text-xl text-white\">\n      <span>{title}</span>\n      {\n        attribution ? (\n          <span class=\"text-sm text-t3-purple-200\">\n            Designed by{\" \"}\n            <a\n              href=\"https://github.com/zaknaj\"\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              Zak\n            </a>\n          </span>\n        ) : null\n      }\n    </div>\n    <p class=\"flex-1\">\n      {description}\n    </p>\n    <div class=\"flex gap-2\">\n      {\n        svg ? (\n          <Button\n            variant=\"secondary\"\n            rounded=\"md\"\n            className=\"h-8 w-min gap-2\"\n            href={svg}\n            download={getDownloadName(svg)}\n          >\n            .svg\n            <svg\n              data-hk=\"0-0\"\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              xmlns=\"http://www.w3.org/2000/svg\"\n              aria-hidden=\"true\"\n              class=\"w-4\"\n            >\n              <path\n                d=\"M21 14C20.7348 14 20.4804 14.1054 20.2929 14.2929C20.1054 14.4804 20 14.7348 20 15V19C20 19.2652 19.8946 19.5196 19.7071 19.7071C19.5196 19.8946 19.2652 20 19 20H5C4.73478 20 4.48043 19.8946 4.29289 19.7071C4.10536 19.5196 4 19.2652 4 19V15C4 14.7348 3.89464 14.4804 3.70711 14.2929C3.51957 14.1054 3.26522 14 3 14C2.73478 14 2.48043 14.1054 2.29289 14.2929C2.10536 14.4804 2 14.7348 2 15V19C2 19.7956 2.31607 20.5587 2.87868 21.1213C3.44129 21.6839 4.20435 22 5 22H19C19.7956 22 20.5587 21.6839 21.1213 21.1213C21.6839 20.5587 22 19.7956 22 19V15C22 14.7348 21.8946 14.4804 21.7071 14.2929C21.5196 14.1054 21.2652 14 21 14ZM11.29 15.71C11.3851 15.801 11.4972 15.8724 11.62 15.92C11.7397 15.9729 11.8691 16.0002 12 16.0002C12.1309 16.0002 12.2603 15.9729 12.38 15.92C12.5028 15.8724 12.6149 15.801 12.71 15.71L16.71 11.71C16.8983 11.5217 17.0041 11.2663 17.0041 11C17.0041 10.7337 16.8983 10.4783 16.71 10.29C16.5217 10.1017 16.2663 9.99591 16 9.99591C15.7337 9.99591 15.4783 10.1017 15.29 10.29L13 12.59V3C13 2.73478 12.8946 2.48043 12.7071 2.29289C12.5196 2.10536 12.2652 2 12 2C11.7348 2 11.4804 2.10536 11.2929 2.29289C11.1054 2.48043 11 2.73478 11 3V12.59L8.71 10.29C8.61676 10.1968 8.50607 10.1228 8.38425 10.0723C8.26243 10.0219 8.13186 9.99591 8 9.99591C7.86814 9.99591 7.73757 10.0219 7.61575 10.0723C7.49393 10.1228 7.38324 10.1968 7.29 10.29C7.19676 10.3832 7.1228 10.4939 7.07234 10.6158C7.02188 10.7376 6.99591 10.8681 6.99591 11C6.99591 11.1319 7.02188 11.2624 7.07234 11.3842C7.1228 11.5061 7.19676 11.6168 7.29 11.71L11.29 15.71Z\"\n                fill=\"currentColor\"\n              />\n            </svg>\n          </Button>\n        ) : null\n      }\n      {\n        png ? (\n          <Button\n            variant=\"secondary\"\n            rounded=\"md\"\n            className=\"h-8 w-min gap-2\"\n            href={png}\n            download={getDownloadName(png)}\n          >\n            .png\n            <svg\n              data-hk=\"0-0\"\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              xmlns=\"http://www.w3.org/2000/svg\"\n              aria-hidden=\"true\"\n              class=\"w-4\"\n            >\n              <path\n                d=\"M21 14C20.7348 14 20.4804 14.1054 20.2929 14.2929C20.1054 14.4804 20 14.7348 20 15V19C20 19.2652 19.8946 19.5196 19.7071 19.7071C19.5196 19.8946 19.2652 20 19 20H5C4.73478 20 4.48043 19.8946 4.29289 19.7071C4.10536 19.5196 4 19.2652 4 19V15C4 14.7348 3.89464 14.4804 3.70711 14.2929C3.51957 14.1054 3.26522 14 3 14C2.73478 14 2.48043 14.1054 2.29289 14.2929C2.10536 14.4804 2 14.7348 2 15V19C2 19.7956 2.31607 20.5587 2.87868 21.1213C3.44129 21.6839 4.20435 22 5 22H19C19.7956 22 20.5587 21.6839 21.1213 21.1213C21.6839 20.5587 22 19.7956 22 19V15C22 14.7348 21.8946 14.4804 21.7071 14.2929C21.5196 14.1054 21.2652 14 21 14ZM11.29 15.71C11.3851 15.801 11.4972 15.8724 11.62 15.92C11.7397 15.9729 11.8691 16.0002 12 16.0002C12.1309 16.0002 12.2603 15.9729 12.38 15.92C12.5028 15.8724 12.6149 15.801 12.71 15.71L16.71 11.71C16.8983 11.5217 17.0041 11.2663 17.0041 11C17.0041 10.7337 16.8983 10.4783 16.71 10.29C16.5217 10.1017 16.2663 9.99591 16 9.99591C15.7337 9.99591 15.4783 10.1017 15.29 10.29L13 12.59V3C13 2.73478 12.8946 2.48043 12.7071 2.29289C12.5196 2.10536 12.2652 2 12 2C11.7348 2 11.4804 2.10536 11.2929 2.29289C11.1054 2.48043 11 2.73478 11 3V12.59L8.71 10.29C8.61676 10.1968 8.50607 10.1228 8.38425 10.0723C8.26243 10.0219 8.13186 9.99591 8 9.99591C7.86814 9.99591 7.73757 10.0219 7.61575 10.0723C7.49393 10.1228 7.38324 10.1968 7.29 10.29C7.19676 10.3832 7.1228 10.4939 7.07234 10.6158C7.02188 10.7376 6.99591 10.8681 6.99591 11C6.99591 11.1319 7.02188 11.2624 7.07234 11.3842C7.1228 11.5061 7.19676 11.6168 7.29 11.71L11.29 15.71Z\"\n                fill=\"currentColor\"\n              />\n            </svg>\n          </Button>\n        ) : null\n      }\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "www/src/components/docs/avatarList.astro",
    "content": "---\nimport { fetchGithub, type Commit } from \"../../utils/fetchGithub\";\n\n// fetch all commits for just this page's path\nexport interface Props {\n  path: string;\n}\nconst { path } = Astro.props;\nconst resolvedPath = `www/${path}`;\nconst url = `https://api.github.com/repos/t3-oss/create-t3-app/commits?path=${resolvedPath}`;\nconst commitsURL = `https://github.com/t3-oss/create-t3-app/commits/main/${resolvedPath}`;\n\nasync function getCommits(url: string) {\n  try {\n    const data = await fetchGithub(url, { fetchType: \"commits\" });\n    return data;\n  } catch (e) {\n    console.warn(`[warn]  /src/components/AvatarList.astro \n    ${(e as Error)?.message ?? e}`);\n    return [] as Commit[];\n  }\n}\n\nfunction removeDups(arr: Commit[]): Pick<Commit[\"author\"], \"login\" | \"id\">[] {\n  const map = new Map<string, Pick<Commit[\"author\"], \"login\" | \"id\">>();\n\n  for (let item of arr) {\n    const author = item.author;\n    if (!author || !author.id || !author.login) continue;\n    // Deduplicate based on author.id\n    map.set(author.id.toString(), { login: author.login, id: author.id });\n  }\n\n  return [...map.values()];\n}\n\nconst data = await getCommits(url);\nconst unique = removeDups(data ?? []);\nconst recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors\nconst additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors\n---\n\n<div class=\"flex flex-col items-center justify-center gap-2 py-3\">\n  <span class=\"py-2\">Recent Contributors To This Page</span>\n  <ul class=\"flex gap-4\">\n    {\n      recentContributors.map((item) => (\n        <li>\n          <a class=\"rounded-full\" href={`https://github.com/${item.login}`}>\n            <img\n              class=\"h-8 w-8 rounded-full sm:h-10 sm:w-10\"\n              alt={`Contributor ${item.login}`}\n              title={`Contributor\n          ${item.login}`}\n              width=\"64\"\n              height=\"64\"\n              src={`https://avatars.githubusercontent.com/u/${item.id}`}\n            />\n          </a>\n        </li>\n      ))\n    }\n  </ul>\n  {\n    additionalContributors > 0 && (\n      <span>\n        <a\n          href={commitsURL}\n        >{`and ${additionalContributors} additional contributor${\n          additionalContributors > 1 ? \"s\" : \"\"\n        }.`}</a>\n      </span>\n    )\n  }\n  {\n    unique.length === 0 && (\n      <a class=\"text-slate-900 dark:text-white\" href={commitsURL}>\n        Contributors\n      </a>\n    )\n  }\n</div>\n"
  },
  {
    "path": "www/src/components/docs/breadCrumbs.tsx",
    "content": "import clsx from \"clsx\";\n\nimport { SIDEBAR, SIDEBAR_HEADER_MAP, type OuterHeaders } from \"../../config\";\nimport { getIsRtlFromLangCode, getLanguageFromURL } from \"../../languages\";\n\ntype SlugType = \"\" | \"deployment\" | \"usage\";\n\nexport default function BreadCrumbs() {\n  const lang = getLanguageFromURL(window.location.href);\n  const isRtl = getIsRtlFromLangCode(lang ?? \"en\");\n  const slugToEntryPath = (slug: SlugType): OuterHeaders => {\n    switch (slug) {\n      case \"\":\n        return \"Create T3 App\";\n      case \"usage\":\n        return \"Usage\";\n      case \"deployment\":\n        return \"Deployment\";\n    }\n  };\n\n  const pathname = window.location.pathname.endsWith(\"/\")\n    ? window.location.pathname.slice(0, -1)\n    : window.location.pathname;\n\n  const slug =\n    pathname.slice(1).split(\"/\").length > 2\n      ? pathname.slice(1).split(\"/\")[1]\n      : \"\";\n\n  const actualEntries =\n    SIDEBAR[lang][\n      slugToEntryPath(\n        slug === undefined || slug === \"\" ? \"\" : (slug as SlugType),\n      )\n    ];\n\n  const getPathNameFromLink = (link: string) => {\n    return [...(actualEntries ?? [])].find((entry) => entry.link === link)\n      ?.text;\n  };\n\n  const getHeaderName = (header: OuterHeaders) => {\n    if (lang === \"en\") return header;\n    return SIDEBAR_HEADER_MAP[lang][header];\n  };\n\n  const breadcrumbs = pathname\n    .split(\"/\")\n    .slice(pathname.split(\"/\").length > 3 ? -2 : -1)\n    .map((crumb) => {\n      const path = pathname\n        .split(\"/\")\n        .slice(0, pathname.split(\"/\").indexOf(crumb) + 1)\n        .join(\"/\");\n\n      return {\n        href: `${window.location.protocol}//${window.location.host}${path}`,\n        key: crumb,\n        text:\n          getPathNameFromLink(path.slice(path.indexOf(lang))) ??\n          getHeaderName(\n            `${crumb[0]?.toUpperCase()}${crumb.slice(1)}` as OuterHeaders,\n          ),\n      };\n    });\n\n  return (\n    <div className=\"flex items-center gap-2 px-4 text-sm\">\n      <a\n        href=\"/\"\n        className=\"rounded-lg border bg-t3-purple-200/50 p-1 hover:bg-t3-purple-200/75 hover:no-underline dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\"\n      >\n        <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\">\n          <path\n            fill=\"currentColor\"\n            d=\"m12 5.561l-7 5.6V19h5v-4h4v4h5v-7.358a1 1 0 0 0-.375-.781L12 5.561ZM12 3l7.874 6.3A3 3 0 0 1 21 11.641V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7.839A2 2 0 0 1 3.75 9.6L12 3Z\"\n          />\n        </svg>\n      </a>\n      <span className=\"flex-shrink-0\">\n        <BreadCrumbsArrow isRtl={isRtl} />\n      </span>\n      {breadcrumbs.map((crumb, index) => (\n        <div className=\"flex items-center gap-2\" key={crumb.key}>\n          <a\n            href={crumb.href}\n            className=\"rounded-lg border bg-t3-purple-200/50 p-1 hover:bg-t3-purple-200/75 hover:no-underline dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\"\n          >\n            {crumb.text}\n          </a>\n          {index < breadcrumbs.length - 1 && (\n            <span className=\"flex-shrink-0\">\n              <BreadCrumbsArrow isRtl={isRtl} />\n            </span>\n          )}\n        </div>\n      ))}\n    </div>\n  );\n}\n\nfunction BreadCrumbsArrow(props: { isRtl: boolean }) {\n  return (\n    <svg\n      className={clsx(props.isRtl && \"rotate-180\")}\n      width=\"16\"\n      height=\"16\"\n      viewBox=\"0 0 24 24\"\n    >\n      <path\n        fill=\"currentColor\"\n        fillRule=\"evenodd\"\n        d=\"m9.005 4l8 8l-8 8L7 18l6.005-6L7 6z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "www/src/components/docs/callout.tsx",
    "content": "import clsx from \"clsx\";\n\nexport default function Callout({\n  type,\n  children,\n}: {\n  type: \"info\" | \"tip\" | \"warning\";\n  children: React.ReactNode;\n}) {\n  const getEmoji = () => {\n    switch (type) {\n      case \"warning\":\n        return \"⚠️\";\n      case \"info\":\n        return \"ℹ️\";\n      case \"tip\":\n        return \"💡\";\n    }\n  };\n\n  return (\n    <div\n      className={clsx(\n        \"my-4 flex w-full gap-3 rounded-md border p-3 text-justify\",\n        {\n          \"border-orange-400 bg-orange-400/50 dark:border-orange-600 dark:bg-orange-600/50\":\n            type === \"warning\",\n          \"border-blue-400 bg-blue-400/50 dark:border-blue-600 dark:bg-blue-600/50\":\n            type === \"info\",\n          \"border-yellow-400 bg-yellow-400/50 dark:border-yellow-600 dark:bg-yellow-600/50\":\n            type === \"tip\",\n        },\n      )}\n    >\n      <span>{getEmoji()}</span>\n      <span className=\"[&>p]:mb-0\">{children}</span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "www/src/components/docs/companyList.tsx",
    "content": "interface Company {\n  name: string;\n  link: string;\n  linkName: string;\n}\n\nconst companies: Company[] = [\n  {\n    name: \"Ping.gg\",\n    linkName: \"ping.gg\",\n    link: \"https://ping.gg\",\n  },\n  {\n    name: \"Social Crow\",\n    linkName: \"socialcrow.co\",\n    link: \"https://www.socialcrow.co\",\n  },\n  {\n    name: \"Nexiona\",\n    linkName: \"nexiona.com\",\n    link: \"https://nexiona.com\",\n  },\n  {\n    name: \"Layer3\",\n    linkName: \"layer3.xyz\",\n    link: \"https://layer3.xyz\",\n  },\n  {\n    name: \"EcoToken\",\n    linkName: \"ecotokens.net\",\n    link: \"https://ecotokens.net\",\n  },\n  {\n    name: \"Civitai\",\n    linkName: \"civitai.com\",\n    link: \"https://civitai.com\",\n  },\n  {\n    name: \"GreatFrontEnd\",\n    linkName: \"greatfrontend.com\",\n    link: \"https://www.greatfrontend.com\",\n  },\n  {\n    name: \"River\",\n    linkName: \"getriver.io\",\n    link: \"https://getriver.io\",\n  },\n  {\n    name: \"FlowGPT\",\n    linkName: \"flowgpt.com\",\n    link: \"https://flowgpt.com\",\n  },\n  {\n    name: \"Papertrail\",\n    linkName: \"Papertrail\",\n    link: \"https://papertrail.biblish.com\",\n  },\n  {\n    name: \"AIKeywording\",\n    linkName: \"aikeywording.com/\",\n    link: \"https://aikeywording.com/\",\n  },\n  {\n    name: \"HIX AI\",\n    linkName: \"HIX AI\",\n    link: \"https://hix.ai\",\n  },\n];\n\nexport default function CompanyList({\n  companyIntl = \"Description\",\n  linkIntl = \"Link\",\n}: {\n  companyIntl: string;\n  linkIntl: string;\n}) {\n  return (\n    <table>\n      <tr>\n        <th>{companyIntl}</th>\n        <th>{linkIntl}</th>\n      </tr>\n      {companies.map((company) => (\n        <tr>\n          <td>{company.name}</td>\n          <td>\n            <a href={company.link}>{company.linkName}</a>\n          </td>\n        </tr>\n      ))}\n    </table>\n  );\n}\n"
  },
  {
    "path": "www/src/components/docs/exampleOptionForm.astro",
    "content": "---\nconst options = {\n  nextAuth: \"NextAuth.js\",\n  prisma: \"Prisma\",\n  tailwind: \"Tailwind CSS\",\n  trpc: \"tRPC\",\n  drizzle: \"Drizzle\",\n};\n---\n\n<script>\n  import sdk from \"@stackblitz/sdk\";\n\n  function directToStackBlitz(checkedInputs: any) {\n    try {\n      sdk.openProject(\n        {\n          title: \"T3 Examples\",\n          description: \"T3 example apps.\",\n          template: \"node\",\n          files: {\n            \"package.json\": `{\n                    \"name\": \"T3 Examples\",\n                    \"version\": \"1.0.0\",\n                    \"description\": \"My Next.js app\",\n                    \"scripts\":{\n                        \"dev\": \" echo 'y' | npx create-t3-app example-app --CI ${checkedInputs} && cd ./example-app  && rm ../package.json \" }\n                }`,\n          },\n          settings: {\n            compile: {\n              trigger: \"auto\",\n              clearConsole: false,\n            },\n          },\n        },\n        {\n          newWindow: true,\n          openFile: [\"package.json\"],\n        },\n      );\n    } catch (error) {\n      console.error(\"Error\", error);\n    }\n  }\n\n  function handleFormSubmit(e: Event) {\n    e.preventDefault();\n\n    const inputs = Array.from(\n      (e.target as HTMLFormElement).querySelectorAll(\"input\"),\n    );\n    let checkedInputs = \"\";\n    inputs\n      .filter((input) => input.checked)\n      .map((input) => (checkedInputs += ` --${input.value}`));\n\n    directToStackBlitz(checkedInputs);\n  }\n\n  const form = document.getElementById(\"componentForm\") as HTMLFormElement;\n\n  const prismaInput = document.getElementById(\"prisma\") as HTMLInputElement;\n  const drizzleInput = document.getElementById(\"drizzle\") as HTMLInputElement;\n\n  function handleCheckboxChange(e: Event) {\n    if (e.target === prismaInput && drizzleInput.checked) {\n      drizzleInput.checked = false;\n    } else if (e.target === drizzleInput && prismaInput.checked) {\n      prismaInput.checked = false;\n    }\n  }\n\n  prismaInput.addEventListener(\"change\", handleCheckboxChange);\n  drizzleInput.addEventListener(\"change\", handleCheckboxChange);\n\n  form.addEventListener(\"submit\", handleFormSubmit);\n</script>\n\n<form\n  method=\"get\"\n  id=\"componentForm\"\n  class=\"mb-4 w-full rounded border border-t3-purple-300 p-4 text-lg\"\n>\n  {\n    Object.entries(options).map(([code, name]) => (\n      <div>\n        <input\n          id={code}\n          type=\"checkbox\"\n          name={name}\n          value={code}\n          class=\"h-4 w-4\"\n        />\n        <label for={code}>{name}</label>\n      </div>\n    ))\n  }\n  <button\n    class=\"text-md inline-flex cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-md border-2 bg-t3-purple-200/50 px-3 py-2 font-medium hover:bg-t3-purple-200/75 dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\"\n  >\n    View in StackBlitz\n  </button>\n</form>\n"
  },
  {
    "path": "www/src/components/docs/folderStructureDiagramApp.astro",
    "content": "<script>\n  import { asTree, type TreeObject } from \"treeify\";\n\n  const element = document.getElementById(\"fileStructure\");\n\n  // Get new selection from the form\n  //@ts-ignore\n  document.addEventListener(\n    \"fileStructureComponentsChange\",\n    (event: CustomEvent<{ selected: string[] }>) => {\n      renderDiagram(event.detail.selected);\n    },\n  );\n\n  const allFiles = {\n    \"prisma/schema.prisma\": [\"prisma\"], // This file is included with prisma\n    \"public/favicon.ico\": [], // This file is included in every configuration\n    \"src/app/_components/post.tsx\": [\"trpc\"],\n    \"src/app/api/auth/[...nextauth]/route.ts\": [\"nextauth\"],\n    \"src/app/api/trpc/[trpc]/route.ts\": [\"trpc\"],\n    \"src/app/layout.tsx\": [],\n    \"src/app/page.tsx\": [],\n    \"src/server/auth.ts\": [\"nextauth\"],\n    \"src/server/db.ts\": [\"prisma\"],\n    \"src/server/db/index.ts\": [\"drizzle\"],\n    \"src/server/db/schema.ts\": [\"drizzle\"],\n    \"src/server/api/routers/example.ts\": [\"trpc\"],\n    \"src/server/api/trpc.ts\": [\"trpc\"],\n    \"src/server/api/root.ts\": [\"trpc\"],\n    \"src/styles/globals.css\": [],\n    \"src/env.js\": [],\n    \"src/trpc/query-client.ts\": [\"trpc\"],\n    \"src/trpc/react.tsx\": [\"trpc\"],\n    \"src/trpc/server.ts\": [\"trpc\"],\n    \".env\": [],\n    \".env.example\": [],\n    \".eslintrc.cjs\": [],\n    \".gitignore\": [],\n    \"db.sqlite (after `db:push`, sqlite only)\": [\"drizzle\"],\n    \"drizzle.config.ts\": [\"drizzle\"],\n    \"next-env.d.ts\": [],\n    \"next.config.js\": [],\n    \"package.json\": [],\n    \"postcss.config.js\": [\"tailwind\"],\n    \"prettier.config.js\": [\"tailwind\"],\n    \"README.md\": [],\n    \"start-database.sh (mysql or postgres only)\": [\"drizzle\"],\n    \"tailwind.config.ts\": [\"tailwind\"],\n    \"tsconfig.json\": [],\n  };\n\n  const renderDiagram = (selected: string[]) => {\n    // Filter files based on selected components\n    const files = Object.entries(allFiles)\n      .map(([filename, components]) => {\n        if (components.length === 0) return filename;\n        return components.some((component) =>\n          component.split(\"+\").every((option) => selected.includes(option)),\n        )\n          ? filename\n          : null;\n      })\n      .filter((file) => file) as string[];\n\n    // Transform files to a tree object for the treeify library\n    const filesTree: TreeObject = {};\n    files.forEach((file) => {\n      const path = file.split(\"/\");\n      let folder = filesTree;\n      path.forEach((name) => {\n        if (!folder[name]) folder[name] = {};\n        folder = folder[name] as TreeObject;\n      });\n    });\n\n    if (element) element.textContent = `.\\n${asTree(filesTree, false, true)}`;\n  };\n\n  const getSelectedFromPackagesQueryParam = () => {\n    const selectedParam = new URLSearchParams(window.location.search).get(\n      \"packages\",\n    );\n\n    if (selectedParam === null) {\n      return [\"nextauth\", \"drizzle\", \"tailwind\", \"trpc\"];\n    }\n\n    return selectedParam.split(\",\");\n  };\n\n  renderDiagram(getSelectedFromPackagesQueryParam());\n</script>\n\n<pre\n  style=\"background-color: #191724; color: #e8ddff;\">\n  <code id=\"fileStructure\" />\n</pre>\n"
  },
  {
    "path": "www/src/components/docs/folderStructureDiagramPages.astro",
    "content": "<script>\n  import { asTree, type TreeObject } from \"treeify\";\n\n  const element = document.getElementById(\"fileStructure\");\n\n  // Get new selection from the form\n  //@ts-ignore\n  document.addEventListener(\n    \"fileStructureComponentsChange\",\n    (event: CustomEvent<{ selected: string[] }>) => {\n      renderDiagram(event.detail.selected);\n    },\n  );\n\n  const allFiles = {\n    \"prisma/schema.prisma\": [\"prisma\"], // This file is included with prisma\n    \"public/favicon.ico\": [], // This file is included in every configuration\n    \"src/env.js\": [],\n    \"src/pages/_app.tsx\": [],\n    \"src/pages/api/auth/[...nextauth].ts\": [\"nextauth\"],\n    \"src/pages/api/trpc/[trpc].ts\": [\"trpc\"],\n    \"src/pages/index.tsx\": [],\n    \"src/server/auth.ts\": [\"nextauth\"],\n    \"src/server/db.ts\": [\"prisma\"],\n    \"src/server/db/index.ts\": [\"drizzle\"],\n    \"src/server/db/schema.ts\": [\"drizzle\"],\n    \"src/server/api/routers/example.ts\": [\"trpc\"],\n    \"src/server/api/trpc.ts\": [\"trpc\"],\n    \"src/server/api/root.ts\": [\"trpc\"],\n    \"src/styles/globals.css\": [],\n    \"src/utils/api.ts\": [\"trpc\"],\n    \".env\": [],\n    \".env.example\": [],\n    \".eslintrc.cjs\": [],\n    \".gitignore\": [],\n    \"db.sqlite (after `db:push`, sqlite only)\": [\"drizzle\"],\n    \"drizzle.config.ts\": [\"drizzle\"],\n    \"next-env.d.ts\": [],\n    \"next.config.js\": [],\n    \"package.json\": [],\n    \"postcss.config.js\": [\"tailwind\"],\n    \"prettier.config.js\": [\"tailwind\"],\n    \"README.md\": [],\n    \"start-database.sh (mysql or postgres only)\": [\"drizzle\"],\n    \"tailwind.config.ts\": [\"tailwind\"],\n    \"tsconfig.json\": [],\n  };\n\n  const renderDiagram = (selected: string[]) => {\n    // Filter files based on selected components\n    const files = Object.entries(allFiles)\n      .map(([filename, components]) => {\n        if (components.length === 0) return filename;\n        return components.some((component) =>\n          component.split(\"+\").every((option) => selected.includes(option)),\n        )\n          ? filename\n          : null;\n      })\n      .filter((file) => file) as string[];\n\n    // Transform files to a tree object for the treeify library\n    const filesTree: TreeObject = {};\n    files.forEach((file) => {\n      const path = file.split(\"/\");\n      let folder = filesTree;\n      path.forEach((name) => {\n        if (!folder[name]) folder[name] = {};\n        folder = folder[name] as TreeObject;\n      });\n    });\n\n    if (element) element.textContent = `.\\n${asTree(filesTree, false, true)}`;\n  };\n\n  const getSelectedFromPackagesQueryParam = () => {\n    const selectedParam = new URLSearchParams(window.location.search).get(\n      \"packages\",\n    );\n\n    if (selectedParam === null) {\n      return [\"nextauth\", \"drizzle\", \"tailwind\", \"trpc\"];\n    }\n\n    return selectedParam.split(\",\");\n  };\n\n  renderDiagram(getSelectedFromPackagesQueryParam());\n</script>\n\n<pre\n  style=\"background-color: #191724; color: #e8ddff;\">\n  <code id=\"fileStructure\" />\n</pre>\n"
  },
  {
    "path": "www/src/components/docs/folderStructureForm.astro",
    "content": "---\nconst options = {\n  nextauth: \"NextAuth.js\",\n  prisma: \"Prisma\",\n  drizzle: \"Drizzle\",\n  tailwind: \"Tailwind CSS\",\n  trpc: \"tRPC\",\n};\n---\n\n<script>\n  const inputs = document\n    .getElementById(\"componentForm\")\n    ?.querySelectorAll(\"input\") as NodeListOf<HTMLInputElement>;\n\n  const updatePackagesQueryParam = (selected: string[]) => {\n    const packagesQueryParam = selected.join(\",\");\n\n    const url = new URL(window.location.href);\n    url.searchParams.set(\"packages\", packagesQueryParam);\n    window.history.pushState({}, \"\", url);\n  };\n\n  const getSelectedFromPackagesQueryParam = () => {\n    const selectedParam = new URLSearchParams(window.location.search).get(\n      \"packages\",\n    );\n\n    if (selectedParam === null) {\n      return [\"nextauth\", \"drizzle\", \"tailwind\", \"trpc\"];\n    }\n\n    return selectedParam.split(\",\");\n  };\n\n  inputs.forEach((input) =>\n    input.addEventListener(\"change\", (aaa) => {\n      console.log({ inputs, aaa, input });\n      const initialSelected = Array.from(inputs).flatMap(\n        ({ value, checked }) => {\n          return checked ? [value] : [];\n        },\n      );\n\n      if (\n        input.value === \"drizzle\" &&\n        initialSelected.includes(\"drizzle\") &&\n        initialSelected.includes(\"prisma\")\n      ) {\n        document.getElementById(\"prisma\")?.click();\n      } else if (\n        input.value === \"prisma\" &&\n        initialSelected.includes(\"prisma\") &&\n        initialSelected.includes(\"drizzle\")\n      ) {\n        document.getElementById(\"drizzle\")?.click();\n      }\n\n      const selected = Array.from(inputs).flatMap(({ value, checked }) => {\n        return checked ? [value] : [];\n      });\n\n      updatePackagesQueryParam(selected);\n\n      // Rerender the diagram\n      document.dispatchEvent(\n        new CustomEvent(\"fileStructureComponentsChange\", {\n          detail: { selected },\n        }),\n      );\n\n      hideUnselectedDocs(selected);\n    }),\n  );\n\n  const hideUnselectedDocs = (selected: string[]) => {\n    document\n      .querySelectorAll<HTMLElement>(\"*[data-components]\")\n      .forEach((el) => {\n        el.style.display = !el.dataset.components\n          ?.split(\" \")\n          .some((components) =>\n            components.split(\"+\").every((option) => selected.includes(option)),\n          )\n          ? \"none\"\n          : \"\";\n      });\n  };\n\n  // Set initial state based on query param\n  const initialSelected = getSelectedFromPackagesQueryParam();\n\n  inputs.forEach((input) => {\n    input.checked = initialSelected.includes(input.value);\n  });\n\n  hideUnselectedDocs(initialSelected);\n</script>\n\n<form\n  method=\"get\"\n  id=\"componentForm\"\n  class=\"mb-4 w-full rounded border border-t3-purple-300 p-4 text-lg\"\n>\n  {\n    Object.entries(options).map(([code, name]) => (\n      <div>\n        <input\n          id={code}\n          type=\"checkbox\"\n          name=\"conf\"\n          checked={code !== \"prisma\"}\n          value={code}\n          class=\"h-4 w-4\"\n        />\n        <label for={code}>{name}</label>\n      </div>\n    ))\n  }\n</form>\n"
  },
  {
    "path": "www/src/components/docs/indexPage.astro",
    "content": "---\nimport { type Frontmatter } from \"../../config\";\n\nexport interface Props {\n  sidebarEntries: { text: string; link: string }[];\n  frontmatter: Frontmatter;\n  files: Record<string, any>[];\n}\nconst { sidebarEntries, frontmatter, files } = Astro.props;\n---\n\n<p>{frontmatter.description}</p>\n<div class=\"grid w-full grid-cols-1 gap-4 p-0 md:grid-cols-2\">\n  {\n    sidebarEntries.map(({ text, link }, index) => {\n      const frontmatter = files.find((file) => file.url === `/${link}`)\n        ?.frontmatter as Frontmatter;\n\n      return (\n        <a\n          href={`/${link}`}\n          class=\"m-0 w-full cursor-pointer rounded-lg border border-t3-purple-500/20 p-4 duration-300 hover:border-t3-purple-500/50 hover:shadow-lg dark:border-t3-purple-200/20 dark:hover:border-t3-purple-200/50\"\n          style={{ \"list-style-type\": \"none\", \"text-decoration\": \"none\" }}\n        >\n          <h2\n            class=\"leading-none\"\n            style={{ \"margin-top\": \"0\", \"margin-bottom\": \"1.5rem\" }}\n          >\n            <span class=\"text-base\">#{index + 1}</span> {text}\n          </h2>\n          {frontmatter?.description && (\n            <p class=\"text-sm text-gray-600 dark:text-gray-400\">\n              {frontmatter.description}\n            </p>\n          )}\n        </a>\n      );\n    })\n  }\n</div>\n"
  },
  {
    "path": "www/src/components/docs/introductionTab.tsx",
    "content": "import { useState } from \"react\";\n\nexport function IntroductionTab() {\n  const [isAppRouterSelected, setIsAppRouterSelected] = useState(true);\n  return (\n    <>\n      <div className=\"flex w-full justify-center gap-10 py-5\">\n        <button\n          className={`${isAppRouterSelected ? \"bg-primary text-white\" : \"bg-transparent\"} inline-flex cursor-pointer items-center rounded-lg px-4 py-2 text-sm font-semibold transition-colors duration-500 hover:no-underline md:px-5 md:text-base lg:px-4 lg:py-3`}\n          onClick={() => setIsAppRouterSelected(true)}\n        >\n          App Router\n        </button>\n        <button\n          className={`${!isAppRouterSelected ? \"bg-primary text-white\" : \"bg-transparent\"} inline-flex cursor-pointer items-center rounded-lg px-4 py-2 text-sm font-semibold transition-colors duration-500 hover:no-underline md:px-5 md:text-base lg:px-4 lg:py-3`}\n          onClick={() => setIsAppRouterSelected(false)}\n        >\n          {\" \"}\n          Pages Router\n        </button>\n      </div>\n      <div className=\"embed\">\n        <iframe\n          width=\"560\"\n          height=\"315\"\n          src={\n            isAppRouterSelected\n              ? \"https://www.youtube.com/embed/d5x0JCZbAJs\"\n              : \"https://www.youtube.com/embed/YkOSUVzOAA4\"\n          }\n          title=\"The best stack for your next project\"\n          allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n        ></iframe>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "www/src/components/docs/openSourceAppList.tsx",
    "content": "interface App {\n  description: string;\n  repoName: string;\n  repo: string;\n  linkName: string;\n  linkExtra?: string;\n  link: string;\n}\n\nconst projects: App[] = [\n  {\n    description: \"OpenBio - Open Source Link in Bio\",\n    repoName: \"vanxh/openbio\",\n    repo: \"https://github.com/vanxh/openbio\",\n    linkName: \"openbio.app\",\n    link: \"https://openbio.app\",\n  },\n  {\n    description: \"Exaya - Organic transportation processes manager\",\n    repoName: \"exaya\",\n    repo: \"https://github.com/kralion/exaya\",\n    linkName: \"exaya.app\",\n    link: \"https://exaya.vercel.app\",\n  },\n  {\n    description: \"TheNinja-RPG - A free browser-based ninja game\",\n    repoName: \"TheNinjaRPG\",\n    repo: \"https://github.com/MathiasGruber/TheNinjaRPG\",\n    linkName: \"theninja-rpg.com\",\n    link: \"https://www.theninja-rpg.com\",\n  },\n  {\n    description: \"Create T3 Turbo - T3 Stack using Turborepo\",\n    repoName: \"create-t3-turbo\",\n    repo: \"https://github.com/t3-oss/create-t3-turbo\",\n    linkName: \"create-t3-turbo.vercel.app\",\n    link: \"https://create-t3-turbo.vercel.app/\",\n  },\n  {\n    description:\n      \"T3 turborepo template with biomejs and both shadcn native and web ui\",\n    repoName: \"rajatsandeepsen/t3-turbo-biome\",\n    repo: \"https://github.com/rajatsandeepsen/t3-turbo-biome\",\n    linkName: \"create-t3-turbo.vercel.app\",\n    link: \"https://create-t3-turbo.vercel.app/\",\n  },\n  {\n    description: \"Zapdos - a QnA app for streamers\",\n    repoName: \"pingdotgg/zapdos\",\n    repo: \"https://github.com/pingdotgg/zapdos\",\n    linkName: \"ask.ping.gg\",\n    link: \"https://ask.ping.gg\",\n  },\n\n  {\n    description:\n      \"Shoutify - Free, open-source, self-hosted social media management\",\n    repoName: \"techsquidtv/shoutify\",\n    repo: \"https://github.com/TechSquidTV/Shoutify\",\n    linkName: \"shoutify.app\",\n    link: \"https://github.com/TechSquidTV/Shoutify\",\n    linkExtra: \"(coming soon)\",\n  },\n\n  {\n    description:\n      \"Me3 - Describe yourself in 3 things and share with your friends.\",\n    repoName: \"henriqgoncalvs/me3\",\n    repo: \"https://github.com/henriqgoncalvs/me3\",\n    linkName: \"me3-henriiqueg.vercel.app\",\n    link: \"https://me3-henriiqueg.vercel.app/\",\n  },\n\n  {\n    description: \"Josh's personal site\",\n    repoName: \"GentikSolm/imjosh-blog\",\n    repo: \"https://github.com/GentikSolm/imjosh-blog\",\n    linkName: \"imjosh.dev\",\n    link: \"https://imjosh.dev\",\n  },\n\n  {\n    description: \"Cal.com - Scheduling infrastructure for absolutely everyone.\",\n    repoName: \"calcom/cal.com\",\n    repo: \"https://github.com/calcom/cal.com\",\n    linkName: \"cal.com\",\n    link: \"https://cal.com\",\n  },\n\n  {\n    description: \"My FAQ Page - An FAQ Page generator\",\n    repoName: \"ronanru/myfaq.page\",\n    repo: \"https://github.com/ronanru/myfaq.page\",\n    linkName: \"MyFAQ.page\",\n    link: \"https://myfaq.page\",\n  },\n\n  {\n    description: \"Tincy Pics - A tincy wincy image host\",\n    repoName: \"mozzius/tincypics\",\n    repo: \"https://github.com/mozzius/tincypics\",\n    linkName: \"tincy.pics\",\n    link: \"https://tincy.pics\",\n  },\n\n  {\n    description: \"Ayanava's Guestbook\",\n    repoName: \"AyanavaKarmakar/Guestbook\",\n    repo: \"https://github.com/AyanavaKarmakar/Guestbook\",\n    linkName: \"guestbook.ayanavakarmakar.software\",\n    link: \"https://guestbook.ayanavakarmakar.software/\",\n  },\n\n  {\n    description: \"Slug - URL Shortener\",\n    repoName: \"pheralb/slug\",\n    repo: \"https://github.com/pheralb/slug\",\n    linkName: \"slug.vercel.app\",\n    link: \"https://slug.vercel.app\",\n  },\n\n  {\n    description:\n      \"AI TTS Donations - FOSS AI Text To Speech service for Streamers.\",\n    repoName: \"mmattDonk/AI-TTS-Donations\",\n    repo: \"https://github.com/mmattDonk/AI-TTS-Donations\",\n    linkName: \"staging.solrock.mmattDonk.com\",\n    link: \"https://staging.solrock.mmattDonk.com\",\n  },\n\n  {\n    description: \"The Doom\",\n    repoName: \"moltivie/slug\",\n    repo: \"https://github.com/Moltivie/the-t3-stack\",\n    linkName: \"the-t3-stack.vercel.app\",\n    link: \"https://the-t3-stack.vercel.app\",\n  },\n\n  {\n    description: \"Railtrack\",\n    repoName: \"noahflk/railtrack\",\n    repo: \"https://github.com/noahflk/railtrack\",\n    linkName: \"railtrack.ch\",\n    link: \"https://railtrack.ch\",\n  },\n\n  {\n    description: \"KARA Shop - Ecommerce website\",\n    repoName: \"mehrabmp/kara-shop\",\n    repo: \"https://github.com/mehrabmp/kara-shop\",\n    linkName: \"karashop.vercel.app\",\n    link: \"https://karashop.vercel.app/\",\n  },\n\n  {\n    description: \"Tauri T3 App - Tauri App using T3 Stack\",\n    repoName: \"tauri-t3-app\",\n    repo: \"https://github.com/AyanavaKarmakar/tauri-t3-app\",\n    linkName: \"tauri-t3-app.docs\",\n    link: \"https://github.com/AyanavaKarmakar/tauri-t3-app#readme\",\n  },\n\n  {\n    description: \"Azon - E-Commerce website\",\n    repoName: \"andrewsolonets/Azon-Shop\",\n    repo: \"https://github.com/andrewsolonets/Azon-Shop\",\n    linkName: \"azon-shop.vercel.app\",\n    link: \"https://azon-shop.vercel.app/\",\n  },\n\n  {\n    description: \"Analyzemyrepo.com - Useful insights for any GitHub repo\",\n    repoName: \"CrowdDotDev/analyzemyrepo\",\n    repo: \"https://github.com/CrowdDotDev/analyzemyrepo\",\n    linkName: \"analyzemyrepo.com\",\n    link: \"https://analyzemyrepo.com\",\n  },\n\n  {\n    description:\n      \"Answer Overflow - Discord bot to index help channels into Google\",\n    repoName: \"AnswerOverflow/AnswerOverflow\",\n    repo: \"https://github.com/AnswerOverflow/AnswerOverflow\",\n    linkName: \"answeroverflow.com\",\n    link: \"https://www.answeroverflow.com/\",\n  },\n\n  {\n    description: \"CUA - Create an Universal App for web, native and desktop\",\n    repoName: \"chen-rn/CUA\",\n    repo: \"https://github.com/chen-rn/CUA\",\n    linkName: \"cua-demo.vercel.app\",\n    link: \"https://cua-demo.vercel.app/\",\n  },\n\n  {\n    description: \"Menufic - Digital menu generator for restaurants\",\n    repoName: \"kaje94/menufic\",\n    repo: \"https://github.com/kaje94/menufic\",\n    linkName: \"menufic.com\",\n    link: \"https://menufic.com\",\n  },\n\n  {\n    description: \"Twitter clone - A simple Twitter clone\",\n    repoName: \"AlandSleman/t3-twitter-clone\",\n    repo: \"https://github.com/AlandSleman/t3-twitter-clone\",\n    linkName: \"twitter-clone.kurdmake.com\",\n    link: \"https://twitter-clone.kurdmake.com\",\n  },\n\n  {\n    description:\n      \"Prisma Editor - A powerful tool to visualize and edit Prisma Schema\",\n    repoName: \"mohammed-bahumaish/prisma-editor\",\n    repo: \"https://github.com/mohammed-bahumaish/prisma-editor\",\n    linkName: \"prisma-editor.bahumaish.com\",\n    link: \"https://prisma-editor.bahumaish.com\",\n  },\n\n  {\n    description: \"Judge devs - website, where developers share their projects\",\n    repoName: \"judge-devs (gh)\",\n    repo: \"https://github.com/serzhan181/judge-devs\",\n    linkName: \"judge-devs.com\",\n    link: \"https://judge-devs.vercel.app/\",\n  },\n\n  {\n    description: \"T3 Blog - A Reddit inspired forum website\",\n    repoName: \"leojuriolli7/t3-blog\",\n    repo: \"https://github.com/leojuriolli7/t3-blog\",\n    linkName: \"t3-blog-pi.vercel.app\",\n    link: \"https://t3-blog-pi.vercel.app\",\n  },\n\n  {\n    description: \"Checkinout - A checklist management project using T3 Stack\",\n    repoName: \"burak-sevinc/t3-checkinout\",\n    repo: \"https://github.com/burak-sevinc/t3-checkinout\",\n    linkName: \"checkinout.vercel.app\",\n    link: \"https://checkinout.vercel.app/\",\n  },\n\n  {\n    description: \"Sozluk Clone - A simple clone of Ekşi Sözlük\",\n    repoName: \"doandroidsdreamof/sozluk-clone\",\n    repo: \"https://github.com/doandroidsdreamof/sozluk-clone\",\n    linkName: \"sozluk-clone.vercel.app\",\n    link: \"https://sozluk-clone.vercel.app\",\n  },\n\n  {\n    description: \"Henrique's personal site\",\n    repoName: \"henriqgoncalvs/website\",\n    repo: \"https://github.com/henriqgoncalvs/website\",\n    linkName: \"henriqgoncalvs.com\",\n    link: \"https://henriqgoncalvs.com\",\n  },\n\n  {\n    description: \"Code Notes - Takes your notes without any b*llshit\",\n    repoName: \"JungRama/code-notes\",\n    repo: \"https://github.com/JungRama/code-notes\",\n    linkName: \"code-notes-app.vercel.app\",\n    link: \"https://code-notes-app.vercel.app\",\n  },\n  {\n    description:\n      \"Rao.Pics - :electron: 帮助你远程访问 Eagle、Pixcall、Billfish 的素材资源。\",\n    repoName: \"meetqy/rao-pics\",\n    repo: \"https://github.com/meetqy/rao-pics\",\n    linkName: \"rao.pics\",\n    link: \"https://rao.pics\",\n  },\n  {\n    description: \"eBoto - One-Stop Online Voting Solution\",\n    repoName: \"bricesuazo/eboto\",\n    repo: \"https://github.com/bricesuazo/eboto\",\n    linkName: \"eboto-mo.com\",\n    link: \"https://eboto-mo.com/\",\n  },\n  {\n    description:\n      \"ImprovDB - The ultimate repository for improv games & exercises\",\n    repoName: \"aberonni/improvdb\",\n    repo: \"https://github.com/aberonni/improvdb\",\n    linkName: \"improvdb.com\",\n    link: \"https://improvdb.com/\",\n  },\n  {\n    description: \"Simple Todo app - with custom auth\",\n    repoName: \"Parthvsquare/t3-todo-mvc\",\n    repo: \"https://github.com/Parthvsquare/t3-todo-mvc\",\n    linkName: \"\",\n    link: \"\",\n  },\n  {\n    description: \"Profilee - A Profile Link Builder\",\n    repoName: \"mittalsam98/profilee\",\n    repo: \"https://github.com/mittalsam98/profilee\",\n    linkName: \"Profilee\",\n    link: \"https://www.profilee.info/\",\n  },\n  {\n    description: \"SunalRahal - Your Spotify, in a SVG\",\n    repoName: \"prabincankod/sunal-rahal\",\n    repo: \"https://github.com/prabincankod/sunal-rahal\",\n    linkName: \"SunalRhal\",\n    link: \"https://sunal-rahal.vercel.app\",\n  },\n  {\n    description: \"RobertHavelaar.dev - A Modern Portfolio and Tool Showcase\",\n    repoName: \"EastTexasElectronics/portfolio\",\n    repo: \"https://github.com/EastTexasElectronics/portfolio\",\n    linkName: \"RobertHavelaar.dev\",\n    link: \"https://www.roberthavelaar.dev/\",\n  },\n  {\n    description: \"Tasky - Simplify task management\",\n    repoName: \"ismaelherreradev/tasky\",\n    repo: \"https://github.com/ismaelherreradev/tasky\",\n    linkName: \"taskyboard\",\n    link: \"https://taskyboard.vercel.app\",\n  },\n  {\n    description: \"Squeak - A multiplayer Solitaire-based game\",\n    repoName: \"michaelongaro/Squeak\",\n    repo: \"https://github.com/michaelongaro/Squeak\",\n    linkName: \"Squeak\",\n    link: \"https://playsqueak.com/\",\n  },\n  {\n    description: \"Ray - A full stack admin starter\",\n    repoName: \"koujialong/ray-admin\",\n    repo: \"https://github.com/koujialong/ray-admin\",\n    linkName: \"Ray\",\n    link: \"https://koujialong-ray.vercel.app/\",\n  },\n  {\n    description: \"Aiseka - Discover the best Color Palette & Color Tools\",\n    repoName: \"meetqy/aiseka\",\n    repo: \"https://github.com/meetqy/aiseka\",\n    linkName: \"AISEKA\",\n    link: \"https://aiseka.com/\",\n  },\n];\n\nexport default function OpenSourceAppList({\n  descriptionIntl = \"Description\",\n  repoIntl = \"Repo\",\n  linkIntl = \"Link\",\n}: {\n  descriptionIntl: string;\n  repoIntl: string;\n  linkIntl: string;\n}) {\n  return (\n    <table>\n      <tr>\n        <th>{descriptionIntl}</th>\n        <th>{repoIntl}</th>\n        <th>{linkIntl}</th>\n      </tr>\n      {projects.map((project) => (\n        <tr>\n          <td>{project.description}</td>\n          <td>\n            <a href={project.repo}>{project.repoName}</a>\n          </td>\n          <td>\n            <a href={project.link}>{project.linkName}</a>\n            {project.linkExtra && <span> {project.linkExtra}</span>}\n          </td>\n        </tr>\n      ))}\n    </table>\n  );\n}\n"
  },
  {
    "path": "www/src/components/docs/outdatedDocsBanner.astro",
    "content": "---\nimport { fetchGithub } from \"../../utils/fetchGithub\";\n\nexport interface Props {\n  path: string;\n}\nconst { path } = Astro.props;\n\nconst [_1, _2, _3, ...rest] = path.split(\"/\");\n\nconst englishPath = `src/pages/en/${rest.join(\"/\")}`;\nconst engHref = `/en/${rest.join(\"/\").replace(/\\.[^/.]+$/, \"\")}`;\n\nconst url = `https://api.github.com/repos/t3-oss/create-t3-app/commits?path=www/${path}&per_page=1`;\nconst engUrl = `https://api.github.com/repos/t3-oss/create-t3-app/commits?path=www/${englishPath}&per_page=1`;\n\n// File may not be on Github yet, so we only throw an error if we're in production\nasync function getCommitDiff() {\n  try {\n    const thisLangCommit = await fetchGithub(url, { fetchType: \"commits\" });\n    const englishCommit = await fetchGithub(engUrl, { fetchType: \"commits\" });\n\n    const thisLangDate = thisLangCommit?.length\n      ? new Date(thisLangCommit[0]?.commit.author.date ?? \"\")\n      : new Date();\n    const englishDate = englishCommit?.length\n      ? new Date(englishCommit[0]?.commit.author.date ?? \"\")\n      : new Date();\n\n    const diffInDays = Math.round(\n      (englishDate.getTime() - thisLangDate.getTime()) / (1000 * 3600 * 24),\n    );\n    return diffInDays;\n  } catch (e) {\n    console.warn(`[warn]  /src/components/outDatedDocsBanner.astro \n    ${(e as Error)?.message ?? e}\n    If you're in production, this is a problem. If you're in dev, it's probably fine.\n    If this warning appears on a translated file that's not yet on origin, it's fine.`);\n\n    return 0;\n  }\n}\n\nconst diffInDays = await getCommitDiff();\n\nconst ONE_WEEK = 1000 * 60 * 60 * 24 * 7;\nAstro.response.headers.set(\"Cache-Control\", `s-max-age=${ONE_WEEK}`);\n---\n\n{\n  diffInDays > 0 && (\n    <div\n      dir=\"ltr\"\n      class=\"mx-4 mb-6 rounded-lg bg-t3-purple-200/50 p-4 font-medium lg:mx-0 lg:ml-4 dark:bg-t3-purple-200/10\"\n    >\n      <p>\n        Attention: This page is{\" \"}\n        <span class=\"font-extrabold\">\n          {diffInDays} {diffInDays === 1 ? \"day\" : \"days\"}\n        </span>\n        older than the English version and might be outdated. If you're a native\n        speaker of this language and would like to contribute to the project,\n        please consider updating this page to match the latest English version.\n      </p>\n      <p class=\"mt-3\">\n        You can also\n        <a class=\"inline-block text-t3-purple-400\" href={engHref}>\n          view the English version\n        </a>\n        of this page.\n      </p>\n    </div>\n  )\n}\n"
  },
  {
    "path": "www/src/components/docs/pageContent.astro",
    "content": "---\nimport { type MarkdownHeading } from \"astro\";\n\nimport { type Frontmatter, type KnownLanguageCode } from \"../../config\";\nimport { getIsRtlFromLangCode } from \"../../languages\";\nimport OnThisPageLinks from \"../navigation/OnThisPageLinks\";\nimport BreadCrumbs from \"./breadCrumbs\";\nimport OutdatedDocsBanner from \"./outdatedDocsBanner.astro\";\nimport Pagination from \"./pagination.astro\";\n\nexport interface Props {\n  frontmatter: Frontmatter;\n  path: string;\n  headings: MarkdownHeading[];\n}\n\nconst { frontmatter, path, headings } = Astro.props;\nconst title = frontmatter.title;\n\nconst [_1, _2, lang] = path.split(\"/\");\nconst isRtl = getIsRtlFromLangCode((lang || \"en\") as KnownLanguageCode);\n---\n\n<article id=\"article\" class=\"flex w-full max-w-screen-lg flex-col\">\n  {lang && lang !== \"en\" && <OutdatedDocsBanner path={path} />}\n  <div class=\"mb-4 h-8\">\n    <BreadCrumbs client:only />\n  </div>\n  <OnThisPageLinks\n    client:media=\"(max-width: 1024px)\"\n    headings={headings}\n    title={title}\n    isRtl={isRtl}\n  />\n  <section class=\"w-full\">\n    <h1\n      id=\"overview\"\n      class=\"mb-4 px-4 text-3xl font-extrabold dark:text-t3-purple-100\"\n    >\n      <a\n        href=\"#overview\"\n        class=\"heading-link heading-link--hidden---effects\"\n        data-heading-link\n      >\n        {title}\n      </a>\n    </h1>\n    <article class=\"markdown w-full\">\n      <slot />\n    </article>\n  </section>\n</article>\n<Pagination />\n<script>\n  const copySVG = `<svg width=\"1.3em\" height=\"1.3em\" viewBox=\"0 0 256 256\"><path fill=\"currentColor\" d=\"M216 36H88a4 4 0 0 0-4 4v44H40a4 4 0 0 0-4 4v128a4 4 0 0 0 4 4h128a4 4 0 0 0 4-4v-44h44a4 4 0 0 0 4-4V40a4 4 0 0 0-4-4Zm-52 176H44V92h120Zm48-48h-40V88a4 4 0 0 0-4-4H92V44h120Z\"/></svg>`;\n\n  let titles = document.querySelectorAll(\n    \".remark-code-title\",\n  ) as NodeListOf<HTMLDivElement>;\n  titles.forEach((title) => {\n    title.dir = \"ltr\";\n  });\n\n  let blocks = document.querySelectorAll(\"pre\");\n  blocks.forEach((block) => {\n    block.className = \"relative flex w-full h-full\";\n    block.dir = \"ltr\";\n\n    let copyButton = document.createElement(\"button\");\n    copyButton.className =\n      \"inline-flex absolute right-[.45em] top-[.5em] bg-zinc-100/20 rounded px-1 py-1 text-sm text-zinc-50 hover:bg-zinc-100/25 focus:outline-none focus:shadow-outline text-brand-primary\";\n    copyButton.innerHTML = copySVG;\n    copyButton.addEventListener(\"click\", () => {\n      let text = \"\";\n      const pre = copyButton.parentElement;\n      let code = pre?.querySelector(\"code\");\n      if (code) {\n        text = code.innerText;\n      } else {\n        const span = pre?.querySelector(\"span\");\n        if (span) {\n          text = span.innerText;\n        }\n      }\n      if (text) {\n        try {\n          navigator.clipboard.writeText(text);\n        } catch (err) {\n          console.error(\"Failed to copy: \", err);\n        }\n        copyButton.innerHTML = `<svg width=\"1.3em\" height=\"1.3em\" viewBox=\"0 0 256 256\"><path fill=\"#22c55e\" d=\"M104 192a8.5 8.5 0 0 1-5.7-2.3l-56-56a8.1 8.1 0 0 1 11.4-11.4l50.3 50.4L210.3 66.3a8.1 8.1 0 0 1 11.4 11.4l-112 112a8.5 8.5 0 0 1-5.7 2.3Z\"/></svg>`;\n\n        setTimeout(() => {\n          copyButton.innerHTML = copySVG;\n        }, 1000);\n      }\n    });\n\n    block.appendChild(copyButton);\n    block.setAttribute(\"tabindex\", \"0\");\n  });\n</script>\n<script is:inline>\n  //FIXME: We can make this properly typed later\n  /**\n   * Allows us to animate the details element\n   * for it to work make sure the details element contains a summary element\n   * and a div element with the class of content\n   * @param {*} element the details element which we wish to animate\n   */\n  const AnimateDetails = (element) => {\n    const summary = element.querySelector(\"summary\");\n    const content = element.querySelector(\".content\");\n    let props = { animation: null, isClosing: false, isExpanding: false };\n\n    /**\n     * onClick event handler for the summary element\n     * @param {*} event the event object\n     */\n    const onClick = (event) => {\n      event.preventDefault();\n\n      element.style.overflow = \"hidden\";\n\n      if (props.isClosing || !element.open) open();\n      else if (props.isExpanded || element.open) close();\n    };\n\n    /**\n     * Closes the details element\n     * This function is in charge of animating the closing of the\n     * details element\n     */\n    const close = () => {\n      props.isClosing = true;\n\n      const startHeight = `${element.offsetHeight}px`;\n      const endHeight = `${summary.offsetHeight}px`;\n\n      if (props.animation) props.animation.cancel();\n\n      props.animation = element.animate(\n        {\n          height: [startHeight, endHeight],\n        },\n        {\n          duration: 300,\n          easing: \"ease-in-out\",\n        },\n      );\n\n      props.animation.onfinish = () => onAnimationFinish(false);\n      props.animation.oncancel = () => (props.isClosing = false);\n    };\n\n    /**\n     * Opens the details element\n     * requests the animation frame to animate the opening of the details element\n     */\n    const open = () => {\n      element.style.height = `${summary.offsetHeight}px`;\n      element.open = true;\n      window.requestAnimationFrame(() => expand());\n    };\n\n    /**\n     * Expands the details element\n     * This function is in charge of animating the expansion of the\n     * details element\n     */\n    const expand = () => {\n      props.isExpanding = true;\n\n      const startHeight = `${element.offsetHeight}px`;\n      const endHeight = `${content.offsetHeight + summary.offsetHeight}px`;\n\n      if (props.animation) props.animation.cancel();\n\n      props.animation = element.animate(\n        {\n          height: [startHeight, endHeight],\n        },\n        {\n          duration: 300,\n          easing: \"ease-in-out\",\n        },\n      );\n\n      props.animation.onfinish = () => onAnimationFinish(true);\n      props.animation.oncancel = () => (props.isExpanding = false);\n    };\n\n    /**\n     * Called when the animation is finished\n     * @param {*} open whether the details element is open or not\n     */\n    const onAnimationFinish = (open) => {\n      element.open = open;\n      props.animation = null;\n      props.isClosing = false;\n      props.isExpanding = false;\n\n      element.style.height = element.style.overflow = \"\";\n    };\n\n    /**\n     * Adds our new event listener to the summary element\n     */\n    summary.addEventListener(\"click\", (event) => onClick(event));\n  };\n\n  /**\n   * Allows us to animate all the details elements on the page\n   * Will check if the details element contains a div element with the class of content\n   */\n  const viableDetails = document.querySelectorAll(\"details\");\n  viableDetails.forEach((element) => {\n    if (element.querySelector(\".content\")) {\n      AnimateDetails(element);\n    }\n  });\n</script>\n<script>\n  const main = () => {\n    const codeElements = Array.from(document.querySelectorAll(\"code\")).filter(\n      (codeElement) => codeElement.parentNode?.nodeName !== \"PRE\",\n    );\n\n    codeElements.forEach((codeElement) => {\n      const codeWrapper = document.createElement(\"div\");\n      codeWrapper.classList.add(\"code-wrapper\");\n      codeElement.parentNode?.insertBefore(codeWrapper, codeElement);\n\n      codeWrapper.appendChild(codeElement);\n    });\n  };\n  main();\n</script>\n"
  },
  {
    "path": "www/src/components/docs/pagination.astro",
    "content": "---\nimport { type SidebarItemLink } from \"../../config\";\nimport { getIsRtlFromUrl, getLanguageFromURL } from \"../../languages\";\nimport { paginate } from \"../../utils/pagination\";\nimport LeftArrow from \"../icons/leftArrow.astro\";\nimport RightArrow from \"../icons/rightArrow.astro\";\n\nconst currentPage = Astro.url.pathname;\nconst hasTrailing = currentPage.endsWith(\"/\");\nconst currentPageMatch = currentPage.slice(\n  1,\n  hasTrailing ? -1 : currentPage.length,\n) as SidebarItemLink;\n\nconst langCode = getLanguageFromURL(currentPage);\nconst { next, prev } = paginate(langCode, currentPageMatch);\n\nconst { pathname } = Astro.url;\nconst isRtl = getIsRtlFromUrl(pathname);\n---\n\n<div\n  class=\"mb-8 mt-16 flex flex-row items-center justify-between px-4 pt-4 font-medium text-t3-purple-800 lg:px-8 dark:text-t3-purple-200\"\n>\n  <div>\n    {\n      prev ? (\n        <a\n          class=\"flex items-center underline-offset-2 hover:text-t3-purple-400 hover:underline dark:hover:text-t3-purple-100\"\n          rel=\"prev\"\n          href={Astro.site?.pathname + prev.link}\n        >\n          <>\n            {isRtl ? <RightArrow /> : <LeftArrow />}\n            {prev.text}\n          </>\n        </a>\n      ) : null\n    }\n  </div>\n  <div>\n    {\n      next ? (\n        <a\n          rel=\"next\"\n          class=\"flex items-center underline-offset-2 hover:text-t3-purple-400 hover:underline dark:hover:text-t3-purple-100\"\n          href={Astro.site?.pathname + next.link}\n        >\n          <>\n            {next.text}\n            {isRtl ? <LeftArrow /> : <RightArrow />}\n          </>\n        </a>\n      ) : null\n    }\n  </div>\n</div>\n\n<hr class=\"border-t-2 border-t3-purple-300/20\" />\n"
  },
  {
    "path": "www/src/components/docs/tabs.astro",
    "content": "---\nconst { tabName, slotOne, slotTwo } = Astro.props;\n---\n\n<style>\n  .tab-list {\n    display: flex;\n    cursor: pointer;\n  }\n\n  .tab {\n    padding: 0.5rem 1rem;\n    margin-right: 1rem;\n    font-weight: bold;\n    border: none;\n    background: none;\n    cursor: pointer;\n    outline: none;\n    transition: border-bottom 0.3s;\n  }\n\n  .tab.active {\n    color: white;\n    border-radius: 0.5rem;\n    background-color: #4a3eeb;\n  }\n\n  .tab-panel.hidden {\n    display: none;\n  }\n\n  .tab-panel {\n    padding: 1rem 0;\n  }\n</style>\n\n<div>\n  <div class=\"tab-list\">\n    <button class={`tab active ${tabName}`} data-target={slotOne}\n      >{slotOne}</button\n    >\n    <button class={`tab ${tabName}`} data-target={slotTwo}>{slotTwo}</button>\n  </div>\n  <div class=\"tab-panels\">\n    <div id={slotOne} class={`tab-panel ${tabName}-panel`}>\n      <slot name=\"1\" />\n    </div>\n    <div id={slotTwo} class={`tab-panel hidden ${tabName}-panel`}>\n      <slot name=\"2\" />\n    </div>\n  </div>\n</div>\n\n<script define:vars={{ tabName }}>\n  document.addEventListener(\"DOMContentLoaded\", () => {\n    const tabs = document.querySelectorAll(`.${tabName}`);\n    const panels = document.querySelectorAll(`.${tabName}-panel`);\n\n    tabs.forEach((tab) => {\n      tab.addEventListener(\"click\", () => {\n        tabs.forEach((t) => t.classList.remove(\"active\"));\n\n        panels.forEach((panel) => panel.classList.add(\"hidden\"));\n\n        tab.classList.add(\"active\");\n\n        const target = tab.getAttribute(\"data-target\");\n        if (target) {\n          const targetPanel = document.getElementById(target);\n          if (targetPanel) {\n            targetPanel.classList.remove(\"hidden\");\n          }\n        }\n      });\n    });\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/footer/footer.astro",
    "content": "---\nimport AvatarList from \"../docs/avatarList.astro\";\n\nexport interface Props {\n  path: string;\n  isBlog: boolean;\n}\nconst { path, isBlog } = Astro.props;\n---\n\n<footer class=\"mt-auto flex flex-col bg-transparent py-12 transition-colors\">\n  {isBlog && <AvatarList path={path} />}\n  <div class=\"container mx-auto divide-gray-400 divide-opacity-50 px-6 pt-6\">\n    <div class=\"flex w-full flex-col items-center justify-between\">\n      <div class=\"pb-2\">\n        <a\n          class=\"mt-6 flex rounded-lg\"\n          href=\"https://vercel.com/?utm_source=t3-oss&utm_campaign=oss\"\n          rel=\"noopener noreferrer\"\n          target=\"_blank\"\n        >\n          <img\n            src=\"/images/powered-by-vercel.svg\"\n            class=\"h-10 w-full\"\n            alt=\"Powered by Vercel\"\n          />\n        </a>\n      </div>\n    </div>\n  </div>\n</footer>\n"
  },
  {
    "path": "www/src/components/headCommon.astro",
    "content": "<!-- Global Metadata -->\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width\" />\n<meta name=\"generator\" content={Astro.generator} />\n\n<link\n  href=\"/images/t3-dark.svg\"\n  rel=\"icon\"\n  media=\"(prefers-color-scheme:light)\"\n/>\n<link\n  href=\"/images/t3-light.svg\"\n  rel=\"icon\"\n  media=\"(prefers-color-scheme:dark)\"\n/>\n<link\n  rel=\"alternate icon\"\n  type=\"image/x-icon\"\n  href=\"/favicon.ico\"\n  media=\"(prefers-color-scheme:light)\"\n/>\n<link\n  rel=\"alternate icon\"\n  type=\"image/x-icon\"\n  href=\"/favicon-dark.ico\"\n  media=\"(prefers-color-scheme:dark)\"\n/>\n<link rel=\"sitemap\" href=\"/sitemap.xml\" />\n\n<script defer src=\"/_vercel/insights/script.js\"></script>\n"
  },
  {
    "path": "www/src/components/headSeo.astro",
    "content": "---\nimport { OPEN_GRAPH, SITE, type Frontmatter } from \"../config\";\nimport { SITE_URL } from \"../utils/siteUrl\";\n\nexport interface Props {\n  frontmatter?: Frontmatter;\n  type?: string;\n}\n\nconst { frontmatter, type } = Astro.props as Props;\n\nconst canonicalUrl = new URL(Astro.url.pathname, Astro.site);\n\nconst formattedContentTitle = frontmatter\n  ? `${frontmatter.title} 🚀 ${SITE.title}`\n  : SITE.title;\n\nconst ogTitle = frontmatter ? frontmatter.title : SITE.title;\nconst ogDescription = frontmatter ? frontmatter.description : SITE.description;\n\nconst ogImageData = {\n  title: ogTitle,\n  description: ogDescription,\n  pagePath: Astro.url.pathname,\n};\n\nconst imageSrc =\n  frontmatter?.image?.src ??\n  `${SITE_URL}/og?${Object.entries(ogImageData)\n    .map(([key, value]) => `${key}=${value}`)\n    .join(\"&\")}`;\n\nconst imageUrl = new URL(imageSrc, Astro.url.origin);\nconst imageAlt = frontmatter?.image?.alt ?? OPEN_GRAPH.image.alt;\n\nconst ogType = type ?? \"article\";\n---\n\n<!-- Page Metadata -->\n<link rel=\"canonical\" href={canonicalUrl} />\n<meta name=\"description\" property=\"og:description\" content={SITE.description} />\n\n<!-- OpenGraph Tags -->\n<meta property=\"og:title\" content={formattedContentTitle} />\n<meta property=\"og:type\" content={ogType} />\n<meta property=\"og:url\" content={canonicalUrl} />\n<meta property=\"og:locale\" content={SITE.defaultLanguage} />\n<meta property=\"og:image\" content={imageUrl} />\n<meta property=\"og:image:alt\" content={imageAlt} />\n<meta property=\"og:site_name\" content={SITE.title} />\n\n<!-- Twitter Tags -->\n<meta name=\"twitter:card\" content=\"summary_large_image\" />\n<meta name=\"twitter:site\" content={OPEN_GRAPH.twitter} />\n<meta name=\"twitter:title\" content={formattedContentTitle} />\n<meta name=\"twitter:description\" content={SITE.description} />\n<meta name=\"twitter:image\" content={imageUrl} />\n<meta name=\"twitter:image:alt\" content={imageAlt} />\n\n<!--\n  TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?\n  Docs: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data\n  https://www.npmjs.com/package/schema-dts seems like a great resource for implementing this.\n  Even better, there's a React component that integrates with `schema-dts`: https://github.com/google/react-schemaorg\n-->\n"
  },
  {
    "path": "www/src/components/icons/leftArrow.astro",
    "content": "<svg\n  fill=\"none\"\n  viewBox=\"0 0 24 24\"\n  stroke=\"currentColor\"\n  height={24}\n  class=\"mr-1 inline flex-shrink-0 rotate-180 transform\"\n>\n  <path\n    stroke-linecap=\"round\"\n    stroke-linejoin=\"round\"\n    stroke-width={2}\n    d=\"M9 5l7 7-7 7\"></path>\n</svg>\n"
  },
  {
    "path": "www/src/components/icons/rightArrow.astro",
    "content": "<svg\n  fill=\"none\"\n  viewBox=\"0 0 24 24\"\n  stroke=\"currentColor\"\n  height={24}\n  class=\"ml-1 inline flex-shrink-0 transform\"\n>\n  <path\n    stroke-linecap=\"round\"\n    stroke-linejoin=\"round\"\n    stroke-width={2}\n    d=\"M9 5l7 7-7 7\"></path>\n</svg>\n"
  },
  {
    "path": "www/src/components/landingPage/ClipboardSelect.tsx",
    "content": "import { Menu, Transition } from \"@headlessui/react\";\nimport clsx from \"clsx\";\nimport { Fragment, useState } from \"react\";\n\nconst commands = [\n  {\n    command: \"create t3-app@latest\",\n    manager: \"npm\",\n  },\n  {\n    command: \"create t3-app\",\n    manager: \"yarn\",\n  },\n  {\n    command: \"create t3-app@latest\",\n    manager: \"pnpm\",\n  },\n  {\n    command: \"create t3-app@latest\",\n    manager: \"bun\",\n  },\n];\n\nexport default function ClipboardSelect() {\n  const [coolDown, setCoolDown] = useState(false);\n\n  const handleCopyToClipboard = async (manager: string, command: string) => {\n    const nextClipboard = `${manager} ${command}`;\n    try {\n      await navigator.clipboard.writeText(nextClipboard);\n    } catch (err) {\n      console.error(\"Failed to copy text: \", err);\n    }\n  };\n\n  const checkStyles = {\n    strokeDasharray: 450,\n    strokeDashoffset: -30,\n  };\n\n  return (\n    <div className=\"flex items-center gap-2\">\n      <Menu as=\"div\">\n        <div className=\"relative\">\n          <Menu.Button className=\"relative flex cursor-pointer items-center justify-center rounded-lg border bg-t3-purple-200/50 p-2 text-left focus:outline-none hover:bg-t3-purple-200/75 sm:text-sm dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\">\n            <svg\n              className={`h-[1em] w-[1em] ${coolDown && \"hidden\"}`}\n              xmlns=\"http://www.w3.org/2000/svg\"\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect>\n              <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path>\n            </svg>\n            <svg\n              className={`h-[1em] w-[1em] animate-draw ${\n                !coolDown && \"hidden\"\n              }`}\n              style={checkStyles}\n              xmlns=\"http://www.w3.org/2000/svg\"\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <polyline points=\"20 6 9 17 4 12\"></polyline>\n            </svg>\n          </Menu.Button>\n          <Transition\n            as={Fragment}\n            enter={\"transition ease-out duration-100\"}\n            enterFrom={\"transform opacity-0 -translate-y-1\"}\n            enterTo={\"transform opacity-100 -translate-y-0\"}\n          >\n            <Menu.Items\n              className={clsx(\n                \"focus-none shadow-l t3-scrollbar absolute right-0 mt-1 max-h-60 w-fit min-w-[6em] overflow-auto rounded-lg border bg-default text-base focus:outline-none focus-visible:outline-none sm:text-sm dark:border-t3-purple-200/20\",\n              )}\n            >\n              {commands.map(({ manager, command }) => (\n                <Menu.Item key={manager}>\n                  {({ active }) => {\n                    return (\n                      <button\n                        className={`${\n                          active && \"bg-t3-purple-200/20\"\n                        } group flex w-full items-center bg-t3-purple-200/10 px-4 py-2 text-sm font-medium hover:bg-t3-purple-200/20`}\n                        onClick={() => {\n                          handleCopyToClipboard(manager, command)\n                            .then(() => {\n                              setCoolDown(true);\n                              setTimeout(() => {\n                                setCoolDown(false);\n                              }, 1000);\n                            })\n                            .catch((err) => console.log(err));\n                        }}\n                      >\n                        {manager}\n                      </button>\n                    );\n                  }}\n                </Menu.Item>\n              ))}\n            </Menu.Items>\n          </Transition>\n        </div>\n      </Menu>\n    </div>\n  );\n}\n"
  },
  {
    "path": "www/src/components/landingPage/about.astro",
    "content": "---\nimport CliPreview from \"./cli\";\nimport PageSection from \"./pageSection.astro\";\n---\n\n<PageSection\n  className=\"mx-auto grid max-w-7xl grid-cols-1 items-center gap-8 px-4 pb-12 sm:px-6 lg:grid lg:gap-x-8 lg:px-8 xl:grid-cols-2 xl:gap-x-12\"\n  size={\"24\"}\n  id=\"about\"\n>\n  <div class=\"mx-auto flex max-w-[800px] flex-col gap-2 md:gap-4 xl:max-w-full\">\n    <h2\n      class=\"mb-2 w-full text-3xl font-bold text-t3-purple-50 md:text-5xl lg:text-5xl\"\n    >\n      Typesafe From The Start\n    </h2>\n    <p\n      class=\"mx-auto mt-4 max-w-3xl text-base text-t3-purple-200 md:text-xl lg:text-xl xl:text-xl\"\n    >\n      We made create-t3-app to do one thing: Streamline the setup of typesafe\n      Next.js apps WITHOUT compromising modularity.\n    </p>\n    <p\n      class=\"mx-auto mt-4 max-w-3xl text-base text-t3-purple-200 md:text-xl lg:text-xl xl:text-xl\"\n    >\n      After countless projects and many years on this tech, we have lots of\n      opinions and insights. We've done our best to encode them into this CLI.\n    </p>\n    <p\n      class=\"mx-auto mt-4 max-w-3xl text-base text-t3-purple-200 md:text-xl lg:text-xl xl:text-xl\"\n    >\n      This is NOT an all-inclusive template. <b\n        >We expect you to bring your own libraries.</b\n      > Check out <a href=\"/en/other-recs\" class=\"text-t3-purple-600\"\n        >our other recommendations</a\n      > for things like state management and deployment.\n    </p>\n  </div>\n  <div class=\"min-h-[300px] md:min-h-[400px]\">\n    <CliPreview client:only=\"react\" />\n  </div>\n</PageSection>\n"
  },
  {
    "path": "www/src/components/landingPage/banner.astro",
    "content": "---\nimport Button from \"./button.astro\";\nimport ClipboardSelect from \"./ClipboardSelect\";\n---\n\n<div class=\"py-12 sm:py-8 md:py-12 lg:py-14 xl:py-12 2xl:py-28\">\n  <div class=\"mx-auto max-w-[800px] xl:max-w-7xl\">\n    <div class=\"lg:px-8\">\n      <div class=\"flex flex-col items-center\">\n        <div\n          class=\"max-w-md px-4 sm:max-w-2xl sm:px-6 md:max-w-3xl lg:max-w-4xl lg:px-0 xl:max-w-5xl 2xl:max-w-6xl\"\n        >\n          <div class=\"flex w-full flex-col items-center gap-4\">\n            <div class=\"flex flex-col items-start justify-between\">\n              <h1\n                class=\"text-center text-4xl font-bold tracking-tight text-white sm:text-6xl sm:tracking-tight lg:text-[4rem] xl:text-[6rem] xl:tracking-tight 2xl:text-[6.5rem]\"\n              >\n                The best way to start a\n                <span class=\"text-[hsl(200,100%,60%)]\"> full-stack,</span>\n                <span class=\"whitespace-nowrap text-[hsl(240,100%,70%)]\">\n                  typesafe</span\n                >\n                <span class=\"text-[hsl(280,100%,60%)]\">Next.js</span> app\n              </h1>\n\n              <div\n                class=\"mt-4 flex w-full items-center justify-center gap-4 xl:mt-8\"\n              >\n                <Button\n                  href=\"/en/introduction\"\n                  openInNewTab={false}\n                  rounded=\"md\"\n                  className=\"group\"\n                  rounded=\"full\"\n                  specialHover={true}\n                >\n                  Documentation\n                  <svg\n                    class=\"stroke -mr-1 ml-2 mt-0.5 h-3 stroke-current stroke-2\"\n                    fill=\"none\"\n                    viewBox=\"0 0 10 10\"\n                    aria-hidden=\"true\"\n                  >\n                    <path\n                      class=\"opacity-0 transition group-hover:opacity-100\"\n                      d=\"M0 5h7\"></path>\n                    <path\n                      class=\"transition group-hover:translate-x-[3px]\"\n                      d=\"M1 1l4 4-4 4\"></path>\n                  </svg>\n                </Button>\n                <Button\n                  href=\"https://github.com/t3-oss/create-t3-app\"\n                  openInNewTab={true}\n                  variant=\"secondary\"\n                  rounded=\"full\"\n                >\n                  GitHub\n                  <svg\n                    xmlns=\"http://www.w3.org/2000/svg\"\n                    viewBox=\"0 0 448 512\"\n                    class=\"ml-2 h-3 fill-white\"\n                  >\n                    <path\n                      d=\"M256 64C256 46.33 270.3 32 288 32H415.1C415.1 32 415.1 32 415.1 32C420.3 32 424.5 32.86 428.2 34.43C431.1 35.98 435.5 38.27 438.6 41.3C438.6 41.35 438.6 41.4 438.7 41.44C444.9 47.66 447.1 55.78 448 63.9C448 63.94 448 63.97 448 64V192C448 209.7 433.7 224 416 224C398.3 224 384 209.7 384 192V141.3L214.6 310.6C202.1 323.1 181.9 323.1 169.4 310.6C156.9 298.1 156.9 277.9 169.4 265.4L338.7 96H288C270.3 96 256 81.67 256 64V64zM0 128C0 92.65 28.65 64 64 64H160C177.7 64 192 78.33 192 96C192 113.7 177.7 128 160 128H64V416H352V320C352 302.3 366.3 288 384 288C401.7 288 416 302.3 416 320V416C416 451.3 387.3 480 352 480H64C28.65 480 0 451.3 0 416V128z\"\n                    ></path>\n                  </svg>\n                </Button>\n              </div>\n\n              <div class=\"flex w-full flex-col items-center\">\n                <div class=\"relative mt-4 flex h-full xl:mt-8\">\n                  <div\n                    class=\"relative flex items-center rounded-lg border border-t3-purple-200/20 bg-t3-purple-100/10 px-2 py-2 text-sm md:px-3 md:py-3 md:text-lg lg:px-5 lg:py-4 lg:text-xl\"\n                  >\n                    <code class=\"mr-12\">npm create t3-app@latest</code>\n                    <ClipboardSelect client:load />\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "www/src/components/landingPage/button.astro",
    "content": "---\nexport interface Props {\n  href?: string;\n  openInNewTab?: boolean;\n  rounded?: \"full\" | \"md\" | \"none\";\n  variant?: \"primary\" | \"secondary\";\n  specialHover?: boolean;\n  className?: string;\n  download?: string | false;\n}\n\nconst {\n  href = \"\",\n  rounded = \"md\",\n  variant = \"primary\",\n  openInNewTab = false,\n  className = \"\",\n  specialHover = false,\n  download = false,\n} = Astro.props;\n\nconst roundedClass =\n  rounded === \"full\" ? \"rounded-full\" : rounded === \"md\" ? \"rounded-md\" : \"\";\nconst variantClass =\n  variant === \"primary\"\n    ? \"bg-t3-purple-100 hover:bg-t3-purple-200 text-slate-800\"\n    : \"bg-white/10 hover:bg-white/20 text-white\";\n\nconst specialHoverClass = specialHover\n  ? \"hover:shadow hover:shadow-[#300171] duration-500\"\n  : \"\";\n---\n\n<a\n  href={href}\n  target={openInNewTab ? \"_blank\" : \"_self\"}\n  rel=\"noopener noreferrer\"\n  class={`${specialHoverClass} ${roundedClass} ${variantClass} ${className} inline-flex items-center px-3 lg:px-4 lg:py-3 md:px-5 py-2 text-sm md:text-base font-semibold cursor-pointer hover:no-underline transition-colors`}\n  {...download ? { download } : {}}\n>\n  <slot />\n</a>\n"
  },
  {
    "path": "www/src/components/landingPage/cli.tsx",
    "content": "/** @jsxImportSource react */\nimport Typist from \"react-typist\";\n\nexport default function CodeCard() {\n  return (\n    <div\n      className=\"mx-auto w-full overflow-hidden rounded-lg sm:w-[600px]\"\n      aria-hidden=\"true\"\n    >\n      <div className=\"inverse-toggle h-[300px] overflow-hidden rounded-lg border border-t3-purple-200/20 bg-white/10 px-1 pb-6 pt-4 font-mono text-[10px] leading-normal text-t3-purple-50 subpixel-antialiased shadow-lg transition-all sm:h-[400px] sm:px-2 sm:text-xs md:px-5\">\n        <div className=\"top mb-2 flex\">\n          <div className=\"h-3 w-3 rounded-full bg-red-500\"></div>\n          <div className=\"ml-2 h-3 w-3 rounded-full bg-orange-300\"></div>\n          <div className=\"ml-2 h-3 w-3 rounded-full bg-green-500\"></div>\n        </div>\n        <Typist cursor={{ hideWhenDone: true, hideWhenDoneDelay: 0 }}>\n          npm create t3-app@latest\n          <Typist.Delay ms={1250} />\n        </Typist>\n        <Typist\n          className=\"leading-1 translate-y-[-0.2rem] bg-gradient-to-r from-blue-400 via-green-300 to-pink-600 bg-clip-text font-mono text-[7px] text-transparent sm:text-sm md:translate-y-[-0.4rem]\"\n          cursor={{ show: false }}\n          avgTypingDelay={-500}\n        >\n          <Typist.Delay ms={2000} />\n          &nbsp;&nbsp;&nbsp;&nbsp;___&nbsp;___&nbsp;___&nbsp;&nbsp;&nbsp;__&nbsp;_____&nbsp;___&nbsp;&nbsp;&nbsp;_____&nbsp;____&nbsp;&nbsp;&nbsp;&nbsp;__&nbsp;&nbsp;&nbsp;___&nbsp;___&nbsp;\n          <br />\n          &nbsp;&nbsp;&nbsp;/&nbsp;__|&nbsp;_&nbsp;\\&nbsp;__|&nbsp;/&nbsp;&nbsp;\\_&nbsp;&nbsp;&nbsp;_|&nbsp;__|&nbsp;|_&nbsp;&nbsp;&nbsp;_|__&nbsp;/&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;\\&nbsp;|&nbsp;_&nbsp;\\&nbsp;_&nbsp;\\&nbsp;&nbsp;\n          <br />\n          &nbsp;&nbsp;|&nbsp;(__|&nbsp;&nbsp;&nbsp;/&nbsp;_|&nbsp;/&nbsp;/\\&nbsp;\\|&nbsp;|&nbsp;|&nbsp;_|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;|&nbsp;&nbsp;|_&nbsp;\\&nbsp;&nbsp;/&nbsp;/\\&nbsp;\\|&nbsp;&nbsp;_/&nbsp;&nbsp;_/&nbsp;\n          <br />\n          &nbsp;&nbsp;&nbsp;\\___|_|_\\___|_/¯¯\\_\\_|&nbsp;|___|&nbsp;&nbsp;&nbsp;|_|&nbsp;|___/&nbsp;/_/¯¯\\_\\_|&nbsp;|_|&nbsp;&nbsp;\n          <br />\n        </Typist>\n        <Typist\n          startDelay={2100}\n          className=\"\"\n          cursor={{ show: false }}\n          avgTypingDelay={-500}\n        >\n          <div>\n            ? What will your project be called? (my-t3-app)\n            <Typist.Delay ms={500} />\n            <Typist\n              cursor={{ hideWhenDone: true, hideWhenDoneDelay: 0 }}\n              avgTypingDelay={50}\n              className=\"inline pl-1 text-blue-400\"\n            >\n              my-t3-app\n            </Typist>\n          </div>\n          <br />\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={4800}\n          avgTypingDelay={-10000}\n        >\n          ? Will you be using JavaScript or TypeScript? (Use arrow keys)\n          <br />\n          ❯ TypeScript\n          <br />\n          &nbsp;&nbsp;JavaScript\n          <Typist.Backspace count={87} delay={1000} />\n          <Typist\n            cursor={{ show: false }}\n            avgTypingDelay={-10000}\n            className=\"translate-y-[-1.8rem] md:translate-y-[-2.0rem]\"\n          >\n            <span>\n              <span>? Will you be using JavaScript or TypeScript?</span>\n              <span className=\"pl-2 text-blue-400\">TypeScript</span>\n            </span>\n          </Typist>\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={6300}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-1.8rem] text-green-400 md:translate-y-[-2.0rem]\"\n        >\n          Good choice! Using TypeScript!\n          <br />\n          <Typist.Delay ms={1000} />\n          <span className=\"text-white\">{`? Which packages would you like to enable? (Press <space> to select, <a> to toggle all, <i> to invert selection, and\n<enter> to proceed)`}</span>\n          <br />\n          <span className=\"text-blue-400\">❯</span>\n          <span className=\"text-blue-400\">◯ nextAuth</span>\n          <br />\n          <span className=\"text-white\">&nbsp;◯ prisma</span>\n          <br />\n          <span className=\"text-white\">&nbsp;◯ tailwind</span>\n          <br />\n          <span className=\"text-white\">&nbsp;◯ trpc</span>\n          <Typist.Delay ms={900} />\n          <Typist.Backspace count={38} />\n          <Typist.Delay ms={1200} />\n          <Typist.Backspace count={136} />\n          <span></span>\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={10000}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-5.6rem] sm:translate-y-[-6.0rem]\"\n        >\n          <span>? Which packages would you like to enable?</span>\n          <span className=\"pl-1 text-blue-400\">\n            nextAuth, prisma, tailwind, trpc\n          </span>\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          avgTypingDelay={-20000}\n          className=\"translate-y-[-4.6rem] sm:translate-y-[-5.0rem]\"\n          startDelay={8700}\n        >\n          <span className=\"text-blue-400\">❯</span>\n          <span className=\"text-blue-400\">◉ nextAuth</span>\n          <span className=\"text-blue-400\">◉ better-auth</span>\n          <br />\n          &nbsp;◉ prisma\n          <br />\n          &nbsp;◉ tailwind\n          <br />\n          &nbsp;◉ trpc\n          <br />\n          <Typist.Delay ms={1000} />\n          <Typist.Backspace count={50} />\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={10500}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-9.4rem] sm:translate-y-[-10rem]\"\n        >\n          <div className=\"flex whitespace-nowrap\">\n            <span>? Initialize a new git repository? (Y/n)</span>\n            <Typist.Delay ms={1000} />\n            <Typist\n              cursor={{ hideWhenDone: true, hideWhenDoneDelay: 0 }}\n              className=\"pl-2 text-blue-400\"\n            >\n              n\n            </Typist>\n            <Typist.Delay ms={1500} />\n            <Typist.Backspace count={1} />\n            <span className=\"text-blue-400\">No</span>\n          </div>\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={13000}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-9.4rem] text-green-400 sm:translate-y-[-10rem]\"\n        >\n          Sounds good! You can come back and run git init later.\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={14500}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-9.4rem] sm:translate-y-[-10rem]\"\n        >\n          <div>\n            <span className=\"whitespace\">\n              ? Would you like us to run npm install? (Y/n)\n            </span>\n            <Typist.Delay ms={1000} />\n            <Typist\n              cursor={{ hideWhenDone: true, hideWhenDoneDelay: 0 }}\n              className=\"inline pl-2 text-blue-400\"\n              avgTypingDelay={-10000}\n            >\n              y\n              <Typist.Backspace count={1} delay={500} />\n              <span className=\"text-blue-400\">Yes</span>\n            </Typist>\n          </div>\n        </Typist>\n        <Typist\n          cursor={{ show: false }}\n          startDelay={16000}\n          avgTypingDelay={-10000}\n          className=\"translate-y-[-9.4rem] text-green-400 sm:translate-y-[-10rem]\"\n        >\n          Alright. We&apos;ll install the dependencies for you!\n        </Typist>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "www/src/components/landingPage/community/community.astro",
    "content": "---\nimport PageSection from \"../pageSection.astro\";\nimport CommunityCard from \"./communityCard.astro\";\n\n// eslint-disable-next-line -- need to export something to make it a module\nexport interface Props {}\n---\n\n<PageSection size={\"24\"} bottomPadding={false} id=\"community\">\n  <div\n    class=\"mx-auto flex max-w-7xl flex-col items-center justify-center px-4 text-t3-purple-100 sm:px-6 lg:px-8\"\n  >\n    <h3\n      class=\"mt-2 w-full text-left text-3xl font-bold tracking-tight text-t3-purple-50 md:text-center md:text-5xl lg:text-5xl\"\n    >\n      Community\n    </h3>\n    <p\n      class=\"mb-10 mt-4 w-full max-w-3xl text-left text-base text-t3-purple-200 md:text-center md:text-xl lg:text-xl\"\n    >\n      Join our community to get help, share your projects, and even contribute\n      to the project!\n    </p>\n    <div\n      class=\"flex flex-col items-start justify-center space-y-4 sm:flex-row sm:space-x-6 sm:space-y-0\"\n    >\n      <CommunityCard\n        title=\"Discord\"\n        text=\"Join our Discord server to chat with other developers and get help with your projects.\"\n        href=\"https://t3.gg/discord\"\n      >\n        <svg\n          role=\"img\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          class=\"fill-[#5865F2]\"\n          slot=\"icon\"\n        >\n          <title>Discord</title>\n          <path\n            d=\"M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z\"\n          ></path>\n        </svg>\n      </CommunityCard>\n      <CommunityCard\n        title=\"GitHub\"\n        text=\"Contribute to the project by submitting issues and pull requests on our GitHub repository.\"\n        href=\"https://github.com/t3-oss/create-t3-app\"\n      >\n        <svg\n          role=\"img\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          class=\"fill-white\"\n          slot=\"icon\"\n        >\n          <title>GitHub</title>\n          <path\n            d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\n          ></path>\n        </svg>\n      </CommunityCard>\n      <CommunityCard\n        title=\"Twitter\"\n        text=\"Join us on Twitter for shitposts.\"\n        href=\"https://twitter.com/t3dotgg\"\n      >\n        <svg\n          role=\"img\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          class=\"fill-[#1DA1F2]\"\n          slot=\"icon\"\n        >\n          <title>Twitter</title>\n          <path\n            d=\"M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z\"\n          ></path>\n        </svg>\n      </CommunityCard>\n    </div>\n  </div>\n</PageSection>\n"
  },
  {
    "path": "www/src/components/landingPage/community/communityCard.astro",
    "content": "---\nexport interface Props {\n  title: string;\n  text: string;\n  href: string;\n}\n\nconst { text, title, href } = Astro.props;\n---\n\n<a\n  href={href}\n  target=\"_blank\"\n  rel=\"noopener noreferrer\"\n  class=\"w-full cursor-pointer rounded-lg border border-t3-purple-200/20 bg-t3-purple-200/10 transition-colors hover:border-t3-purple-300/50 hover:bg-t3-purple-200/20 hover:no-underline sm:h-64\"\n>\n  <div\n    class=\"flex h-full flex-col items-center justify-center space-y-3 p-4 sm:p-2 md:p-4\"\n  >\n    <div class=\"h-14 w-14\"><slot name=\"icon\" /></div>\n    <h2 class=\"text-xl font-black\">{title}</h2>\n    <p class=\"text-center\">\n      {text}\n    </p>\n  </div>\n</a>\n"
  },
  {
    "path": "www/src/components/landingPage/pageSection.astro",
    "content": "---\nexport interface Props {\n  size: \"6\" | \"12\" | \"16\" | \"24\" | \"32\";\n  className?: string;\n  bottomPadding?: boolean;\n  id?: string;\n}\n\nconst sizes = {\n  6: \"py-2 md:py-4 lg:py-6\",\n  12: \"py-4 md:py-8 lg:py-12\",\n  16: \"py-6 md:py-10 lg:py-16\",\n  24: \"py-8 md:py-16 lg:py-24\",\n  32: \"py-12 md:py-20 lg:py-32\",\n};\n\nconst sizesOnlyTop = {\n  6: \"pt-2 md:pt-4 lg:pt-6\",\n  12: \"pt-4 md:pt-8 lg:pt-12\",\n  16: \"pt-6 md:pt-10 lg:pt-16\",\n  24: \"pt-8 md:pt-16 lg:pt-24\",\n  32: \"pt-12 md:pt-20 lg:pt-32\",\n};\n\nconst { size, className, bottomPadding = true, id = \"\" } = Astro.props;\n---\n\n<section\n  id={id}\n  class:list={[className, bottomPadding ? sizes[size] : sizesOnlyTop[size]]}\n>\n  <slot />\n</section>\n"
  },
  {
    "path": "www/src/components/landingPage/stack/card.astro",
    "content": "---\nexport interface Props {\n  title: string;\n  href: string;\n}\nconst { title, href } = Astro.props;\n---\n\n<div\n  class=\"relative flex flex-col justify-between overflow-hidden rounded-md border border-t3-purple-200/20 bg-white/5 transition-colors hover:border-t3-purple-300/50\"\n>\n  <div\n    class=\"flex items-center space-x-4 bg-white/10 p-2 pl-5 transition-colors hover:bg-white/20\"\n  >\n    <slot name=\"icon\" />\n    <p class=\"text-lg font-medium leading-6 text-t3-purple-200 md:text-xl\">\n      <a\n        href={href}\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        class=\"h-full rounded-md before:absolute before:inset-0 before:content-[''] focus:no-underline hover:no-underline active:no-underline\"\n      >\n        {title}\n      </a>\n    </p>\n  </div>\n  <div\n    class=\"m-6 h-full text-sm text-t3-purple-100 subpixel-antialiased md:text-base\"\n  >\n    <slot name=\"description\" />\n  </div>\n</div>\n"
  },
  {
    "path": "www/src/components/landingPage/stack/stack.astro",
    "content": "---\nimport PageSection from \"../pageSection.astro\";\nimport Feature from \"./card.astro\";\n---\n\n<PageSection size={\"24\"} id=\"stack\">\n  <div class=\"mx-auto max-w-7xl px-4 pb-12 text-t3-purple-100 sm:px-6 lg:px-8\">\n    <div class=\"mb-10 md:text-center\">\n      <h2\n        class=\"text-xl font-semibold text-t3-purple-200 md:text-2xl lg:text-2xl\"\n      >\n        The best of the full stack TypeScript ecosystem...\n      </h2>\n      <h3\n        class=\"mt-2 text-3xl font-bold tracking-tight text-t3-purple-50 md:text-5xl lg:text-5xl\"\n      >\n        ...but ONLY the parts you need\n      </h3>\n      <p class=\"mt-4 text-base text-t3-purple-200 md:text-lg\">\n        Take what you want and nothing more!\n      </p>\n    </div>\n    <div>\n      <div\n        class=\"space-y-10 sm:grid sm:grid-flow-col sm:grid-cols-2 sm:grid-rows-3 sm:gap-x-6 sm:gap-y-14 sm:space-y-0 md:grid-cols-3 md:grid-rows-2 lg:gap-x-8\"\n      >\n        <Feature title=\"Next.js\" href=\"https://nextjs.org/\">\n          <svg\n            aria-hidden=\"true\"\n            slot=\"icon\"\n            role=\"img\"\n            viewBox=\"0 0 24 24\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            class=\"aspect-square h-10 fill-white py-1\"\n          >\n            <title>Next.js</title>\n            <path\n              d=\"M11.5725 0c-.1763 0-.3098.0013-.3584.0067-.0516.0053-.2159.021-.3636.0328-3.4088.3073-6.6017 2.1463-8.624 4.9728C1.1004 6.584.3802 8.3666.1082 10.255c-.0962.659-.108.8537-.108 1.7474s.012 1.0884.108 1.7476c.652 4.506 3.8591 8.2919 8.2087 9.6945.7789.2511 1.6.4223 2.5337.5255.3636.04 1.9354.04 2.299 0 1.6117-.1783 2.9772-.577 4.3237-1.2643.2065-.1056.2464-.1337.2183-.1573-.0188-.0139-.8987-1.1938-1.9543-2.62l-1.919-2.592-2.4047-3.5583c-1.3231-1.9564-2.4117-3.556-2.4211-3.556-.0094-.0026-.0187 1.5787-.0235 3.509-.0067 3.3802-.0093 3.5162-.0516 3.596-.061.115-.108.1618-.2064.2134-.075.0374-.1408.0445-.495.0445h-.406l-.1078-.068a.4383.4383 0 01-.1572-.1712l-.0493-.1056.0053-4.703.0067-4.7054.0726-.0915c.0376-.0493.1174-.1125.1736-.143.0962-.047.1338-.0517.5396-.0517.4787 0 .5584.0187.6827.1547.0353.0377 1.3373 1.9987 2.895 4.3608a10760.433 10760.433 0 004.7344 7.1706l1.9002 2.8782.096-.0633c.8518-.5536 1.7525-1.3418 2.4657-2.1627 1.5179-1.7429 2.4963-3.868 2.8247-6.134.0961-.6591.1078-.854.1078-1.7475 0-.8937-.012-1.0884-.1078-1.7476-.6522-4.506-3.8592-8.2919-8.2087-9.6945-.7672-.2487-1.5836-.42-2.4985-.5232-.169-.0176-1.0835-.0366-1.6123-.037zm4.0685 7.217c.3473 0 .4082.0053.4857.047.1127.0562.204.1642.237.2767.0186.061.0234 1.3653.0186 4.3044l-.0067 4.2175-.7436-1.14-.7461-1.14v-3.066c0-1.982.0093-3.0963.0234-3.1502.0375-.1313.1196-.2346.2323-.2955.0961-.0494.1313-.054.4997-.054z\"\n            >\n            </path>\n          </svg>\n\n          <Fragment slot=\"description\">\n            Next.js offers a lightly opinionated, heavily optimized approach to\n            creating applications using React. It's the industry standard and\n            we're proud to build on top of it :)\n          </Fragment>\n        </Feature>\n        <Feature title=\"Prisma\" href=\"https://www.prisma.io/\">\n          <svg\n            aria-hidden=\"true\"\n            slot=\"icon\"\n            role=\"img\"\n            viewBox=\"0 0 24 24\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            class=\"h-10 fill-white py-1\"\n          >\n            <title>Prisma</title>\n            <path\n              d=\"M21.8068 18.2848L13.5528.7565c-.207-.4382-.639-.7273-1.1286-.7541-.5023-.0293-.9523.213-1.2062.6253L2.266 15.1271c-.2773.4518-.2718 1.0091.0158 1.4555l4.3759 6.7786c.2608.4046.7127.6388 1.1823.6388.1332 0 .267-.0188.3987-.0577l12.7019-3.7568c.3891-.1151.7072-.3904.8737-.7553s.1633-.7828-.0075-1.1454zm-1.8481.7519L9.1814 22.2242c-.3292.0975-.6448-.1873-.5756-.5194l3.8501-18.4386c.072-.3448.5486-.3996.699-.0803l7.1288 15.138c.1344.2856-.019.6224-.325.7128z\"\n            ></path>\n          </svg>\n          <Fragment slot=\"description\">\n            Prisma is the best way to work with databases in TypeScript. It\n            provides a simple, type-safe API to query your database, and it can\n            be used with most SQL dialects (and Mongo too!).\n          </Fragment>\n        </Feature>\n\n        <Feature title=\"TypeScript\" href=\"https://www.typescriptlang.org/\">\n          <svg\n            aria-hidden=\"true\"\n            slot=\"icon\"\n            version=\"1.1\"\n            viewBox=\"0 0 512 512\"\n            class=\"aspect-square h-10 py-1\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <title>TypeScript</title>\n            <rect width=\"512\" height=\"512\" rx=\"50\" fill=\"#3178c6\"></rect>\n            <path\n              d=\"m317 407v50c8.1 4.2 18 7.3 29 9.4s23 3.1 35 3.1c12 0 23-1.1 34-3.4 11-2.3 20-6.1 28-11 8.1-5.3 15-12 19-21s7.1-19 7.1-32c0-9.1-1.4-17-4.1-24s-6.6-13-12-18c-5.1-5.3-11-10-18-14s-15-8.2-24-12c-6.6-2.7-12-5.3-18-7.9-5.2-2.6-9.7-5.2-13-7.8-3.7-2.7-6.5-5.5-8.5-8.4-2-3-3-6.3-3-10 0-3.4 0.89-6.5 2.7-9.3s4.3-5.1 7.5-7.1c3.2-2 7.2-3.5 12-4.6 4.7-1.1 9.9-1.6 16-1.6 4.2 0 8.6 0.31 13 0.94 4.6 0.63 9.3 1.6 14 2.9 4.7 1.3 9.3 2.9 14 4.9 4.4 2 8.5 4.3 12 6.9v-47c-7.6-2.9-16-5.1-25-6.5s-19-2.1-31-2.1c-12 0-23 1.3-34 3.8s-20 6.5-28 12c-8.1 5.4-14 12-19 21-4.7 8.4-7 18-7 30 0 15 4.3 28 13 38 8.6 11 22 19 39 27 6.9 2.8 13 5.6 19 8.3s11 5.5 15 8.4c4.3 2.9 7.7 6.1 10 9.5 2.5 3.4 3.8 7.4 3.8 12 0 3.2-0.78 6.2-2.3 9s-3.9 5.2-7.1 7.2-7.1 3.6-12 4.8c-4.7 1.1-10 1.7-17 1.7-11 0-22-1.9-32-5.7-11-3.8-21-9.5-30-17zm-84-123h64v-41h-179v41h64v183h51z\"\n              clip-rule=\"evenodd\"\n              fill=\"#fff\"\n              fill-rule=\"evenodd\"\n              style=\"fill:#fff\"></path>\n          </svg>\n          <Fragment slot=\"description\">\n            We firmly believe TypeScript will help you be a better web\n            developer. Whether you're new to JS or a seasoned pro, the\n            \"strictness\" of TypeScript leads to smoother building.\n          </Fragment>\n        </Feature>\n\n        <Feature title=\"Tailwind CSS\" href=\"https://tailwindcss.com/\">\n          <svg\n            aria-hidden=\"true\"\n            slot=\"icon\"\n            role=\"img\"\n            viewBox=\"0 0 24 24\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            class=\"aspect-square h-10 fill-[#06B6D4] py-1\"\n          >\n            <title>Tailwind CSS</title>\n            <path\n              d=\"M12.001,4.8c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 C13.666,10.618,15.027,12,18.001,12c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C16.337,6.182,14.976,4.8,12.001,4.8z M6.001,12c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 c1.177,1.194,2.538,2.576,5.512,2.576c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C10.337,13.382,8.976,12,6.001,12z\"\n            ></path>\n          </svg>\n          <Fragment slot=\"description\">\n            Tailwind CSS is a utility-first CSS framework that helps you build\n            beautiful, responsive designs without any extra configuration. It’s\n            built with utility-first principles, and is completely customizable\n            and extendable.\n          </Fragment>\n        </Feature>\n\n        <Feature title=\"tRPC\" href=\"https://trpc.io/\">\n          <svg\n            aria-hidden=\"true\"\n            slot=\"icon\"\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            class=\"aspect-square h-10 fill-[#398CCB] py-1\"\n          >\n            <title>tRPC</title>\n            <rect width=\"512\" height=\"512\" rx=\"150\" fill=\"#398CCB\"></rect>\n            <path\n              fill-rule=\"evenodd\"\n              clip-rule=\"evenodd\"\n              d=\"M255.446 75L326.523 116.008V138.556L412.554 188.238V273.224L435.631 286.546V368.608L364.6 409.615L333.065 391.378L256.392 435.646L180.178 391.634L149.085 409.615L78.0538 368.538V286.546L100.231 273.743V188.238L184.415 139.638L184.462 139.636V116.008L255.446 75ZM326.523 159.879V198.023L255.492 239.031L184.462 198.023V160.936L184.415 160.938L118.692 198.9V263.084L149.085 245.538L220.115 286.546V368.538L198.626 380.965L256.392 414.323L314.618 380.712L293.569 368.538V286.546L364.6 245.538L394.092 262.565V198.9L326.523 159.879ZM312.031 357.969V307.915L355.369 332.931V382.985L312.031 357.969ZM417.169 307.846L373.831 332.862V382.985L417.169 357.9V307.846ZM96.5154 357.9V307.846L139.854 332.862V382.915L96.5154 357.9ZM201.654 307.846L158.315 332.862V382.915L201.654 357.9V307.846ZM321.262 291.923L364.6 266.908L407.938 291.923L364.6 316.962L321.262 291.923ZM149.085 266.838L105.746 291.923L149.085 316.892L192.423 291.923L149.085 266.838ZM202.923 187.362V137.308L246.215 162.346V212.377L202.923 187.362ZM308.015 137.308L264.723 162.346V212.354L308.015 187.362V137.308ZM212.154 121.338L255.446 96.3231L298.785 121.338L255.446 146.354L212.154 121.338Z\"\n              fill=\"white\"></path>\n          </svg>\n          <Fragment slot=\"description\">\n            If your frontend and backend are TypeScript, it's really hard to\n            beat the DX of tRPC. Kinda like GraphQL but without the work -\n            seriously this lib is magic.\n          </Fragment>\n        </Feature>\n\n        <Feature title=\"NextAuth.js\" href=\"https://next-auth.js.org/\">\n          <img\n            src=\"/images/nextauth.webp\"\n            slot=\"icon\"\n            height={40}\n            width={32}\n            alt=\"NextAuth.js\"\n          />\n          <Fragment slot=\"description\">\n            When you need flexible, secure, and scalable auth, NextAuth.js is\n            top notch. It ties into your existing database and provides a simple\n            API to manage users and sessions.\n          </Fragment>\n        </Feature>\n      </div>\n    </div>\n  </div>\n</PageSection>\n"
  },
  {
    "path": "www/src/components/landingPage/tweets/featuredTweets.ts",
    "content": "export interface Tweet {\n  id: string;\n  handle: string;\n  verified: boolean;\n  author: string;\n  avatar: string;\n  date: Date;\n  text: string;\n  likes: number;\n  retweets: number;\n  replies: number;\n  quotes: number;\n}\n\n// featured tweets for the testimonials on the landing page\nexport const featuredTweets: Tweet[] = [\n  // https://twitter.com/ajcwebdev/status/1544909672137867264\n  {\n    id: \"1544909672137867264\",\n    handle: \"ajcwebdev\",\n    author: \"❤️ Anthony (ajcwebdev.x)\",\n    verified: false,\n    avatar:\n      \"https://pbs.twimg.com/profile_images/1549247631867711488/hK_Qr-Dx_normal.png\",\n    date: new Date(\"2022-07-07T05:02:23.000Z\"),\n    text: \"Now that Blitz.js has pivoted and Bison has stagnated, create-t3-app will be the only framework to give Redwood a run for its money in the quest to build a legitimate fullstack React framework.\",\n    likes: 32,\n    retweets: 3,\n    replies: 9,\n    quotes: 2,\n  },\n\n  // https://twitter.com/tomdoes_tech/status/1595652166173458434\n  {\n    id: \"1595652166173458434\",\n    handle: \"tomdoes_tech\",\n    author: \"Tom\",\n    verified: false,\n    avatar:\n      \"https://pbs.twimg.com/profile_images/1551907445856997385/3m8M35Cn_400x400.png\",\n    date: new Date(\"2022-11-24T08:34:00.000Z\"),\n    text: \"Used create-t3-app for a hackathon today. I don't think I've ever created an app that works so well and does so much in a single day before\",\n    likes: 194,\n    retweets: 6,\n    replies: 10,\n    quotes: 2,\n  },\n\n  // https://twitter.com/synecdokey/status/1553580714591158272\n  {\n    id: \"1553580714591158272\",\n    handle: \"synecdokey\",\n    author: \"Emilia Zapata\",\n    verified: false,\n    avatar:\n      \"https://pbs.twimg.com/profile_images/1426010455055638531/xUFu5JP7_400x400.jpg\",\n    date: new Date(\"2022-07-31T07:18:00.000Z\"),\n    text: \"Finally had the chance to play with @trpcio and it's scary how easy it makes to make your data flow, with full type safety and backend validation. With create-t3-app and @supabase , I was able to create a simple to-do app with auth in less than 3 hours, scary.\",\n    likes: 76,\n    retweets: 10,\n    replies: 2,\n    quotes: 0,\n  },\n\n  // https://twitter.com/royanger/status/1553191258771841024\n  {\n    id: \"1553191258771841024\",\n    handle: \"royanger\",\n    author: \"Roy Anger\",\n    verified: false,\n    avatar:\n      \"https://pbs.twimg.com/profile_images/1346968887/dsc652499-2_400x400.jpg\",\n    date: new Date(\"2022-07-30T05:30:00.000Z\"),\n    text: \"create-t3-app is amazing. I worked on a MVP over the last 10 days on the side, and easily built it out using the stack. Working with data via tRPC was amazing. Try out the t3 stack, or at least tRPC.\",\n    likes: 19,\n    retweets: 2,\n    replies: 0,\n    quotes: 0,\n  },\n\n  // https://twitter.com/jonhigger/status/1570054715240763393\n  {\n    id: \"1570054715240763393\",\n    handle: \"jonhigger\",\n    author: \"jon\",\n    verified: false,\n    avatar:\n      \"https://pbs.twimg.com/profile_images/1466866060007723008/QXEf5Vbs_400x400.jpg\",\n    date: new Date(\"2022-09-14T18:19:00.000Z\"),\n    text: \"If you're a Rails developer, you should give full stack TS frameworks a try. @remix_run 's stacks or @pingdotgg 's create-t3-app are two great options. If you learn these tools, your long term productivity will be faster than Rails. The performance benefits are just a side bonus.\",\n    likes: 5,\n    retweets: 1,\n    replies: 1,\n    quotes: 0,\n  },\n];\n"
  },
  {
    "path": "www/src/components/landingPage/tweets/tweetCard.astro",
    "content": "---\nimport { Image } from \"astro:assets\";\n\nimport { type Tweet } from \"./featuredTweets\";\n\nconst {\n  id,\n  handle,\n  author,\n  verified,\n  avatar,\n  date,\n  text,\n  likes,\n  retweets,\n  replies,\n} = Astro.props as Tweet;\n---\n\n<article\n  class=\"flex flex-wrap items-start rounded-lg border border-t3-purple-200/20 bg-white/10 bg-cover px-4 pb-1 pt-4 transition-colors hover:border-t3-purple-300/50 hover:bg-white/20 hover:no-underline\"\n>\n  <Image\n    src={avatar}\n    width={48}\n    height={48}\n    format=\"webp\"\n    class=\"mr-3 h-12 w-12 rounded-full\"\n    alt={`@${handle}'s Avatar`}\n  />\n  <div class=\"flex flex-1 flex-wrap justify-start\">\n    <div class=\"flex flex-1 items-center\">\n      <div>\n        <h3 class=\"mr-2 font-bold hover:underline\">\n          <a\n            href={`https://twitter.com/${handle}`}\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            class=\"text-sm hover:text-[#1da1f2] sm:text-base\"\n          >\n            {author}\n          </a>\n        </h3>\n        {\n          verified && (\n            <span class=\"mr-2\">\n              <svg\n                class=\"h-4 w-4\"\n                fill=\"#1da1f2\"\n                viewBox=\"0 0 24 24\"\n                aria-label=\"Verified account\"\n              >\n                <g>\n                  <path d=\"M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z\" />\n                </g>\n              </svg>\n            </span>\n          )\n        }\n        <a\n          href={`https://twitter.com/${handle}`}\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"mr-1 whitespace-nowrap text-sm text-t3-purple-100 hover:text-[#1da1f2] lg:text-sm\"\n        >\n          @{handle}\n        </a>\n      </div>\n    </div>\n    <a\n      href={`https://twitter.com/${handle}/status/${id}`}\n      target=\"_blank\"\n      rel=\"noopener noreferrer\"\n      class=\"whitespace-nowrap text-sm text-t3-purple-100 hover:text-[#1da1f2] lg:text-sm\"\n    >\n      {date.toDateString()}\n    </a>\n  </div>\n  <div class=\"w-full\">\n    <p class=\"my-1 whitespace-pre-line text-sm xl:text-base\">{text}</p>\n\n    <div class=\"flex items-center justify-start py-2\">\n      <div\n        class=\"mr-8 flex items-center text-t3-purple-100 hover:text-blue-500\"\n      >\n        <a\n          aria-label={`Comment on ${author.split(\" (\")[0]}'s Tweet`}\n          href={`https://twitter.com/intent/tweet?in_reply_to=${id}`}\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"flex h-8 w-8 items-center justify-center rounded-full hover:text-blue-500\"\n        >\n          <svg viewBox=\"0 0 24 24\" class=\"h-5 w-5 fill-current\">\n            <g>\n              <path\n                d=\"M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z\"\n              ></path>\n            </g>\n          </svg>\n        </a>\n        <span class=\"ml-1\">{replies}</span>\n      </div>\n      <div\n        class=\"mr-8 flex items-center text-t3-purple-100 hover:text-green-500\"\n      >\n        <a\n          aria-label={`Retweet ${author.split(\" (\")[0]}'s Tweet`}\n          href={`https://twitter.com/intent/retweet?tweet_id=${id}`}\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"flex h-8 w-8 items-center justify-center rounded-full hover:text-green-500\"\n        >\n          <svg viewBox=\"0 0 24 24\" class=\"h-5 w-5 fill-current\">\n            <g>\n              <path\n                d=\"M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z\"\n              ></path>\n            </g>\n          </svg>\n        </a>\n        <span class=\"ml-1\">{retweets}</span>\n      </div>\n      <div class=\"mr-6 flex items-center text-t3-purple-100 hover:text-red-500\">\n        <a\n          aria-label={`Like ${author.split(\" (\")[0]}'s Tweet`}\n          href={`https://twitter.com/intent/like?tweet_id=${id}`}\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"flex h-8 w-8 items-center justify-center rounded-full hover:text-red-500\"\n        >\n          <svg viewBox=\"0 0 24 24\" class=\"h-5 w-5 fill-current\">\n            <g>\n              <path\n                d=\"M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z\"\n              ></path>\n            </g>\n          </svg>\n        </a>\n        <span class=\"ml-1\">{likes}</span>\n      </div>\n    </div>\n  </div>\n</article>\n"
  },
  {
    "path": "www/src/components/landingPage/tweets/tweetSlider.astro",
    "content": "---\nimport { type Tweet } from \"./featuredTweets\";\nimport TweetCard from \"./tweetCard.astro\";\n\nexport interface Props {\n  tweets: Tweet[];\n}\n\nconst { tweets } = Astro.props as Props;\n---\n\n<div class=\"w-full cursor-grab overflow-hidden rounded-lg\" id=\"tweet-slider\">\n  <div class=\"flex w-full space-x-5\">\n    {\n      tweets.map((tweet) => (\n        <div class=\"w-full shrink-0 first:ml-0 last:mr-0\">\n          <TweetCard {...tweet} />\n        </div>\n      ))\n    }\n  </div>\n\n  {/* Pagination */}\n  <div class=\"mb-10 mt-6 flex justify-center\">\n    {\n      tweets.map((_, idx) => (\n        // Larger click area while keeping the visual circles small\n        <button\n          aria-label={`Scroll to slide ${idx + 1}`}\n          class=\"0 -mx-0.5 p-1.5\"\n          data-slider-page={idx}\n        >\n          <div\n            class:list={[\n              \"aspect-square h-2 rounded-full bg-white/20 transition-colors ease-in-out [&.active]:bg-primary [&:not(.active)]:hover:bg-white/40\",\n              {\n                active: idx === 0,\n              },\n            ]}\n          />\n        </button>\n      ))\n    }\n  </div>\n</div>\n\n<script>\n  import Embla from \"embla-carousel\";\n  import autoplay from \"embla-carousel-autoplay\";\n\n  const sliderElement = document.getElementById(\"tweet-slider\");\n\n  if (!sliderElement) throw new Error(\"Slider is missing\");\n\n  const embla = Embla(\n    sliderElement,\n    {\n      skipSnaps: false,\n    },\n    [\n      autoplay({\n        delay: 3000,\n        stopOnMouseEnter: true,\n        stopOnInteraction: false,\n      }),\n    ],\n  );\n\n  const paginationButtons = document.querySelectorAll(\"[data-slider-page]\");\n\n  paginationButtons.forEach((paginationButton) => {\n    const page = paginationButton.getAttribute(\"data-slider-page\");\n\n    if (!page) return;\n\n    paginationButton.addEventListener(\"click\", () => {\n      embla.scrollTo(+page);\n    });\n  });\n\n  embla.on(\"select\", () => {\n    const previousSlideIndex = embla.previousScrollSnap();\n    const previousSlideButton = paginationButtons[previousSlideIndex];\n\n    if (previousSlideButton) {\n      previousSlideButton?.firstElementChild?.classList.remove(\"active\");\n    }\n\n    const currentSlideIndex = embla.selectedScrollSnap();\n    const currentSlideButton = paginationButtons[currentSlideIndex];\n\n    if (currentSlideButton) {\n      currentSlideButton?.firstElementChild?.classList.add(\"active\");\n    }\n  });\n\n  // Disable tab navigation for tweet slides\n  sliderElement.querySelectorAll(\"a\").forEach((a) => {\n    a.tabIndex = -1;\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/landingPage/tweets/tweets.astro",
    "content": "---\nimport PageSection from \"../pageSection.astro\";\nimport { featuredTweets } from \"./featuredTweets\";\nimport TweetSlider from \"./tweetSlider.astro\";\n---\n\n<PageSection\n  size={\"24\"}\n  className=\"mx-auto grid max-w-7xl grid-cols-1 gap-4 px-4 pb-12 sm:px-6 md:grid-cols-2 md:gap-10 lg:px-8\"\n  id=\"love\"\n>\n  <div\n    class=\"order-first mb-10 flex flex-col items-start text-left md:order-last\"\n  >\n    <h2\n      class=\"text-xl font-semibold text-t3-purple-200 md:text-2xl lg:text-2xl\"\n    >\n      Well loved in production (and on Twitter)\n    </h2>\n    <h3\n      class=\"mt-2 text-3xl font-bold tracking-tight text-t3-purple-50 md:text-5xl lg:text-5xl\"\n    >\n      Our users ship. <span class=\"italic\">Fast.</span>\n    </h3>\n    <p\n      class=\"mt-4 max-w-3xl text-base text-t3-purple-200 md:text-lg lg:text-lg\"\n    >\n      Mention <a\n        href=\"https://twitter.com/search?q=create-t3-app\"\n        rel=\"noopener noreferrer\"\n        class=\"text-t3-purple-100\">create-t3-app</a\n      > if you want to pop up here ;)\n    </p>\n  </div>\n  <TweetSlider tweets={featuredTweets} />\n</PageSection>\n"
  },
  {
    "path": "www/src/components/navigation/LanguageSelect.tsx",
    "content": "import { Listbox, Transition } from \"@headlessui/react\";\nimport clsx from \"clsx\";\nimport { Fragment } from \"react\";\n\nimport { KNOWN_LANGUAGES, type KnownLanguageCode } from \"../../config\";\nimport { getIsRtlFromLangCode } from \"../../languages\";\n\ninterface LanguageSelectProps {\n  language: KnownLanguageCode;\n}\n\nexport default function LanguageSelect({ language }: LanguageSelectProps) {\n  const handleSelect = (code: string) => {\n    const [_1, _2, ...slug] = window.location.pathname.split(\"/\");\n    window.location.pathname = `/${code}/${slug.join(\"/\")}`;\n  };\n\n  const isRTL = getIsRtlFromLangCode(language);\n\n  return (\n    <div className=\"flex items-center gap-2\">\n      <Listbox value={language} onChange={handleSelect}>\n        <div className=\"relative\">\n          <Listbox.Button className=\"relative flex cursor-pointer items-center justify-center rounded-lg border bg-t3-purple-200/50 p-2 text-left focus:outline-none hover:bg-t3-purple-200/75 sm:text-sm dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\">\n            <svg\n              viewBox=\"0 0 88.6 77.3\"\n              className=\"h-6 w-6 text-slate-900 dark:text-t3-purple-100\"\n              role=\"img\"\n            >\n              <path\n                fill=\"currentColor\"\n                d=\"M61 24.6h7.9l18.7 51.6h-7.7l-5.4-15.5H54.3l-5.6 15.5h-7.2L61 24.6zM72.6 55l-8-22.8L56.3 55h16.3z\"\n              ></path>\n              <path\n                fill=\"currentColor\"\n                d=\"M53.6 60.6c-10-4-16-9-22-14 0 0 1.3 1.3 0 0-6 5-20 13-20 13l-4-6c8-5 10-6 19-13-2.1-1.9-12-13-13-19h8c4 9 10 14 10 14 10-8 10-19 10-19h8s-1 13-12 24c5 5 10 9 19 13l-3 7zm-52-44h56v-8h-23v-7h-9v7h-24v8z\"\n              ></path>\n            </svg>\n          </Listbox.Button>\n          <Transition\n            as={Fragment}\n            enter={\"transition ease-out duration-100\"}\n            enterFrom={\"transform opacity-0 -translate-y-1\"}\n            enterTo={\"transform opacity-100 -translate-y-0\"}\n          >\n            <Listbox.Options\n              dir=\"ltr\"\n              className={clsx(\n                \"focus-none shadow-l t3-scrollbar absolute right-0 mt-1 max-h-60 w-fit overflow-auto rounded-lg border bg-default text-base focus:outline-none focus-visible:outline-none sm:text-sm dark:border-t3-purple-200/20\",\n                isRTL && \"text-right\",\n              )}\n            >\n              {Object.entries(KNOWN_LANGUAGES).map(([code, name]) => (\n                <Listbox.Option\n                  key={code}\n                  className={({ selected, active }) =>\n                    `focus-none relative cursor-pointer bg-t3-purple-200/50 px-4 py-2 text-slate-900 outline-none hover:bg-t3-purple-300/75 dark:bg-t3-purple-200/10 dark:text-t3-purple-100 dark:hover:bg-t3-purple-200/20 ${\n                      selected && \"bg-t3-purple-400/75 dark:bg-t3-purple-400/20\"\n                    } ${active && \"bg-t3-purple-300/75 dark:bg-t3-purple-200/20\"}`\n                  }\n                  value={code}\n                >\n                  {({ selected }) => (\n                    <span\n                      className={clsx(\n                        \"truncate\",\n                        selected && \"font-medium\",\n                        !selected && \"font-normal\",\n                      )}\n                    >\n                      {name}\n                    </span>\n                  )}\n                </Listbox.Option>\n              ))}\n            </Listbox.Options>\n          </Transition>\n        </div>\n      </Listbox>\n    </div>\n  );\n}\n"
  },
  {
    "path": "www/src/components/navigation/OnThisPageLinks.tsx",
    "content": "import { Menu } from \"@headlessui/react\";\nimport { type MarkdownHeading } from \"astro\";\nimport clsx from \"clsx\";\nimport { useEffect, useMemo, useState } from \"react\";\n\ninterface OnThisPageLinksProps {\n  headings: MarkdownHeading[];\n  title: string;\n  isRtl: boolean;\n}\n\nexport default function OnThisPageLinks({\n  headings,\n  title,\n  isRtl,\n}: OnThisPageLinksProps) {\n  const isLtr = !isRtl;\n\n  const memoedHeadings = useMemo(() => {\n    // add isVisible flag in headers\n    const headers = [\n      { depth: 2, slug: \"overview\", text: title, isVisible: true },\n      ...headings.map((h) => ({ ...h, isVisible: false })),\n    ];\n\n    return headers.filter(({ depth }) => depth > 1 && depth < 4);\n  }, [headings, title]);\n\n  const [headingWithIsVisible, setHeadingWithIsVisible] =\n    useState(memoedHeadings);\n\n  useEffect(() => {\n    const articleHeadings = Array.from(\n      document.querySelectorAll(\"article :is(h1,h2,h3)\"),\n    );\n\n    const allObservers = articleHeadings.map((h) => {\n      const observer = new IntersectionObserver(\n        (entries) => {\n          entries.forEach((entry) => {\n            const id = entry.target.id;\n            const tocItem = Array.from(\n              document.querySelectorAll(`a[href=\"#${id}\"]`),\n            ).at(-1);\n            // occurs when the id = \"toc-heading\"\n            if (!tocItem) return;\n\n            if (entry.isIntersecting) {\n              const headings = headingWithIsVisible.map((h) =>\n                h.slug === id\n                  ? { ...h, isVisible: true }\n                  : { ...h, isVisible: false },\n              );\n              setHeadingWithIsVisible(headings);\n            }\n          });\n        },\n        {\n          rootMargin: \"-100px 0% -66%\",\n          threshold: 1,\n        },\n      );\n\n      observer.observe(h);\n\n      return observer;\n    });\n\n    return () => {\n      // unobserve elements\n      articleHeadings.map((h, index) => {\n        allObservers[index]?.unobserve(h);\n      });\n    };\n  }, [headings, title]);\n\n  return (\n    <div className=\"sticky inset-x-0 top-[72px] z-[11] block w-full bg-default px-4 pb-4 pt-2 lg:hidden\">\n      <Menu>\n        {({ open }) => (\n          <div className=\"relative w-full\">\n            <div className=\"\">\n              <Menu.Button className=\"text-md inline-flex cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-md border-2 bg-t3-purple-200/50 px-3 py-2 font-medium hover:bg-t3-purple-200/75 dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\">\n                On this page\n                <svg\n                  xmlns=\"http://www.w3.org/2000/svg\"\n                  fill=\"none\"\n                  viewBox=\"0 0 24 24\"\n                  strokeWidth={1.5}\n                  stroke=\"currentColor\"\n                  className={clsx(\n                    \"h-3 w-3 sm:h-4 sm:w-4\",\n                    isRtl && \"-scale-x-100\",\n                  )}\n                >\n                  <path\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                    d={\n                      open\n                        ? \"M19.5 8.25l-7.5 7.5-7.5-7.5\"\n                        : \"M8.25 4.5l7.5 7.5-7.5 7.5\"\n                    }\n                  />\n                </svg>\n              </Menu.Button>\n            </div>\n            <Menu.Items\n              dir=\"ltr\"\n              className=\"t3-scrollbar absolute top-full z-10 mt-3 max-h-[45vh] w-full overflow-y-auto rounded-md border-2 border-primary bg-default py-1.5 shadow-md dark:border-t3-purple-200/20 dark:bg-default\"\n            >\n              <ul dir={isLtr ? \"ltr\" : \"rtl\"}>\n                {headingWithIsVisible.map((heading) => (\n                  <li key={heading.slug} className=\"w-full\">\n                    <Menu.Item>\n                      {({ active }) => (\n                        <a\n                          className={clsx(\n                            \"text-md line-clamp-1 block w-full py-2 text-t3-purple-800 transition-colors hover:bg-t3-purple-300/20 hover:text-t3-purple-400 dark:text-t3-purple-200 dark:hover:bg-t3-purple-300/10 dark:hover:text-t3-purple-50\",\n                            isLtr && (heading.depth === 2 ? \"pl-3\" : \"pl-8\"),\n                            isRtl && (heading.depth === 2 ? \"pr-3\" : \"pr-8\"),\n                            {\n                              \"bg-t3-purple-300/20 text-t3-purple-400 underline dark:bg-t3-purple-300/10 dark:text-t3-purple-100\":\n                                active,\n                              \"bg-t3-purple-300/30 font-medium text-t3-purple-700 underline dark:bg-t3-purple-300/20 dark:text-t3-purple-100\":\n                                heading.isVisible,\n                            },\n                          )}\n                          href={`#${heading.slug}`}\n                        >\n                          {heading.text}\n                        </a>\n                      )}\n                    </Menu.Item>\n                  </li>\n                ))}\n              </ul>\n            </Menu.Items>\n          </div>\n        )}\n      </Menu>\n    </div>\n  );\n}\n"
  },
  {
    "path": "www/src/components/navigation/Search.tsx",
    "content": "/** @jsxImportSource react */\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport { ALGOLIA } from \"../../config\";\n\nimport \"../../styles/algolia/style.css\";\n\nimport * as docSearchReact from \"@docsearch/react\";\nimport clsx from \"clsx\";\nimport { createPortal } from \"react-dom\";\n\n/** FIXME: This is still kinda nasty, but DocSearch is not ESM ready. */\nconst DocSearchModal =\n  docSearchReact.DocSearchModal ||\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n  (docSearchReact as any).default.DocSearchModal;\nconst useDocSearchKeyboardEvents =\n  docSearchReact.useDocSearchKeyboardEvents ||\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n  (docSearchReact as any).default.useDocSearchKeyboardEvents;\n\nexport default function Search({ isLanding }: { isLanding: boolean }) {\n  const [isOpen, setIsOpen] = useState(false);\n  const searchButtonRef = useRef<HTMLButtonElement>(null);\n  const [initialQuery, setInitialQuery] = useState(\"\");\n\n  const onOpen = useCallback(() => {\n    setIsOpen(true);\n  }, [setIsOpen]);\n\n  const onClose = useCallback(() => {\n    setIsOpen(false);\n  }, [setIsOpen]);\n\n  const onInput = useCallback(\n    (e: KeyboardEvent) => {\n      setIsOpen(true);\n      setInitialQuery(e.key);\n    },\n    [setIsOpen, setInitialQuery],\n  );\n\n  useDocSearchKeyboardEvents({\n    isOpen,\n    onOpen,\n    onClose,\n    onInput,\n    searchButtonRef,\n  });\n\n  return (\n    <>\n      <button\n        type=\"button\"\n        aria-label=\"Search Create T3 App\"\n        ref={searchButtonRef}\n        onClick={onOpen}\n        className={clsx(\n          \"flex w-full cursor-text items-center justify-between rounded-lg px-4 py-2 text-sm font-medium text-slate-800 !transition-colors !duration-300 dark:text-slate-100\",\n          {\n            \"hover:bg-t3-purple/20 border border-t3-purple-200/20 bg-t3-purple-200/10 duration-300 hover:border-t3-purple-200/50\":\n              isLanding,\n            \"dark:hover:bg-t3-purple/20 border bg-t3-purple-200/50 duration-300 hover:bg-t3-purple-200/75 dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:text-slate-100 dark:hover:border-t3-purple-200/50\":\n              !isLanding,\n          },\n        )}\n      >\n        <div className=\"flex items-center justify-center gap-1 lg:gap-3\">\n          <svg className=\"h-6 w-6\" fill=\"none\">\n            <path\n              d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            />\n          </svg>\n\n          <span>Search</span>\n        </div>\n\n        <span className=\"rounded-md border border-current px-1\">\n          <span className=\"sr-only\">Press </span>\n          <kbd>/</kbd>\n          <span className=\"sr-only\"> to search</span>\n        </span>\n      </button>\n\n      {isOpen &&\n        createPortal(\n          <div className=\"z-50\">\n            <DocSearchModal\n              initialQuery={initialQuery}\n              initialScrollY={window.scrollY}\n              onClose={onClose}\n              indexName={ALGOLIA.indexName}\n              appId={ALGOLIA.appId}\n              apiKey={ALGOLIA.apiKey}\n              transformItems={(items) => {\n                return items.map((item) => {\n                  // We transform the absolute URL into a relative URL to\n                  // work better on localhost, preview URLS.\n                  const a = document.createElement(\"a\");\n                  a.href = item.url;\n                  const hash = a.hash === \"#overview\" ? \"\" : a.hash;\n                  return {\n                    ...item,\n                    url: `${a.pathname}${hash}`,\n                  };\n                });\n              }}\n            />\n          </div>,\n          document.body,\n        )}\n    </>\n  );\n}\n"
  },
  {
    "path": "www/src/components/navigation/githubIcon.astro",
    "content": "---\nimport { getIsRtlFromUrl, getLanguageFromURL } from \"../../languages\";\nimport { fetchGithub } from \"../../utils/fetchGithub\";\n\nlet githubStars = 28000;\n\ntry {\n  const fetchedStars = await fetchGithub(\n    \"https://api.github.com/repos/t3-oss/create-t3-app\",\n    {\n      throwIfNoAuth: false,\n      fetchType: \"repo\",\n    },\n  ).then((data) => data?.stargazers_count);\n\n  githubStars = fetchedStars ?? 28000;\n} catch (e) {\n  console.error(\"unable to fetch from github\", e);\n}\n\nconst ONE_HOUR = 1 * 60 * 60;\n\nAstro.response.headers.set(\"Cache-Control\", `public, max-age=${ONE_HOUR}`);\n\nconst { pathname } = Astro.url;\n\nconst formattedStars = new Intl.NumberFormat(getLanguageFromURL(pathname), {\n  notation: \"compact\",\n}).format(githubStars);\n\nconst isRtl = getIsRtlFromUrl(pathname);\n---\n\n<a\n  id=\"github-link\"\n  href=\"https://github.com/t3-oss/create-t3-app\"\n  class=\"group flex items-center gap-1 rounded-lg no-underline\"\n  aria-label=\"github repository link\"\n>\n  <div\n    id=\"github-star\"\n    class:list={[\n      \"relative hidden items-center rounded-lg border border-t3-purple-200/50 bg-t3-purple-200/50 bg-clip-padding px-2 py-1 text-slate-800 no-underline !transition-colors !duration-300 group-hover:border-t3-purple-200/75 group-hover:bg-t3-purple-200/75 md:flex ltr:mr-[.33em] rtl:ml-[.33em] dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:text-slate-100 dark:group-hover:border-t3-purple-200/50 dark:group-hover:bg-t3-purple-200/10\",\n      [\n        /** triangle arrow */\n        \"after:absolute after:h-0 after:w-0 after:border-8 after:border-transparent after:transition-colors after:duration-300\",\n        isRtl &&\n          \"after:left-[calc(-0.5em-1px)] after:border-l-0 after:border-r-t3-purple-200/50 after:group-hover:border-r-t3-purple-200/75 dark:after:border-r-t3-purple-200/20 dark:after:group-hover:border-r-t3-purple-200/50\",\n        !isRtl &&\n          \"after:right-[calc(-0.5em-1px)] after:border-r-0 after:border-l-t3-purple-200/50 after:group-hover:border-l-t3-purple-200/75 dark:after:border-l-t3-purple-200/20 dark:after:group-hover:border-l-t3-purple-200/50\",\n      ],\n    ]}\n  >\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 576 512\"\n      class=\"h-4 w-4 fill-slate-900 transition-colors duration-300 [margin-inline-end:4px] dark:fill-t3-purple-100\"\n    >\n      <path\n        d=\"M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z\"\n      ></path>\n    </svg>\n    {formattedStars}\n  </div>\n  <svg\n    role=\"img\"\n    viewBox=\"0 0 24 24\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    id=\"github-icon\"\n    class=\"h-10 w-10 fill-slate-900 py-1 transition-colors duration-300 dark:fill-t3-purple-100\"\n    ><title>GitHub</title><path\n      d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\n    ></path>\n  </svg>\n</a>\n\n<style>\n  #github-link:hover {\n    text-decoration: none !important;\n  }\n</style>\n"
  },
  {
    "path": "www/src/components/navigation/leftSidebar.astro",
    "content": "---\nimport { SIDEBAR, SIDEBAR_HEADER_MAP, type Frontmatter } from \"../../config\";\nimport { getIsRtlFromUrl } from \"../../languages\";\nimport Search from \"./Search\";\n\nexport interface Props {\n  frontmatter?: Frontmatter;\n  currentPage: string;\n  isNotFound?: boolean;\n}\n\nconst { frontmatter, currentPage, isNotFound } = Astro.props;\nconst isLanding = currentPage === \"/\" || !!isNotFound;\nconst hasTrailing = currentPage.endsWith(\"/\");\nconst currentPageMatch = currentPage.slice(\n  1,\n  hasTrailing ? -1 : currentPage.length,\n);\nconst isRtl = getIsRtlFromUrl(currentPage);\n\nconst langCode = frontmatter?.lang ?? \"en\";\nconst englishSidebar = SIDEBAR[\"en\"];\nconst nativeSidebar = SIDEBAR[langCode];\nlet sidebar: Record<\n  string,\n  { text: string; link: string; isTranslated?: boolean }[]\n> = englishSidebar;\nif (langCode !== \"en\") {\n  sidebar = Object.fromEntries(\n    Object.entries(englishSidebar).map(([header, items]) => {\n      // Set header to translated one if it exists\n      const innerHeader = SIDEBAR_HEADER_MAP[langCode];\n      const nativeHeader =\n        innerHeader[header as keyof typeof innerHeader] ?? header;\n\n      const nativeItems = items.map((item) => {\n        const match = Object.values(nativeSidebar)\n          .flat()\n          .find(\n            ({ link: nativeLink }) =>\n              // trailing slash + language code\n              nativeLink.slice(langCode.length + 1) === item.link.slice(3),\n          );\n        return {\n          text: match?.text ?? item.text,\n          link: match?.link ?? item.link,\n          isTranslated: !!match,\n        };\n      });\n\n      return [nativeHeader, nativeItems];\n    }),\n  );\n}\n---\n\n<div class=\"mx-auto mb-6 ml--40 w-full px-6 md:ml-0 md:hidden md:px-8\">\n  <Search isLanding={isLanding} client:idle />\n</div>\n<div\n  dir=\"ltr\"\n  class=\"t3-scrollbar h-full w-full overflow-auto bg-default transition-colors duration-300 lg:mb-12\"\n>\n  <ul\n    dir={isRtl ? \"rtl\" : \"ltr\"}\n    class=\"px-4 pb-28 text-slate-900 md:pb-0 dark:text-t3-purple-50\"\n  >\n    {\n      Object.entries(sidebar).map(([header, children]) => (\n        <li>\n          <div>\n            <h2\n              class:list={[\n                \"pb-2 text-xl font-semibold transition-colors duration-300 sm:text-lg\",\n                {\n                  // mobile menu on landing page\n                  \"text-slate-50\": isLanding,\n                },\n              ]}\n            >\n              {header}\n            </h2>\n            <ul class=\"mb-2\">\n              {children.map((child) => {\n                const url = Astro.site?.pathname + child.link;\n                const isActive = currentPageMatch === child.link;\n                return (\n                  <li>\n                    <a\n                      href={url}\n                      aria-current={isActive ? \"page\" : false}\n                      class:list={[\n                        \"text-md block py-2 text-t3-purple-800 transition-colors [padding-inline-start:16px] hover:border-t3-purple-300/50 hover:bg-t3-purple-300/20 hover:text-t3-purple-400 dark:text-t3-purple-200 dark:hover:bg-t3-purple-300/10 dark:hover:text-t3-purple-100\",\n                        isActive\n                          ? \"border-t3-purple-300 bg-t3-purple-300/30 font-medium dark:bg-t3-purple-300/20\"\n                          : \"border-t3-purple-300/20\",\n                        isRtl ? \"border-r-2\" : \"border-l-2\",\n                      ]}\n                    >\n                      <span>{child.text}</span>\n                      {!child.isTranslated && langCode !== \"en\" && (\n                        <span class=\"text-xs text-t3-purple-400 [margin-inline-start:4px] dark:text-t3-purple-300\">\n                          EN\n                        </span>\n                      )}\n                    </a>\n                  </li>\n                );\n              })}\n            </ul>\n          </div>\n        </li>\n      ))\n    }\n  </ul>\n</div>\n"
  },
  {
    "path": "www/src/components/navigation/moreMenu.astro",
    "content": "---\nimport * as CONFIG from \"../../config\";\nimport { getIsRtlFromUrl, getLanguageFromURL } from \"../../languages\";\n\nexport interface Props {\n  editHref: string;\n}\n\nconst { editHref } = Astro.props;\nconst { pathname } = Astro.url;\nconst isRtl = getIsRtlFromUrl(pathname);\nconst isLangEN = getLanguageFromURL(pathname) === \"en\";\n---\n\n<div\n  dir={isRtl ? \"rtl\" : \"ltr\"}\n  class=\"flex w-full flex-col pt-8 text-center md:text-start lg:py-0\"\n>\n  <h2\n    class=\"mb-4 hidden text-lg font-semibold text-slate-900 md:block dark:text-t3-purple-50\"\n  >\n    More\n  </h2>\n\n  <ul class=\"flex flex-col items-center gap-2 text-sm md:items-start\">\n    <li\n      class=\"hidden text-t3-purple-800 hover:text-t3-purple-400 md:block dark:text-t3-purple-200 dark:hover:text-t3-purple-100\"\n    >\n      <a\n        class=\"flex items-center gap-2\"\n        href={editHref}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n      >\n        <span>\n          <svg\n            class=\"svg-inline--fa fa-pen fa-w-16 inline\"\n            aria-hidden=\"true\"\n            focusable=\"false\"\n            data-prefix=\"fas\"\n            data-icon=\"pen\"\n            role=\"img\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            viewBox=\"0 0 512 512\"\n            height=\"1em\"\n            width=\"1em\"\n          >\n            <path\n              fill=\"currentColor\"\n              d=\"M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z\"\n            ></path>\n          </svg>\n        </span>\n        <span> Edit this page</span>\n      </a>\n    </li>\n\n    <li\n      class:list={[\n        \"hidden text-t3-purple-800 hover:text-t3-purple-400 dark:text-t3-purple-200 dark:hover:text-t3-purple-100\",\n        isLangEN && \"md:block\",\n      ]}\n    >\n      <a\n        class=\"flex items-center gap-2\"\n        href={\"https://github.com/t3-oss/create-t3-app/blob/main/www/TRANSLATIONS.md\"}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n      >\n        <span>\n          <svg\n            aria-hidden=\"true\"\n            focusable=\"false\"\n            role=\"img\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            viewBox=\"0 0 88.6 77.3\"\n            height=\"1.3em\"\n            width=\"1.3em\"\n            style=\"margin: -2px;\"\n          >\n            <path\n              fill=\"currentColor\"\n              d=\"M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z\"\n            ></path>\n            <path\n              fill=\"currentColor\"\n              d=\"M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8          c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z\"\n            ></path>\n          </svg>\n        </span>\n        <span> Translate this page</span>\n      </a>\n    </li>\n\n    <li\n      class=\"text-t3-purple-800 hover:text-t3-purple-400 dark:text-t3-purple-200 dark:hover:text-t3-purple-100\"\n    >\n      <a\n        class=\"items-top flex gap-2\"\n        href={CONFIG.COMMUNITY_INVITE_URL}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n      >\n        <span>\n          <svg\n            class=\"svg-inline--fa fa-comment-alt fa-w-16 inline\"\n            aria-hidden=\"true\"\n            focusable=\"false\"\n            data-prefix=\"fas\"\n            data-icon=\"comment-alt\"\n            role=\"img\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            viewBox=\"0 0 512 512\"\n            height=\"1em\"\n            width=\"1em\"\n          >\n            <path\n              fill=\"currentColor\"\n              d=\"M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z\"\n            ></path>\n          </svg>\n        </span>\n        <span> Join Our Discord Community</span>\n      </a>\n    </li>\n  </ul>\n</div>\n"
  },
  {
    "path": "www/src/components/navigation/navbar.astro",
    "content": "---\nimport { getIsRtlFromUrl, getLanguageFromURL } from \"../../languages\";\nimport GithubIcon from \"./githubIcon.astro\";\nimport LanguageSelect from \"./LanguageSelect\";\nimport Search from \"./Search\";\nimport SidebarToggle from \"./sidebarToggle.astro\";\nimport ThemeToggleButton from \"./themeToggleButton.astro\";\n\nexport interface Props {\n  isNotFound?: boolean;\n}\n\nconst { pathname } = Astro.url;\nconst isRtl = getIsRtlFromUrl(pathname);\nconst isLtr = !isRtl;\nconst isLanding = pathname === \"/\" || !!Astro.props.isNotFound;\nconst hasTrailing = pathname.endsWith(\"/\");\nconst currentPage = pathname.slice(0, hasTrailing ? -1 : pathname.length);\nconst langCode = getLanguageFromURL(pathname);\n\nconst navbarLinks: Array<{ href: string; label: string }> = [\n  {\n    href: `/${langCode}/introduction`,\n    label: \"Docs\",\n  },\n  {\n    href: `/${langCode}/faq`,\n    label: \"FAQ\",\n  },\n];\n---\n\n<nav\n  class:list={[\n    \"navbar relative flex flex-col items-center justify-between py-4\",\n    {\n      \"z-40 text-slate-50\": isLanding,\n      \"transition-colors duration-300\": !isLanding,\n    },\n  ]}\n  aria-label=\"Global\"\n>\n  <div class=\"flex w-full max-w-7xl items-center justify-between px-4\">\n    <div class=\"flex w-full items-center justify-between md:w-auto\">\n      <div>\n        <a href=\"/\" class=\"flex\" title=\"Home\" data-home-link>\n          <img\n            class=\"block dark:hidden\"\n            width=\"50\"\n            height=\"50\"\n            src=\"/images/t3-dark.svg\"\n            alt=\"T3 Logo Dark\"\n          />\n          <img\n            class=\"hidden dark:block\"\n            width=\"50\"\n            height=\"50\"\n            src=\"/images/t3-light.svg\"\n            alt=\"T3 Logo Light\"\n          />\n        </a>\n      </div>\n      <div\n        class:list={[\n          \"hidden gap-2 -space-x-1 md:flex\",\n          isLtr && \"md:ml-10\",\n          isRtl && \"md:mr-10\",\n        ]}\n      >\n        {\n          navbarLinks.map((navbarLink) => (\n            <a\n              class:list={[\n                \"relative inline-flex items-center rounded-md border border-transparent px-3 py-2 transition-colors hover:no-underline\",\n                {\n                  \"border bg-t3-purple-200/50 text-t3-purple-800 dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\":\n                    navbarLink.href === currentPage,\n                  \"rounded-lg text-t3-purple-100 hover:bg-t3-purple-200/10 hover:text-t3-purple-300\":\n                    isLanding,\n                  \"rounded-lg text-t3-purple-800 hover:bg-t3-purple-200/50 hover:text-t3-purple-800 dark:text-t3-purple-100 dark:hover:bg-t3-purple-200/10 dark:hover:text-t3-purple-300\":\n                    !isLanding,\n                },\n              ]}\n              aria-current={navbarLink.href === currentPage ? \"page\" : \"false\"}\n              href={navbarLink.href}\n            >\n              {navbarLink.label}\n            </a>\n          ))\n        }\n      </div>\n    </div>\n    <div class=\"flex flex-grow items-center justify-end gap-4\">\n      <GithubIcon />\n      {!isLanding && <LanguageSelect language={langCode} client:load />}\n      <div\n        class:list={[\n          \"text-center\",\n          {\n            hidden: isLanding,\n          },\n        ]}\n      >\n        <ThemeToggleButton />\n      </div>\n      <div class=\"block md:hidden\">\n        <SidebarToggle isLanding={isLanding} />\n      </div>\n      <div class=\"hidden w-full max-w-xs rounded-lg md:block\">\n        <Search isLanding={isLanding} client:load />\n      </div>\n    </div>\n  </div>\n</nav>\n<script>\n  const logo = document.querySelector(\"[data-home-link]\") as HTMLAnchorElement;\n\n  logo.addEventListener(\"contextmenu\", (e) => {\n    e.preventDefault();\n    window.location.pathname = \"/branding\";\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/navigation/rightSidebar.astro",
    "content": "---\nimport { type MarkdownHeading } from \"astro\";\n\nimport MoreMenu from \"./moreMenu.astro\";\nimport TableOfContents from \"./tableOfContents.astro\";\n\nexport interface Props {\n  headings: MarkdownHeading[];\n  githubEditUrl: string;\n  title: string;\n}\n\nconst { headings, githubEditUrl, title } = Astro.props;\n---\n\n<TableOfContents headings={headings} title={title} />\n<MoreMenu editHref={githubEditUrl} />\n"
  },
  {
    "path": "www/src/components/navigation/sidebarToggle.astro",
    "content": "---\nexport interface Props {\n  isLanding: boolean;\n}\n\nconst { isLanding } = Astro.props;\n---\n\n<button\n  id=\"sidebar-toggle\"\n  type=\"button\"\n  aria-pressed=\"false\"\n  class:list={[\n    \"z-20 block md:hidden\",\n    {\n      \"text-white\": isLanding,\n      \"text-black dark:text-white\": !isLanding,\n    },\n  ]}\n>\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    class=\"h-10 w-10 fill-transparent stroke-current\"\n    viewBox=\"0 0 24 24\"\n  >\n    <path\n      stroke-linecap=\"round\"\n      stroke-linejoin=\"round\"\n      stroke-width=\"2\"\n      d=\"M4 6h16M4 12h16M4 18h16\"></path>\n  </svg>\n  <span class=\"sr-only\">Toggle sidebar</span>\n</button>\n\n<script is:inline>\n  const button = document.querySelector(\"#sidebar-toggle\");\n\n  button.addEventListener(\"click\", () => {\n    // html query selector is already defined in the themeToggleButton script\n    html.classList.toggle(\"mobile-sidebar-toggle\");\n    button.toggleAttribute(\"aria-pressed\");\n    button.innerHTML =\n      button.getAttribute(\"aria-pressed\") === null\n        ? `<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 w-10 stroke-current fill-transparent\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path></svg><span class=\"sr-only\">Close sidebar</span>`\n        : `<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-10 w-10 stroke-current fill-transparent\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path></svg><span class=\"sr-only\">Toggle sidebar</span>`;\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/navigation/tableOfContents.astro",
    "content": "---\nimport { type MarkdownHeading } from \"astro\";\n\nimport { getIsRtlFromUrl } from \"../../languages\";\n\nexport interface Props {\n  headings: MarkdownHeading[];\n  title: string;\n}\n\nlet { headings, title } = Astro.props;\nheadings = [{ depth: 2, slug: \"overview\", text: title }, ...headings].filter(\n  ({ depth }) => depth > 1 && depth < 4,\n);\n\nconst { pathname } = Astro.url;\nconst isRtl = getIsRtlFromUrl(pathname);\n---\n\n<div dir={isRtl ? \"rtl\" : \"ltr\"}>\n  <h2\n    class=\"mb-4 text-lg font-semibold text-slate-900 dark:text-t3-purple-50\"\n    id=\"toc-heading\"\n  >\n    On this page\n  </h2>\n  <ul class=\"mb-4 w-full list-none marker:text-t3-purple-300\">\n    {\n      headings.map((heading) => {\n        const { depth, slug, text } = heading;\n\n        //add data-component-type to headings to be able to filter them in the sidebar\n        let dataComponentType = \"\";\n        switch (text) {\n          case \"prisma\":\n            dataComponentType = \"prisma\";\n            break;\n          case \"src/types\":\n          case \"src/server/auth.ts\":\n            dataComponentType = \"nextauth\";\n            break;\n          case \"postcss.config.js\":\n          case \"prettier.config.mjs\":\n            dataComponentType = \"tailwind\";\n            break;\n          case \"src/server/api\":\n          case \"src/server/api/routers\":\n          case \"src/utils\":\n            dataComponentType = \"trpc\";\n            break;\n        }\n\n        return (\n          <li\n            data-components={dataComponentType || null}\n            class:list={[\n              \"w-full list-none border-t3-purple-300/20 p-1 text-sm transition-colors duration-300 hover:border-t3-purple-300/50\",\n              isRtl\n                ? [\"border-r-2\", depth === 2 ? \"pr-2\" : \"pr-4\"]\n                : [\"border-l-2\", depth === 2 ? \"pl-2\" : \"pl-4\"],\n            ]}\n          >\n            <a\n              class=\"text-t3-purple-800 hover:text-t3-purple-400 dark:text-t3-purple-200 dark:hover:text-t3-purple-100\"\n              href={`#${slug}`}\n            >\n              {text}\n            </a>\n          </li>\n        );\n      })\n    }\n  </ul>\n</div>\n\n<script is:inline>\n  // Toggle classes when items are in view\n  document.querySelectorAll(\"article :is(h1,h2,h3)\").forEach((h) => {\n    new IntersectionObserver(\n      (entries) => {\n        entries.forEach((entry) => {\n          const id = entry.target.id;\n          // have to do \"All\" here cause we render this component in pageContent for mobile too\n          const tocItem = Array.from(\n            document.querySelectorAll(`a[href=\"#${id}\"]`),\n          ).at(-1);\n          // this occurs when the id = \"toc-heading\"\n          if (!tocItem) return;\n\n          if (entry.isIntersecting) {\n            // get current all active elements\n            const currentActiveElements = Array.from(\n              document.querySelectorAll(\n                `[data-current-active-tab-content-item=\"true\"]`,\n              ),\n            );\n\n            // get current all parent active elements\n            const currentActiveParentElements = Array.from(\n              document.querySelectorAll(\n                `[data-current-active-parent-tab-content-item=\"true\"]`,\n              ),\n            );\n\n            // if has active elements\n            if (currentActiveElements.length) {\n              // loop through all elements and remove class and attr\n              for (const el of currentActiveElements) {\n                el.classList.remove(\n                  \"font-medium\",\n                  \"bg-t3-purple-300/20\",\n                  \"text-t3-purple-700\",\n                  \"dark:text-t3-purple-100\",\n                );\n                el.removeAttribute(\"data-current-active-tab-content-item\");\n              }\n            }\n            // if has active parent elements\n            if (currentActiveParentElements.length) {\n              // loop through all parent elements and remove class and attr\n              for (const parentEl of currentActiveParentElements) {\n                parentEl.classList.remove(\n                  \"dark:bg-t3-purple-300/20\",\n                  \"bg-t3-purple-300/30\",\n                  \"border-t3-purple-300/100\",\n                );\n                parentEl.removeAttribute(\n                  \"data-current-active-parent-tab-content-item\",\n                );\n              }\n            }\n\n            tocItem.classList.add(\n              \"font-medium\",\n              \"text-t3-purple-700\",\n              \"dark:text-t3-purple-100\",\n            );\n            tocItem.parentElement.classList.add(\n              \"border-t3-purple-300/100\",\n              \"dark:bg-t3-purple-300/20\",\n              \"bg-t3-purple-300/30\",\n            );\n            // set data attr to active element also will helpful when need to remove active state\n            tocItem.setAttribute(\"data-current-active-tab-content-item\", true);\n            tocItem.parentElement.setAttribute(\n              \"data-current-active-parent-tab-content-item\",\n              true,\n            );\n          }\n        });\n      },\n      {\n        rootMargin: \"-100px 0% -66%\",\n        threshold: 1,\n      },\n    ).observe(h);\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/navigation/themeToggleButton.astro",
    "content": "<button\n  class=\"mx-auto flex w-fit gap-3 rounded-lg border bg-t3-purple-200/50 p-2 hover:bg-t3-purple-200/75 dark:border-t3-purple-200/20 dark:bg-t3-purple-200/10 dark:hover:border-t3-purple-200/50\"\n  name=\"theme-toggle\"\n>\n  <label class=\"cursor-pointer text-t3-purple-500 dark:text-slate-50\">\n    <!-- Sun -->\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      class=\"h-6 w-6 fill-current stroke-current stroke-2 transition-colors duration-300\"\n      viewBox=\"0 0 24 24\"\n    >\n      <path\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        d=\"M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z\"\n      ></path>\n    </svg>\n  </label>\n  <label class=\"cursor-pointer text-slate-900 dark:text-t3-purple-500\">\n    <!-- Moon -->\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      class=\"h-6 w-6 fill-current stroke-current transition-colors duration-300\"\n      viewBox=\"0 0 20 20\"\n    >\n      <path\n        d=\"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z\"\n      ></path>\n    </svg>\n  </label>\n</button>\n\n<script>\n  const html = document.documentElement;\n\n  const themeToggle = document.querySelector('[name=\"theme-toggle\"]');\n\n  const getMessage = () => {\n    const theme = html.classList.contains(\"dark\") ? \"light\" : \"dark\";\n    return `Use ${theme}-mode`;\n  };\n\n  themeToggle!.setAttribute(\"title\", getMessage());\n  themeToggle!.setAttribute(\"aria-label\", getMessage());\n  themeToggle!.setAttribute(\n    \"value\",\n    html.classList.contains(\"dark\") ? \"dark\" : \"light\",\n  );\n\n  const toggleTheme = (t: \"light\" | \"dark\") => {\n    localStorage.setItem(\"theme\", t);\n    html.classList.add(t === \"dark\" ? \"dark\" : \"light\");\n    html.classList.remove(t === \"dark\" ? \"light\" : \"dark\");\n    themeToggle!.setAttribute(\"title\", getMessage());\n    themeToggle!.setAttribute(\"aria-label\", getMessage());\n    themeToggle!.setAttribute(\"value\", t);\n  };\n\n  themeToggle!.addEventListener(\"click\", () => {\n    toggleTheme(html.classList.contains(\"dark\") ? \"light\" : \"dark\");\n  });\n</script>\n"
  },
  {
    "path": "www/src/components/openGraph.tsx",
    "content": "interface OpenGraphProps {\n  title: string;\n  description: string;\n  imageBase: string;\n  pageUrl: string;\n  rtl: boolean;\n}\n\nexport default function OpenGraph({\n  title,\n  description,\n  imageBase,\n  pageUrl,\n  rtl,\n}: OpenGraphProps) {\n  return (\n    <div\n      style={{\n        display: \"flex\",\n        width: \"1200px\",\n        height: \"630px\",\n        justifyContent: \"center\",\n        alignItems: \"center\",\n        gap: \"3rem\",\n        flexDirection: rtl ? \"row-reverse\" : \"row\",\n        background:\n          \"linear-gradient(180deg, rgba(48,1,113,1) 0%, rgba(17,24,39,1) 100%)\",\n      }}\n    >\n      <img\n        src={`${imageBase}/images/background-pattern.svg`}\n        style={{\n          position: \"absolute\",\n          width: \"1200px\",\n          height: \"1200px\",\n          opacity: 0.15,\n        }}\n      />\n      <Logo color={\"#F5F5F5\"} />\n      <div\n        style={{\n          display: \"flex\",\n          flexDirection: \"column\",\n          alignItems: \"center\",\n          gap: \"1.2rem\",\n        }}\n      >\n        <h1\n          style={{\n            textAlign: \"center\",\n            fontSize: title.length > 15 ? \"70px\" : \"90px\",\n            lineHeight: \"5rem\",\n            fontWeight: 700,\n            color: \"#fff\",\n            maxWidth: \"700px\",\n          }}\n        >\n          {title}\n        </h1>\n        <h2\n          style={{\n            color: \"#F5F5F5\",\n            fontSize: \"40px\",\n            fontWeight: 400,\n            maxWidth: \"700px\",\n            textAlign: \"center\",\n            wordBreak: \"break-word\",\n          }}\n        >\n          {description}\n        </h2>\n      </div>\n      <h3\n        style={{\n          fontSize: \"40px\",\n          color: \"#c3b4fc\",\n          fontWeight: 400,\n          position: \"absolute\",\n          bottom: \"20px\",\n        }}\n      >\n        {pageUrl}\n      </h3>\n    </div>\n  );\n}\n\nconst Logo = ({ color }: { color: string }) => (\n  <svg\n    width=\"268\"\n    height=\"203\"\n    viewBox=\"0 0 268 203\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      d=\"M152.981 29.4786L180.491 0.918945L0.850377 0.918945V29.4786H152.981Z\"\n      fill={color}\n    />\n    <path\n      d=\"M159.664 101.527L257.947 1.29251L218.808 1.29228L137.874 83.0602L159.664 101.527Z\"\n      fill={color}\n    />\n    <path\n      d=\"M155.638 131.857L132.692 154.803L135.035 160.378C145.494 185.262 170.104 202.762 198.823 202.762C237.023 202.762 267.99 171.795 267.99 133.595C267.99 108.277 254.171 86.3783 234.102 74.3543L228.039 70.7214L207.028 92.0006L217.746 97.6588C230.659 104.475 239.427 118.019 239.427 133.595C239.427 156.021 221.248 174.2 198.823 174.2C180.714 174.2 165.352 162.339 160.126 145.94L155.638 131.857Z\"\n      fill={color}\n    />\n    <path\n      d=\"M98.4934 197.078L98.4934 52.2128H69.9338L69.9338 197.078H98.4934Z\"\n      fill={color}\n    />\n  </svg>\n);\n"
  },
  {
    "path": "www/src/config.ts",
    "content": "export const SITE = {\n  title: \"Create T3 App\",\n  description: \"The best way to start a full-stack, typesafe Next.js app.\",\n  defaultLanguage: \"en_US\",\n};\n\nexport const OPEN_GRAPH = {\n  image: {\n    src: \"images/og-image.png\",\n    alt: \"Create T3 App: The best way to start a full-stack, typesafe Next.js app.\",\n  },\n  twitter: \"t3dotgg\",\n};\n\n// This is the type of the frontmatter you put in the docs markdown files.\nexport interface Frontmatter {\n  title: string;\n  description: string;\n  layout: string;\n  image?: { src: string; alt: string };\n  dir?: \"ltr\" | \"rtl\";\n  ogLocale?: string;\n  lang?: KnownLanguageCode;\n  isMdx?: boolean;\n}\n\nexport const KNOWN_LANGUAGES = {\n  // Add more languages here\n  // sv: \"Svenska\",\n  ar: \"العربية\",\n  en: \"English\",\n  es: \"Español\",\n  fr: \"Français\",\n  ja: \"日本語\",\n  pt: \"Português\",\n  ru: \"Русский\",\n  no: \"Norsk\",\n  pl: \"Polski\",\n  uk: \"Українська\",\n  \"zh-hans\": \"简体中文\",\n} as const;\nexport type KnownLanguageCode = keyof typeof KNOWN_LANGUAGES;\n\nexport const GITHUB_EDIT_URL = `https://github.com/t3-oss/create-t3-app/tree/main/www`;\n\nexport const COMMUNITY_INVITE_URL = `https://t3.gg/discord`;\n\n// See \"Algolia\" section of the README for more information.\nexport const ALGOLIA = {\n  indexName: \"create-t3-app\",\n  appId: \"0LE5592BV4\",\n  apiKey: \"892c4647b96fe1b3d0b7d8de1c5b5e40\",\n};\n\nexport type OuterHeaders = \"Create T3 App\" | \"Deployment\" | \"Usage\";\n\nexport interface SidebarItem<\n  TCode extends KnownLanguageCode = KnownLanguageCode,\n> {\n  text: string;\n  link: `${TCode}/${string}`;\n}\n\nexport type SidebarItemLink = SidebarItem[\"link\"];\n\nexport type Sidebar = {\n  [TCode in KnownLanguageCode]: {\n    [THeader in OuterHeaders]?: SidebarItem<TCode>[];\n  };\n};\nexport const SIDEBAR: Sidebar = {\n  // For Translations:\n  // Keep the \"outer headers\" in English so we can match them.\n  // Translate the \"inner headers\" to the language you're translating to.\n  // Omit any files you haven't translated, they'll fallback to English.\n  // Example:\n  // sv: {\n  //   \"Create T3 App\": [\n  //     { text: \"Introduktion\", link: \"sv/introduction\" },\n  //     { text: \"Installation\", link: \"sv/installation\" },\n  //   ],\n  //   Usage: [{ text: \"Miljövariabler\", link: \"sv/usage/env-variables\" }],\n  // },\n  ar: {\n    \"Create T3 App\": [\n      { text: \"مُقدمة\", link: \"ar/introduction\" },\n      { text: \"لماذا CT3A؟\", link: \"ar/why\" },\n      { text: \"التثبيت\", link: \"ar/installation\" },\n      { text: \"(Pages)بِنية المجلد\", link: \"ar/folder-structure-pages\" },\n      { text: \"أسئلة شائعة\", link: \"ar/faq\" },\n      { text: \"اعمال بواسطة T3\", link: \"ar/t3-collection\" },\n      { text: \"ترشيحات أُخري\", link: \"ar/other-recs\" },\n    ],\n    Usage: [\n      { text: \"الخُطوات الأُولي\", link: \"ar/usage/first-steps\" },\n      { text: \"Next.js\", link: \"ar/usage/next-js\" },\n      { text: \"TypeScript\", link: \"ar/usage/typescript\" },\n      { text: \"tRPC\", link: \"ar/usage/trpc\" },\n      { text: \"Prisma\", link: \"ar/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"ar/usage/next-auth\" },\n      {\n        text: \"Environment Variables\",\n        link: \"ar/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"ar/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"ar/deployment/vercel\" },\n      { text: \"Docker\", link: \"ar/deployment/docker\" },\n    ],\n  },\n  en: {\n    \"Create T3 App\": [\n      { text: \"Introduction\", link: \"en/introduction\" },\n      { text: \"Why CT3A?\", link: \"en/why\" },\n      { text: \"Installation\", link: \"en/installation\" },\n      { text: \"Folder Structure (Pages)\", link: \"en/folder-structure-pages\" },\n      { text: \"Folder Structure (App)\", link: \"en/folder-structure-app\" },\n      { text: \"FAQ\", link: \"en/faq\" },\n      { text: \"T3 Collection\", link: \"en/t3-collection\" },\n      { text: \"Examples\", link: \"en/examples\" },\n      { text: \"Other Recommendations\", link: \"en/other-recs\" },\n    ],\n    Usage: [\n      { text: \"First Steps\", link: \"en/usage/first-steps\" },\n      { text: \"Next.js\", link: \"en/usage/next-js\" },\n      { text: \"TypeScript\", link: \"en/usage/typescript\" },\n      { text: \"tRPC\", link: \"en/usage/trpc\" },\n      { text: \"Drizzle\", link: \"en/usage/drizzle\" },\n      { text: \"Prisma\", link: \"en/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"en/usage/next-auth\" },\n      {\n        text: \"Environment Variables\",\n        link: \"en/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"en/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"en/deployment/vercel\" },\n      { text: \"Netlify\", link: \"en/deployment/netlify\" },\n      { text: \"Docker\", link: \"en/deployment/docker\" },\n    ],\n  },\n  es: {\n    \"Create T3 App\": [\n      { text: \"Introducción\", link: \"es/introduction\" },\n      { text: \"¿Por qué CT3A?\", link: \"es/why\" },\n      { text: \"Instalación\", link: \"es/installation\" },\n      {\n        text: \"Estructura de Carpetas (Pages)\",\n        link: \"es/folder-structure-pages\",\n      },\n      { text: \"Preguntas Frecuentes\", link: \"es/faq\" },\n      { text: \"Colección T3\", link: \"es/t3-collection\" },\n      { text: \"Otras Recomendaciones\", link: \"es/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Primeros Pasos\", link: \"es/usage/first-steps\" },\n      { text: \"Next.js\", link: \"es/usage/next-js\" },\n      { text: \"TypeScript\", link: \"es/usage/typescript\" },\n      { text: \"tRPC\", link: \"es/usage/trpc\" },\n      { text: \"Prisma\", link: \"es/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"es/usage/next-auth\" },\n      { text: \"Variables de Entorno\", link: \"es/usage/env-variables\" },\n      { text: \"Tailwind CSS\", link: \"es/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"es/deployment/vercel\" },\n      { text: \"Netlify\", link: \"es/deployment/netlify\" },\n      { text: \"Docker\", link: \"es/deployment/docker\" },\n    ],\n  },\n  ja: {\n    \"Create T3 App\": [\n      { text: \"イントロダクション\", link: \"ja/introduction\" },\n      { text: \"CT3A を選ぶ理由\", link: \"ja/why\" },\n      { text: \"インストール\", link: \"ja/installation\" },\n      { text: \"ファルダ構成 (Pages)\", link: \"ja/folder-structure-pages\" },\n      { text: \"FAQ\", link: \"ja/faq\" },\n      { text: \"T3 コレクション\", link: \"ja/t3-collection\" },\n      { text: \"その他のオススメ\", link: \"ja/other-recs\" },\n    ],\n    Usage: [\n      { text: \"はじめの一歩\", link: \"ja/usage/first-steps\" },\n      { text: \"Next.js\", link: \"ja/usage/next-js\" },\n      { text: \"TypeScript\", link: \"ja/usage/typescript\" },\n      { text: \"tRPC\", link: \"ja/usage/trpc\" },\n      { text: \"Prisma\", link: \"ja/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"ja/usage/next-auth\" },\n      {\n        text: \"環境変数\",\n        link: \"ja/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"ja/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"ja/deployment/vercel\" },\n      { text: \"Netlify\", link: \"ja/deployment/netlify\" },\n      { text: \"Docker\", link: \"ja/deployment/docker\" },\n    ],\n  },\n  pl: {\n    \"Create T3 App\": [\n      { text: \"Wstęp\", link: \"pl/introduction\" },\n      { text: \"Dlaczego CT3A?\", link: \"pl/why\" },\n      { text: \"Instalacja\", link: \"pl/installation\" },\n      { text: \"Struktura Projektu (Pages)\", link: \"pl/folder-structure-pages\" },\n      { text: \"FAQ\", link: \"pl/faq\" },\n      { text: \"Kolekcja T3\", link: \"pl/t3-collection\" },\n      { text: \"Przykłady\", link: \"pl/examples\" },\n      { text: \"Inne Rekomendacje\", link: \"pl/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Pierwsze Kroki\", link: \"pl/usage/first-steps\" },\n      { text: \"Next.js\", link: \"pl/usage/next-js\" },\n      { text: \"TypeScript\", link: \"pl/usage/typescript\" },\n      { text: \"tRPC\", link: \"pl/usage/trpc\" },\n      { text: \"Prisma\", link: \"pl/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"pl/usage/next-auth\" },\n      {\n        text: \"Zmienne Środowiskowe\",\n        link: \"pl/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"pl/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"pl/deployment/vercel\" },\n      { text: \"Netlify\", link: \"pl/deployment/netlify\" },\n      { text: \"Docker\", link: \"pl/deployment/docker\" },\n    ],\n  },\n  uk: {\n    \"Create T3 App\": [\n      { text: \"Вступ\", link: \"uk/introduction\" },\n      { text: \"Чому CT3A?\", link: \"uk/why\" },\n      { text: \"Встановлення\", link: \"uk/installation\" },\n      { text: \"Структура папок (Pages)\", link: \"uk/folder-structure-pages\" },\n      { text: \"FAQ\", link: \"uk/faq\" },\n      { text: \"T3 Колекція\", link: \"uk/t3-collection\" },\n      { text: \"Приклади\", link: \"uk/examples\" },\n      { text: \"Інші рекомендації\", link: \"uk/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Перші кроки\", link: \"uk/usage/first-steps\" },\n      { text: \"Next.js\", link: \"uk/usage/next-js\" },\n      { text: \"TypeScript\", link: \"uk/usage/typescript\" },\n      { text: \"tRPC\", link: \"uk/usage/trpc\" },\n      { text: \"Drizzle\", link: \"uk/usage/drizzle\" },\n      { text: \"Prisma\", link: \"uk/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"uk/usage/next-auth\" },\n      {\n        text: \"Змінні середовища\",\n        link: \"uk/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"uk/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"uk/deployment/vercel\" },\n      { text: \"Netlify\", link: \"uk/deployment/netlify\" },\n      { text: \"Docker\", link: \"uk/deployment/docker\" },\n    ],\n  },\n  fr: {\n    \"Create T3 App\": [\n      { text: \"Introduction\", link: \"fr/introduction\" },\n      { text: \"Pourquoi CT3A?\", link: \"fr/why\" },\n      { text: \"Installation\", link: \"fr/installation\" },\n      {\n        text: \"Structure des dossiers (Pages)\",\n        link: \"fr/folder-structure-pages\",\n      },\n      { text: \"FAQ\", link: \"fr/faq\" },\n      { text: \"Collection T3\", link: \"fr/t3-collection\" },\n      { text: \"Exemples\", link: \"fr/examples\" },\n      { text: \"Autres recommandations\", link: \"fr/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Premiers pas\", link: \"fr/usage/first-steps\" },\n      { text: \"Next.js\", link: \"fr/usage/next-js\" },\n      { text: \"TypeScript\", link: \"fr/usage/typescript\" },\n      { text: \"tRPC\", link: \"fr/usage/trpc\" },\n      { text: \"Prisma\", link: \"fr/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"fr/usage/next-auth\" },\n      {\n        text: \"Variables d'environnement\",\n        link: \"fr/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"fr/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"fr/deployment/vercel\" },\n      { text: \"Netlify\", link: \"fr/deployment/netlify\" },\n      { text: \"Docker\", link: \"fr/deployment/docker\" },\n    ],\n  },\n  pt: {\n    \"Create T3 App\": [\n      { text: \"Introdução\", link: \"pt/introduction\" },\n      { text: \"Por que o CT3A?\", link: \"pt/why\" },\n      { text: \"Instalação\", link: \"pt/installation\" },\n      {\n        text: \"Estrutura de Pastas (Pages)\",\n        link: \"pt/folder-structure-pages\",\n      },\n      { text: \"Perguntas Frequentes\", link: \"pt/faq\" },\n      { text: \"Coleção T3\", link: \"pt/t3-collection\" },\n      { text: \"Outras Recomendações\", link: \"pt/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Primeiros Passos\", link: \"pt/usage/first-steps\" },\n      { text: \"Next.js\", link: \"pt/usage/next-js\" },\n      { text: \"TypeScript\", link: \"pt/usage/typescript\" },\n      { text: \"tRPC\", link: \"pt/usage/trpc\" },\n      { text: \"Prisma\", link: \"pt/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"pt/usage/next-auth\" },\n      {\n        text: \"Variáveis de Ambiente\",\n        link: \"pt/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"pt/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"pt/deployment/vercel\" },\n      { text: \"Netlify\", link: \"pt/deployment/netlify\" },\n      { text: \"Docker\", link: \"pt/deployment/docker\" },\n    ],\n  },\n  ru: {\n    \"Create T3 App\": [\n      { text: \"Введение\", link: \"ru/introduction\" },\n      { text: \"Почему CT3A?\", link: \"ru/why\" },\n      { text: \"Установка\", link: \"ru/installation\" },\n      { text: \"Файловая структура (Pages)\", link: \"ru/folder-structure-pages\" },\n      { text: \"FAQ\", link: \"ru/faq\" },\n      { text: \"T3 коллекция\", link: \"ru/t3-collection\" },\n      { text: \"Дополнительные рекомендации\", link: \"ru/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Первые шаги\", link: \"ru/usage/first-steps\" },\n      { text: \"Next.js\", link: \"ru/usage/next-js\" },\n      { text: \"TypeScript\", link: \"ru/usage/typescript\" },\n      { text: \"tRPC\", link: \"ru/usage/trpc\" },\n      { text: \"Prisma\", link: \"ru/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"ru/usage/next-auth\" },\n      {\n        text: \"Переменные среды\",\n        link: \"ru/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"ru/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"ru/deployment/vercel\" },\n      { text: \"Docker\", link: \"ru/deployment/docker\" },\n      { text: \"Netlify\", link: \"ru/deployment/netlify\" },\n    ],\n  },\n  no: {\n    \"Create T3 App\": [\n      { text: \"Introduksjon\", link: \"no/introduction\" },\n      { text: \"Hvorfor CT3A?\", link: \"no/why\" },\n      { text: \"Installasjon\", link: \"no/installation\" },\n      { text: \"Mappestruktur (Pages)\", link: \"no/folder-structure-pages\" },\n      { text: \"FAQ\", link: \"no/faq\" },\n      { text: \"T3-Kolleksjonen\", link: \"no/t3-collection\" },\n      { text: \"Andre Anbefalinger\", link: \"no/other-recs\" },\n    ],\n    Usage: [\n      { text: \"Første Steg\", link: \"no/usage/first-steps\" },\n      { text: \"Next.js\", link: \"no/usage/next-js\" },\n      { text: \"TypeScript\", link: \"no/usage/typescript\" },\n      { text: \"tRPC\", link: \"no/usage/trpc\" },\n      { text: \"Prisma\", link: \"no/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"no/usage/next-auth\" },\n      {\n        text: \"Miljøvariabler\",\n        link: \"no/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"no/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"no/deployment/vercel\" },\n      { text: \"Netlify\", link: \"no/deployment/netlify\" },\n      { text: \"Docker\", link: \"no/deployment/docker\" },\n    ],\n  },\n  \"zh-hans\": {\n    \"Create T3 App\": [\n      { text: \"简介\", link: \"zh-hans/introduction\" },\n      { text: \"为什么选择 CT3A?\", link: \"zh-hans/why\" },\n      { text: \"安装\", link: \"zh-hans/installation\" },\n      { text: \"文件夹结构 (Pages)\", link: \"zh-hans/folder-structure-pages\" },\n      { text: \"常见疑问\", link: \"zh-hans/faq\" },\n      { text: \"T3 合集\", link: \"zh-hans/t3-collection\" },\n      { text: \"其他推荐\", link: \"zh-hans/other-recs\" },\n    ],\n    Usage: [\n      { text: \"第一步\", link: \"zh-hans/usage/first-steps\" },\n      { text: \"Next.js\", link: \"zh-hans/usage/next-js\" },\n      { text: \"TypeScript\", link: \"zh-hans/usage/typescript\" },\n      { text: \"tRPC\", link: \"zh-hans/usage/trpc\" },\n      { text: \"Drizzle\", link: \"zh-hans/usage/drizzle\" },\n      { text: \"Prisma\", link: \"zh-hans/usage/prisma\" },\n      { text: \"NextAuth.js\", link: \"zh-hans/usage/next-auth\" },\n      {\n        text: \"环境变量\",\n        link: \"zh-hans/usage/env-variables\",\n      },\n      { text: \"Tailwind CSS\", link: \"zh-hans/usage/tailwind\" },\n    ],\n    Deployment: [\n      { text: \"Vercel\", link: \"zh-hans/deployment/vercel\" },\n      { text: \"Netlify\", link: \"zh-hans/deployment/netlify\" },\n      { text: \"Docker\", link: \"zh-hans/deployment/docker\" },\n    ],\n  },\n};\n\nexport const SIDEBAR_HEADER_MAP: Record<\n  Exclude<KnownLanguageCode, \"en\">,\n  Record<OuterHeaders, string>\n> = {\n  es: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Uso\",\n    Deployment: \"Despliegue\",\n  },\n  // Translate the sidebar's \"outer headers\" here\n  // sv: {\n  //   \"Create T3 App\": \"Create T3 App\",\n  //   Usage: \"Användarguide\",\n  //   Deployment: \"Deployment\",\n  // },\n  ja: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"使用法\",\n    Deployment: \"デプロイ\",\n  },\n  pl: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Korzystanie Z Narzędzia\",\n    Deployment: \"Deployment\",\n  },\n  uk: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Використання\",\n    Deployment: \"Деплоймент\",\n  },\n  ar: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"كيفية الإستخدام؟\",\n    Deployment: \"نَشر تطبيقك\",\n  },\n  fr: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Utilisation\",\n    Deployment: \"Déploiement\",\n  },\n  pt: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Uso\",\n    Deployment: \"Deploy\",\n  },\n  ru: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Использование\",\n    Deployment: \"Развертывание\",\n  },\n  no: {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"Bruk\",\n    Deployment: \"Utrulling\",\n  },\n  \"zh-hans\": {\n    \"Create T3 App\": \"Create T3 App\",\n    Usage: \"用法\",\n    Deployment: \"部署\",\n  },\n};\n"
  },
  {
    "path": "www/src/env.d.ts",
    "content": "/// <reference types=\"astro/client\" />\n"
  },
  {
    "path": "www/src/languages.ts",
    "content": "import { type KnownLanguageCode } from \"./config\";\n\nexport { KNOWN_LANGUAGES, type KnownLanguageCode } from \"./config\";\n\nexport const langPathRegex = /\\/([a-z]{2,3}-?[a-zA-Z]{0,4})\\//;\n\nexport function getLanguageFromURL(pathname: string) {\n  const langCodeMatch = langPathRegex.exec(pathname);\n  const langCode = langCodeMatch ? langCodeMatch[1] : \"en\";\n  return langCode as KnownLanguageCode;\n}\n\n// all RTL languages according to: https://lingohub.com/academy/best-practices/rtl-language-list\nconst rtlLanguages = [\n  \"ar\",\n  \"arc\",\n  \"dv\",\n  \"fa\",\n  \"ha\",\n  \"he\",\n  \"khw\",\n  \"ks\",\n  \"ku\",\n  \"ps\",\n  \"ur\",\n  \"yi\",\n];\n\nexport function getIsRtlFromUrl(pathname: string) {\n  const language = getLanguageFromURL(pathname);\n  return getIsRtlFromLangCode(language);\n}\n\nexport function getIsRtlFromLangCode(language: KnownLanguageCode) {\n  if (rtlLanguages.includes(language)) {\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "www/src/layouts/docs.astro",
    "content": "---\nimport { type MarkdownHeading } from \"astro\";\n\nimport PageContent from \"../components/docs/pageContent.astro\";\nimport Footer from \"../components/footer/footer.astro\";\nimport HeadCommon from \"../components/headCommon.astro\";\nimport HeadSEO from \"../components/headSeo.astro\";\nimport LeftSidebar from \"../components/navigation/leftSidebar.astro\";\nimport Navbar from \"../components/navigation/navbar.astro\";\nimport RightSidebar from \"../components/navigation/rightSidebar.astro\";\nimport * as CONFIG from \"../config\";\n\nimport \"../styles/global.css\";\nimport \"../styles/accessibility.css\";\nimport \"@fontsource-variable/inter\";\n\nimport JumpToContent from \"../components/accessibility/jumpToContent.astro\";\nimport MoreMenu from \"../components/navigation/moreMenu.astro\";\n\nexport interface Props {\n  frontmatter: CONFIG.Frontmatter;\n  headings: MarkdownHeading[];\n}\n\nconst { frontmatter, headings } = Astro.props;\nconst currentPage = Astro.url.pathname;\nconst currentFile = `src/pages${currentPage.replace(/\\/$/, \"\")}.${\n  frontmatter.isMdx ? \"mdx\" : \"md\"\n}`;\n\nconst githubEditUrl = `${CONFIG.GITHUB_EDIT_URL}/${currentFile}`;\n---\n\n<html\n  dir={frontmatter.dir ?? \"ltr\"}\n  lang={frontmatter.lang ?? \"en-us\"}\n  class=\"initial\"\n>\n  <head>\n    <HeadCommon />\n    <HeadSEO frontmatter={frontmatter} />\n    <title>\n      {frontmatter.title} • {CONFIG.SITE.title}\n    </title>\n\n    <script is:inline>\n      const html = document.documentElement;\n      const theme = (() => {\n        if (\n          typeof localStorage !== \"undefined\" &&\n          localStorage.getItem(\"theme\")\n        ) {\n          return localStorage.getItem(\"theme\");\n        }\n        if (window.matchMedia(\"(prefers-color-scheme: dark)\").matches) {\n          return \"dark\";\n        }\n        return \"light\";\n      })();\n      if (theme === \"light\") {\n        html.classList.remove(\"dark\");\n        html.classList.add(\"light\");\n      } else {\n        html.classList.add(\"dark\");\n        html.classList.remove(\"light\");\n      }\n    </script>\n  </head>\n\n  <body\n    class=\"flex min-h-screen flex-col items-center bg-default transition-colors duration-300\"\n  >\n    <JumpToContent />\n    <div\n      class=\"sticky top-0 z-40 max-h-full w-full bg-default transition-colors duration-300\"\n    >\n      <Navbar />\n    </div>\n    <main\n      class=\"grid w-full max-w-7xl flex-1 grid-cols-1 gap-4 md:grid-cols-[250px_auto] lg:grid-cols-[250px_auto_250px]\"\n    >\n      <nav\n        id=\"grid-left\"\n        title=\"Site Navigation\"\n        class=\"t3-scrollbar sticky top-20 col-span-1 hidden h-auto max-h-[calc(100vh-80px)] w-full flex-col justify-start overflow-y-auto bg-default pt-4 transition-colors duration-300 md:top-24 md:flex md:max-h-[calc(100vh-96px)] md:pt-0 md:[margin-inline-start:16px]\"\n      >\n        <LeftSidebar frontmatter={frontmatter} currentPage={currentPage} />\n      </nav>\n\n      <div class=\"col-span-1 flex min-h-full w-full flex-col pt-5\" id=\"content\">\n        <PageContent\n          frontmatter={frontmatter}\n          path={currentFile}\n          headings={headings}\n        >\n          <slot />\n        </PageContent>\n        <nav class=\"mx-3 flex lg:hidden\">\n          <MoreMenu editHref={githubEditUrl} />\n        </nav>\n        <Footer path={currentFile} isBlog={true} />\n      </div>\n      <div class=\"md:[margin-inline-end:16px]\">\n        <aside\n          id=\"grid-right\"\n          title=\"Table of Contents\"\n          dir=\"ltr\"\n          class=\"t3-scrollbar sticky top-[100px] col-span-1 hidden h-auto max-h-[calc(100vh-100px)] w-full [padding-inline-end:16px] lg:mb-12 lg:flex lg:flex-col lg:justify-start\"\n        >\n          <RightSidebar\n            headings={headings}\n            githubEditUrl={githubEditUrl}\n            title={frontmatter.title}\n          />\n        </aside>\n      </div>\n    </main>\n    <script defer>\n      const matches = document.querySelectorAll(\"[data-heading-link]\");\n      if (matches && matches.length) {\n        matches.forEach((elem) => {\n          const href = elem.href;\n          elem.addEventListener(\n            \"click\",\n            () => {\n              navigator.clipboard.writeText(href);\n            },\n            false,\n          );\n        });\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "www/src/layouts/landingPage.astro",
    "content": "---\nimport Footer from \"../components/footer/footer.astro\";\nimport LeftSidebar from \"../components/navigation/leftSidebar.astro\";\nimport Navbar from \"../components/navigation/navbar.astro\";\n\nimport \"../styles/global.css\";\nimport \"../styles/algolia/style.css\";\nimport \"../styles/accessibility.css\";\n\nimport HeadCommon from \"../components/headCommon.astro\";\nimport HeadSeo from \"../components/headSeo.astro\";\nimport { SITE } from \"../config\";\n\nimport \"@fontsource-variable/inter\";\n\nimport JumpToContent from \"../components/accessibility/jumpToContent.astro\";\n\nexport interface Props {\n  isNotFound?: boolean;\n}\n\nconst currentPage = Astro.url.pathname;\n\nconst { isNotFound } = Astro.props;\n---\n\n<!doctype html>\n<html dir=\"ltr\" lang=\"en-us\" class={`initial ${isNotFound ? \"not-found\" : \"\"}`}>\n  <head>\n    <HeadCommon />\n    <HeadSeo type=\"website\" />\n    <title>{SITE.title}</title>\n\n    <script is:inline>\n      const html = document.documentElement;\n      if (\n        window.location.pathname === \"/\" ||\n        html.classList.contains(\"not-found\")\n      ) {\n        html.classList.remove(\"not-found\");\n        html.classList.add(\"dark\");\n      }\n    </script>\n  </head>\n  <body\n    class=\"min-h-screen bg-gradient-to-b from-gray-900 via-[#300171] to-slate-900\"\n  >\n    <JumpToContent />\n    <div\n      class=\"relative before:pointer-events-none before:absolute before:inset-0 before:block before:h-full before:w-full before:bg-[url('/images/background-pattern.svg')] before:bg-cover before:bg-no-repeat before:opacity-5\"\n    >\n      <Navbar isNotFound={isNotFound || false} />\n      <aside id=\"grid-left\" class=\"hidden\" title=\"Site Navigation\">\n        <div class=\"fixed left-0 top-0 z-30 h-screen w-screen bg-default\">\n          <div class=\"fixed top-24 h-[calc(100%-96px)] w-full pb-16\">\n            <LeftSidebar\n              currentPage={currentPage}\n              isNotFound={isNotFound || false}\n            />\n          </div>\n        </div>\n      </aside>\n      <main id=\"content\">\n        <slot />\n      </main>\n      <Footer isBlog={false} path=\"/\" />\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "www/src/pages/404.astro",
    "content": "---\nimport Button from \"../components/landingPage/button.astro\";\nimport LandingPage from \"../layouts/landingPage.astro\";\n---\n\n<LandingPage isNotFound={true}>\n  <main>\n    <div>\n      <div\n        class=\"h-[calc(100vh-200px)] py-12 sm:py-8 md:py-12 lg:py-14 xl:py-12 2xl:py-28\"\n      >\n        <div class=\"mx-auto max-w-[800px] xl:max-w-7xl\">\n          <div class=\"lg:px-8\">\n            <div class=\"flex flex-col items-center\">\n              <div\n                class=\"max-w-md px-4 sm:max-w-2xl sm:px-6 md:max-w-3xl lg:max-w-4xl lg:px-0 xl:max-w-5xl 2xl:max-w-6xl\"\n              >\n                <div class=\"flex w-full flex-col items-center gap-4\">\n                  <div class=\"flex flex-col items-start justify-between\">\n                    <h1\n                      class=\"text-center text-4xl font-bold tracking-tight text-white sm:text-6xl sm:tracking-tight lg:text-[4rem] xl:text-[6rem] xl:tracking-tight 2xl:text-[6.5rem]\"\n                    >\n                      Page not found...\n                      <span class=\"text-[hsl(200,100%,60%)]\"> 404!</span>\n                    </h1>\n                    <div\n                      class=\"mt-4 flex w-full items-center justify-center gap-4 xl:mt-8\"\n                    >\n                      <Button\n                        href=\"/\"\n                        openInNewTab={false}\n                        rounded=\"md\"\n                        className=\"group\"\n                        rounded=\"full\"\n                        specialHover={true}\n                      >\n                        Return to the homepage\n                        <svg\n                          class=\"stroke -mr-1 ml-2 mt-0.5 h-3 stroke-current stroke-2\"\n                          fill=\"none\"\n                          viewBox=\"0 0 10 10\"\n                          aria-hidden=\"true\"\n                        >\n                          <path\n                            class=\"opacity-0 transition group-hover:opacity-100\"\n                            d=\"M0 5h7\"></path>\n                          <path\n                            class=\"transition group-hover:translate-x-[3px]\"\n                            d=\"M1 1l4 4-4 4\"></path>\n                        </svg>\n                      </Button>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </main>\n</LandingPage>\n"
  },
  {
    "path": "www/src/pages/ar/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: النشر مع Docker\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nيمكنك إستخدام الـ Stack داخل Docker Container أو كجزء من مجموعة containers عن طريق docker-compose، إقرأ المزيد هنا [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker)\n\n## تهيئة مشروع Docker\n\nيَجب أن تضع في حُسبانك أن Next.js يتطلب process مُنفصلة لـ buildtime و runtime.\nيمكنك الوصول لـ runtime environment فقط في الـ Server.\n\nفي هذا المثال نستخدم مُتغيرين فقط لذلك عليك أن تٌبقي في بالك موقعها في الـ `Dockerfile` والـ command-line arguments, والـ `docker-compose.yml`:\n\n- `DATABASE_URL` (تُستخدم في الـ server)\n- `NEXT_PUBLIC_CLIENTVAR` (تُستخدم في الـ client)\n\n### 1. إعداد Next\n\nفي ملف [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js) قم بإضافة `standalone` حتى [تُقلل حجم الصور تلقائيا](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. إنشاء ملف dockerignore\n\n<details>\n    <summary>\n      إضغط هنا لتقرأ محتوي الملف  <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. إنشاء Dockerfile\n\n> بما أننا لا نقوم بجلب الـ server environment variables إلى داخل الـ container، فإن [environment schema validation](/en/usage/env-variables) سيفشل لتجنب هذا أضف علم `SKIP_ENV_VALIDATION=1` الي الـ command حتى تُوقف عملية الـ validation\n\n<details>\n    <summary>\n      إضغط هنا لتقرأ محتوي الملف  <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# تثبيت Prisma Client - أزلها إن لم تكن تُستخدم Prisma\n\nCOPY prisma ./\n\n# تثبيت المتطلبات وفقا للـ package manager الذي تُفضلة\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_مُلاحظات_**\n>\n> - مُحاكاة `--platform=linux/amd64` قد لا تكون ضرورية في Node 18\n> - إقرأ [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) لتعلم لماذا قد تحتاج `libc6-compat`.\n> - تقوم Next.js بجمع [بيانات خفية عن الاستختدام](https://nextjs.org/telemetry).\n> - قٌم بإالغاء تعليق الـ instance الاولي من ENV NEXT_TELEMETRY_DISABLED 1 حتي تُعيق الـ telemetry أثناء الـ build، قٌم بإلغاء تعليق الـ instance الثانية تٌعيق الـ telemetry أثناء الـ runtime\n\n</div>\n</details>\n\n## البناء والتشغيل locally\n\nقم ببناء وتشغيل هذه الصورة Locally باستخدام الأوامر التالية:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nإفتح [localhost:3000](http://localhost:3000/) لتري تطبيقك يَعمل\n\n## الـ Docker Compose\n\nيُمكنك أيضا إستخدام Docker Compose لبناء وتشغيل الـ Container\n\n<details>\n<summary>\nبعد إتباع الخطوات من 1 إلى 4 في الاعلي إضغط هنا وأضف الملفات الي <code>docker-compose.yml</code>:\n</summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nقٌم بتشغيل أمر `docker compose up`\n\n```bash\ndocker compose up\n```\n\nالآن إفتح [localhost:3000](http://localhost:3000/) لترى تطبيقك يُعمل.\n\n     </div>\n\n</details>\n## الـ Deploy علي Railway\n\nيُمكنك أن تستخدم PaaS كـ [Railway's](https://railway.app) كـ [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles)  \nإذا أردت أن تستخدم [Railway CLI installed](https://docs.railway.app/develop/cli#install) يُمكنك أن تُشغل هذا الأمر:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nإذهب الي \"Variables\" وأضف `DATABASE_URL` ثُم الي \"Settings\" واختر \"Generate Domain.\" لتري أمثلة علي Railway زُر [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## مصدر مُفيدة\n\n| المصدر                               | الرابط                                                               |\n| ------------------------------------ | -------------------------------------------------------------------- |\n| Dockerfile reference                 | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file version 3 reference     | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI reference                 | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI reference         | https://docs.docker.com/compose/reference/                           |\n| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js in Docker                    | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Next.js with Docker Example          | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/ar/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: النَشر الي Vercel\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nننصحك بنشر تطبيقك عبر [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) فهو أسهل، خاصة لتطبيقات Next.js.\n\n## إعداد المشروع\n\nبطبيعة الأمر فإن vercel ستقوم بإعداد المشروع عنك لكن بإمكانك التعديل عليها من خلال إنشاء ملف [`vercel.json`](https://vercel.com/docs/project-configuration)\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## استخدام لوحة تحكم Vercel\n\n1. بعد دفع مشروعك الي Github سجل الدخول إلى [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) عن طريق Github واضغط علي **Add New Project**\n\n![New project on Vercel](/images/vercel-new-project.webp)\n\n2. قم بإستيراد GitHub repository\n\n![Import repository](/images/vercel-import-project.webp)\n\n3. إضف environment variables.\n\n![Add environment variables](/images/vercel-env-vars.webp)\n\n4. إضغط علي **Deploy** الان مع كل مرة تعمل فيها Push ستقوم vercel بإعادة بناء المشوع تلقائيا\n\n## إستخدام Vercel CLI\n\nحتي تنشر مشروع عن طريق CLI [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nشَغل أمر [`vercel`](https://vercel.com/docs/cli/deploying-from-cli)\n\n```bash\nvercel\n```\n\nلا تنس اضافة environment variables مثل `--env DATABASE_URL=YOUR_DATABASE_URL_HERE`، أضف عَلم `--yes` لتخطي كل الاسئلة\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nبطبيعة الامر فإن النشر سيطون علي `preview branch` لكن إذا ما كُنت تريد النشر الي `production` فقُم بإضافة علم `--prod`\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/ar/faq.md",
    "content": "---\ntitle: الأسئلة الشائعة\ndescription: الأسئلة المتكررة حول إنشاء تطبيق T3\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nإليك ما يَكثُر من سٌؤاله عن Create T3 App.\n\n## ماذا بعد؟ كيف استعمل `create-t3-app` لإنشاء تطبيق؟\n\nنحن نحاول أن نُبقي هذا المشروع بَسيطاًً قدر الإمكان، لذلك فَقد وضعنا حَجر الأساس لك، ويمكن إضافة ما تريد وقتما تُريد.\n\nإذا كًنت غير مُلم ببعض التقنيات المُستخدمة في هذا المَشروع فأتجه إلى الـ Docs المَعنية بها، فإذا واجهتك مُشكلة ما فالرجاء الانضمام إلى سيرفر الديسكورد [Discord](https://t3.gg/discord) وأطلب المُساعدة.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [TailwindCSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## ما هي مصادر التعلم المتاحة في الوقت الحالي؟\n\nبالرغم من أن المصادر المذكورة في الأسفل هي من أفضل المصادر الموجودة لتعلم مسار T3، فإننا (و [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) ننصحك أن تبدأ باستخدام الـ Stack وتَعلمه عن طريق أن تبني شيئاَ به.\n\nإذا كُنت تخطط لاستخدام Create T3 App فَربما تكون دِراية ببعض أجزاء هذا الـ Stack، فلماذا لا تَستغل مَعرفتك تِلك لتبدأ العمل مباشرة.\n\nنَحن نُدرك أن هذا المسار لا يَصلح للجميع. لِذلك ، إذا كنت تشعر أنك قد جَربت ما أوصيناك به وما زلت ترغب في المزيد من مصادر التَعلم، أو في حال أن لم تكن واثقًا من قَدرتك علي ذلك وَحدك، فراجع هذه البرامج التعليمية الرائعة عن Create T3 App:\n\n### مقالات\n\n- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n\n### فيديوهات\n\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## لماذا هُناك ملفات بامتداد `.js` في هذا المشروع؟\n\nوِفقًا لـ [T3-Axiom #3](/en/introduction#typesafety-isnt-optional) ، نَحن نَعتبر Typesafety مواطناََ مِن الدرجة الأولى. لِسوء الحَظ، لا يُدعم TypeScript في بَعض الـ Frameworks والاضافات مما يعني ضرورى أن تكتب بعض ملفات للإعدادات (configuration) بلغة JS وهو مُر لابُد منة.\n\nنُحن نُحاول التأكيد على أن هذه الملفات هي `Javascript` لأسباب خَارجة عن إرادتنا وذلك عن طريق إستخدام (cjs أو mjs)، لكن لا تزال جميع البيانات في ملفات js في هذا المشروع، تخضع لفحص باستخدام تعليق `@ts-check` في الأعلى.\n\n## أجد صعوبة في إضافة i18n إلى تطبيقي. هل هناك أي مرجع يمكنني الرجوع إلية؟\n\nلقد قررنا عدم تضمين i18n افتراضيًا في Create T3 App وذلك لأنه موضوع شائك للغاية وهناك العديد من الطرق لتنفيذه.\nومع ذلك، إذا كنان لابُد من تَنفيذه وترغب في رؤية مشروع مَرجعي، فلدينا [مَرجع](https://github.com/juliusmarminge/t3-i18n) يُوضح كيف يمكنك إضافة i18n إلى تَطبيق T3 باستخدام [next-i18next](https://github.com/i18next/next-i18next).\n\n## لماذا نستخدم `/pages` وليس `/app` في Next.js 13؟\n\nكما ذكرنا مُسبقا في [T3-Axiom #2](/en/introduction#bleed-responsibly)، نحن نُحب الأشياء المتطورة لكننا نُقدر الاستقرار، فمن الصعب تَحويل الـ router إلي النظام الجديد، شاهد [not a great place to bleed](https://youtu.be/mnwUbtieOuI?t=1662).\nفإن `/app` [مُجرد لَمحة من المستقبل](https://youtu.be/rnsC-12PVlM?t=818)، فهو ليس جاهزًا للإنتاج؛ غير إن (API) في مَرحلة تجريبية ومن المتوقع أن تحدث له تغييرات جذرية.\n\nلمعرفة الميزات المدعومة والمخطط العمل عليها في dir المسمى `/app`، زر [beta Next.js docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n"
  },
  {
    "path": "www/src/pages/ar/folder-structure-pages.mdx",
    "content": "---\ntitle: (Pages)بِنية المجلد\ndescription: بنية مجلد T3 App\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nاختار أدواتك لترى بنية المجلد عند إنشاء تطبيقك بواسطة تلك ألاختيارات. بالأسفل ستجد وصف عن غرض كلاً منهم.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n## `prisma`\n\nمجلد prisma يحتوي على `prisma.schema` الذي بدوره يحتوي ملف تكوين الاتصال مع قاعدة البيانات كما يحتوي أيضا علي schema التي تحدد شكل الـ tables هذا إلى جانب ملفات الـ migrations و/أو كود لإضافة المعلومات إلى Database، اقرآ [كيفية استخدام Prisma](/ar/usage/prisma).\n\n## `public`\n\nيحتوي مُجلد Public على الملفات الثابتة التي يقوم السيرفر بتقديمها، يكون ملف `favicon.ico` مثال على ذلك.\n\n## `src/env`\n\nيستخدم للتحقق من صحة الـ environment variable وتحديد الأنواع (types)، اقرأ المزيد [Environment Variables](usage/env-variables)\n\n## `src/pages`\n\nمجلد `pages` يحتوي علي كل الصفحات التي يحتوي عليها تطبيق Next.js، يعمل ملف `index.tsx` في مستند root من `/pages` كالصفحة الأساسية للتطبيق، يعمل ملف `__app.tsx` لإمداد التطبيق بما تحتاجه من موفر، لقراءة المزيد [Next.js documentation](https://nextjs.org/docs/basic-features/pages).\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n### `src/pages/api`\n\nيحتوي مجلد `api` علي كل Api routes في تطبيقك الـ Next.js، يحتوي `example.ts` على مثال عن route الذي يستخدم [Next.js API route](https://nextjs.org/docs/api-routes/introduction) مع Prisma. يحتوي ملف `restricted.ts` علي مثال عن route الذي يستخدم خاصية في [Next.js API route](https://nextjs.org/docs/api-routes/introduction) ومحمي من [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nإن ملف `[...nextauth].ts` خط سير التوثيق (authentication slug route) في NextAuth.js، ويستخدم في طلبات التوثيق. اقرأ [NextAuth.js usage](usage/next-auth) و [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) لمزيد من المعلومات حول catch-all/slug.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nيُعتبر ملف `[trpc].ts` المدخل لـ API في tRPC، ويكون مسئول عن تنفيذ طلبات tRPC. اقرأ [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) و [tRPC usage](usage/trpc#-pagesapitrpctrpcts) لمزيد من المعلومات حول catch-all/slug.\n\n</div>\n<div data-components=\"trpc prisma\">\n\n## `src/server`\n\nيُستخدم مجلد `server` للفصل بوضوح بين الكود من جانب السيرفر (Server Side) والكود من جانب العميل (Client Side).\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/server/auth.ts`\n\nيحتوي على الوظائف الخادمة (utilities) التي تقوم بالتوثيق مثل استرداد جلسة المستخدم (user session) من جانب السيرفر. اقرأ [NextAuth.js](https://create.t3.gg/ar/usage/next-auth#usage-with-trpc) للمزيد من المعلومات.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nيستخدم ملف `db.ts` ليوضح استخدام Prisma client بشكل شامل. اقرأ [استخدام Prisma](https://create.t3.gg/ar/usage/prisma#prisma-client) و[افضل الطرق لاستخدام Prisma client مع Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) لمزيد من المعلومات.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db/client.ts`\n\nيستخدم ملف `client.ts` لإنشاء نُسخة لـ Prisma Client علي مستوي التطبيق كلة، اقرأ [Prisma usage](usage/prisma#prisma-client) لمزيد من المعلومات.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nمجلد tRPC يحتوي على كود tRPC للسيرفر.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nيُحتوي مجلد `routers` على كل وطائفك الوصول الفرعية (sub-routers) لمكتبة tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nإن ملف `example.ts` مثال عن وظيفة الوصول tRPC التي تستخدم `publicProcedure` الوطيفة المساعدة (helper) لتوضيح كيف ينشئ وظيفة وصول من tRPC.\n\nسوف يحتوي الملف على وظائف بأعداد مختلفة طبقا لأختيراتك، لتوضيح الاستخدام حسب احتياجك.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nإن ملف `trpc.ts` الملف الرئيسي لإعدادات back-end في tRPC. هنا:\n\n1. يحدد المحتوى المستخدم في طلبات tRPC. اقرأ [استعمال tRPC](https://create.t3.gg/ar/usage/trpc#-serverapitrpcts) للمزيد من المعلومات.\n\n2. يورد (export) نهج الوطيفة المساعدة. اقرأ [استعمال tRPC](https://create.t3.gg/ar/usage/trpc#-serverapitrpcts) للمزيد من المعلومات.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nيُستخدم ملف `root.ts` لدمج وظائف tRPC للوصول, وتوريدهم كوظيفة وصول واحدة، وكذلك أنواع بيانات الوظيفة المحددة، اقرأ المزيد هنا [tRPC usage](https://create.t3.gg/ar/usage/trpc#-serverapirootts).\n\n</div>\n\n<div>\n\n### `src/styles`\n\nيحتوي مجلد `styles` على التصميمات العامة للتطبيق.\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/types`\n\nيحتوي مجلد `types` على الأنواع البيانات (Types) أو الأنواع المحددة (type declarations).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/types/next-auth.d.ts`\n\nيُستخدم ملف `next-auth.d.ts` للتعديل على إعدادات NextAuth الافتراضية، لمزيد من المعلومات [NextAuth.js usage](usage/next-auth#inclusion-of-userid-on-the-session).\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nيُستخدم مجلد `utils` لحفظ الـ functions التي يكثر استخدامها.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/trpc.ts`\n\nيُستخدم ملف `trpc.ts` كـ entrypoint لـ front-end إلى tRPC، اقرآ المزيد هنا [tRPC usage](usage/trpc#-utilstrpcts).\n\n</div>\n<div>\n\n### `.env`\n\nيُستخدم ملف `.env` لتخزين environment variables، اقرأ المزيد [Environment Variables](usage/env-variables). يجب ألا يضاف هذا الملف في تاريخ Git.\n\n</div>\n<div>\n\n### `.env.example`\n\nملف `.env.example` هو مثال لاستخدام example environment مبني على المكتبات المختارة. يجب أن يضاف هذا الملف في تاريخ Git.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nيٌستخدم ملف `.eslintrc.cjs` لإعداد ESLint، اقرأ المزيد هنا [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files).\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nيحقق ملف `next-env.d.ts` أن Typescript تأخذ Types في Next.js في الحسبان. **لا تُعدل عليها ولا تحذفها لأنها تتغير باستمرار**، لمزيد من المعلومات [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects).\n\n</div>\n<div>\n\n### `next.config.js`\n\nيستخدم ملف `next.config.js` لإعداد Next.js، لمزيد من المعلومات [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction). تلميح: يسمح تمديد `.mjx` باستخدام ESM imports.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nإن ملف `postcss.config.js` ضروري عند استخدام TailwindCSS PostCSS، لمزيد من المعلومات [Taiwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss).\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.js`\n\nإن ملف `prettier.config.js` ضروري عند استخدام Prettier ولإضافة prettier-plugin-tailwindcss لتنظيم الفئات (classes) مع Tailwind CSS، لمزيد من المعلومات [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier).\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nإن ملف `tsconfig.json` ضروري عند استخدام TypeScript. فعيلت بعض الإعدادات الغير افتراضية، مثل `strict mode`، لتوفير أفضل إمكانية للاستخدام الـ TypeScript في Create T3 App ومكتباتها، لمزيد من المعلومات اقرأ [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) أو [TypeScript Usage](usage/typescript).\n\n</div>\n"
  },
  {
    "path": "www/src/pages/ar/installation.mdx",
    "content": "---\ntitle: التثبيت\ndescription: تعليمات التثبيت لـ Create T3 App\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nلإنشاء تَطبيق بإستخدام `create-t3-app`، نفيذ أي من الأوامر الثلاث التالية وأجب عن أسئلة مٌوجه الأوامر (command prompt):\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nبعد أن تَنتهي عَملية إنشاء التطبيق، اَلق نَظرة عَلي [الخطوات الأولى](/ar/usage/first-steps) للبدء في تطبيقك الجديد.\n\n## الخصائص المَتقدمة\n\n| خصائص             | الوظيفة                                                      |\n| ----------------- | ------------------------------------------------------------ |\n| `[dir]`           | تحتوي على معطى الملف الذي سيسما عليه التطبيق                 |\n| `--noGit`         | أخبار الـ CLI إلا يهيئ GIT repo للتطبيق قصداً                |\n| `-y`, `--default` | تعدي أسئلة الـ CLI وإنشاء تطبيق t3 مع اختيار جميع الاختيارات |\n| `--noInstall`     | إنشاء تطبيق دون تثبيت الـ dependencies                       |\n\n## خصائص تجريبية\n\nهُناك بعض خصائص التجريبية (Flags) التي تسمح لك بإنشاء أي تطبيق دون أي أسئلة من مُوجة الأوامر. إذا كانت حالة الاستخدام هذه تنطبق عليك ، فيمكنك إستخدام هذه خصائص. يٌرجى مٌلاحظة أن هذه خصائص تجريبية وقد تتغير في المستقبل دون أن نُخصص لها semver versioning.\n\n| خصائص        | الوظيفة                      |\n| ------------ | ---------------------------- |\n| `--CI`       | دع CLI يعرف أنك في وضع CI    |\n| `--trpc`     | أضف tRPC إلى التطبيق         |\n| `--prisma`   | أضف Prisma إلى التطبيق       |\n| `--nextAuth` | أضف NextAuth.js الي التطبيق  |\n| `--tailwind` | أضف Tailwind CSS الي التطبيق |\n\n<Callout type=\"warning\">\n  ملاحظة: إذا لم تضع الخاصية `CI` ، فلن يكون لبقية هذه الخصائص أي تأثير.\n</Callout>\nيمكنك الا تُضيف الخيارات في حال لم تكن تريد ذلك، لكننا ننصحك بذلك تحرياََ للدقة فعليك\nتمرير `false` مع الخاصية مثل `--nextAuth false`.\n\n### أمثلة\n\nالامر التالي سَيٌنشئ تطبيق T3 باستخدام tRPC و Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/ar/introduction.md",
    "content": "---\ntitle: مقدمة\ndescription: مقدمة إلى T3 Stack\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\nالـ T3 Stack هو Stack لتطوير تطبيقات الويب بُني علي فَلسفة البساطة، قابلية إعادة الاستخدام (فصل المركبات وإعادة استخدامها) و الحصول على typesafety في جميع أزكان التطبيق.\n\nالأجزاء الأساسية هم [**Next.js**](https://nextjs.org/)، و [**TypeScript**](https://typescriptlang.org/)، و [**Tailwind CSS**](https://tailwindcss.com/) ودائما ما تَكون مُضافة، إذا كان مشروعك يتطلب Backend فَيُمكنك إضافة [**tRPC**](https://trpc.io/)، و [**Prisma**](https://prisma.io/)، و [**NextAuth.js**](https://next-auth.js.org/).\n\nلعلك لاحظت أن هناك الكثير من... الأجزاء. هذا ما رغبنا بتصميمه, لك مُطلق الحرية أن تُضف جزء وتَحذف أُخرى كما تحتاج - يكون أساس Stack خاضع لاحتياجاتك.\n\n## حسنا… ما هو create-t3-app؟ أهو قالب (template)؟\n\nنوعا من. أُنشئ `create-t3-app` بواسطة مطورون متمرسون ليبسط CLI إعداد تطبيق T3 قَدر الإمكان. فَكُل جزء اختياري، هذا يعني أنك تنشئ قالبك حسب احتياجك.\n\nبعد أنشاء العديد من المشروعات وممارسة تلك الأدوات لسنين، كسبنا العديد من الخبرات والآراء، وفعلنا قدر المستطاع لوضعهم داخل CLI.\n\n**أنه ليس** بقالب شامل علي كل ما تحتاجة، نتوقع منك أن تُضيف مكتباتك الخاصة لحل ما سيواجهك من مشكلات **في تطبيقك**. علي الرغم من أننا نريد أن نترك لك مُطلق الحرية في حل المشاكل مثل state management ونشر التطبيق، [لكن لدينا بعض الترشيحات لك](/ar/other-recs).\n\n## T3 Axioms\n\nلنكون شفافون - هذا _مشروع متعدد الآراء_. نتشارك جميعاََ في عدد قليل من المعتقدات الأساسية حَول كيفية البناء ونتخذها كأساس قراراتنا.\n\n### Solve Problems\n\nمن السهل أن تَقع في فخ فتُضيف \"كل شيئ\" - لكننا لا نريد ذَلك صراحتاً، يَجب أن يكون لكل شيئ مَغزي وهدف مُحدد كما هو الحال في ما أضفناه مُسبقا ويَترتب علي ذلك عدم إضافة مكتبات مِثل (`zustand`, `redux`)، لكننا نُضيف مكتبات أُخري مُثل NextAuth.js, و Prisma و tRPC.\n\n### غامر، لكن علي مسؤوليتك\n\nنحن نحب التقنيات الحديثة، تجرِبة الأشياء الجديدة تجلب السعادة، لكن عليك تَوخى الحذر فلا تَستخدام التقنيات الغير مستقرة في الأماكن الحساسة، فمثلا نحن لا نراهن ⛔️ على قواعد بيانات حديثة (فإن SQL رائعة)، لكننا نراهن ✅ علي tRPC لأنها مجرد Functions ومن السهل الاستغناء عنها.\n\n### Typesafety ليس خياراََ\n\nقد حددنا مُسبقاَ أن الهدف الأوحد من `create-t3-app` هو أن نوفر بِداية سَريعة لتطوير تطبيقات full-stack مع اتخاذ **typesafe** كأولوية, فهو أمر لابد منه لتحسين فاعليتك كمطور بواسطة تقليل عدد Bugs قدر الإمكان.\nأي حل وسط يضر typesafe في `create-t3-app` يَجب اتخاذه في مشروع مختلف.\n"
  },
  {
    "path": "www/src/pages/ar/other-recs.md",
    "content": "---\ntitle: ترشيحات أخرى\ndescription: مكتبات وخدمات نرشحها لك\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nنٌدرك تمام الإدراك أن المَكتبات الإفتراضية في `create-t3-app` لا تَحٌل كُل المشاكل التي قد تواجهك، بغض النظر عن ذلك فنحن ننصحك أن تبدأ بالأشياء التي نٌقدمها، فعاجلاََ أم أجلا سيأتي عليك وقت تحتاج فيه الي إستخدام مكتبات خَارجية، أنت وَحدك مَن يدري إحتياجات مشروعك.\n\nهَاك بَعضٌ المَصادر التي نٌشجعك على أن تّتبعها.\nبَعض الترشيحات التالية قَدمها مٌساهمون مٌنفردون فلا يَجب أن تُؤخذ على أنها تَرشيحات رَسمية من فريق T3 أو T3-OSS، لذلك **قُم بالبحث، خاصة قبل أن تشترك في خدمات مدفوعة**\n\n## State Management\n\n**ملحوظة المحرر**: مكتبات الـ State Management رائعة لكنها في مٌعظم الحالات ليست ضَرورية، فـ tRPC و ReactQuery تقوم بالوظيفة بشكل جيد، لذلك إبدأ بـ`useState` وانتقل إلى أحد البدائل المتاحة فقط عندما يلزم الأمر.\n\n### Zustand\n\n**حتي لا تستعمل Redux أبداََ مرة اخرى**\n\nبديل Redux الذي لم تكن تعلم إنك تحتاجة، غير إمكانية الوثوق بها فأنة بإستخدام [Poimandres](https://github.com/pmndrs) يمكنك صُنع **كل شي** من تطبيقات المكالمات الي الالعاب وغيرها.\n\n- [Zustand Homepage](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n## Component Libraries\n\nتحتاج مٌعظم التطبيقات إلى نَفس مَجمٌوعة المٌكونات - أزرار التبديل والقوائم المنسدلة وغيرها.\nتٌوفر هَذه المَكتبات مُكونات رَائعة يُمكنك إستخدامها وتَخصيصها حَسب رَغبتك.\n\n### Unstyled Component Libraries\n\nتُعرف أيضًا باسم Headless libraries ، فهي تٌوفر مٌكونات رائعة يمكنك عمل styling لها كما تشاء, هذا الي جانب كونها Accessible و يمكنك تخصيصها حسب رغبتك.\n\n- [Radix UI](https://www.radix-ui.com/)\n- [Headless UI](https://headlessui.com/)\n- [React Aria](https://react-spectrum.adobe.com/react-aria/)\n\n### Styled Component Libraries\n\nفي بعض الأحيان تقوم ببناء مشروع وكل ما تريدة هو أن تبدو واجهة المستخدم جيدة. كـ لوحات التحكم وغيرها ، سَتٌنجز أي هذه المكتبات هذه المهمة على أكمل وجه\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n\n### Class Variance Authority\n\n** لبناء مكتبات UI **\nتُساعدك علي إنشاء مكتبات واجهة مستخدم بشكل تصريحي (Declarative) بألوان وأحجام مختلفة ومتغيرات مختلفة. عندما يصل مشروعك إلى حجم يلزمك فيه مجموعة موحدة من مكونات الـ UI مع مُتغيرات مٌتعددة لـ Tailwind CSS ، فإن CVA هي أداة رائعة.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Animations\n\n### AutoAnimate\n\n**الانميشن بسطر كود واحد**\n\nتحاول معظم مكتبات الانميشن إرضاء كل حالات الاستخدام الممكنة ، نتيجة لذلك تصبح غير مرغوب فيها. AutoAnimate هي أداة لا تحتاج إلى تكوين تٌوفر تَحسينًا كبيرًا في UX دون بَذل جٌهد إضافي من المطور.\n\n- [AutoAnimate Homepage](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**الرسوم المتحركة المعقدة**\n\nتٌوفر FramerMotion اٌسلوبا بَسيطا لكتابة الكود، فَتسمح لك بكتابة رسوميات معقدة بكود أقل\n\n- [Framer Motion Homepage](https://framer.com/motion)\n- [Framer Motion Documentation](https://www.framer.com/docs/)\n\n## Deployments، و Infrastructure، و Databases، و CI\n\n### Vercel\n\n**إستضافة موقعك**\n\nقامت Vervel بتسهيل استضافة موقعك بعد أن كان جِحِيماََ في الماضي، فإنها تَعتمد عََلي AWS لكن مع واجهة أفضل.\n\n- [Vercel Homepage](https://vercel.com/)\n- [Create T3 App Vercel deployment guide](/en/deployment/vercel)\n\n### PlanetScale\n\n**حتي لا تقلق علي قواعد بياناتك بعد الآن**\n\nتُعد PlanetScale أحد أفضل مٌزودي خِدمة قَواعد البيانات عَلي الإطلاق لقٌدرتها عَلى التَوسع وتجربة المطور الممتازة والأسعار المعقولة.\n\n- [PlanetScale Homepage](https://planetscale.com/)\n\n### Railway\n\n**لإستضافة البنية التحتية للموقع**\n\nفهي Heroku العصر الحديث، إذا كان Vercelli , PlanetScale غير كافيين لك، فـ Railway سَتكون خيارك المناسب.\n\n- [Railway Homepage](https://railway.app/)\n\n### Upstash\n\nنحن نٌحب Prisma و Planet Scale لكن بعض المشاريع تتطلب حٌلولا أكثر سٌرعة.\nفإن **Upstash** تٌعطيك القٌدرة علي إستخدام Redis في مشروعك دون الحاجة أن تٌدير البنية التحتية.\n\n- [Upstash موقع](https://upstash.com/)\n\n### Pusher\n\n**For serverless WebSockets**\n\nإذا كان الـ WebSockets مُهمة بالنسبة لك، فإنه مِن الأفضل الإعتماد على سيرفر تقليدي مثل [Fastify](https://www.fastify.io/) والتي أيضا تدعم [tRPC](https://trpc.io/docs/v10/fastify)\nلكن إذا كانت السرعة مهمة لك فإن Pusher هو الخيار المناسب لك.\n\n- [Pusher Homepage](https://pusher.com/)\n\n### Soketi\n\nSoketi هو بديل بسيط وسريع للاستضافة الذاتية لـ Pusher. إنه متوافق تمامًا مع Pusher SDK الذي يمكنك استخدامه للاتصال بالخادم. Soketi serverless هو أيضًا في مرحلة تجريبية.\n\n- [Soketi Homepage](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Analytics\n\nتعتبر بيانات المستخدم ذات قيمة كبيرة عند إنشاء تطبيق. فيما يلي بعض موفري التحليلات الذين نوصيك بهم.\n\n### Plausible\n\nهل تحتاج إلى تحليلات؟ Plausible هو أحد أسرع الطرق للحصول عليها [simple plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Plausible Homepage](https://plausible.io/)\n\n### Umami\n\nيعد Umami بديلًا بسيطًا وسريعًا لبرنامج Google Analytics. يمكنك استخدامه بسهولة في Vercel و Railway وما إلى ذلك باستخدام PlanetScale كقاعدة بيانات.\n\n- [Umami Homepage](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n## غيرها\n\n### Next Bundle Analyzer\n\nقد يكون من الصعب أحيانًا تحديد ما سيتم تضمينه في الإصدار النهائي لتطبيقك. يُعد Next Bundle Analyzer طريقة سهلة لتصور وتحليل حزم JavaScript التي تم إنشاؤها.\n\n- [next/bundle-analyzer](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/ar/t3-collection.mdx",
    "content": "---\ntitle: اعمال بواسطة T3\ndescription: تطبيقات مفتوحة المصدر صنعت باستخدام Stack T3\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\nisMdx: true\n---\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\n\nهل قٌمت بعمل تطبيق بإستخدام T3 Stack وتريد مشاركته؟ أضافه إلى القائمة التالية!\n\n## تطبيقات مفتوحة المصدر صُنعت بواسطة T3\n\n<OpenSourceAppList descriptionIntl=\"الوصف\" linkIntl=\"الرابط\"/>\n\n## شركات تَستخدم T3 Stack\n\nنَوَدٌ مَعرفة الشَركات التي تَستخدم Stack T3 لتَطبيقاتها. إذا كانت شَركتك تَستخدم Stack T3 وتَرغب في مشاركته؟ أضافه إلى القائمة التالية!\n\n<CompanyList companyIntl=\"الشركة\" linkIntl=\"الرابط\"/>\n\n_أصنعت مشروعاً باستخدام T3 Stack؟ أنشئ [Pull Request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx). وضفه هنا!_\n"
  },
  {
    "path": "www/src/pages/ar/usage/env-variables.md",
    "content": "---\ntitle: Environment Variables\ndescription: بدء الاستخدام مع create-t3-app\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nإن `Create-T3-App` تستخدم [Zod](https://github.com/colinhacks/zod) للتأكد من صلاحية الـ environment variables أثناء الـ runtime عن طريق توفير بعض الملفات الاضافة\n\n📁 src/env\n\n┫ 📄 client.mjs\n\n┫ 📄 schema.mjs\n\n┫ 📄 server.mjs\n\nقد يبدو محتوى هذه الملفات مخيفًا للوهلة الأولى ، لكن لا تقلق ، فهو ليس معقدًا كما يبدو. دعنا نلقي نظرة عليها واحدة تلو الأخرى ، ونسير خلال عملية إضافة environment variables إضافية.\n\nإذا كنت تريد إضافة environment variable جديد ، فيجب عليك إضافته إلى كل من \".env\" وكذلك في `env / schema.mjs`.\\_\n\n## ملف schema.mjs\n\nهذا هو الملف الذي ستعمل علية. يَحتوي على مُخططين ، أحدهما environment variables من جانب الخادم والآخر من جانب العميل بالإضافة إلى Object الـ \"clientEnv\".\n\n```ts:env/schema.mjs\nexport const serverSchema = z.object({\n  // DATABASE_URL: z.string().url(),\n});\n\nexport const serverEnv = {\n  // DATABASE_URL: process.env.DATABASE_URL,\n};\n\nexport const clientSchema = z.object({\n  // NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nexport const clientEnv = {\n  // NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,\n};\n```\n\n### الـ Server Schema\n\nأنشئ الـ environment variables schema من جانب الخادم هنا.\nتأكد أن لا تضيف `NEXT_PUBLIC` قبل اسم المتغير، سيفشل الـ Validation إذا ما فعلت هذا.\n\n### الـ Client Schema\n\nأنشئ الـ client-side environment variables هنا، حتى تجعلهم متاحيت للـ client أضف `NEXT_PUBLIC` قبل الاسم.\n\n### الـ clientEnv Object\n\nهُنا حيثُ تقوم بعمل Destruct لـ `process.env`\nتحتاج Zod الي Object لتكون قادرة على تصحيح المُدخلات وبسبب طريقة عمل Next.js فلن نستطيع فعل هذا تلقائيا لذلك يجب أن تتم هذة العملية يدويا، لا تقلق فـ Typescript تقوم بتحذيرك إذا ارتكبت خطاّ.\n\n```ts\n// ❌ This doesn't work, we need to destruct it manually\nconst schema = z.object({\n  NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nconst validated = schema.parse(process.env);\n```\n\n## الـ server.mjs & client.mjs\n\nهذا هو المكان الذي يتم فيه التحقق من الـ Object ومن ثم تصديرها. لن تحتاج إلى تعديل هذه الملفات.\n\n## إستخدام الـ Environment Variables\n\nإذا أردت إستخدام الـ env vars فيمكنك إستيراد` env.js` واستعمالهم طبيعيا. إذا إستيرادت الملف في Client وحولت استعمال قيم الserver-side، ستنذر بوجود خطأ في run-time.\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` is fully typesafe and provides autocompletion\nconst dbUrl = env.DATABASE_URL;\n```\n\n## الـ .env.example\n\nبما أن ملف `.env` ليس مُضمناَ في الـ version control، فقد أضفنا ملف `.env.example` والذي يمكنك أن تتركه، وأضياََ ننصحك أن تُبقي هذا الملف متزامنا مع الملف الاساسي حتي تحصل علي أفضل تجربة تطوير ممكنة\n\n## أضف Environment Variables\n\nحتى نتأكد من أنك ستضيف الـ environment variables، يجب عليك أن تضيفها في مكانين مختلفين\n\n📄 ملف `.env`: هنا نضيف المتغيرات بشكل طبيعي كانك تتعامل مع ملف `.env` عادي\n\n📄 ملف `schema.mjs`: هنا تضيف الـ Logic التي ستستخدمة Zod لفحص صلاحية المتغيرات\n\n📄 ملف `.env.example`: هنا تضيف المتغيرات لكن بدون أي كلمات سرية للحفاظ على أمانك\n\n### أمثلة\n\n1. أضف the environment variable الي `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. أضف environment variable to `schema.mjs`:\n\n```ts\nexport const serverSchema = z.object({\n  // ...\n  TWITTER_API_TOKEN: z.string(),\n});\n\nexport const serverEnv = {\n  // ...\n  TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n};\n```\n\n**ملحوطة:** أضف إسم المُتغيير `TWITTER_API_TOKEN` في example.env ولكن لا تُضف الـ token\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/ar/usage/first-steps.md",
    "content": "---\ntitle: الخطوات الاول\ndescription: الخطوات الاولي في create-t3-app\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nلقد أنشأت للتو مَشروعا باستخدام T3 Stack ، هذة هي الخُطوات الاجبارية التي يجب إتباعها قبل أن تتمكن من تشغيل المشروع.\n\n## قواعد البيانات\n\nاذا كان مشروعك يحتوي على Prisma فعليك ان تقوم بتشغيل أمر `npx prisma db push` ، هذا الأمر يقوم بمزامنة الـ Schema مع قاعدة البيانات ليضمن الـ Typesafety عند الـ Client، **لاحظ أن هذه الخطوة تتطلب إعادة تشغيل الخادم**\n\n## الـمصادقة\n\nإذا كان تطبيقك يتضمن NextAuth.js ، سنبدأ مع Discord Provider. يُعد هذا أحد أبسط مُزودي الخدمة التي تدععمها NextAuth.js ، لكنه لا يزال يتطلب القليل من الإعداد الأولي من جانبك.\nبالطبع ، إذا كنت تفضل استخدام موفر مصادقة مختلف ، فيمكنك أيضًا استخدام أحد المزودين العديدين الذين يقدمهم NextAuth.js.\n\nستحتاج إلى حساب Discord ، أنشئ واحداََ إذا لم تكن قد قمت بذلك بالفعل.\nاذهب https://discord.com/developers/applications واضغط علي New Application في الجانب الايمن الاعلي .\n\nثم اذهب **<** Settings **<** OAuth2 **<** General\n\nقم بنسخ Client ID وضعه في `.env `كـ `AUTH_DISCORD_ID`\n\nاضغط علي Reset Secret ثم انسخ كلمة السر الجديدة وضعها في .env كـ AUTH_DISCORD_SECRET\nاضغط علي Add Redirect واضف http://localhost:3000/api/auth/callback/discord\nاضف AUTH_SECRET الي .env كـ String، في الـ Production اضف كلمة سر قوية.\n"
  },
  {
    "path": "www/src/pages/ar/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: إستخدام  NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nعندما تُريد نِظام مُصادقة في تَطبيق Next.js ، فإن NextAuth.js يُعد حلاً ممتازًا دون الحاجة إلى إنشائة بنفسك. يأتي مزودًا بقائمة واسعة من الموفرين لإضافة مصادقة OAuth بسرعة ويوفر Adapters للعديد من قواعد البيانات و ORMs.\n\n## Context Provider\n\nفي نقطة الدُخول إلي تطبيقك ، سترى أن تطبيقك في [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nيسمح الـ context Provider لـ تطبيقك ان يصل إلى بيانات المستخدم دون الحاجة الى ادخال اي بيانات اضافيه\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Handle unauthenticated state, e.g. render a SignIn component\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## تضمين `user.id` في الـ Session\n\nيُستخدم `create-t3-app` الـ Session callback الموجودة في ملف تكوين NextAuth.js ليضيف الـ User ID الي Session Object.\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nبنفس الطريقة يمكن اضافة اي بيانات الى الـ Session Object\n\n## Usage with tRPC\n\nعند استخدام NextAuth.js مع tRPC، يمكنك إنشاء producers وحمايتها باستخدام [middleware](https://trpc.io/docs/v10/middlewares)، وهذا يسمح لك بإنشاء procedures لا يمكن الوصول لها إلا بواسطة أشخاص معينين\n\nيُمكن فَعل هذا في خطوتين:\n\n1. للحصول علي Object الـ Session يمكنك استخدام getServerSession،\n   نفضل getServerSession عن getSession لانها تعمل علي الخام فلا يحدث invoke غير مرغوب فيه ، قد تحملت `create-t3-app` عناء إنشاء هذه المادة عنك :\n\n```ts:server/common/get-server-auth-session.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await getServerSession(ctx.req, ctx.res, nextAuthOptions);\n};\n```\n\nباستخدام هذه الاداة يمكنك الحصول علي الـ Session وتمريرها إلى الـ tRPC Context\n\n```ts:server/trpc/context.ts\nimport { getServerAuthSession } from \"../common/get-server-auth-session\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. أنشئ tRPC Middleware وتأكد ما اذا كان هذا المستخدم يملك الصلاحيات اللازمة أم لا.\n\n```ts:server/trpc/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n});\n```\n\nالـ Session Object صغير ويحتوي علي عدد قليل من الخانات، وعند استخدامك لـ `protectedProcedures`يمكنك الوصول الى هذة البيانات منها الـ UserId وعندها يمكنك عمل fetch لبيانات اخرى من قاعدة البيانات.\n\n```ts:server/trpc/router/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## الاستخدام مع Prisma\n\nيتطلب إستخدام NextAuth.js للعمل مع Prisma الكثير من الإعداد الأولي. يتعامل تطبيق create-t3-app مع كل هذا من أجلك ، وإذا حددت كل من Prisma و NextAuth.js ، فستحصل على نظام مصادقة يعمل بكامل طاقته مع جميع النماذج المطلوبة التي تم تكوينها مسبقًا. نقوم بشحن تطبيقك الاولي مع مزود Discord OAuth المكون مسبقًا ، والذي اخترناه لأنه من أسهل البدء معة - ما عليك سوى توفير الرموز المميزة في .env وستكون جاهزًا للبدء. ومع ذلك ، يمكنك بسهولة إضافة المزيد من مقدمي الخدمة باتباع NextAuth.js Docs. لاحظ أن بعض مقدمي الخدمة يطلبون إضافة حقول إضافية إلى نماذج معينة. نوصيك بقراءة الـ Docs الخاصة بالموفر الذي ترغب في استخدامه للتأكد من أن لديك جميع الحقول المطلوبة.\n\n### إضافة المزيد من الحقول إلى الـ models\n\nعند الحاجة إلى إضافة حقول إضافية الي `User` أو `Account` أو `Session` -على اغلب الظن انك لن تحتاج الى تعديل شئ غير `User` اَ بق في بالك أن Prisma Adapter سينشئ هذا الحقل تلقائيا مع كل مستخدم جديد لذا عليك أن تضيف قيمة افتراضية Default Value.\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## الاستخدام مع Next.js Middleware.\n\nيتطلب استخدام NextAuth.js مع Middleware Next.js استخدام [JWT Session Strategy](https://next-auth.js.org/configuration/nextjs#caveats). هذا لأن الـ Middleware قادرة فقط على الوصول إلى ملف تعريف ارتباط JWT\n\nبشكل افتراضي ، يتم تكوين التطبيق create-t3-app لاستخدام استراتيجية قاعدة البيانات Database Strategy ، بالاشتراك مع Prisma كـ Adapter لـ قاعدة البيانات.\n\n## إعداد DiscordProvider\n\n1. اتجه الى [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications) واضغط على New Application.\n\n2. في settings menu اضغط على OAuth2 ثم General\n\n3. إنسخ الـ Client ID وضعة في `.env` كـ AUTH_DISCORD_ID\n\n4. تحت Client Secret اضغط على \"Reset Secret\" ونسخ النص الجديد وضعه في `.env` كـ `AUTH_DISCORD_SECRET `.\n   كن حذرًا لأنك لن تتمكن من رؤية هذا كلمة السر مرة أخرى ، ستؤدي إعادة تعيينها إلى انتهاء صلاحية كلمة السر الحالية\n5. اضغط على Add Redirect واضف رابط إعادة التوجيه`http://localhost:3000/api/auth/callback/discord` كمثال\n6. احفظ التعديلات\n\n- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) during development.\n\n## مصادر مُفيدة\n\n| المَصدر                           | الرابط                                  |\n| --------------------------------- | --------------------------------------- |\n| NextAuth.js Docs                  | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/ar/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: إستخدام Next.js\nlang: ar\ndir: rtl\nlayout: ../../../layouts/docs.astro\n---\n\nNext.js هو إطار عمل Backend لتطبيقات React\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nشاهد هذا الفيديو لتعرف المزيد عن [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw)\n\n## لماذا عَلي أن أستخدمها ؟\n\nنحن نحب React. لقد جعلت تطوير واجهة المستخدم سهلا بطرية لم نتخيلها من قبل. لكنها يمكن أن تؤدي بالمطورين إلى أن يتبع بعض المسارات الصعبة. تقدم Next.js أسلوبًا سلساََ لإنشاء التطبيقات باستخدام React. بداية بالـ Routing انتقالا إلى الـ Api ومن ثم الصور ، نضع ثقتنا فى Next.js لتقود المطورين نحو قرارات جيدة.\n\nإقران Next.js مع Vercel يجعل تطوير تطبيقات الويب ونشرها أسهل من أي وقت مضى. فتوفر طرية مجانية لنشر موقعك (نحن ❤️ Vercel)\n\n## Get Static/Server Props\n\nالميزة الرئيسية لـ Next.js هي الـ Data Fetching. نوصيك بشدة أن تقرأ الـ Docs لكي تفهم كيفية استخدام كل واحدة منهما. لا يُنصح باستخدام getServerSideProps عمومًا ما لم يكن هناك سبب وجيه لذلك ، نظرًا لأنها مُكلفة ماديا وتُؤدي إلى إبطاء موقعك. Incremental Static Regeneration هو بديل رائع لـ getServerSideProps عندما تكون البيانات ديناميكية ويمكن جلبها بشكل متزايد.\n\n## مصادر مفيدة\n\n| المَصدر                        | الرابط                             |\n| ------------------------------ | ---------------------------------- |\n| Next.js Documentation          | https://nextjs.org/docs            |\n| Next.js GitHub                 | https://github.com/vercel/next.js  |\n| Next.js Blog                   | https://nextjs.org/blog            |\n| Next.js Discord                | https://nextjs.org/discord         |\n| Next.js Twitter                | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/ar/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: إستخدام Prisma\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nمكتبة Prisma هي ORM مكتوب لغة TypeScript والتي تسمح للمطور أن يُخصص Schema لقاعدة البيانات في ملف `schema.prisma` من ثَم يقوم بتوليد type-safe client والذي بدوره يتفاعل مع قاعدة البيانات.\n\n## ما هو Prisma Client\n\nيقع في `/server/db/client.ts` ويعمل كـ global variable كما تنصح الـ docs الرسمية [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) ,وننصحك باستخدامها كذلك بدلا من ندائها في ملف بشكل منفرد [Context](usage/trpc#-serverapitrpcts)\n\n## الـ Schema\n\nسوف تجد الـ Schema في `/prisma/schema.prisma` حيث تقوم بتخصيص الـ schema الخاص بقاعدة البيانات والتي يتم استخدامها لتوليد Prisma Client.\n\n### مع NextAuth.js\n\nعندما تستخدم Prisma مع NextAuth فان الـ Adapter يتحمل عنك عناء توليد الـ `User`, `Session`, `Account`, and `VerificationToken` mo، إقرأ المزيد هنا [NextAuth.js documentation](https://next-auth.js.org/adapters/prisma).\n\n## Default Database\n\nقاعدة البيانات الافتراضية هي قاعدة بيانات SQLite ، وهي رائعة لتطوير وتسريع عملية proof-of-concept ولكن لا يوصى بها للإنتاج. يمكنك تغيير قاعدة البيانات لاستخدامها عن طريق تغيير `provider` في الـ DataSource Object إلى `postgresql` أو `mysql` ، ثم تحديث URL داخل `.env` إلى قاعدة البيانات الخاصة بك.\n\n## Seeding your Database\n\n[يُعد زرع قاعدة البيانات](https://www.prisma.io/docs/guides/database/seed-database)\nطريقة رائعة لملء قاعدة البيانات بسرعة ببيانات الاختبار لمساعدتك على البدء. من أجل إعداد البذور\nمن أجل إعداد البذر ، ستحتاج إلى إنشاء `seed.ts` في مُجلد `prisma/` ، ثم قم بإضافة `seed` script إلى ملف package.json الخاص بك. ستحتاج أيضًا إلى مُشغل TypeScript يمكنه تنفيذ الـ script. نحن نُوصي بـ tsx ، وهو عِبارة عَن مُشغل TypeScript عالي الأداء يَستخدم esbuild ولا يتطلب أي تكوين ESM ، ولكن ts-node أو أي من المُشغلين الاخرين سيفي بالغرض.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db/client\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nثُم قُم بتشغيل `pnpm db-seed` او `npm` او `yarn`\n\n## مصادر مُفيدة\n\n| المَصدر                      | الرابط                                                                                                                                            |\n| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Prisma Docs                  | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                | https://github.com/prisma/prisma                                                                                                                  |\n| NextAuth.JS Prisma Adapter   | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/ar/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: إستخدام Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\n## ما هي Tailwind CSS ؟\n\nمكتبة Tailwind CSS هي مكتبة صغيرة، بُنيت على فلسفة [utility first](https://tailwindcss.com/docs/utility-first)، وتُستخدم في التصميم والبناء دون الحاجة إلي إستخدام Pure CSS، فهي مكتبة نقية لا تُقدم أي Components مُسبقة التصميم، غير أنها توفر مزايا عديدة بالمقارنة بباقي المكتبات، لمزيد من المعلومات شاهد a very different set of benefits](https://www.youtube.com/watch?v=CQuTF-bkOgc)\nفهي تجعل عملية التصميم سريعة بشكل لا يُصدق.\n\n1. في الماضي كنا نكتب css في ملفات منفصلة\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. ثم نقوم استدعائها في مكان آخر\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. ثم نُضيف الـ class الي HTML\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nالمقابل لكل الخطوات السابقة في Tailwind CSS\n\n1. فقط اكتب الـ Class في HTML وانتهى الموضوع\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nإستخدام هذة الخصائص جَنبا إلى جَنب مع React Components يُعطيك قُوة هائلة لا مَثيل لها.\nتأتي Tailwind CSS بنظام مُدمج وجميل مُزود بمجموعة الوان واحجام و styles مُختارة بعناية كالطول والعرض والحواف، كما أيضا تاني مع breakpoints لإنشاء تصميم متوافق.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nأعطي [mewtru](https://twitter.com/trunarla) خطابا رائعا عن [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## الاستخدام\n\nتأكد من تثبيت إضافة Tailwind CSS لمحرر اكوادك لتُحسن جودة العمل.\n\n### الاضافات\n\n- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### الـ Formatting\n\nالـ Classes في TailwindCSS يمكن أن تصبح فوضوية بسهولة، لذلك الـ Formating هو أمر لابد منه، إضافة [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) تحمل عنك هَم تنظيمها، لمزيد من المعلومات إقرأ [recommended order](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted)\n\n### إضافة الـ classes إختبارياَ\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## مصادر مفيدة\n\n| المصدر                       | الرابط                                                   |\n| ---------------------------- | -------------------------------------------------------- |\n| Tailwind Docs                | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet         | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss          | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community           | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord Server      | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground          | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/ar/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Usage of tRPC\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nتسمح لك tRPC بكتابة type safe api دُون الحَاجة إلى تَوليد كود فتُنحي عنك حَدوث أخطاء مفاجئة أثناء الـ runtime، حيث إنها تَستغل خاصية الـ inference في Typescript حتى تضمن الـ type safety عِند نداء الـ Api من الـ Frontend\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>I built tRPC to allow people to move faster by removing the need of a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 mr-4 rounded-full bg-neutral-500\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creator of tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Files\n\nلسوء الحظ فإن tRPC تتطلب قليلاً من الـ boilerplate ولكن لحسن الحظ فان `create-t3-app` تحمل عنك هذا العبء.\n\n### 📄 ملف `pages/api/trpc/[trpc].ts`\n\nهذة هي نقطة دخولك الي tRPC Api، في الأوضاع الطبيعية لن تحتاج الي أن تَمس هذا الملف كثيرا. فيمكنك تغييره عند تفعيل CORS Middleware او شئ من هذا القبيل ويقوم بعمل export لـ `createNextHandler` [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) والذي يقبل [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) و [response](https://developer.mozilla.org/en-US/docs/Web/API/Response)\n\nمما يعني أنك قادر على استخدام `createNextApiHandler` في أي middleware تريده، إقرأ [example snippet](#enabling-cors)\n\n### ملف 📄 `server/trpc/context.ts`\n\nفي هذا الملف تقوم بانشاء الـ Context التي سيتم تمريره الي tRPC Procedure ، الـ Context هو عبارة عن البيانات التي سيكون لكل الـ Procedures وصول لها وهي مكان مُناسب لتضع أشياء مثل database connections ومعلومات المصادقة وغيرها.\n\n- ما هو `createContextInner`: هُنا تَقوم بإنشاء الـ Context الذي لا يَعتمد عَلى الـ request مِثل إتصال قاعدة البيانات. ويمكنك إستخدام function لـ [integration testing](#sample-integration-test) او [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers)\n- ما هو `createContext` ؟ هُنا حَيث تَقوم بإنشاء الـ Context الذي يعتمد على الـ request فيمكنك الوصول الى الـ `req Object` عن طريق `opts.req` ومن ثُم تَمريرة الي `createContextInner`لإنشاء الـ Context النهائي\n\n### 📄ملف `server/trpc/trpc.ts`\n\nفي هذا حَيثُ يمكنك تحديد الـ [procedures](https://trpc.io/docs/v10/procedures) و [middlewares](https://trpc.io/docs/v10)، من الافضل ان لا تقوم بعمل export لـ t Object كاملا\n/middlewares) بل قم بتصدير procedures و middlewares\nستلاحظ أننا نستخدم `superjson` كـ [data transformer](https://trpc.io/docs/v10/data-transformers)، ذلك حتى نحفظ الـ Types لحين إستخدامها في في الـ client، فمثلا إذا كان الـ Type هو Date فإن الـ client سَيُعيد Date ,gds string\n\n### 📄 ملف `server/trpc/router/*.ts`\n\nهنا يمكنك تحديد الـ route ,والـ procedure للـ API، من الافضل [أن تُنشئ routers](https://trpc.io/docs/v10/router) مُنفصلة للـ procedures المتقاربة ومن ثَم [دمجها](https://trpc.io/docs/v10/merging-routers) في router واحد في `server/trpc/router/_app.ts`\n\n### 📄 ملف `utils/trpc.ts`\n\nهذه هي نقطة دخول الواجهة الأمامية لـ tRPC. هذا هو المكان الذي ستقوم فيه باستيراد **type definition** الخاص بالـ procedure وإنشاء tRPC client الخاص بك جنبًا إلى\nجنب مع react query hooks. نظرًا لأننا قمنا بتفعيل \"superjson\" في الواجهة الخلفية\nفنحن بحاجة إلى تفعيلة على الواجهة الأمامية أيضًا. هذا لان البيانات التي يحدث لها serialized في الـ client يتم عمل deserialized لها في الـ client.\n\nهنا تقوم بتحديد [روابط](https://trpc.io/docs/v10/links) الـ tRPC حيث تُُحدد المسار الذي سيمر به الـ request من الـ client إلى الـ server\nنحن نستخدم [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink) بشكل إفتراضي مع تفعيل [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch) و [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink)\n\nوفي الاخير نقوم بتصدير [helper type](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) حتى نستعمل الـ type infre في الـ frontend\n\n## كيف أستخدم tRPC ؟\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nننصحك بمشاهدة هذا[a killer talk at Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) من [trashh_dev](https://twitter.com/trashh_dev)\n\nمع tRPCتكتب Function في الـ backend والتي يمكن مناداتها من الـ frontend\n\n```ts:server/trpc/router/user.ts\nconst userRouter = t.router({\n  getById: t.procedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nفي نهاية الأمر تتحول tRPC procedure الي backend عادي فيقوم بفحص الـ input ويمرر الـ request إذا كان صحيحاًويعيد رسالة خطأ إذا كانت المدخلات غير صحيحة.\nبعد التأكد من صحة البيانات يتم نداء function والتي إما لجلب بيانات ([query](https://trpc.io/docs/v10/react-queries)) أو أن تغير في البانات ([mutation](https://trpc.io/docs/v10/react-mutations))\nأنت\n\n```ts:server/trpc/router/_app.ts\nconst appRouter = t.router({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nلاحظ أننا نقوم بعمل export فقط لـ router's type أي أننا لا نستخدم اي من الـ server code في الـ client\nالان دعنا ننادي الـ procedure من الـ frontend ، tRPC توفر wrapper لمكتبة `@tanstack/react-query` مما يسمح لك بإستخدام المكتبة بكامل قوتها.\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = trpc.user.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nستلاحظ على الفور مدى جودة الإكمال التلقائي والـ typesafety. بمجرد كتابة \"trpc.\" ، ستظهر `router` الخاصة بك في الإكمال التلقائي ، وعندما تحدد الـ `router`،\nستظهر الـ procedures. وستحصل أيضًا على خطأ TypeScript إذا كانت المُدخلات الخاص بك لا يتطابق مع الـ schema الذي حددته مسبقا.\n\n## كيف اُنادي API خارجي ؟\n\nباستخدام الـ API العادية ، يمكنك استدعاء الـ End point الخاصة بك باستخدام أي عميل HTTP مثل `curl` أو` Postman` أو `fetch` أو مباشرة من متصفحك.\nمع tRPC ، الأمر مختلف بعض الشيء. إذا كنت ترغب في الاتصال بالـ procedure بدون عميل tRPC ، فهناك طريقتان موصى بهما للقيام بذلك:\n\n### Expose a single procedure externally\n\nإذا أردت أن تُتيح procedure للـ Apis الخارجية الق نظرة علي [server side calls](https://trpc.io/docs/v10/server-side-calls)، مما سيسمح لك بعمل Next.js Api إعتيادية\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### تحول كل الـ Procedures الي REST endpoint ؟\n\nإذا كنت ترغب في كشف كل الـ ؛قخؤثيعقثس ، الق نظرة علي [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master).\n\n### It's just HTTP Requests\n\ntRPC communicates over HTTP, so it is also possible to call your tRPC procedures using \"regular\" HTTP requests. However, the syntax can be cumbersome due to the [RPC protocol](https://trpc.io/docs/v10/rpc) that tRPC uses. If you're curious, you can check what tRPC requests and responses look like in your browser's network tab, but we suggest doing this only as an educational exercise and sticking to one of the solutions outlined above.\n\n## Comparison to a Next.js API endpoint\n\nدعنا نقارن \" Next.js Endpoint\" بـ \"tRPC procedure\". لنفترض أننا نريد جلب \"Object\" مستخدم معين من قاعدة بياناتنا وإعادته إلى الواجهة الأمامية.\nيمكننا كتابة Next.js API Endpoint مثل هذا:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db/client\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nقارن هذا بمثال tRPC أعلاه ويمكنك رؤية بعض مزايا tRPC:\n\n- بدلاً من تحديد عنوان url لكل مسار ، والذي يمكن أن يصبح مزعجًا إذا حاولت نقل شيء ما ، فإن الـ `router` بأكمله عبارة عن `Object` مع الإكمال التلقائي.\n- لست بحاجة إلى التحقق من HTTP method التي تم استخدامها.\n- لا تحتاج إلى التحقق من أن الطلب أو الـ `query` ، لأن Zod يعتني بذلك.\n- بدلاً من إنشاء الـ responde object ، يمكنك إرجاع أخطاء او قيمة أو Object كما تفعل في أي function.\n\n## snippets مفيدة\n\n### تفعيل CORS\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/trpc/router/_app\";\nimport { createContext } from \"~/server/trpc/context\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Optimistic updates\n\nالـ Optimistic updates هي تحديثات تحديث واجهة المستخدم قبل أن ينتهي الـ Request مما يُحسن تجربة المستخدم، لكن التطبيقات التي تُفضل دقة المعلومات يجب أن تتجنب الـ Optimistic updates، للمزيد من المعلومات إقرا [React Query docs](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = trpc.post.list.useQuery();\n\n  const utils = trpc.useContext();\n  const postCreate = trpc.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### عينة من Integration Test\n\nإقرأ [Vitest](https://vitest.dev)\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/router/_app\";\nimport { createContextInner } from \"~/server/router/context\";\n\ntest(\"example router\", async () => {\n  const ctx = await createContextInner({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n## Useful Resources\n\n| Resource               | Link                                                    |\n| ---------------------- | ------------------------------------------------------- |\n| tRPC Docs              | https://www.trpc.io                                     |\n| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples         |\n| React Query Docs       | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/ar/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: إستخدام TypeScript\nlayout: ../../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 mr-4 rounded-full bg-neutral-500\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creator of the T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nسواءََ كُنت مُبرمجا مُبتدئاََ أو مُتمرسًا ، فعلبك أن تتأكد تمام الثقة أن TypeScript أمر لا بد منه. قد تبدو مخيفتاََ في البداية ، ولكنها في الواقع فحالها كحال الأدوات الأخرى، وهي شيء لا يَنظر فية الكثيرون أبدًا بعد البدء في استخدامها.\n\nفتُوفر مٌلاحظات مٌباشرة أثناء كِتابة الكود عَن طَريق تَحديد أنواع البيانات المتوقعة ، وأيضا تٌوفر خاصية الإكمال التلقائي في الـ Editor الخاص بك ، أو ربما ستصرخ عَليك بِخطوط مُتعرجة حمراء إذا حاولت الوصول إلى خاصية غير موجودة أو إذا قمت بتمرير قيمة من النوع الخطأ ، التي قد تضطر إلى تصحيحها.\n\n## الـ Type Inference\n\nيميل الكثير من مٌطوري Typescript إلى كِتابة الكثير من الـ types وفي واقع الامر أن هذا ليس ضرورياََ أبداََخاصتاََ مع وجود الـ Inference.\nلكن ... إنتظر لحظة .. ، ما هو الـ Inference اصلا ؟ حسنا .. الـ Inference هو تَتَبُع الـ Types لك في كل مكان في الكود، يُفيدك في أنه يُغنيك عن تِكرار كتابة الـ Types في أماكن أخرى.\n\n<div class=\"embed\">\n    <iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nالق نظرة علي [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## إستخدامات الـ type inference\n\n### مكتبة Zod\n\nمكتبة [Zod](https://github.com/colinhacks/zod) هي schema validation library تم بِنائوها بـ Typescript. فَقط اٌكتب الـ Schema التي تٌمثل مَصدر الحقيقة الاساسي single source of truth ودع الباقي لـ zod وهي ستتكفل بة.\n\n### مكتبة Tanstack Query\n\nتُسهل عليك كِتابة وإدارة الـ queries و الـ mutations مما يٌدوي الي تحسين تجربة المٌطور والمستخدم.\n\n## مصادر مفيدة\n\n| المصدر                                                    | الرابط                                                            |\n| --------------------------------------------------------- | ----------------------------------------------------------------- |\n| TypeScript Handbook                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| Beginners TypeScript Tutorial                             | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                           | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/ar/why.md",
    "content": "---\ntitle: لماذا CT3A؟\ndescription: لماذا يجب عليك اختيار Create T3 App لتطبيقك المقبل\nlayout: ../../layouts/docs.astro\nlang: ar\ndir: rtl\n---\n\nلقد أنشئنا Create T3 App لان [Theo](https://twitter.com/t3dotgg) رفض أن يصنع قالب محضَر لتِقنيته المُفضلة. ألهمنا حُبنا لـ typesafety، جَنباََ إلى جَنب مع create-next-app، و [Astro's CLI](https://astro.build)، للعمل عَلى قَدم وساق لصُنع أفضل نُقطة بِداية مُمكنة لمشروعات T3.\n\nإذا كُنت مُهتمًا باستخدام Next.js بطريقةِِ آمنة، فَهذا هو المكان المُناسب للبدء. إذا كُنت مهتمًا بأي من تِلك التقنيات، فاقرأ :)\n\n## لماذا TypeScript؟\n\nإن JavaScript صَعبة. لماذا نُضيف المزيد من القوَاعد؟\n\nلأننا نَعتقد اعتقادًا راسخًا أن التَجربة التي توفرها TypeScript سَتدفعك إلى أن تَكون مٌبرمجا أَفضل، فَتوفر لك المُلاحظات مُباشرة خلال كِتابة الكُود من خِلال تحديد أنواع البيانات المُتوقعة (Types)، هذا إلى جانب ميزة الإكمال التلقائي، غَير أنهُ يُنبهك في حَال ارتكبت خطأَ بوضع خط أحمر تحت الخطأ عند المحاولة لوصول إلى خاصية غَير مَوجودة أو تُمرير قِيمة من النوع الخَطأ فَيجبرك أن تصححها. سَواء كُنت مٌبتدئًا في تَطوير الويب أو محترفًا متمرسًا، فإن \"صَرامة\" TypeScript سَتُوفر لك تَجربة أقل إحباطًا وأكثر اتساقًا من Vanilla JS.\n\nهل مازلت غَير مُقتنع إن Typesafety تجعلك أسرع؟ إذاََ شَاهد هَذا [might be using TypeScript wrong…](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## لماذا Next.js؟\n\nنَحن نُحب React، بفضلها أصبح تَطوير واجهات المُستخدم UI سَهل المَنال بَطريقة لم نَكن نَتخيلها. لقد أَخَذَت بِيد المُطورين وعَبرت به أوديةَ سَحيقة وطرقاََ وَعرة.\n\nعَلي الرَغم أن Next.js تِقنية عَنيدة قليلاَ، إلا أنها تُقدم تَجربة أقرب إلى الكَمال مع React في شَتى النَواحي، من routing و API حَتي عَرض الصُور، فَنحن نَثق تمام الثِقةٍٍ أن Next.js سَتقود المُطورين إلى الأمام بِقراراتها الحَكيمة.\n\n## لماذا tRPC/Prisma/Tailwind وغيرها؟\n\nبينما نؤمن بالحفاظ عَلى بَساطة الأشياء قَدرَ الإمكان، فإن هُناك أجزاء بَرمجيةَّ صَغيرة تَتكرر في كُل \"تَطبيق\" مثل المشروعات التي ننشئها، `create-t3-app` تَسمح لك بتبني الجزء بصورةِِ رائعة.\n\n### لماذا tRPC؟\n\nتوفر tRPC تجرِبة سلسة في تطوير تطبيقات المستخدم (Client Side) كما في GraphQl دون الحاجة لكتابة كود متداول (boilarplate)، فإنها نستعمل TypeScript قدر ألإمكان لتوفر تجرِبة ممتازة للمطور.\n\n### لماذا Prisma؟\n\nإن Prisma بالنسبة لـ SQL كـ Typescript بالنسبة لـ Javascript، فإنها تخلق تجربة لمطور لم تكن موجودة من قبل، فتولد الأنواع (Types) من Schema يقوم المطور بوضعها، ذلك إلى جانب توافقها مع [العديد من قواعد البيانات](https://www.prisma.io/docs/concepts/database-connectors)\nفبذلك تضمن Prisma الـ TypeSafety بين التطبيق وقاعدة البيانات\n\nتوفر Prisma [مجموعة كاملة من الأدوات](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) التي تجعل التفاعلات اليومية مع قاعدة البيانات أسهل.\n\nوالجدير بالذكر أن Prisma Client مسؤول عن الاستعلام عن SQL وجعله أمرًا سهلاً للغاية لدرجة أنك بالكاد ستلاحظ أنك تستخدمه. ويكون Prisma Studio واجهة مستخدم رسومية (GUI) ملائمة لقاعدة بياناتك التي تتيح لك قراءة بياناتك ومعالجتها بسرعة دون الحاجة إلى كتابة الكود.\n\n### لماذا Tailwind CSS؟\n\nيوفر Tailwind \"أسلوب مرن مع CSS\"\n\nتوفر لك Tailwind العناصر الإنشائية اللازمة من الألوان وتباعد وغيرها، فتُسهل أنشاء تطبيق جيد المظهر. وعلى خلاف المكتبات الأخرى فإنها لا تعيقك عندما تريد نقل تطبيقك إلى مستوي اعلي و أنشاء شيئ جميل وفريد من نوعه.\n\nبالإضافة، باتخاذها أسلوب كتابة التصميم داخل المكون (inline-like)، تشجعك Tailwind على عمل دون قلق على عبء التسمية، أو تنظيم الملفات، أو مواجهة معدلة ليست بصلة بالمشكلة التي تريد حلها.\n\n### لماذا NextAuth.js؟\n\nإذا كنت تريد نظام توثيق صالحيه في تطبيقك NextJS، فإن NextAuth.js يعد حلاً ممتازًا دون الحاجة إلى إنشاءه بنفسك. فيأتي مزودًا بقائمة واسعة من المزودين (Providers) إضافة مصادقة OAuth بسرعة ويوفر محولات (Adapters) للعديد من قواعد البيانات و ORMs.\n"
  },
  {
    "path": "www/src/pages/branding.astro",
    "content": "---\nimport JumpToContent from \"../components/accessibility/jumpToContent.astro\";\nimport Asset from \"../components/branding/Asset.astro\";\nimport LandingPage from \"../layouts/landingPage.astro\";\n---\n\n<JumpToContent />\n<LandingPage isNotFound={true}>\n  <div>\n    <div class=\"py-12 sm:py-8 md:py-12 lg:py-14 xl:py-12\">\n      <div class=\"max-w-3/4 mx-auto px-8\">\n        <div class=\"flex flex-col items-center gap-8 lg:gap-12\">\n          <h1\n            class=\"text-center text-5xl font-bold tracking-tight text-white sm:text-6xl sm:tracking-tight lg:text-[4rem] xl:text-[5rem] xl:tracking-tight\"\n          >\n            Brand assets\n          </h1>\n          <div class=\"flex w-full flex-wrap justify-center gap-8\">\n            <Asset\n              assets={{\n                png: null,\n                svg: \"/images/t3-dark.svg\",\n              }}\n              bg=\"white\"\n              description=\"Please use this asset on light background\"\n              title=\"Dark T3 Logo\"\n              attribution={true}\n            />\n            <Asset\n              assets={{\n                png: null,\n                svg: \"/images/t3-light.svg\",\n              }}\n              bg=\"black\"\n              description=\"Please use this asset on dark background\"\n              title=\"Light T3 Logo\"\n              attribution={true}\n            />\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</LandingPage>\n"
  },
  {
    "path": "www/src/pages/en/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Deployment with Docker\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\nYou can containerize this stack and deploy it as a single container using Docker, or as a part of a group of containers using docker-compose. See [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) for an example repo based on this doc.\n\n## Docker Project Configuration\n\nPlease note that Next.js requires a different process for build time (available in the frontend, prefixed by `NEXT_PUBLIC`) and runtime environment, server-side only, variables. In this demo we are using two variables, pay attention to their positions in the `Dockerfile`, command-line arguments, and `docker-compose.yml`:\n\n- `DATABASE_URL` (used by the server)\n- `NEXT_PUBLIC_CLIENTVAR` (used by the client)\n\n### 1. Next Configuration\n\nIn your [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), add the `standalone` output-option configuration to [reduce image size by automatically leveraging output traces](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Create dockerignore file\n\n<details>\n    <summary>\n      Click here and include contents in <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Create Dockerfile\n\n> Since we're not pulling the server environment variables into our container, the [environment schema validation](/en/usage/env-variables) will fail. To prevent this, we have to add a `SKIP_ENV_VALIDATION=1` flag to the build command so that the env-schemas aren't validated at build time.\n\n<details>\n    <summary>\n      Click here and include contents in <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:20-alpine AS deps\nRUN apk add --no-cache libc6-compat openssl\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n    if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n    elif [ -f package-lock.json ]; then npm ci; \\\n    elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm i; \\\n    else echo \"Lockfile not found.\" && exit 1; \\\n    fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:20-alpine AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n    if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n    elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n    elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n    else echo \"Lockfile not found.\" && exit 1; \\\n    fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 gcr.io/distroless/nodejs20-debian12 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder /app/.next/standalone ./\nCOPY --from=builder /app/.next/static ./.next/static\n\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"server.js\"]\n```\n\n> **_Notes_**\n>\n> - _Emulation of `--platform=linux/amd64` may not be necessary after moving to Node 18._\n> - _See [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) to understand why `libc6-compat` might be needed._\n> - _Using Alpine 3.17 based images [can cause issues with Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Setting `engineType = \"binary\"` solves the issue in Alpine 3.17, [but has an associated performance cost](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js collects [anonymous telemetry data about general usage](https://nextjs.org/telemetry). Uncomment the first instance of `ENV NEXT_TELEMETRY_DISABLED 1` to disable telemetry during the build. Uncomment the second instance to disable telemetry during runtime._\n\n</div>\n</details>\n\n## Build and Run Image Locally\n\nBuild and run this image locally with the following commands:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nOpen [localhost:3000](http://localhost:3000/) to see your running application.\n\n## Docker Compose\n\nYou can also use Docker Compose to build the image and run the container.\n\n<details>\n    <summary>\n      Follow steps 1-3 above, click here, and include contents in <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nBuild and run this using the `docker compose up --build` command:\n\n```bash\ndocker compose up --build\n```\n\nOpen [localhost:3000](http://localhost:3000/) to see your running application.\n\n</div>\n</details>\n\n## Deploy to Railway\n\nYou can use a PaaS such as [Railway's](https://railway.app) automated [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles) to deploy your app. If you have the [Railway CLI installed](https://docs.railway.app/develop/cli#install) you can deploy your app with the following commands:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nGo to \"Variables\" and include your `DATABASE_URL`. Then go to \"Settings\" and select \"Generate Domain.\" To view a running example on Railway, visit [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Useful Resources\n\n| Resource                             | Link                                                                 |\n| ------------------------------------ | -------------------------------------------------------------------- |\n| Dockerfile reference                 | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file version 3 reference     | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI reference                 | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI reference         | https://docs.docker.com/compose/reference/                           |\n| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js in Docker                    | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Next.js with Docker Example          | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/en/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Deployment\",\n  layout: \"docs\",\n  description: \"Learn how to deploy your T3 app to production.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/en/deployment/netlify.mdx",
    "content": "---\ntitle: Netlify\ndescription: Deploying to Netlify\nlayout: ../../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nNetlify is an alternative deployment provider in a similar vein to Vercel. See [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) for an example repo based on this doc.\n\n## Why Host on Netlify\n\nConventional wisdom says Vercel has superior Next.js support because Vercel develops Next.js. They have a vested interest in ensuring the platform is tuned for optimal performance and DX with Next.js. For the majority of use cases, this will be true and it won't make sense to deviate from the standard path.\n\nThere's also a common sentiment that many Next.js features are only supported on Vercel. While it's true that new Next.js features will be tested and supported on Vercel at the time of release by default, it's also the case that other providers like Netlify will [quickly implement and release support](https://www.netlify.com/blog/deploy-nextjs-13/) for [stable Next.js features](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nThere are relative pros and cons for all deployment providers since no single host can have the best support for all use cases. For example, Netlify built their own [custom Next.js runtime](https://github.com/netlify/next-runtime) for Netlify's Edge Functions (which run on Deno Deploy) and [maintain unique middleware to access and modify HTTP responses](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n<Callout type=\"info\">\n  To track the status of non-stable Next 13 features see [Using the Next 13\n  `app` directory on\n  Netlify](https://github.com/netlify/next-runtime/discussions/1724).\n</Callout>\n\n## Project Configuration\n\nThere are numerous ways to configure your build instructions including directly through the Netlify CLI or Netlify dashboard. While not required, it is advisable to create and include a [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) file. This ensures that forked and cloned versions of the project will be easier to reproducibly deploy.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Using the Netlify Dashboard\n\n1. Push your code to a GitHub repository and sign up for [Netlify](https://app.netlify.com/signup). After you've created an account, click on **Add new site** and then **Import an existing project**.\n\n![New project on Netlify](/images/netlify-01-new-project.webp)\n\n2. Connect your Git provider.\n\n![Import repository](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Select your project's repository.\n\n![Select your project's repository](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify will detect if you have a `netlify.toml` file and automatically configure your build command and publish directory.\n\n![Nextjs build settings](/images/netlify-04-configure-build-settings.webp)\n\n5. Click **Show advanced** and then **New variable** to add your environment variables.\n\n![Add environment variables](/images/netlify-05-env-vars.webp)\n\n6. Click **Deploy site**, wait for the build to complete, and view your new site.\n\n## Using the Netlify CLI\n\nTo deploy from the command line you must first push your project to a GitHub repo and [install the Netlify CLI](https://docs.netlify.com/cli/get-started/). You can install `netlify-cli` as a project dependency or install it globally on your machine with the following command:\n\n```bash\nnpm i -g netlify-cli\n```\n\nTo test your project locally, run the [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) command and open [`localhost:8888`](http://localhost:8888/) to view your locally running Netlify app:\n\n```bash\nntl dev\n```\n\nRun the [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) command to configure your project:\n\n```bash\nntl init\n```\n\nImport your project's environment variables from your `.env` file with [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nDeploy your project with [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). You'll need to pass the `--build` flag to run the build command before deployment and the `--prod` flag to deploy to your site's main URL:\n\n```bash\nntl deploy --prod --build\n```\n\nTo view a running example on Netlify, visit [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/en/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Deploying to Vercel\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\nWe recommend deploying your app to [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). It makes it super easy to deploy Next.js apps.\n\n## Project Configuration\n\nVercel will likely configure your build command and publish the directory automatically. However, you can also specify this information along with other configurations by creating a file called [`vercel.json`](https://vercel.com/docs/project-configuration) and including the following commands. **This is not required for most projects.**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Using the Vercel Dashboard\n\n1. After pushing your code to a GitHub repository, sign up for [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) with GitHub and click on **Add New Project**.\n\n![New project on Vercel](/images/vercel-new-project.webp)\n\n2. Import the GitHub repository with your project.\n\n![Import repository](/images/vercel-import-project.webp)\n\n3. Add your environment variables.\n\n![Add environment variables](/images/vercel-env-vars.webp)\n\n4. Click **Deploy**. Now whenever you push a change to your repository, Vercel will automatically redeploy your app!\n\n## Using the Vercel CLI\n\nTo deploy from the command line you must first [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nRun the [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) command to deploy your project.\n\n```bash\nvercel\n```\n\nInclude `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` for environment variables like the database connection string. Use `--yes` if you want to skip the deployment questions and give the default answer for each.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nAfter the first deployment, this command will deploy to a preview branch. You will need to include `--prod` to push changes directly to the live site for future deployments.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/en/examples.mdx",
    "content": "---\ntitle: Examples\ndescription: Examples of different live apps\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\nimport Form from \"../../components/docs/exampleOptionForm.astro\";\n\nYou can try out different combinations of technologies that create-t3-app offers. \n\n<Callout type=\"info\">\n  You cannot select `prisma` and `drizzle` at the same time.\n</Callout>\n\n<Form />\n\n<Callout type=\"warning\">\n  Some features might not work unless you create an env file\n</Callout>\n"
  },
  {
    "path": "www/src/pages/en/faq.mdx",
    "content": "---\ntitle: FAQ\ndescription: Frequently asked questions about Create T3 App\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nHere are some commonly asked questions about Create T3 App.\n\n## What's next? How do I make an app with this?\n\nWe try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary.\n\nIf you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n- [Drizzle](https://orm.drizzle.team/docs/overview)\n\n## How do I keep my app up to date?\n\nCreate T3 App is a scaffolding tool, not a framework. This means that once you initialize an app, it's yours. There is no postinstall CLI tool similar to help you stay up to date. If you want to keep track of any improvements we make to the template, you could [enable notifications for releases](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) on our repository. That being said it is not really necessary to implement every change we make to the template in your app.\n\n## What learning resources are currently available?\n\nAlthough the resources listed below are some of the best that exist for the T3 Stack, the community (and [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) recommend that you just start using the stack and learn along the way by building with it.\n\nIf you are considering Create T3 App, chances are you might have already used some of the parts of the stack. So why not just dive in head first and learn the other parts while you build something?\n\nNow, we realize this path doesn't work for everyone. So, if you feel like you've tried the recommendation and would still like some resources, or you just aren't confident doing it by yourself and/or feel overwhelmed by the stack, checkout these awesome tutorials on Create T3 App:\n\n### Articles\n\nSome of these might be outdated.\n\n- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Videos\n\n- [From 0 to Production - The Modern React Tutorial (RSCs, Next.js, Shadui, Drizzle, TS and more)](https://www.youtube.com/watch?v=d5x0JCZbAJs) **(recommended)** (updated 2024)*\n- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Why are there `.js` files in the project?\n\nAs per [T3-Axiom #3](/en/introduction#typesafety-isnt-optional), we treat typesafety as a first class citizen. Unfortunately, not all frameworks and plugins support TypeScript which means some of the configuration files have to be `.js` files.\n\nWe try to emphasize that these files are JavaScript for a reason, by explicitly declaring each file's type (`cjs` or `mjs`) depending on what's supported by the library it is used by. Also, all the `js` files in this project are still typechecked using a checkJs option in the compiler (tsconfig).\n\n## I'm struggling to add i18n to my app. Is there any reference I can use?\n\nWe have decided against including i18n by default in `create-t3-app` because it's a very opinionated topic and there are many ways to implement it.\n\nHowever, if you struggle to implement it and want to see a reference project, we have a [reference repo](https://github.com/juliusmarminge/t3-i18n) that shows how you can add i18n to a T3 App using [next-i18next](https://github.com/i18next/next-i18next).\n\n## Should I use `/app` from Next.js 13 or the more mature `/pages` paradigm?\n\nYou have the option when scaffolding an app using Create T3 App to opt into the `/app` directory structure. As of the time of writing, this feature is generally considered mature enough to be used in production by the T3 stack community. For an explanation of why it took us so long to include, you can watch [this video](https://www.youtube.com/watch?v=PmBfq-SpzCU).\n\nNevertheless, if you strongly prefer to use the old `/pages` paradigm, that's still an option. Porting over your existing router can be a monumental effort, so do not feel undue pressure to do so unnecessarily.\n\n<Callout type=\"info\">\n  For a list of supported, planned, and worked on features in the `/app` dir,\n  visit the [beta Next.js\n  docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n</Callout>\n"
  },
  {
    "path": "www/src/pages/en/folder-structure-app.mdx",
    "content": "---\ntitle: Folder Structure (App)\ndescription: Folder structure of a newly scaffolded T3 App with the App Router\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramApp.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nPlease select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nThe `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information.\n\n</div>\n<div>\n\n### `public`\n\nThe `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset.\n\n</div>\n<div>\n\n### `src/env`\n\nUsed for environment variable validation and type definitions - see [Environment Variables](usage/env-variables).\n\n</div>\n<div>\n\n### `src/app`\n\nThe `app` folder contains all the routes of the Next.js application. The `page.tsx` file at the root directory of `/app` is the homepage of the application. The `layout.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/app/_components/post.tsx`\n\nThe `post.tsx` file is an example of a client component that calls a tRPC mutation.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/app/api/auth/[...nextauth]/route.ts`\n\nThe `[...nextauth]/route.ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) for info on catch-all/slug routes.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/app/api/trpc/[trpc]/route.ts`\n\nThe `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/routing/dynamic-routes) for info on catch-all/slug routes.\n\n</div>\n<div data-components=\"trpc prisma nextauth drizzle\">\n\n### `src/server`\n\nThe `server` folder is used to clearly separate code that is only used on the server.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nThe main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nThe `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `src/server/db`\n\nThe `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below).\n\n</div>\n<div data-components=\"drizzle\">\n\n#### `src/server/db/index.ts`\n\nThe `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n#### `src/server/db/schema.ts`\n\nThe `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nThe `api` folder contains the tRPC server-side code.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nThe `routers` folder contains all your tRPC sub-routers.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nThe `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route.\n\nDepending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nThe `trpc.ts` file is the main configuration file for your tRPC back-end. In here we:\n\n1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.\n2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nThe `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/trpc`\n\nThe `trpc` folder contains the setup to let you call tRPC procedures from server components and client components.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/trpc/query-client.ts`\n\nThe `query-client.ts` file creates the Query Client that tRPC uses to cache and deduplicate data in client components.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/trpc/react.tsx`\n\nThe `react.tsx` file is the front-end entrypoint to tRPC. It also contains utility types for the router inputs and outputs. See [tRPC usage](usage/trpc#-utilsapits) for more information.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/trpc/server.ts`\n\nThe `server.ts` file is the entrypoint for using tRPC in Server Components.\n\n</div>\n<div>\n\n### `.env`\n\nThe `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history.\n\n</div>\n<div>\n\n### `.env.example`\n\nThe `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nThe `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `db.sqlite (sqlite only)`\n\nThe `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `drizzle.config.ts`\n\nThe `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nThe `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/app/building-your-application/configuring/typescript) for more information.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nThe `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nThe `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nThe `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `start-database.sh (mysql or postgres only)`\n\nThe `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nThe `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/en/folder-structure-pages.mdx",
    "content": "---\ntitle: Folder Structure (Pages)\ndescription: Folder structure of a newly scaffolded T3 App with the Pages Router\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nPlease select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nThe `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information.\n\n</div>\n<div>\n\n### `public`\n\nThe `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset.\n\n</div>\n<div>\n\n### `src/env`\n\nUsed for environment variable validation and type definitions - see [Environment Variables](usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nThe `pages` folder contains all the pages of the Next.js application. The `index.tsx` file at the root directory of `/pages` is the homepage of the application. The `_app.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nThe `api` folder contains all the API routes of the Next.js application. See [Next.js Api Routes Docs](https://nextjs.org/docs/api-routes/introduction) for info on api routes.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nThe `[...nextauth].ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nThe `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes.\n\n</div>\n<div data-components=\"trpc prisma nextauth drizzle\">\n\n### `src/server`\n\nThe `server` folder is used to clearly separate code that is only used on the server.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nThe main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nThe `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `src/server/db`\n\nThe `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below).\n\n</div>\n<div data-components=\"drizzle\">\n\n#### `src/server/db/index.ts`\n\nThe `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n#### `src/server/db/schema.ts`\n\nThe `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nThe `api` folder contains the tRPC server-side code.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nThe `routers` folder contains all your tRPC sub-routers.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nThe `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route.\n\nDepending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nThe `trpc.ts` file is the main configuration file for your tRPC back-end. In here we:\n\n1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.\n2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nThe `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information.\n\n</div>\n<div>\n\n### `src/styles`\n\nThe `styles` folder contains the global styles of the application.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nThe `utils` folder is used to store commonly re-used utility functions.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nThe `api.ts` file is the front-end entrypoint to tRPC. See [tRPC usage](usage/trpc#-utilsapits) for more information.\n\n</div>\n<div>\n\n### `.env`\n\nThe `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history.\n\n</div>\n<div>\n\n### `.env.example`\n\nThe `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nThe `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `db.sqlite (sqlite only)`\n\nThe `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `drizzle.config.ts`\n\nThe `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nThe `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects) for more information.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nThe `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nThe `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nThe `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information.\n\n</div>\n<div data-components=\"drizzle\">\n\n### `start-database.sh (mysql or postgres only)`\n\nThe `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nThe `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/en/installation.mdx",
    "content": "---\ntitle: Installation\ndescription: Installation instructions for Create T3 App\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nTo scaffold an app using `create-t3-app`, run any of the following commands and answer the command prompt questions:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nAfter your app has been scaffolded, check out the [first steps](/en/usage/first-steps) to get started on your new application.\n\n## Advanced usage\n\n| Option/Flag       | Description                                                             |\n| ----------------- | ----------------------------------------------------------------------- |\n| `[dir]`           | Include a directory argument with a name for the project                |\n| `--noGit`         | Explicitly tell the CLI to not initialize a new git repo in the project |\n| `-y`, `--default` | Bypass the CLI and bootstrap a new t3-app with all options selected     |\n| `--noInstall`     | Generate project without installing dependencies                        |\n\n## Experimental usage\n\nFor our CI, we have some experimental flags that allow you to scaffold any app without any prompts. If this use case applies to you, you can use these flags. Please note that these flags are experimental and may change in the future without following semver versioning.\n\n| Flag                      | Description                                  |\n| ------------------------- | -------------------------------------------- |\n| `--CI`                    | Let the CLI know you're in CI mode           |\n| `--trpc`                  | Include tRPC in the project                  |\n| `--prisma`                | Include Prisma in the project                |\n| `--drizzle`               | Include Drizzle in the project               |\n| `--nextAuth`              | Include NextAuth.js in the project           |\n| `--tailwind`              | Include Tailwind CSS in the project          |\n| `--dbProvider [provider]` | Include a configured database in the project |\n| `--appRouter`             | Use Next.js App Router in the project        |\n\n<Callout type=\"warning\">\n  If you don't provide the `CI` flag, the rest of these flags have no effect.\n</Callout>\n\nYou don't need to explicitly opt-out of the packages you don't want. However, if you prefer to be explicit, you can pass `false`, e.g. `--nextAuth false`.\n\nThe --dbProvider command has 4 database values to choose from: mysql, postgres, planetscale, sqlite. If the command is not provided the default value will be sqlite.\n\n### Example\n\nThe following would scaffold a T3 App with tRPC and Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n\nThe following would scaffold a T3 App with NextAuth.js, Tailwind CSS, Drizzle, and PostgreSQL.\n\n```bash\npnpm dlx create-t3-app@latest --CI --nextAuth --tailwind --drizzle --dbProvider postgres\n```\n"
  },
  {
    "path": "www/src/pages/en/introduction.mdx",
    "content": "---\ntitle: Introduction\ndescription: Introduction to the T3 Stack\nlayout: ../../layouts/docs.astro\nlang: en\n---\n\nimport { IntroductionTab } from \"../../components/docs/introductionTab\";\n\n<IntroductionTab client:load />\n## The T3 Stack\n\nThe _\"T3 Stack\"_ is a web development stack made by [Theo](https://twitter.com/t3dotgg) focused on simplicity, modularity, and full-stack typesafety.\n\nThe core pieces are [**Next.js**](https://nextjs.org/) and [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) is almost always included. If you're doing anything resembling backend, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), and [**NextAuth.js**](https://next-auth.js.org/) are great additions too.\n\nYou may have noticed that there are a… lot of pieces. That's by design. Swap pieces in and out as you need - this stack is modular at its core :)\n\n## So... what is create-t3-app? A template?\n\nKind of? `create-t3-app` is a CLI built by seasoned T3 Stack devs to streamline the setup of a modular T3 Stack app. This means each piece is optional, and the \"template\" is generated based on your specific needs.\n\nAfter countless projects and many years on this tech, we have lots of opinions and insights. We've done our best to encode them into this CLI.\n\nThis is **NOT** an all-inclusive template. We **expect** you to bring your own libraries that solve the needs of **YOUR** application. While we don't want to prescribe solutions to more specific problems like state management and deployment, we [do have some recommendations listed here](/en/other-recs).\n\n## T3 Axioms\n\nWe'll be frank - this is an _opinionated project_. We share a handful of core beliefs around building and we treat them as the basis for our decisions.\n\n### Solve Problems\n\nIt's easy to fall into the trap of \"adding everything\" - we explicitly don't want to do that. Everything added to `create-t3-app` should solve a specific problem that exists within the core technologies included. This means we won't add things like state libraries (`zustand`, `redux`) but we will add things like NextAuth.js and integrate Prisma and tRPC for you.\n\n### Bleed Responsibly\n\nWe love our bleeding edge tech. The amount of speed and, honestly, fun that comes out of new shit is really cool. We think it's important to bleed responsibly, using riskier tech in the less risky parts. This means we wouldn't ⛔️ bet on risky new database tech (SQL is great!). But we happily ✅ bet on tRPC since it's just functions that are trivial to move off.\n\n### Typesafety Isn't Optional\n\nThe stated goal of Create T3 App is to provide the quickest way to start a new full-stack, **typesafe** web application. We take typesafety seriously in these parts as it improves our productivity and helps us ship fewer bugs. Any decision that compromises the typesafe nature of Create T3 App is a decision that should be made in a different project.\n"
  },
  {
    "path": "www/src/pages/en/other-recs.md",
    "content": "---\ntitle: Other Recommendations\ndescription: Libraries and Services that we recommend for many projects\nlayout: ../../layouts/docs.astro\nlang: en\n---\n\nWe recognize that the libraries included in `create-t3-app` don't solve every problem. While we encourage you to begin your project with the things that we provide, there will come a time when you need to bring in other packages. Only you can know what your project needs, but here are some things that we find ourselves recommending frequently.\n\nThese are recommendations by individual Create T3 App contributors and should not be seen as \"official\" endorsements by the Create T3 App team or T3-OSS. _**Please do your own research, especially before committing to paid services**_.\n\n## State Management\n\n_**Editor's Note**_: State management libraries can be great, but often aren't necessary. tRPC's React Query hooks should be able to take care of your server state. For client state, start with React's `useState`, and reach for one of these options when you need more.\n\n### Zustand\n\n**For never using Redux again**\n\nThe \"modern, simple Redux\" you didn't know you needed. [Poimandres](https://github.com/pmndrs) can always be trusted. You can build everything from video call apps to games to servers with this little library.\n\n- [Zustand Homepage](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**For never using Context again**\n\nFor a more atomic approach, Jotai is hard to beat. Also by [Poimandres](https://github.com/pmndrs), Jotai lets you define singletons that feel like global useState. A great option for stateful behaviors that don't need a state machine just yet.\n\n- [Jotai Homepage](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## Component Libraries\n\nMost apps need the same handful of components - toggle buttons, dropdown menus, modals, and so on. These libraries provide great, accessible components that you can use and customize to your liking.\n\n### Unstyled Component Libraries\n\nAlso known as headless libraries, they provide great unstyled, and accessible components that you can customize to your liking. Here are a few recommendations.\n\n- [Radix UI](https://www.radix-ui.com/) gives you a powerful set of convenient and accessible primitives that you can style with vanilla or Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) made by the Tailwind CSS team also provides unstyled, accessible components that integrate seamlessly with Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) provides accessible UI primitives for your design system. Their Date Picker component is top tier.\n\n### Styled Component Libraries\n\n**For when you just want your app to look OK**\n\nSometimes you're building a project where you just want the UI to look decent out of the box. For Admin Dashboards and other similar projects, any of these component libraries will get the job done.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**For building UI Libraries**\n\nDeclaratively build a UI Library with different color, size, etc. variants. When your project reaches a scale where you want a standardized set of UI components with multiple variants using Tailwind CSS, CVA is a great tool.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Animations\n\nFor when you need animations in your app, here are our recommendations.\n\n### AutoAnimate\n\n**For animations with a single line of code**\n\nMost animation libraries try to satisfy every possible use case, and become clunky as a result. AutoAnimate is a zero-configuration tool that will give you a significant improvement in UX with no additional developer effort.\n\n- [AutoAnimate Homepage](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**For complex animations with declarative code**\n\nFramer Motion provides a simple, declarative syntax and allows you to write less code to craft everything from complex animations to even gestures.\n\n- [Framer Motion Homepage](https://framer.com/motion)\n- [Framer Motion Documentation](https://www.framer.com/docs/)\n\n## Deployments, Infrastructure, Databases and CI\n\n### Vercel\n\n**For hosting your app**\n\nVercel took the hell of web deployments and made it a set-and-forget GitHub integration. We've scaled to hundreds of thousands of users without issue. AWS-powered, just a way better interface :)\n\n- [Vercel Homepage](https://vercel.com/)\n- [Create T3 App Vercel deployment guide](/en/deployment/vercel)\n\n### PlanetScale\n\n**For databases without the worry**\n\nPlanetScale is the best \"serverless database platform\" we've used by far. Insane scale, great developer experience, and fantastic pricing. If you're using SQL (and hopefully Prisma), this is hard to beat.\n\n- [PlanetScale Homepage](https://planetscale.com/)\n\n### Railway\n\n**For hosting your infra**\n\n\"Modern Heroku\". The easiest way to get a real server up and running. If Vercel and PlanetScale aren't enough, Railway probably is. Point it at a GitHub repo and go.\n\n- [Railway Homepage](https://railway.app/)\n\n### Upstash\n\n**For serverless Redis**\n\nWe love Prisma and PlanetScale, but some projects require a more performant solution. Upstash allows you to get the in-memory performance of Redis in your serverless project, without having to manage the infrastructure and scaling yourself.\n\n- [Upstash Homepage](https://upstash.com/)\n\n### Pusher\n\n**For serverless WebSockets**\n\nIf WebSockets are the primary focus of your project, you may want to consider a more traditional backend such as [Fastify](https://www.fastify.io/) (which [also works with tRPC!](https://trpc.io/docs/v10/fastify)). But for quickly adding WebSockets to a T3 App, Pusher is an excellent choice.\n\n- [Pusher Homepage](https://pusher.com/)\n\n### Soketi\n\nSoketi is a self-hostable, simple, and fast alternative to Pusher. It's fully compatible with the Pusher SDK which you can use to connect to the server. Soketi serverless is also in beta.\n\n- [Soketi Homepage](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Analytics\n\nUser data is very valuable when you're building an app. Here are some analytics providers we recommend.\n\n### PostHog\n\nPostHog is a full-featured, open-source, and self-hostable solution for bringing in depth analytics to your product. They have SDKs for every library/framework imaginable.\n\n- [PostHog Homepage](https://posthog.com/)\n\n### Plausible\n\nNeed analytics? Plausible is one of the quickest ways to get them. Super minimal. It even has a [simple plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Plausible Homepage](https://plausible.io/)\n\n### Umami\n\nUmami is an open-sourced, self-hostable, simple, fast, privacy-focused alternative to Google Analytics. You can deploy it really easily to Vercel, Railway, etc. with PlanetScale as your database or you can also use its cloud version.\n\n- [Umami Homepage](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n- [Umami Cloud](https://cloud.umami.is/)\n\n## Other\n\n### Next Bundle Analyzer\n\nIt can sometimes be difficult to determine what will be included in the build output for your app. Next Bundle Analyzer is an easy way to visualize and analyze the JavaScript bundles that are generated.\n\n- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/en/t3-collection.mdx",
    "content": "---\ntitle: T3 Collection\ndescription: Cool open source projects and companies using the T3 stack\nlayout: ../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\nMade a project using the T3 stack and want to share it? Add it to the list!\n\n## Open Source apps made using the T3 Stack\n\n<OpenSourceAppList />\n\n## Companies using the T3 Stack\n\nWe'd love to know of companies that use the T3 stack for their apps. Is your company using the T3 stack and would like to share it? Add it to the list!\n\n<CompanyList />\n\n<Callout type=\"tip\">\n  Have a cool project using the T3 stack? Make a [pull\n  request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)\n  and add it here!\n</Callout>\n"
  },
  {
    "path": "www/src/pages/en/usage/_next-auth-app-router.mdx",
    "content": "import Callout from \"../../../components/docs/callout.tsx\";\nimport Tabs from \"../../../components/docs/tabs.astro\";\n\n<Callout type=\"warning\">\n  The newest version of NextAuth has migrated to [Auth.js](https://authjs.dev/)\n</Callout>\n\n## Retrieving session server side\n\nSometimes you might want to request the session on the server. To do so, use the `auth` helper function that `create-t3-app` provides.\n\n```tsx:app/page.tsx\nimport { auth } from \"~/server/auth\";\n\nexport default async function Home() {\n  const session = await auth();\n  ...\n}\n```\n\n## Inclusion of `user.id` on the Session\n\nCreate T3 App is configured to utilise the [session callback](https://authjs.dev/guides/extending-the-session) in the NextAuth.js config to include the user's ID within the `session` object.\n\n```ts:server/auth/config.ts\ncallbacks: {\n    session: ({ session, user }) => ({\n      ...session,\n      user: {\n        ...session.user,\n        id: user.id,\n      },\n    }),\n  },\n```\n\nThis is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://authjs.dev/getting-started/typescript#resources*module-augmentation) on NextAuth.js's docs.\n\n```ts:server/auth/config.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session extends DefaultSession {\n    user: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n```\n\nThe same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client.\n\n## Usage with tRPC\n\nWhen using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures.\n\nThis is done in a two step process:\n\n1. Pass the authentication session into the tRPC context:\n\n```ts:server/api/trpc.ts\nimport { auth } from \"~/server/auth\";\nimport { db } from \"~/server/db\";\n\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth();\n\n  return {\n    db,\n    session,\n    ...opts,\n  };\n};\n```\n\n2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure\n  .use(({ ctx, next }) => {\n    if (!ctx.session?.user) {\n      throw new TRPCError({ code: \"UNAUTHORIZED\" });\n    }\n    return next({\n      ctx: {\n        session: { ...ctx.session, user: ctx.session.user },\n      },\n    });\n  });\n```\n\nThe session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Usage with a database provider\n\n<Tabs slotOne=\"Prisma\" slotTwo=\"Drizzle\" tabName=\"db-provider\">\n  <div slot=\"1\">\n    Getting NextAuth.js to work with Prisma requires a lot of [initial\n    setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app`\n    handles all of this for you, and if you select both Prisma and NextAuth.js,\n    you'll get a fully working authentication system with all the required\n    models preconfigured. We ship your scaffolded app with a preconfigured\n    Discord OAuth provider, which we chose because it is one of the easiest to\n    get started with - just provide your tokens in the `.env` and you're good to\n    go. However, you can easily add more providers by following the [Auth.js\n    docs](https://authjs.dev/getting-started/authentication/oauth). Note that\n    certain providers require extra fields to be added to certain models. We\n    recommend you read the documentation for the provider you would like to use\n    to make sure you have all the required fields.\n  </div>\n  <div slot=\"2\">\n    Getting NextAuth.js to work with Drizzle requires a lot of [initial\n    setup](https://authjs.dev/getting-started/adapters/drizzle). `create-t3-app`\n    handles all of this for you, and if you select both Drizzle and NextAuth.js,\n    you'll get a fully working authentication system with all the required\n    models preconfigured. We ship your scaffolded app with a preconfigured\n    Discord OAuth provider, which we chose because it is one of the easiest to\n    get started with - just provide your tokens in the `.env` and you're good to\n    go. However, you can easily add more providers by following the [Auth.js\n    docs](https://authjs.dev/getting-started/authentication/oauth). Note that\n    certain providers require extra fields to be added to certain models. We\n    recommend you read the documentation for the provider you would like to use\n    to make sure you have all the required fields.\n  </div>\n</Tabs>\n\n### Adding new fields to your models\n\nWhen adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://authjs.dev/reference/adapter/prisma/) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields.\n\nIf for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Usage with Next.js middleware\n\nWith Next.js 12+, the easiest way to protect a set of pages is using the [middleware file](https://authjs.dev/getting-started/session-management/protecting?framework=express#nextjs-middleware). You can create a middleware.ts file in your root pages directory with the following contents.\n\n```middleware.ts\nexport { auth as middleware } from \"@/auth\"\n```\n\nThen define authorized callback in your auth.ts file. For more details check out the [reference docs.](https://authjs.dev/reference/nextjs#authorized)\n\n```app/auth.ts\nasync authorized({ request, auth }) {\n  const url = request.nextUrl\n\n  if(request.method === \"POST\") {\n    const { authToken } = (await request.json()) ?? {}\n    // If the request has a valid auth token, it is authorized\n    const valid = await validateAuthToken(authToken)\n    if(valid) return true\n    return NextResponse.json(\"Invalid auth token\", { status: 401 })\n  }\n\n  // Logged in users are authenticated, otherwise redirect to login page\n  return !!auth.user\n}\n```\n\n<Callout type=\"warning\">\n  You should not rely on middleware exclusively for authorization. Always ensure\n  that the session is verified as close to your data fetching as possible.\n</Callout>\n\n## Setting up the default DiscordProvider\n\n1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on \"New Application\"\n2. In the settings menu, go to \"OAuth2 => General\"\n\n- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`.\n- Under Client Secret, click \"Reset Secret\" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire.\n- Click \"Add Redirect\" and paste in `<app url>/api/auth/callback/discord` (example for local development: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Save your changes\n- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development.\n\n## Useful Resources\n\n| Resource                          | Link                                    |\n| --------------------------------- | --------------------------------------- |\n| NextAuth.js Docs                  | https://authjs.dev/                     |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/en/usage/_next-auth-pages.mdx",
    "content": "import Callout from \"../../../components/docs/callout.tsx\";\n\n## Context Provider\n\nIn your app's entrypoint, you'll see that your application is wrapped in a [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nThis context provider allows your application to access the session data from anywhere in your application, without having to pass it down as props:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Handle unauthenticated state, e.g. render a SignIn component\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Retrieving session server-side\n\nSometimes you might want to request the session on the server. To do so, prefetch the session using the `getServerAuthSession` helper function that `create-t3-app` provides, and pass it down to the client using `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTE: `session` wont have a loading state since it's already prefetched on the server\n\n  ...\n}\n```\n\n## Inclusion of `user.id` on the Session\n\nCreate T3 App is configured to utilise the [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) in the NextAuth.js config to include the user's ID within the `session` object.\n\n```ts:server/auth.ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nThis is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) on NextAuth.js's docs.\n\n```ts:server/auth.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nThe same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client.\n\n## Usage with tRPC\n\nWhen using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures.\n\nThis is done in a two step process:\n\n1. Grab the session from the request headers using the [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession) function. The advantage of using `getServerSession` instead of the regular `getSession` is that it's a server-side only function and doesn't trigger unnecessary fetch calls. `create-t3-app` creates a helper function that abstracts this peculiar API away so that you don't need to import both your NextAuth.js options as well as the `getServerSession` function every time you need to access the session.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nUsing this helper function, we can grab the session and pass it through to the tRPC context:\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nThe session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Usage with Prisma\n\nGetting NextAuth.js to work with Prisma requires a lot of [initial setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` handles all of this for you, and if you select both Prisma and NextAuth.js, you'll get a fully working authentication system with all the required models preconfigured. We ship your scaffolded app with a preconfigured Discord OAuth provider, which we chose because it is one of the easiest to get started with - just provide your tokens in the `.env` and you're good to go. However, you can easily add more providers by following the [NextAuth.js docs](https://next-auth.js.org/providers/). Note that certain providers require extra fields to be added to certain models. We recommend you read the documentation for the provider you would like to use to make sure you have all the required fields.\n\n### Adding new fields to your models\n\nWhen adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://next-auth.js.org/adapters/prisma) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields.\n\nIf for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Usage with Next.js middleware\n\nUsage of NextAuth.js with Next.js middleware [requires the use of the JWT session strategy](https://next-auth.js.org/configuration/nextjs#caveats) for authentication. This is because the middleware is only able to access the session cookie if it is a JWT. By default, Create T3 App is configured to use the **default** database strategy, in combination with Prisma as the database adapter.\n\n<Callout type=\"warning\">\n  Using database sessions is the recommended approach and you should read up on\n  JWTs before switching to the JWT session strategy to avoid any security\n  issues.\n</Callout>\n\nAfter switching to the JWT session strategy. Make sure to update the `session` callback in `src/server/auth.ts`.\nThe `user` object will be `undefined`. Instead, retrieve the user's ID from the `token` object.\nI.e.:\n\n```diff:server/auth.ts\n  export const authOptions: NextAuthOptions = {\n+   session: {\n+     strategy: \"jwt\",\n+   },\n    callbacks: {\n-     session: ({ session, user }) => ({\n+     session: ({ session, token }) => ({\n        ...session,\n        user: {\n          ...session.user,\n-         id: user.id,\n+         id: token.sub,\n        },\n      }),\n    },\n  }\n```\n\n## Setting up the default DiscordProvider\n\n1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on \"New Application\"\n2. In the settings menu, go to \"OAuth2 => General\"\n\n- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`.\n- Under Client Secret, click \"Reset Secret\" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire.\n- Click \"Add Redirect\" and paste in `<app url>/api/auth/callback/discord` (example for local development: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Save your changes\n- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development.\n\n## Useful Resources\n\n| Resource                          | Link                                    |\n| --------------------------------- | --------------------------------------- |\n| NextAuth.js Docs                  | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/en/usage/drizzle.mdx",
    "content": "---\ntitle: Drizzle\ndescription: Usage of Drizzle\nlayout: ../../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nDrizzle is a headless Typescript ORM with [relational](https://orm.drizzle.team/docs/rqb) and [SQL-like](https://orm.drizzle.team/docs/select) query APIs. It can handle database migrations and schemas, and provides a type safe database client. It also comes with [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview), a set of companion tools that help with querying your database.\n\n## Drizzle Client\n\nThe Drizzle Client is located at `src/server/db/index.ts`. In this file, you can define your database connection url and connect your schema to the database object.\n\n```ts:src/server/db/index.ts\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\nimport postgres from \"postgres\";\n\n\nconst conn = postgres(env.DATABASE_URL)\n\nexport const db = drizzle(conn, { schema });\n```\n\nWe reccommend including the database client in your tRPC Context:\n\n```ts:src/server/api/trpc.ts\nimport { db } from \"~/server/db\";\n\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth();\n\n  return {\n    db,\n    session,\n    ...opts,\n  };\n};\n```\n\n## Schema\n\nThe Drizzle schema file can be found at `src/server/db/schema.ts`. This file is where you can define your database schema and models, and connects to the Drizzle Client.\n\nWhen you select NextAuth.js in combination with Drizzle, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [Auth.js documentation](https://authjs.dev/getting-started/adapters/drizzle).\n\n## Drizzle Kit\n\nDrizzle Kit is a collection of command line tools designed to help you manage your database. T3 Stack automatically includes drizzle kit when you select Drizzle as your ORM.\n\n```json:package.json\n\"scripts\": {\n    ...\n    \"db:generate\": \"drizzle-kit generate\",\n    \"db:migrate\": \"drizzle-kit migrate\",\n    \"db:push\": \"drizzle-kit push\",\n    \"db:studio\": \"drizzle-kit studio\",\n    ...\n  },\n```\n\n### Script Explanations\n\n`db:generate`\nGenerates TypeScript types and models from your database schema, ensuring type safety and easy integration with Drizzle ORM.\n\n`db:migrate`\nApplies pending migrations to your database, keeping your schema in sync with changes and updates in your project.\n\n`db:push`\nPushes local schema changes directly to the database without needing explicit migration files. This can be useful for quick syncing in development.\n\n`db:studio`\nOpens a visual interface for managing and inspecting your database tables, data, and relationships.\n\n## Useful Resources\n\n| Resource                    | Link                                                |\n| --------------------------- | --------------------------------------------------- |\n| Drizzle Docs                | https://orm.drizzle.team/docs/overview              |\n| Drizzle GitHub              | https://github.com/drizzle-team/drizzle-orm         |\n| Auth.JS Drizzle Adapter     | https://authjs.dev/getting-started/adapters/drizzle |\n| Drizzle Kit Migration Guide | https://orm.drizzle.team/docs/kit-overview          |\n"
  },
  {
    "path": "www/src/pages/en/usage/env-variables.mdx",
    "content": "---\ntitle: Environment Variables\ndescription: Getting started with Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App uses its own package [@t3-oss/env-nextjs](https://env.t3.gg) along with [zod](https://zod.dev) under the hood for validating environment variables at runtime _and_ buildtime by providing a simple logic in `src/env.js`.\n\n## env.js\n\n_TLDR; If you want to add a new environment variable, you must add a validator for it in `src/env.js`, and then add the KV-pair in `.env`_\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env uses the `createEnv` function to create the schema validate both client and server-side environment variables.\n\n<Callout type=\"info\">\n  For more information about how `createEnv` works internally, check out the [T3\n  Env](https://env.t3.gg/docs/introduction) docs\n</Callout>\n\n## Using Environment Variables\n\nWhen you want to use your environment variables, you can import them from the created `env.js` and use them as you would normally do. If you import this on the client and try accessing a server-side environment variable, you will get a runtime error.\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` is fully typesafe and provides autocompletion\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ This will throw a runtime error\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ This is fine\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nSince the default `.env` file is not committed to version control, we have also included a `.env.example` file, in which you can optionally keep a copy of your `.env` file with any secrets removed. This is not required, but we recommend keeping the example up to date to make it as easy as possible for contributors to get started with their environment.\n\nSome frameworks and build tools, like Next.js, suggest that you store secrets in a `.env.local` file and commit `.env` files to your project. This is not recommended, as it could make it easy to accidentally commit secrets to your project. Instead, we recommend that you store secrets in `.env`, keep your `.env` file in your `.gitignore` and only commit `.env.example` files to your project.\n\n## Adding Environment Variables\n\nTo ensure your build never completes without the environment variables the project needs, you will need to add new environment variables in **two** locations:\n\n📄 `.env`: Enter your environment variable like you would normally do in a `.env` file, i.e. `KEY=VALUE`\n\n📄 `env.js`: Add the appropriate validation logic for the environment variables by defining a Zod schema inside `createEnv` for each one, e.g. `KEY: z.string()`. Besides that, make sure to destruct them in the `runtimeEnv` option, e.g.: `KEY: process.env.KEY`\n\n<Callout type=\"info\">\n  Why do I need to destructure the environment variable in the `runtimeEnv`?\n  This is due to how Next.js bundles environment variables in certain runtimes.\n  By destructuring it manually, you ensure that the variable will never be\n  stripped out from the bundle.\n</Callout>\n\nOptionally, you can also keep `.env.example` updated:\n\n📄 `.env.example`: Enter your environment variable, but be sure to not include the value if it is secret, i.e. `KEY=VALUE` or `KEY=`\n\n### Example\n\n_I want to add my Twitter API Token as a server-side environment variable_\n\n1. Add the environment variable to `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Add the environment variable to `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n  runtimeEnv: {\n    // ...\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n\n3. _Optional:_ Add the environment variable to `.env.example` and make sure not to include the secret in the `runtimeEnv` option\n\n```bash\nTWITTER_API_TOKEN=\n```\n\n## Type Coercion\n\nAll variables you add to `.env` will be imported as strings, even if their value is intended to represent a different type. If you want to use your environment variables as a different type at runtime, you can use Zod's `coerce` to convert the string to the type you want. It will throw if the coercion fails.\n\nAdd the variables to your `.env`:\n\n```\nSOME_NUMBER=123\nSOME_BOOLEAN=true\n```\n\nThen, validate them in `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    SOME_NUMBER: z.coerce.number(),\n    SOME_BOOLEAN: z.coerce.boolean(),\n  },\n  // ...\n  runtimeEnv: {\n    SOME_NUMBER: process.env.SOME_NUMBER,\n    SOME_BOOLEAN: process.env.SOME_BOOLEAN,\n  },\n});\n```\n"
  },
  {
    "path": "www/src/pages/en/usage/first-steps.md",
    "content": "---\ntitle: First Steps\ndescription: Getting started with your new T3 App\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\nYou just scaffolded a new T3 App and are ready to go. Here is the bare minimum to get your app working.\n\n## Database\n\n### MySQL, PostgreSQL\n\nIf you chose MySQL or PostgreSQL as your database, your T3 app will come with a `start-database.sh` bash script that can create a docker container with a database for local development. If you already have a database, feel free to delete this file and put your database credentials in `.env`. On macOS, you can also use [DBngin](https://dbngin.com/) if you don't want to use docker.\n\n### Prisma\n\nIf your app includes Prisma, make sure to run `npx prisma db push` from the root directory of your app. This command will sync your Prisma schema with your database and will generate the TypeScript types for the Prisma Client based on your schema. Note that you need to [restart the TypeScript server](https://tinytip.co/tips/vscode-restart-ts/) after doing this so that it can detect the generated types.\n\n### Drizzle\n\nIf your app includes Drizzle, check the `.env` file for instructions on how to construct your `DATABASE_URL` env variable. Once your env file is ready, run `pnpm db:push` (or the equivalent for other package managers) to push your schema.\n\n## Authentication\n\nIf your app includes NextAuth.js, we get you started with the `DiscordProvider`. This is one of the simplest providers that NextAuth.js offers, but it still requires a bit of initial setup on your part.\n\nOf course, if you prefer to use a different auth provider, you can also use one of the [many providers](https://next-auth.js.org/providers/) that NextAuth.js offers.\n\n1. You will need a Discord account, so register one if you haven't already.\n2. Navigate to https://discord.com/developers/applications and click \"New Application\" in the top right corner. Give your application a name and agree to the Terms of Service.\n3. Once your application has been created, navigate to \"Settings → OAuth2 → General\".\n4. Copy the \"Client ID\" and add it to your `.env` as `AUTH_DISCORD_ID`.\n5. Click \"Reset Secret\", copy the new secret, and add it to your `.env` as `AUTH_DISCORD_SECRET`.\n6. Click \"Add Redirect\" and type in `http://localhost:3000/api/auth/callback/discord`.\n   - For production deployment, follow the previous steps to create another Discord Application, but this time replace `http://localhost:3000` with the URL that you are deploying to.\n7. Save Changes.\n\nYou should now be able to log in.\n\n## Editor Setup\n\nThe following extensions are recommended for an optimal developer experience. The links below provide editor specific plugin support.\n\n- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)\n- [Prettier Extension](https://prettier.io/docs/en/editors.html)\n\n## Next Steps\n\n- If your app includes tRPC, check out `src/pages/index.tsx` and `src/server/api/routers/post.ts` to see how tRPC queries work.\n- Have a look around the Create T3 App docs, as well as the docs of the packages that your app includes.\n- Join our [Discord](https://t3.gg/discord) and give us a star on [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/en/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Usage\",\n  layout: \"docs\",\n  description: \"Learn how to use the different technology from the T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/en/usage/next-auth.mdx",
    "content": "---\ntitle: NextAuth.js\ndescription: Usage of NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: en\nisMdx: true\n---\n\nimport Tabs from \"../../../components/docs/tabs.astro\";\nimport AppRouter from \"./_next-auth-app-router.mdx\";\nimport Pages from \"./_next-auth-pages.mdx\";\n\nWhen you want an authentication system in your Next.js application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs.\n\n<Tabs slotOne=\"Pages Router\" slotTwo=\"App Router\" tabName=\"app-router\">\n  <Pages slot=\"1\" />\n  <AppRouter slot=\"2\" />\n</Tabs>\n"
  },
  {
    "path": "www/src/pages/en/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Usage of Next.js\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\nNext.js is a backend framework for your React applications.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCheck out [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw) to get a better understanding of what Next.js is and how it works.</p>\n\n## Why should I use it?\n\nWe love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths. Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers towards good decisions.\n\nPairing Next.js with [Vercel](https://vercel.com/) makes developing and deploying web apps easier than ever before. Their extremely generous free-tier and super intuitive interface provides a point and click solution to deploy your site (We ❤️ Vercel)\n\n## Get Static/Server Props\n\nA key feature of Next.js is its data fetching capabilities. We highly recommend reading through the [official documentation](https://nextjs.org/docs/basic-features/data-fetching) to understand how to use each method and how they differ. `getServerSideProps` is generally discouraged unless there is a good reason for it, due to the fact that it is a blocking call and will slow down your site. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) is a great alternative to `getServerSideProps` when the data is dynamic and can be fetched incrementally.\n\nIf you need to use this feature anyway, check these links out: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) and [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers)\n\n## Useful Resources\n\n| Resource                       | Link                               |\n| ------------------------------ | ---------------------------------- |\n| Next.js Documentation          | https://nextjs.org/docs            |\n| Next.js GitHub                 | https://github.com/vercel/next.js  |\n| Next.js Blog                   | https://nextjs.org/blog            |\n| Next.js Discord                | https://nextjs.org/discord         |\n| Next.js Twitter                | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/en/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Usage of Prisma\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\nPrisma is an ORM for TypeScript, that allows you to define your database schema and models in a `schema.prisma` file, and then generate a type-safe client that can be used to interact with your database from your backend.\n\n## Prisma Client\n\nLocated at `src/server/db.ts`, the Prisma Client is instantiated as a global variable (as recommended as [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) by the team at Prisma) and exported to be used in your API routes. We include the Prisma Client in [Context](/en/usage/trpc#-serverapitrpcts) by default and recommend using this instead of importing it separately in each file.\n\n## Schema\n\nYou will find the Prisma schema file at `/prisma/schema.prisma`. This file is where you define your database schema and models, and is used when generating the Prisma Client.\n\n### With NextAuth.js\n\nWhen you select NextAuth.js in combination with Prisma, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [NextAuth.js documentation](https://next-auth.js.org/adapters/prisma).\n\n## Default Database\n\nThe default database is an SQLite database, which is great for development and quickly spinning up a proof-of-concept but is not recommended for production. You can change the database to use by changing the `provider` in the `datasource` block to either `postgresql` or `mysql`, and then updating the connection string within environment variables to point to your database.\n\n## Seeding your Database\n\n[Seeding your database](https://www.prisma.io/docs/guides/database/seed-database) is a great way to quickly populate your database with test data to help you get started. In order to setup seeding, you will need to create a `seed.ts` file in the `/prisma` directory, and then add a `seed` script to your `package.json` file. You'll also need a TypeScript runner that can execute the seed-script. We recommend [tsx](https://github.com/esbuild-kit/tsx), which is a very performant TypeScript runner that uses esbuild and doesn't require any ESM configuration, but `ts-node` or other runners will work as well.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nThen, just run `pnpm db-seed` (or `npm`/`yarn`) to seed your database.\n\n## Useful Resources\n\n| Resource                     | Link                                                                                                                                              |\n| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Prisma Docs                  | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                | https://github.com/prisma/prisma                                                                                                                  |\n| Prisma Migrate Playground    | https://playground.prisma.io/guides                                                                                                               |\n| NextAuth.JS Prisma Adapter   | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/en/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Usage of Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\n## What is Tailwind CSS?\n\nTailwind CSS is a tiny, [utility first](https://tailwindcss.com/docs/utility-first) CSS framework for building custom designs, without the context switching that regular CSS requires. It is purely a CSS framework and does not provide any pre-built components or logic, and provides [a very different set of benefits](https://www.youtube.com/watch?v=CQuTF-bkOgc) compared to a component library like Material UI.\n\nIt makes CSS incredibly easy and quick to write, as shown by the following example:\n\nOld CSS:\n\n1. Write CSS, often in a separate file\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Import CSS into your component\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Add the class to your HTML\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nEquivalent in Tailwind:\n\n1. Just write classes in your HTML\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nWhen used together with React Components, it is extremely powerful for quickly building UIs.\n\nTailwind CSS has a beautiful built-in design system, that comes out of the box with a carefully chosen color palette, sizing patterns for styles such as width/height and padding/margin for a uniform design, as well as media breakpoints for creating responsive layouts. This design system can be customized and extended to create the exact toolbox of styles that your project needs.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla better known as [mewtru](https://twitter.com/trunarla) gave an amazing talk on [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Usage\n\nMake sure you have editor plugins for Tailwind installed to improve your experience writing Tailwind.\n\n### Extensions and Plugins\n\n- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formatting\n\nTailwind CSS classes can easily get a bit messy, so a formatter for the classes is a must have. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sorts the classes in the [recommended order](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) so that the classes match the outputted css bundle. When selecting Tailwind in the CLI, we will install and configure this for you.\n\n### Conditionally Applying Classes\n\nConditionally adding classes using ternaries can get very messy and hard to read. These packages help in organizing your classes when using some conditional logic.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Useful Resources\n\n| Resource                     | Link                                                     |\n| ---------------------------- | -------------------------------------------------------- |\n| Tailwind Docs                | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet         | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss          | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community           | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord Server      | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground          | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/en/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Usage of tRPC\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\ntRPC allows us to write end-to-end typesafe APIs without any code generation or runtime bloat. It uses TypeScript's great inference to infer your API router's type definitions and lets you call your API procedures from your frontend with full typesafety and auto-completion. When using tRPC, your frontend and backend feel closer together than ever before, allowing for an outstanding developer experience.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>I built tRPC to allow people to move faster by removing the need for a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creator of tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## How do I use tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC contributor [trashh_dev](https://twitter.com/trashh_dev) made [a killer talk at Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) about tRPC. We highly recommend you watch it if you haven't already.\n\nWith tRPC, you write TypeScript functions on your backend, and then call them from your frontend. A simple tRPC procedure could look like this:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nThis is a tRPC procedure (equivalent to a route handler in a traditional backend) that first validates the input using Zod (which is the same validation library that we use for [environment variables](./env-variables)) - in this case, it's making sure that the input is a string. If the input is not a string it will send an informative error instead.\n\nAfter the input, we chain a resolver function which can be either a [query](https://trpc.io/docs/client/react/useQuery), [mutation](https://trpc.io/docs/v11/client/react/useMutation), or a [subscription](https://trpc.io/docs/v11/subscriptions). In our example, the resolver calls our database using our [prisma](./prisma) client and returns the user whose `id` matches the one we passed in.\n\nYou define your procedures in `routers` which represent a collection of related procedures with a shared namespace. You may have one router for `users`, one for `posts`, and another one for `messages`. These routers can then be merged into a single, centralized `appRouter`:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nNotice that we only need to export our router's type definitions, which means we are never importing any server code on our client.\n\nNow let's call the procedure on our frontend. tRPC provides a wrapper for `@tanstack/react-query` which lets you utilize the full power of the hooks they provide, but with the added benefit of having your API calls typed and inferred. We can call our procedures from our frontend like this:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nYou'll immediately notice how good the autocompletion and typesafety is. As soon as you write `api.`, your routers will show up in autocomplete, and when you select a router, its procedures will show up as well. You'll also get a TypeScript error if your input doesn't match the validator that you defined on the backend.\n\n## Inferring errors\n\nBy default, `create-t3-app` sets up an [error formatter](https://trpc.io/docs/v11/server/error-formatting) that lets you infer your Zod Errors if you get validation errors on the backend.\n\nExample usage:\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` returned with an error on the `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## Files\n\ntRPC requires quite a lot of boilerplate that `create-t3-app` sets up for you. Let's go over the files that are generated:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nThis is the entry point for your API and exposes the tRPC router. Normally, you won't touch this file very much, but if you need to, for example, enable CORS middleware or similar, it's useful to know that the exported `createNextApiHandler` is a [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) which takes a [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object. This means that you can wrap the `createNextApiHandler` in any middleware you want. See below for an [example snippet](#enabling-cors) of adding CORS.\n\n### 📄 `server/api/trpc.ts`\n\nThis file is split up in two parts, context creation and tRPC initialization:\n\n1. We define the context that is passed to your tRPC procedures. Context is data that all of your tRPC procedures will have access to, and is a great place to put things like database connections, authentication information, etc. In create-t3-app we use two functions, to enable using a subset of the context when we do not have access to the request object.\n\n- `createInnerTRPCContext`: This is where you define context which doesn't depend on the request, e.g. your database connection. You can use this function for [integration testing](#sample-integration-test) or [ssg-helpers](https://trpc.io/docs/v10/client/nextjs/server-side-helpers) where you don't have a request object.\n\n- `createTRPCContext`: This is where you define context which depends on the request, e.g. the user's session. You request the session using the `opts.req` object, and then pass the session down to the `createInnerTRPCContext` function to create the final context.\n\n2. We initialize tRPC and define reusable [procedures](https://trpc.io/docs/v11/server/procedures) and [middlewares](https://trpc.io/docs/v11/server/middlewares). By convention, you shouldn't export the entire `t`-object but instead, create reusable procedures and middlewares and export those.\n\nYou'll notice we use `superjson` as [data transformer](https://trpc.io/docs/v10/server/data-transformers). This makes it so that your data types are preserved when they reach the client, so if you for example send a `Date` object, the client will return a `Date` and not a string which is the case for most APIs.\n\n### 📄 `server/api/routers/*.ts`\n\nThis is where you define the routes and procedures of your API. By convention, you [create separate routers](https://trpc.io/docs/v11/server/routers) for related procedures.\n\n### 📄 `server/api/root.ts`\n\nHere we [merge](https://trpc.io/docs/v11/server/merging-routers) all the sub-routers defined in `routers/**` into a single app router.\n\n### 📄 `utils/api.ts`\n\nThis is the frontend entry point for tRPC. This is where you'll import the router's **type definition** and create your tRPC client along with the react-query hooks. Since we enabled `superjson` as our data transformer on the backend, we need to enable it on the frontend as well. This is because the serialized data from the backend is deserialized on the frontend.\n\nYou'll define your tRPC [links](https://trpc.io/docs/v11/client/links) here, which determines the request flow from the client to the server. We use the \"default\" [`httpBatchLink`](https://trpc.io/docs/v11/client/links/httpBatchLink) which enables [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), as well as a [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) which outputs useful request logs during development.\n\nLastly, we export a [helper type](https://trpc.io/docs/client/vanilla/infer-types) which you can use to infer your types on the frontend.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCreate T3 App contributor [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) made [a video about data flows in tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). This video is recommended if you have used tRPC but still feel a bit unclear about how it works.\n\n## How do I call my API externally?\n\nWith regular APIs, you can call your endpoints using any HTTP client such as `curl`, `Postman`, `fetch` or straight from your browser. With tRPC, it's a bit different. If you want to call your procedures without the tRPC client, there are two recommended ways to do it:\n\n### Expose a single procedure externally\n\nIf you want to expose a single procedure externally, you're looking for [server side calls](https://trpc.io/docs/server/server-side-calls). That would allow you to create a normal Next.js API endpoint, but reuse the resolver part of your tRPC procedure.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Exposing every procedure as a REST endpoint\n\nIf you want to expose every single procedure externally, checkout the community built plugin [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). By providing some extra meta-data to your procedures, you can generate an OpenAPI compliant REST API from your tRPC router.\n\n### It's just HTTP Requests\n\ntRPC communicates over HTTP, so it is also possible to call your tRPC procedures using \"regular\" HTTP requests. However, the syntax can be cumbersome due to the [RPC protocol](https://trpc.io/docs/rpc) that tRPC uses. If you're curious, you can check what tRPC requests and responses look like in your browser's network tab, but we suggest doing this only as an educational exercise and sticking to one of the solutions outlined above.\n\n## Comparison to a Next.js API endpoint\n\nLet's compare a Next.js API endpoint to a tRPC procedure. Let's say we want to fetch a user object from our database and return it to the frontend. We could write a Next.js API endpoint like this:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nCompare this to the tRPC example above and you can see some of the advantages of tRPC:\n\n- Instead of specifying a url for each route, which can become annoying to debug if you move something, your entire router is an object with autocomplete.\n- You don’t need to validate which HTTP method was used.\n- You don’t need to validate that the request query or body contains the correct data in the procedure, because Zod takes care of this.\n- Instead of creating a response, you can throw errors and return a value or object as you would in any other TypeScript function.\n- Calling the procedure on the frontend provides autocompletion and type safety.\n\n## Useful snippets\n\nHere are some snippets that might come in handy.\n\n### Enabling CORS\n\nIf you need to consume your API from a different domain, for example in a monorepo that includes a React Native app, you might need to enable CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Optimistic updates\n\nOptimistic updates are when we update the UI before the API call has finished. This gives the user a better experience because they don't have to wait for the API call to finish before the UI reflects the result of their action. However, apps that value data correctness highly should avoid optimistic updates as they are not a \"true\" representation of backend state. You can read more on the [React Query docs](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useUtils();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Sample Integration Test\n\nHere is a sample integration test that uses [Vitest](https://vitest.dev) to check that your tRPC router is working as expected, the input parser infers the correct type, and that the returned data matches the expected output.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\nIf your procedure is protected, you can pass in a mocked `session` object when you create the context:\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n\n  // ...\n});\n```\n\n## Useful Resources\n\n| Resource               | Link                                            |\n| ---------------------- | ----------------------------------------------- |\n| tRPC Docs              | https://www.trpc.io                             |\n| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples |\n| React Query Docs       | https://tanstack.com/query/latest/docs          |\n"
  },
  {
    "path": "www/src/pages/en/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Usage of TypeScript\nlayout: ../../../layouts/docs.astro\nlang: en\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creator of the T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nWhether you're a new or seasoned developer, we think that TypeScript is a must have. It can look intimidating at first, but much like a lot of tools, is something that many never look back from after starting to use it.\n\nIt provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your code editor, or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line.\n\nIt is, perhaps, the tool that provides the most productivity to developers; providing documentation of the code you're writing or consuming directly in your editor, and having instant feedback as you inevitably make mistakes is absolutely priceless.\n\n## Type Inference\n\nWhile many new TypeScript developers are concerned with _writing_ TypeScript, many of its benefits don't actually require you to change your code at all, in particular inference. Inference means that if something is typed, that type will follow it throughout the flow of the application without having to be re-declared in other places. This means that for example once you have defined the types of the arguments that a function takes, the remainder of the function will usually be typesafe without requiring any further TypeScript-specific code. Library developers put a ton of work into maintaining the types for their libraries, which means that we as application developers can benefit from both the inference and the built-in documentation in your code editor that these types provide.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCheck out Theo's video on how [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Powerful uses of type inference\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) is a schema validation library that is built on top of TypeScript. Write a schema that represents a single source of truth for your data, and Zod will ensure that your data is valid throughout your application, even across network boundaries and external APIs.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) gives you declarative, always-up-to-date auto-managed queries and mutations that directly improve both your developer and user experiences.\n\n## Useful Resources\n\n| Resource                                                  | Link                                                              |\n| --------------------------------------------------------- | ----------------------------------------------------------------- |\n| TypeScript Handbook                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| Beginners TypeScript Tutorial                             | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                           | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/en/why.md",
    "content": "---\ntitle: Why CT3A?\ndescription: Why you should pick Create T3 App for your next project\nlayout: ../../layouts/docs.astro\nlang: en\n---\n\nWe started Create T3 App because [Theo](https://twitter.com/t3dotgg) refused to make a template of his favorite technologies. Inspired by create-next-app, [Astro's CLI](https://astro.build), and a general love for typesafety, the Create T3 App team worked hard to build the best possible starting point for new T3 Stack projects.\n\nIf you're interested in using Next.js in a typesafe way, this is the place to start. If you're curious about any of the specific technology choices we made, read on :)\n\n## Why TypeScript?\n\nJavaScript is hard. Why add more rules?\n\nWe firmly believe the experience TypeScript provides will help you be a better developer. It provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your editor or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line. Whether you're new to web development or a seasoned pro, the \"strictness\" of TypeScript will provide a less frustrating, more consistent experience than vanilla JS.\n\nTypesafety makes you faster. If you're not convinced, you [might be using TypeScript wrong...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Why Next.js?\n\nWe love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths.\n\nNext.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers toward good decisions.\n\n## Why tRPC/Prisma/Tailwind/etc?\n\nWhile we believe in keeping things as simple as possible, we find these pieces being used in every \"app\" like project we build. `create-t3-app` does a great job of letting you adopt the pieces you need.\n\n### tRPC\n\ntRPC delivers on GraphQL's promise of seamless client development against a typesafe server without all of the boilerplate. It's a clever abuse of TypeScript that provides an incredible dev experience.\n\n### Prisma\n\nPrisma is to SQL what TypeScript is to JS. It created a developer experience that didn't exist before. By generating types from a user-defined schema compatible with [several databases](https://www.prisma.io/docs/concepts/database-connectors), Prisma guarantees end-to-end typesafety from your database to your app.\n\nPrisma provides a whole [suite of tools](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) making daily interactions with your database easier. Notably, the Prisma Client is responsible for querying and making SQL so easy you'll barely notice you're using it, and Prisma Studio is a convenient GUI for your database that lets you read and manipulate your data quickly without having to write code.\n\n### Tailwind CSS\n\nTailwind feels like \"zen-mode CSS\".\n\nBy providing building blocks in the form of good default colors, spacing, and other primitives, Tailwind makes it easy to create a good-looking app. And unlike component libraries, it does not hold you back when you want to take your app to the next level and create something beautiful and unique.\n\nAdditionally, with its inline-like approach, Tailwind encourages you to style without worrying about naming classes, organizing files, or any other issue not directly tied to the problem you're trying to solve.\n\n### NextAuth.js\n\nWhen you want an authentication system in your NextJS application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs.\n"
  },
  {
    "path": "www/src/pages/es/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Desplegando con Docker\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nPuedes contenerizar este stack y desplegarlo como un solo contenedor mediante Docker, o como parte de un grupo de contenedores mediante docker-compose. Consulta [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) para ver un repositorio de ejemplo basado en este documento.\n\n## Configuración del proyecto Docker\n\nTen en cuenta que Next.js requiere un proceso diferente para compilar (disponible en el frontend, con el prefijo `NEXT_PUBLIC`) y las variables de entorno en tiempo de ejecución, solo del lado del servidor. En esta demostración estamos usando dos variables, presta atención a sus posiciones en `Dockerfile`, argumentos de la línea de comandos y `docker-compose.yml`:\n\n- `DATABASE_URL` (utilizado por el servidor)\n- `NEXT_PUBLIC_CLIENTVAR` (utilizado por el cliente)\n\n### 1. Configuración de Next.js\n\nEn tu [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), agrega la configuración de output `standalone` para [reducir el tamaño de la imagen aprovechando automáticamente el output tracing](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Crear archivo dockerignore\n\n<details>\n    <summary>\n      Haz clic aquí e incluye el contenido en <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Crear archivo Docker\n\n> Como no estamos introduciendo las variables de entorno del servidor en nuestro contenedor, la [validación del esquema de entorno](/en/usage/env-variables) fallará. Para evitar esto, debemos agregar un indicador `SKIP_ENV_VALIDATION=1` al comando de compilación para que las variables de entorno no se validen en el momento de la compilación.\n\n<details>\n    <summary>\n      Haz clic aquí e incluye el contenido en <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIAS\n\nFROM --platform=linux/amd64 node:16-alpine AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Instala el Prisma Client - quitar si no estás usando Prisma\n\nCOPY prisma ./\n\n# Instala dependencias basadas en tu administrador de paquetes preferido\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### CONSTRUCTOR\n\nFROM --platform=linux/amd64 node:16-alpine AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### LANZADOR\n\nFROM --platform=linux/amd64 node:16-alpine AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Notas_**\n>\n> - _La emulación de `--platform=linux/amd64` puede no ser necesaria tras moverse a Node 18._\n> - _Puedes ver [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) para entender porqué `libc6-compat` puede ser necesario._\n> - _Next.js recolecta [datos anónimos de uso general para telemetría](https://nextjs.org/telemetry). Descomenta la primera instancia de `ENV NEXT_TELEMETRY_DISABLED 1` para deshabilitar la telemetría durante el tiempo de compilación. Descomenta la segunda instancia para deshabilitar la telemetría durante tiempo de ejecución._\n\n</div>\n</details>\n\n## Crea y ejecuta la imagen localmente\n\nCrea y ejecuta esta imagen localmente con los siguientes comandos:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nAbre [localhost:3000](http://localhost:3000/) para ver tu aplicación en ejecución.\n\n## Docker Compose\n\nTambién puedes usar Docker Compose para crear la imagen y ejecutar el contenedor.\n\n<details>\n    <summary>\n      Sigue los pasos 1-4 anteriores, haz clic aquí e incluye el contenido en <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nEjecuta esto usando el comando `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nAbre [localhost:3000](http://localhost:3000/) para ver tu aplicación en ejecución.\n\n</div>\n</details>\n\n## Desplegar en Railway\n\nPuedes usar una PaaS como los [despligues de Dockerfile](https://docs.railway.app/deploy/dockerfiles) automatizados de [Railway](https://railway.app) para desplegar tu aplicación. Si tienes instalada la [CLI de Railway](https://docs.railway.app/develop/cli#install), puedes desplegar tu aplicación con los siguientes comandos:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nDirígite a \"Variables\" e incluye tu `DATABASE_URL`. Luego dirígite a \"Configuración\" y selecciona \"Generar dominio\". Para ver un ejemplo en ejecución en Railway, visita [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Otros recursos útiles\n\n| Recurso                                           | Link                                                                 |\n| ------------------------------------------------- | -------------------------------------------------------------------- |\n| Referencia Docker                                 | https://docs.docker.com/engine/reference/builder/                    |\n| Referencia archivo Compose version 3              | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Referencia Docker CLI                             | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Referencia Docker Compose CLI                     | https://docs.docker.com/compose/reference/                           |\n| Despligue Next.js utilizando una imagen de Docker | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js en Docker                                 | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Ejemplo Next.js con Docker                        | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Crear una imagen Docker de una aplicación Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/es/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Despliegue\",\n  layout: \"docs\",\n  description: \"Aprende a desplegar tu aplicación T3 a producción.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/es/deployment/netlify.md",
    "content": "---\ntitle: Netlify\ndescription: Desplegando en Netlify\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nNetlify es una alternativa al proveedor de despliegue en un sentido similar a Vercel. Ver [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) para ver un ejemplo de un repositorio basado en este documento.\n\n## ¿Por qué desplegar en Netlify?\n\nLa sabiduría convencional dice que Vercel tiene un mejor soporte para Next.js, porque Vercel desarrolla Next.js. Tienen un interés en asegurar que la plataforma esté optimizada para un rendimiento y una experiencia de desarrollo óptimos con Next.js. Para la mayoría de los casos de uso, esto será cierto y no tendrá sentido desviarse del camino estándar.\n\nTambién hay un sentimiento común de que muchas características de Next.js solo son compatibles con Vercel. Si bien es cierto que las nuevas características de Next.js se probarán y admitirán en Vercel en el momento del lanzamiento de forma predeterminada, también es cierto que otros proveedores como Netlify [implementarán y lanzarán rápidamente el soporte](https://www.netlify.com/blog/deploy-nextjs-13/) para [características de Next.js estables](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nHay pros y contras relativos para todos los proveedores de despliegue, ya que ningún host puede tener el mejor soporte para todos los casos de uso. Por ejemplo, Netlify construyó su propio [tiempo de ejecución personalizado de Next.js](https://github.com/netlify/next-runtime) para las funciones de _edge_ de Netlify (que se ejecutan en Deno Deploy) y [mantienen un middleware único para acceder y modificar las respuestas HTTP](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n> _NOTA: Para rastrear el estado de las funciones no estables de Next 13, consulta [Using the Next 13 `app` directory on Netlify](https://github.com/netlify/next-runtime/discussions/1724)._\n\n## Configuración del proyecto\n\nHay numerosas formas de configurar tus instrucciones de compilación, incluido el uso directo de la CLI de Netlify o el panel de control de Netlify. Si bien no es obligatorio, es recomendable crear e incluir un archivo [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Esto garantiza que las versiones bifurcadas y clonadas del proyecto sean más fáciles de desplegar de forma reproducible.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Usando el panel de control de Netlify\n\n1. Empuja tu código a un repositorio de GitHub y regístrate en [Netlify](https://app.netlify.com/signup). Después de crear una cuenta, haz clic en **Add new site** y luego en **Import an existing project**.\n\n![Nuevo proyecto en Netlify](/images/netlify-01-new-project.webp)\n\n2. Conecta tu proveedor de Git.\n\n![Importar repositorio](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Selecciona el repositorio de tu proyecto.\n\n![Selecciona el repositorio de tu proyecto](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify detectará si tienes un archivo `netlify.toml` y configurará automáticamente tu comando de compilación y tu directorio de publicación.\n\n5. Haz clic en **Show advanced** y luego en **New variable** para agregar tus variables de entorno.\n\n![Agregar variables de entorno](/images/netlify-05-env-vars.webp)\n\n6. Haz clic en **Deploy site** y espera a que se complete la compilación para ver tu nuevo sitio.\n\n## Usando la CLI de Netlify\n\nPara desplegar desde la línea de comandos, primero debes empujar tu proyecto a un repositorio de GitHub y [instalar la CLI de Netlify](https://docs.netlify.com/cli/get-started/). Puedes instalar `netlify-cli` como una dependencia de proyecto o instalarlo globalmente en tu máquina con el siguiente comando:\n\n```bash\nnpm i -g netlify-cli\n```\n\nPara probar tu proyecto localmente, ejecuta el comando [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) y abre [`localhost:8888`](http://localhost:8888/) para ver tu aplicación Netlify en ejecución localmente:\n\n```bash\nntl dev\n```\n\nCorre el comando [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) para configurar tu proyecto:\n\n```bash\nntl init\n```\n\nImporta las variables de entorno de tu proyecto desde tu archivo `.env` con [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nDespliega tu proyecto con [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Necesitarás pasar la bandera `--build` para ejecutar el comando de compilación antes del despliegue y la bandera `--prod` para desplegar en la URL principal de tu sitio:\n\n```bash\nntl deploy --prod --build\n```\n\nPara ver un ejemplo en ejecución en Netlify, visita [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/es/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Desplegando en Vercel\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nRecomendamos desplegar tu aplicación en [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Vercel hace que sea muy fácil desplegar aplicaciones Next.js.\n\n## Configuración del proyecto\n\nEs probable que Vercel configure el comando de compilación y publique el directorio automáticamente. Sin embargo, también puedes especificar esta información junto con otra configuración creando un archivo llamado [`vercel.json`](https://vercel.com/docs/project-configuration) e incluyendo los siguientes comandos:\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Uso del panel de control de Vercel\n\n1. Después de enviar tu código a un repositorio de GitHub, registrate en [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) con GitHub y haz clic en **Agregar nuevo proyecto**.\n\n![Nuevo proyecto en Vercel](/images/vercel-new-project.webp)\n\n2. Importa el repositorio de GitHub con tu proyecto.\n\n![Importar repositorio](/images/vercel-import-project.webp)\n\n3. Agrega tus variables de entorno.\n\n![Agregando variables de entorno](/images/vercel-env-vars.webp)\n\n4. Haz clic en **Desplegar**. Ahora, cada vez que envíes un cambio a tu repositorio, ¡Vercel volverá a desplegar automáticamente tu aplicación!\n\n## Uso de la CLI de Vercel\n\nPara desplegar desde la línea de comandos, primero debes [instalar la CLI de Vercel globalmente](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nEjecuta el comando [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) para desplegar tu proyecto.\n\n```bash\nvercel\n```\n\nIncluye `--env DATABASE_URL=SU_URL_DE_BASE_DE_DATOS_AQUI` para variables de entorno, como el string de conexión de la base de datos. Utiliza `--yes` si deseas omitir las preguntas de despliegue y dar la respuesta predeterminada para cada una.\n\n```bash\nvercel --env DATABASE_URL=SU_URL_DE_BASE_DE_DATOS_AQUI --yes\n```\n\nDespués del primer despliegue, este comando desplegará en una rama de vista previa. Deberás incluir `--prod` para enviar los cambios directamente a producción en despliegues futuros.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/es/faq.md",
    "content": "---\ntitle: Preguntas Frecuentes\ndescription: Preguntas frecuentes acerca de create T3 app\nlayout: ../../layouts/docs.astro\nlang: es\n---\n\nAquí hay algunas preguntas frecuentes sobre `create-t3-app`.\n\n## ¿Qué sigue? ¿Cómo hago una aplicación con esto?\n\nTratamos de mantener este proyecto lo más simple posible, para que puedas comenzar solo con el esqueleto que configuramos para ti y agregar cosas adicionales más adelante cuando sea necesario.\n\nSi no estás familiarizado con las diferentes tecnologías utilizadas en este proyecto, consulta la documentación respectiva. Si todavía no estás seguro, únete a nuestro [Discord](https://t3.gg/discord) y solicita ayuda.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [TailwindCSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## ¿Qué recursos de aprendizaje están disponibles actualmente?\n\nAunque los recursos que se enumeran a continuación son algunos de los mejores que existen para T3 Stack, la comunidad (y [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) recomiendan que comiences a usar el stack y aprendas en el camino construyendo con él.\n\nSi estás considerando `create-t3-app`, es probable que ya hayas usado algunas de las partes del stack. Entonces, ¿por qué no simplemente sumergirse en el y aprender las otras partes mientras construyes algo?\n\nAhora, sabemos que este camino no funciona para todos. Por lo tanto, si crees que has probado las recomendaciones y todavía te gustarían algunos recursos, o simplemente no estás seguro de hacerlo solo y/o te sientes abrumado por el stack, consulta estos increíbles tutoriales de `create-t3-app `:\n\n### Artículos\n\n- [Build a full stack app with create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [A first look at create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n\n### Vídeos\n\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## ¿Por qué hay archivos `.js` en el proyecto?\n\nDe acuerdo con [Axioma-T3 #3](/es/introduction#la-seguridad-de-tipos-no-es-opcional), tomamos la seguridad de tipos como un ciudadano de primera clase. Desafortunadamente, no todos los frameworks y complementos admiten TypeScript, lo que significa que algunos de los archivos de configuración deben ser archivos `.js`.\n\nIntentamos enfatizar que estos archivos son javascript por una razón, declarando explícitamente el tipo de cada archivo (`cjs` o `mjs`) dependiendo de lo que admita la librería que lo utiliza. Además, todos los archivos `js` en este proyecto aún tienen verificación de tipos usando un comentario `@ts-check` en la parte superior.\n\n## Tengo problemas para agregar i18n a mi aplicación. ¿Hay alguna referencia que pueda usar?\n\nHemos decidido no incluir i18n por defecto en `create-t3-app` porque es un tema muy criticado y hay muchas formas de implementarlo.\n\nSin embargo, si tienes dificultades para implementarlo y quieres ver un proyecto de referencia, tenemos un [repositorio de referencia](https://github.com/juliusmarminge/t3-i18n) que muestra cómo puedes agregar i18n a una aplicación T3 usando [next-i18next](https://github.com/i18next/next-i18next).\n\n## ¿Por qué usamos `/pages` y no `/app` de Next.js 13?\n\nSegún [Axioma-T3 #2](/es/introduction#responsablemente-vanguardista), nos encantan las cosas innovadoras, pero valoramos la estabilidad, todo tu enrutador es difícil de portar, [no es un buen lugar para ser vanguardista](https://youtu.be/mnwUbtieOuI?t=1662). Si bien `/app` es [un vistazo al futuro](https://youtu.be/rnsC-12PVlM?t=818), no está lista para producción; La API está en versión beta y se espera que tenga cambios significativos.\n\nPara obtener una lista de funciones compatibles, planificadas y en las que se ha trabajado en el directorio `/app`, visita [la documentación beta de Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n"
  },
  {
    "path": "www/src/pages/es/folder-structure-pages.mdx",
    "content": "---\ntitle: Estructura de Carpetas (Pages)\ndescription: Estructura de carpetas de una aplicación T3 recién creada\nlayout: ../../layouts/docs.astro\nlang: es\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nPor favor selecciona las librerías que deseas utilizar para ver la estructura de carpetas de una aplicación T3 recién creada con esas selecciones. Más abajo, encontrarás una descripción de cada entrada.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nLa carpeta `prisma` contiene el archivo `schema.prisma` que se utiliza para configurar la conexión de la base de datos y su esquema. También es la ubicación para almacenar archivos de migración y/o scripts que inyectan valores iniciales a la base de datos (seed scripts), si se utilizan. Consulta [uso de Prisma](/es/usage/prisma) para obtener más información.\n\n</div>\n\n<div>\n\n### `public`\n\nLa carpeta `public` contiene archivos estáticos que son servidos por el servidor web. El archivo `favicon.ico` es un ejemplo de un archivo estático.\n\n</div>\n\n<div>\n\n### `src/env`\n\nSe utiliza para la validación de variables de entorno y definiciones de tipo; consulta [variables de entorno](usage/env-variables).\n\n</div>\n\n<div>\n\n### `src/pages`\n\nLa carpeta `pages` contiene todas las páginas de la aplicación Next.js. El archivo `index.tsx` en el directorio raíz de `/pages` es la página de inicio de la aplicación. El archivo `_app.tsx` se usa para componer la aplicación con otros proveedores. Consulta la [documentación de Next.js](https://nextjs.org/docs/basic-features/pages) para obtener más información.\n\n</div>\n\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nLa carpeta `api` contiene todas las rutas API de la aplicación Next.js. El archivo `examples.ts` (con Prisma) contiene un ejemplo de una ruta que hace uso de [rutas API Next.js](https://nextjs.org/docs/api-routes/introduction) junto con Prisma. El archivo `restricted.ts` (con Next-Auth) contiene un ejemplo de una ruta que hace uso de [rutas API Next.js](https://nextjs.org/docs/api-routes/introduction) y está protegida por [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nEl archivo `[...nextauth].ts` es la ruta _slug_ de autenticación NextAuth.js. Se utiliza para manejar solicitudes de autenticación. Consulta [uso de NextAuth.js](usage/next-auth) para obtener más información sobre NextAuth.js y [la documentación de rutas dinámicas de Next.js](https://nextjs.org/docs/routing/dynamic-routes) para obtener información sobre rutas _catch-all/slug_.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nEl archivo `[trpc].ts` es el punto de entrada de la API de tRPC. Se utiliza para manejar solicitudes tRPC. Consulta [uso de tRPC](usage/trpc#-pagesapitrpctrpcts) para obtener más información sobre este archivo y [la documentación de rutas dinámicas de Next.js](https://nextjs.org/docs/routing/dynamic-routes) para obtener información sobre rutas _catch-all/slug_.\n\n</div>\n\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nLa carpeta `server` se usa para separar claramente el código del lado del servidor del código del lado del cliente.\n\n</div>\n\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nLa entrada principal para la lógica de autenticación del lado del servidor. Aquí, configuramos las [opciones de configuración](usage/next-auth) de NextAuth.js, realizamos [ampliación de módulo](usage/next-auth#inclusion-of-userid-on-the-session) y también proporcionamos algunas utilidades DX para la autenticación, como la recuperación de la sesión del usuario en el lado del servidor. Consulta [uso de NextAuth.js](usage/next-auth#usage-with-trpc) para obtener más información.\n\n</div>\n\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nEl archivo `db.ts` se usa para instanciar el cliente Prisma en el ámbito global. Consulta [uso de Prisma](usage/prisma#prisma-client) y [mejores prácticas para usar Prisma con Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) para obtener más información.\n\n</div>\n\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nLa carpeta `api` contiene el código del lado del servidor de tRPC.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nLa carpeta `routers` contiene todos tus sub-routers de tRPC.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nEl archivo `example.ts` es un ejemplo de un sub-router tRPC utilizando el helper `publicProcedure` para demostrar cómo crear una ruta pública tRPC.\n\nDendiendo de tus paquetes elegidos este router contiene más o menos rutas para demostrar mejor el uso a tus necesidades.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nEl archivo `trpc.ts` es el archivo de configuración principal de tu back-end tRPC. Aquí:\n\n1. Define el contexto de tRPC. Consulta [uso de tRPC](usage/trpc#-serverapitrpcts) para obtener más información.\n2. Exporta el router principal de tRPC. Consulta [uso de tRPC](usage/trpc#-serverapitrpcts) para obtener más información.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nEl archivo `root.ts` se usa para combinar los sub-routers de tRPC y exportarlos como un solo router, así como la definición de tipo del router. Consulta [uso de tRPC](usage/trpc#-serverapirootts) para obtener más información.\n\n</div>\n\n<div>\n\n### `src/styles`\n\nLa carpeta `styles` contiene los estilos globales de la aplicación.\n\n</div>\n\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nLa carpeta `utils` se usa para almacenar funciones de utilidad comúnmente reutilizadas.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nEl archivo `api.ts` es el punto de entrada del front-end a tRPC. Consulta [uso de tRPC](usage/trpc#-utilsapits) para obtener más información.\n\n</div>\n\n<div>\n\n### `.env`\n\nEl archivo `.env` se usa para almacenar variables de entorno. Consulta [Variables de entorno](usage/env-variables) para obtener más información. Este archivo **no** debe ser enviado al historial de git.\n\n</div>\n\n<div>\n\n### `.env.example`\n\nEl archivo `.env.example` muestra las variables de entorno de ejemplo basadas en las bibliotecas elegidas. Este archivo debe ser enviado al historial de git.\n\n</div>\n\n<div>\n\n### `.eslintrc.cjs`\n\nEl archivo `.eslintrc.cjs` se usa para configurar ESLint. Consulta [la documentación de ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) para obtener más información.\n\n</div>\n\n<div>\n\n### `next-env.d.ts`\n\nEl archivo `next-env.d.ts` asegura que los tipos de Next.js se detecten en el compilador de TypeScript. **No debe eliminarlo ni editarlo, ya que puede cambiar en cualquier momento.** Consulta [la documentación de Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) para obtener más información.\n\n</div>\n\n<div>\n\n### `next.config.mjs`\n\nEl archivo `next.config.mjs` se usa para configurar Next.js. Consulta [la documentación de Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) para obtener más información. Nota: La extensión .mjs se usa para permitir importaciones ESM.\n\n</div>\n\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nEl archivo `postcss.config.js` se usa para la configuración de Tailwind PostCSS. Consulta [la documentación de Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) para obtener más información.\n\n</div>\n\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nEl archivo `prettier.config.mjs` se usa para configurar Prettier para incluir el prettier-plugin-tailwindcss para formatear las clases de Tailwind CSS. Consulta [el artículo del blog de Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) para obtener más información.\n\n</div>\n\n<div>\n\n### `tsconfig.json`\n\nEl archivo `tscconfig.json` se usa para configurar TypeScript. Algunos no predeterminados, como `modo estricto`, se han habilitado para garantizar el mejor uso de TypeScript para Create T3 App y sus bibliotecas. Consulta [la documentación de TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) o [uso de TypeScript](usage/typescript) para obtener más información.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/es/installation.mdx",
    "content": "---\ntitle: Instalación\ndescription: Instrucciones de instalación para Create T3 App\nlayout: ../../layouts/docs.astro\nlang: es\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nPara crear una aplicación usando `create-t3-app`, ejecuta cualquiera de los siguientes tres comandos y responde las preguntas en la línea de comandos:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nDespués de que tu aplicación haya sido creada, consulta los [primeros pasos](/es/usage/first-steps) para comenzar con tu nueva aplicación.\n\n## Uso avanzado\n\n| Opción/Bandera    | Descripción                                                                               |\n| ----------------- | ----------------------------------------------------------------------------------------- |\n| `[dir]`           | Incluye un argumento de directorio con un nombre para el proyecto                         |\n| `--noGit`         | Dile explícitamente a la CLI que no inicialice un nuevo repositorio de git en el proyecto |\n| `-y`, `--default` | Omite la CLI y arranca una nueva aplicación t3 con todas las opciones seleccionadas       |\n| `--noInstall`     | Generar proyecto sin instalar dependencias                                                |\n\n## Uso experimental\n\nPara nuestro CI, tenemos algunas banderas experimentales que te permiten crear cualquier aplicación sin indicaciones. Si este caso de uso se aplica a ti, puedes usar estas banderas. Ten en cuenta que estas banderas son experimentales y pueden cambiar en el futuro sin seguir las versiones de semver.\n\n| Bandera      | Descripción                           |\n| ------------ | ------------------------------------- |\n| `--CI`       | Informar a la CLI que está en modo CI |\n| `--trpc`     | Incluir tRPC en el proyecto           |\n| `--prisma`   | Incluir Prisma en el proyecto         |\n| `--nextAuth` | Incluir NextAuth.js en el proyecto    |\n| `--tailwind` | Incluir Tailwind CSS en el proyecto   |\n\n<Callout type=\"warning\">\n\nSi no proporcionas la bandera `CI`, el resto de estas banderas no tendrá efecto.\n\n</Callout>\nNo es necesario que se excluya explícitamente los paquetes que no deseas. Sin embargo, si prefieres ser explícito, puedes pasar `false`, ejemplo: `--nextAuth false`.\n\n### Ejemplo\n\nLo siguiente sería una aplicación T3 con tRPC y Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/es/introduction.md",
    "content": "---\ntitle: Introducción\ndescription: Introducción al T3 Stack\nlayout: ../../layouts/docs.astro\nlang: es\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"El mejor stack para su próximo proyecto\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## El T3 Stack\n\nEl _\"T3 Stack\"_ es un stack de desarrollo web creado por [Theo](https://twitter.com/t3dotgg) que está enfocado en simplicidad, modularidad, y seguridad (full-stack) de tipos.\n\nLas piezas centrales son [**Next.js**](https://nextjs.org/) y [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) está casi siempre incluído.\nSi estás haciendo algo parecido a un backend, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), y [**NextAuth.js**](https://next-auth.js.org/) son muy buenas adiciones también.\n\nEs posible que hayas notado que hay muchas... piezas, esto es por diseño. Intercambia piezas dentro y fuera según lo necesites. Este stack es modular desde la base :)\n\n## Entonces... ¿Qué es create-t3-app? ¿Una plantilla?\n\n¿Más o menos? `create-t3-app` es una CLI creada por desarrolladores experimentados del T3 Stack para agilizar la configuración de una aplicación modular T3 Stack. Esto significa que cada pieza es opcional, y la \"plantilla\" es generada en función de tus necesidades específicas.\n\nDespués de innumerables proyectos y muchos años en esta tecnología, tenemos muchas opiniones e ideas. Hemos hecho todo lo posible para codificarlos en esta CLI.\n\nEsta **NO** es una plantilla con todo incluido. **Esperamos** que traigas tus propias librerías que resuelvan las necesidades de **TU** aplicación. Si bien no queremos prescribir soluciones a problemas más específicos, como la administración de estado o la implementación de la aplicación como tal, [tenemos algunas recomendaciones enumeradas aquí](/es/other-recs).\n\n## Axiomas T3\n\nSeremos francos: este es un _proyecto dogmático_. Compartimos muchas creencias fundamentales sobre la construcción y las tratamos como la base de nuestras decisiones.\n\n### Resolver Problemas\n\nEs fácil caer en la trampa de \"agregar todo\"; explícitamente no queremos hacer eso. Todo lo agregado a `create-t3-app` debería resolver un problema específico que existe dentro de las tecnologías principales incluidas. Esto significa que no agregaremos cosas como librerías de manejo de estado (`zustand`, `redux`), pero agregaremos cosas como NextAuth.js e integraremos Prisma y tRPC para ti.\n\n### Responsablemente Vanguardista\n\nNos encanta nuestra tecnología de vanguardia. La velocidad y, sinceramente, la diversión que se obtiene de las nuevas tecnologías es realmente genial. Creemos que es importante ser vanguardista de manera responsable, usando tecnología más riesgosa en las partes con menos riesgo. Esto significa que no apostaríamos ⛔️ por una nueva tecnología de base de datos arriesgada (¡SQL es genial!). Pero felizmente ✅ apostamos por tRPC ya que son sólo funciones que son triviales de remover.\n\n### La Seguridad de Tipos no es Opcional\n\nEl objetivo declarado de `create-t3-app` es proporcionar la forma más rápida de iniciar una nueva aplicación web full-stack **segura en tipos**. Nos tomamos muy en serio la seguridad de tipos en todas las partes, ya que mejora nuestra productividad y nos ayuda a enviar menos errores a producción. Cualquier decisión que comprometa la seguridad de tipos de `create-t3-app` es una decisión que debe tomarse en un proyecto diferente.\n"
  },
  {
    "path": "www/src/pages/es/other-recs.md",
    "content": "---\ntitle: Otras Recomendaciones\ndescription: Librerías y Servicios que nosotros recomendamos para todos los proyectos\nlayout: ../../layouts/docs.astro\nlang: es\n---\n\nReconocemos que las librerías incluidas en `create-t3-app` no resuelven todos los problemas. Si bien te alentamos a comenzar tu proyecto con las cosas que proporcionamos, llegará un momento en que necesitarás traer otros paquetes. Solo tu puedes saber qué necesita tu proyecto, pero aquí hay algunas cosas que recomendamos con frecuencia.\n\nEstas son recomendaciones de colaboradores individuales de create-t3-app y no deben verse como respaldos \"oficiales\" por parte del equipo de create-t3-app o T3-OSS. _**Haz tu propia investigación, especialmente antes de comprometerte con servicios pagados**_.\n\n## Administración de Estado\n\n_**Nota del editor**_: Las librerías de administración de estado pueden ser excelentes, pero a menudo no son necesarias. Los hooks React Query de tRPC deberían poder encargarse del estado de tu servidor. Para el estado del cliente, comienza con `useState` de React y busca una de estas opciones cuando necesites más.\n\n### Zustand\n\n**Para no volver a usar Redux nunca más**\n\nEl \"Redux moderno y simple\" que no sabías que necesitabas. Siempre se puede confiar en [Poimandres](https://github.com/pmndrs). Puede crear todo, desde aplicaciones de videollamadas hasta juegos y servidores con esta pequeña librería.\n\n- [Página de inicio de Zustand](https://zustand-demo.pmnd.rs/)\n- [GitHub de Zustand](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Para nunca volver a usar Context**\n\nPara un enfoque más atómico, Jotai es difícil de superar. También por [Poimandres](https://github.com/pmndrs), Jotai te permite definir singletons que se sienten como estado de uso global. Una excelente opción para comportamientos con estado que todavía no necesiten una máquina de estado.\n\n- [Página de inicio de Jotai](https://jotai.org/)\n- [GitHub de Jotai](https://github.com/pmndrs/jotai)\n\n## Librerías de Componentes\n\nLa mayoría de las aplicaciones necesitan la misma cantidad de componentes: botones de alternancia, menús desplegables, diálogos, etc. Estas librerías proporcionan componentes excelentes y accesibles que puedes usar y personalizar a tu gusto.\n\n### Librerías de componentes sin estilo\n\nTambién conocidas como librerías headless, proporcionan excelentes componentes sin estilo y accesibles que puedes personalizar a tu gusto. Aquí hay algunas recomendaciones.\n\n- [Radix UI](https://www.radix-ui.com/) te brinda un poderoso conjunto de primitivas convenientes y accesibles que puedes diseñar con Vanilla o Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) creado por el equipo de Tailwind CSS también proporciona componentes accesibles y sin estilo que se integran a la perfección con Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) proporciona primitivas de interfaz de usuario accesibles para tu sistema de diseño. Su componente Selector de Fecha es de primer nivel.\n\n### Librerías de componentes con estilo\n\n**Para cuando solo quieres que tu aplicación se vea bien**\n\nA veces, estás creando un proyecto en el que solo deseas que la interfaz de usuario se vea decente desde el primer momento. Para paneles de administración y otros proyectos similares, cualquiera de estas librerías de componentes hará el trabajo.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n\n### Class Variance Authority\n\n**Para crear librerías de interfaz de usuario**\n\nCrea declarativamente una librería de interfaz de usuario con diferentes variaciones de color, tamaño, etc. Cuando tu proyecto alcanza un punto en el que deseas tener un conjunto estandarizado de componentes de interfaz de usuario con múltiples variaciones usando Tailwind CSS, CVA es una gran herramienta.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Animaciones\n\nPara cuando necesites animaciones en tu aplicación, aquí están nuestras recomendaciones.\n\n### AutoAnimate\n\n**Para animaciones con una sola línea de código**\n\nLa mayoría de las librerías de animación intentan satisfacer todos los casos de uso posibles y, como resultado, se vuelven torpes. AutoAnimate es una herramienta de cero configuración que te brindará una mejora significativa en UX sin esfuerzo adicional del desarrollador.\n\n- [Página de inicio de AutoAnimate](https://auto-animate.formkit.com/)\n- [GitHub de AutoAnimate](https://github.com/formkit/auto-animate)\n- [Ejemplo de un Componente con AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Para animaciones complejas con código declarativo**\n\nFramer Motion proporciona una sintaxis declarativa simple y te permite escribir menos código para crear todo, desde animaciones complejas hasta incluso gestos.\n\n- [Página de inicio de Framer Motion](https://framer.com/motion)\n- [Documentación de Framer Motion](https://www.framer.com/docs/)\n\n## Despliegues, Infraestructura, Bases de Datos y CI\n\n### Vercel\n\n**Para alojar tu aplicación**\n\nVercel tomó el infierno de los despliegues web y lo convirtió en una integración de GitHub de configurar y olvidar. Hemos escalado a cientos de miles de usuarios sin problemas. Impulsado por AWS, simplemente una interfaz mucho mejor :)\n\n- [Página de inicio de Vercel](https://vercel.com/)\n- [Guía Create T3 App para desplegar en Vercel](/es/deployment/vercel)\n\n### PlanetScale\n\n**Para bases de datos sin preocupaciones**\n\nPlanetScale es la mejor \"plataforma de base de datos sin servidor\" que hemos usado hasta ahora. Escala increíblemente, excelente experiencia de desarrollador y precios fantásticos. Si estás utilizando SQL (y con suerte Prisma), esto es difícil de superar.\n\n- [Página de inicio de PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Para alojar tu infraestructura**\n\n\"Heroku moderno\". La forma más fácil de poner en marcha un servidor real. Si Vercel y PlanetScale no son suficientes, probablemente Railway lo sea. Apúntalo a un repositorio de GitHub y listo.\n\n- [Página de inicio de Railway](https://railway.app/)\n\n### Upstash\n\n**Para Redis sin servidor**\n\nNos encantan Prisma y PlanetScale, pero algunos proyectos requieren una solución de mayor rendimiento. Upstash te permite obtener el rendimiento en memoria de Redis en tu proyecto sin servidor, sin tener que administrar la infraestructura y escalar por tu cuenta.\n\n- [Página de inicio de Upstash](https://upstash.com/)\n\n### Pusher\n\n**Para WebSockets sin servidor**\n\nSi los WebSockets son el enfoque principal de tu proyecto, es posible que desees considerar un backend más tradicional como [Fastify](https://www.fastify.io/) (que [¡también funciona con tRPC!](https://trpc.io/docs/v10/fastify)). Pero para agregar rápidamente WebSockets a una aplicación T3, Pusher es una excelente opción.\n\n- [Página de inicio de Pusher](https://pusher.com/)\n\n### Soketi\n\nSoketi es una alternativa autohospedable, simple y rápida a Pusher. Es totalmente compatible con Pusher SDK que puedes usar para conectarte al servidor. Soketi serverless también está en versión beta.\n\n- [Página de inicio de Soketi](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Análisis de Datos\n\nLos datos de los usuarios son muy valiosos cuando creas una aplicación. Aquí hay algunos proveedores de análisis que recomendamos.\n\n### Plausible\n\n¿Necesitas análisis? Plausible es una de las formas más rápidas de obtenerlos. Súper minimalista. Incluso tiene un [complemento simple para Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Página de inicio de Plausible](https://plausible.io/)\n\n### Umami\n\nUmami es una alternativa a Google Analytics de código abierto, autohospedable, simple, rápida y centrada en la privacidad. Puedes desplegarlo muy fácilmente en Vercel, Railway, etc. con PlanetScale como tu base de datos.\n\n- [Página de inicio de Umami](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n## Otros\n\n### Next Bundle Analyzer\n\nA veces puede ser difícil determinar qué se incluirá en el resultado de compilación de tu aplicación. Next Bundle Analyzer es una manera fácil de visualizar y analizar los paquetes de JavaScript que se generan.\n\n- [@next/bundle-analyzer en npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/es/t3-collection.mdx",
    "content": "---\ntitle: Colección T3\ndescription: Proyectos geniales open source y compañias utilizando el T3 Stack\nlayout: ../../layouts/docs.astro\nlang: es\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\n\n¿Hiciste un proyecto usando el T3 Stack y quieres compartirlo? ¡Añádelo a la lista!\n\n## Aplicaciones open source creadas con el T3 Stack\n\n<OpenSourceAppList descriptionIntl=\"Descripción\" />\n\n## Empresas que utilizan el T3 Stack\n\nNos encantaría saber de empresas que usan el T3 Stack para sus aplicaciones. ¿Tu empresa utiliza el T3 Stack y te gustaría compartirlo? ¡Añádelo a la lista!\n\n<CompanyList descriptionIntl=\"Descripción\" />\n\n_¿Tienes un proyecto genial usando el T3 Stack? Haz una [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/pages/en/t3-collection.md) y agrégalo aquí._\n"
  },
  {
    "path": "www/src/pages/es/usage/env-variables.md",
    "content": "---\ntitle: Variables de Entorno\ndescription: Empezando con create-t3-app\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nCreate-T3-App usa [Zod](https://github.com/colinhacks/zod) para validar tus variables de entorno en tiempo de ejecución _y_ tiempo de compilación proporcionando algunos archivos adicionales en el directorio `env`:\n\n📁 src/env\n\n┣ 📄 client.mjs\n\n┣ 📄 schema.mjs\n\n┣ 📄 server.mjs\n\nEl contenido de estos archivos puede parecer aterrador a primera vista, pero no te preocupes, no es tan complicado como parece. Echemos un vistazo a ellos uno por uno y recorramos el proceso de agregar variables de entorno adicionales.\n\n_En pocas palabras; Si deseas agregar una nueva variable de entorno, debes agregarla tanto a tu `.env` como definir el validador en `env/schema.mjs`._\n\n## schema.mjs\n\nEste es el archivo que realmente modificarás. Contiene dos esquemas, uno para las variables de entorno del lado del servidor y otro para el lado del cliente, así como un objeto `clientEnv`.\n\n```ts:env/schema.mjs\nexport const serverSchema = z.object({\n  // DATABASE_URL: z.string().url(),\n});\n\nexport const clientSchema = z.object({\n  // NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nexport const clientEnv = {\n  // NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,\n};\n```\n\n### Esquema del Servidor\n\nDefine tu esquema de variables de entorno del lado del servidor aquí.\n\nAsegúrate de no anteponer el nombre de las variables de entorno aquí con `NEXT_PUBLIC`. La validación fallará si lo haces para ayudarte a detectar una configuración no válida.\n\n### Esquema del Cliente\n\nDefine tu esquema de variables de entorno del lado del cliente aquí.\n\nPara exponerlos al cliente, debes anteponerlos con `NEXT_PUBLIC`. La validación fallará si no lo haces para ayudarte a detectar una configuración no válida.\n\n### Objeto clientEnv\n\nDestructuramos el `process.env` aquí.\n\nNecesitamos un objeto de JavaScript con el que podamos analizar nuestros esquemas de Zod y, debido a la forma en que Next.js maneja las variables de entorno, no puede destructurar `process.env` como un objeto normal, por lo que debemos hacerlo manualmente.\n\nTypeScript te ayudará a asegurarte de haber ingresado las claves tanto en `clientEnv` como en `clientSchema`.\n\n```ts\n// ❌ Esto no funciona, necesitamos destructurarlo manualmente\nconst schema = z.object({\n  NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nconst validated = schema.parse(process.env);\n```\n\n## server.mjs & client.mjs\n\nAquí es donde ocurre la validación y se exporta los objetos validados. No deberías necesitar modificar estos archivos.\n\n## Utilizando las Variables de Entorno\n\nCuando quieras utilizar tus variables de entorno, puedes importarlas desde `env/client.mjs` o `env/server.mjs` dependiendo de dónde quieras utilizarlas:\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env/server.mjs\";\n\n// `env` es completamente seguro en tipos y provee autocompletado\nconst dbUrl = env.DATABASE_URL;\n```\n\n## .env.example\n\nDado que el archivo `.env` predeterminado no está guardado en el control de versiones, también hemos incluido un archivo `.env.example`, en el que, de forma opcional, puedes guardar una copia de tu archivo `.env` con los valores secretos eliminados. Esto no es obligatorio, pero recomendamos mantener el ejemplo actualizado para que a los colaboradores les resulte lo más fácil posible comenzar con tu entorno.\n\n## Agregando Variables de Entorno\n\nPara asegurarse de que tu compilación nunca se complete sin las variables de entorno que necesita el proyecto, deberás agregar nuevas variables de entorno en **dos** ubicaciones:\n\n📄 `.env`: Introduce tu variable de entorno como lo harías normalmente en un archivo `.env`, es decir, `LLAVE=VALOR`\n\n📄 `schema.mjs`: agrega la lógica de validación adecuada para la variable de entorno definiendo un esquema Zod, p. `CLAVE: z.string()`\n\nOpcionalmente, también puedes mantener `.env.example` actualizado:\n\n📄 `.env.example`: ingresa tu variable de entorno, pero asegúrate de no incluir el valor si es secreto, es decir, `KEY=VALUE` o `KEY=`\n\n### Ejemplo\n\n_Quiero agregar mi API token de Twitter como una variable de entorno del lado del servidor_\n\n1. Agrega la variable de entorno a `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Agrega la variable de entorno a `schema.mjs`:\n\n```ts\nexport const serverSchema = z.object({\n  // ...\n  TWITTER_API_TOKEN: z.string(),\n});\n```\n\n3. Opcional: agrega la variable de entorno a `.env.example`, pero no incluyas el token\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/es/usage/first-steps.md",
    "content": "---\ntitle: Primeros Pasos\ndescription: Empezando con tu nueva aplicación T3\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nAcabas de crear una nueva aplicación T3 y estás listo para comenzar. Aquí está lo mínimo para que tu aplicación funcione.\n\n## Base de datos\n\nSi tu aplicación incluye Prisma, asegúrate de ejecutar `npx prisma db push` desde el directorio raíz de tu aplicación. Este comando sincronizará tu esquema de Prisma con tu base de datos y generará los tipos de TypeScript para el Prisma Client en función de tu esquema. Ten en cuenta que debes reiniciar el servidor TypeScript después de hacer esto para que pueda detectar los tipos generados.\n\n## Autenticación\n\nSi tu aplicación incluye NextAuth.js, te ayudaremos a comenzar con `DiscordProvider`. Este es uno de los proveedores más simples que ofrece NextAuth.js, pero aún requiere un poco de configuración inicial de tu parte.\n\nPor supuesto, si prefieres usar un proveedor de autenticación diferente, también puedes usar uno de los [muchos proveedores](https://next-auth.js.org/providers/) que ofrece NextAuth.js.\n\n1. Necesitarás una cuenta de Discord, así que crea una cuenta si aún no lo has hecho.\n2. Dirígite a [https://discord.com/developers/applications](https://discord.com/developers/applications) y haz clic en \"New Application\" en la esquina superior derecha. Asigna un nombre a tu aplicación y acepta los términos de servicio.\n3. Una vez creada tu aplicación, dirígite a \"Settings → OAuth2 → General\".\n4. Copia el \"Client ID\" y agrégalo a tu `.env` como `AUTH_DISCORD_ID`.\n5. Haz clic en \"Reset Secret\", copia el nuevo valor secreto y agrégalo a tu `.env` como `AUTH_DISCORD_SECRET`.\n6. Haz clic en \"Add Redirect\" y escribe `http://localhost:3000/api/auth/callback/discord`.\n   - Para la implementación de producción, sigue los pasos anteriores para crear otra aplicación Discord, pero esta vez reemplaza `http://localhost:3000` con la URL de producción en la que está implementando.\n7. Guarda los cambios.\n\nAhora deberías poder iniciar sesión.\n\n## Siguientes pasos\n\n- Si tu aplicación incluye tRPC, consulta `src/pages/index.tsx` y `src/server/trpc/router/post.ts` para ver cómo funcionan las consultas de tRPC.\n- Echa un vistazo a la documentación de `create-t3-app`, así como la documentación de los paquetes que incluye tu aplicación.\n- ¡Únete a nuestro [Discord](https://t3.gg/discord) y danos una estrella en [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/es/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Uso\",\n  layout: \"docs\",\n  description: \"Aprende a utilizar las diferentes tecnologías del stack T3.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/es/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: Uso de NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nCuando desees utilizar un sistema de autenticación en tu aplicación Next.js, NextAuth.js es una excelente solución para incorporar la complejidad de la seguridad sin la molestia de tener que crearla por tu cuenta. Viene con una extensa lista de proveedores para agregar rápidamente la autenticación OAuth y proporciona adaptadores para muchas bases de datos y ORMs.\n\n## Proveedor de contexto\n\nEn el punto de entrada de tu aplicación, verás que tu aplicación está envuelta en un [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nEste proveedor de contexto permite que tu aplicación acceda a los datos de la sesión desde cualquier lugar de tu aplicación, sin tener que pasarlos como propiedades:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Manejar el estado no autenticado, ejemplo: renderizar un componente SignIn\n    return <SignIn />;\n  }\n\n  return <p>Bienvenido {session.user.name}!</p>;\n};\n```\n\n## Incluir `user.id` en la Sesión\n\n`create-t3-app` está configurado para utilizar el [callback de sesión](https://next-auth.js.org/configuration/callbacks#session-callback) en la configuración de NextAuth.js para incluir el ID del usuario dentro del objeto `session`.\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n  session({ session, user }) {\n    if (session.user) {\n      session.user.id = user.id;\n    }\n    return session;\n  },\n},\n```\n\nEsto se combina con un archivo de declaración de tipos para asegurarse de que se pueda escribir `user.id` cuando se acceda al objeto `session`. Obtén más información sobre [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) en la documentación de NextAuth.js.\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nEl mismo patrón se puede usar para agregar cualquier otro dato al objeto `session`, como un campo `role`, pero **no se debe usar incorrectamente para almacenar datos confidenciales** en el cliente.\n\n## Uso con tRPC\n\nCuando utilices NextAuth.js con tRPC, puedes crear procedimientos protegidos reutilizables usando [middleware](https://trpc.io/docs/v10/middlewares). Esto te permite crear procedimientos a los que solo los usuarios autenticados pueden acceder. `create-t3-app` establece todo esto para ti, lo que te permite acceder fácilmente al objeto de sesión dentro de los procedimientos autenticados.\n\nEsto se hace en un proceso de dos pasos:\n\n1. Toma la sesión de las cabeceras de la solicitud utilizando la función [`unstable_getServerSession`](https://next-auth.js.org/configuration/nextjs#unstable_getserversession). No te preocupes, esta función es segura: el nombre incluye `unstable` (_inestable_) solo porque la implementación de la API podría cambiar en el futuro. La ventaja de usar `unstable_getServerSession` en lugar de la función `getSession` regular es que es una función solo del lado del servidor y no activa llamadas innecesarias. `create-t3-app` crea una función de ayuda que abstrae a esta API peculiar.\n\n```ts:server/common/get-server-auth-session.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await unstable_getServerSession(ctx.req, ctx.res, nextAuthOptions);\n};\n```\n\nUsando esta función auxiliar, podemos obtener la sesión y pasarla al contexto de tRPC:\n\n```ts:server/trpc/context.ts\nimport { getServerAuthSession } from \"../common/get-server-auth-session\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Crea un middleware tRPC que verifique si el usuario está autenticado. Luego usamos el middleware en una `protectedProcedure`. Cualquier persona que llama a estos procedimientos debe de estar autenticada, o de lo contrario se lanzará un error que el cliente puede manejar adecuadamente.\n\n```ts:server/trpc/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nEl objeto de sesión es una representación ligera y mínima del usuario y solo contiene algunos campos. Cuando uses `protectedProcedures`, tienes acceso al ID del usuario que puede usarse para obtener más datos de la base de datos.\n\n```ts:server/trpc/router/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Uso con Prisma\n\nHacer que NextAuth.js funcione con Prisma requiere una gran cantidad de [configuración inicial](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` maneja todo esto para ti, y si seleccionas Prisma y NextAuth.js, obtendrás un sistema de autenticación completamente funcional con todos los modelos requeridos preconfigurados. Creamos tu aplicación con un proveedor de Discord Oauth preconfigurado, que elegimos porque es uno de los más fáciles de comenzar, solo proporciona tus tokens en el `.env` y listo. Sin embargo, puedes agregar fácilmente más proveedores siguiendo la documentación de [NextAuth.JS](https://next-auth.js.org/providers/). Ten en cuenta que ciertos proveedores requieren que se agregen campos adicionales a ciertos modelos. Te recomendamos que leas la documentación del proveedor que deseas utilizar para asegurarte de tener todos los campos requeridos.\n\n### Agregar nuevos campos a tus modelos\n\nAl agregar nuevos campos a cualquiera de los modelos `User`, `Account`, `Session` o `VerificationToken` (lo más probable es que solo necesites modificar el modelo `User`), debes tener en cuenta que el [Adaptador de Prisma](https://next-auth.js.org/adapters/prisma) crea automáticamente campos en estos modelos cuando los nuevos usuarios se registran e inician sesión. Por lo tanto, al agregar nuevos campos a estos modelos, debes proporcionar un valor predeterminado por defecto para ellos, ya que el adaptador no es consciente de estos campos.\n\nSi, por ejemplo, deseas agregar un campo `role` al modelo `User`, necesitarías proporcionar un valor predeterminado al campo `role`. Esto se hace agregando un valor `@default` al campo `role` en el modelo `User`:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Uso con el middleware Next.js\n\nEl uso de NextAuth.js con el middleware Next.js [requiere el uso de la estrategia de sesión JWT](https://next-auth.js.org/configuration/nextjs#caveats) para la autenticación. Esto se debe a que el middleware solo puede acceder a la cookie de sesión si es un JWT. De forma predeterminada, `create-t3-app` está configurado para usar la estrategia de base de datos **predeterminada**, en combinación con Prisma como adaptador de base de datos.\n\n## Configuración del DiscordProvider predeterminado\n\n1. Dirígete a [la sección de aplicaciones en el portal del desarrollador de Discord](https://discord.com/developers/applications) y haz clic en \"New Application\"\n2. En el menú de configuración, dirígite a \"OAuth2 => General\"\n\n- Copia el Client ID y pégalo en `AUTH_DISCORD_ID` en `.env`.\n- En Client Secret, haz clic en \"Reset Secret\" y copia ese string en `AUTH_DISCORD_SECRET` en `.env`. Ten cuidado ya que no podrás volver a ver este valor secreto, y restablecerlo hará que el existente expire.\n- Haz clic en \"Add Redirect\" y pega en `<app url>/api/auth/callback/discord` (Ejemplo para desarrollo local: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Guarda tus cambios\n- Es posible, pero no recomendado, usar la misma aplicación de Discord tanto para desarrollo como para producción. También puedes considerar hacer un [mock del proveedor](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) durante el desarrollo.\n\n## Recursos útiles\n\n| Recurso                           | Enlace                                  |\n| --------------------------------- | --------------------------------------- |\n| Documentación de NextAuth.js      | https://next-auth.js.org/               |\n| GitHub de NextAuth.js             | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/es/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Uso de Next.js\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nNext.js es un framework de backend para tus aplicaciones de React.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js es un framework de backend\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nÉchale un vistazo a la [charla de Theo en la Next.js Conf](https://www.youtube.com/embed/W4UhNo3HAMw) para comprender mejor qué es Next.js y cómo funciona.\n\n## ¿Por qué debería usarlo?\n\nAmamos React. Ha hecho que el desarrollo de interfaces de usuario sea accesible de una manera que nunca antes imaginamos. También puede llevar a los desarrolladores por algunos caminos difíciles. Next.js ofrece un enfoque ligeramente dogmático y muy optimizado para crear aplicaciones utilizando React. Desde el enrutamiento, las definiciones de APIs hasta la representación de imágenes, confiamos que Next.js lleve a los desarrolladores hacia la toma de buenas decisiones.\n\nUtilizar Next.js junto con [Vercel](https://vercel.com/) hace que el desarrollo y despliegue de aplicaciones web sea más fácil que nunca. Su opción gratuita extremadamente generosa y su interfaz super intuitiva proporcionan una solución de un solo clic para desplegar tu sitio (nosotros ❤️ Vercel)\n\n## Get Static/Server Props\n\nUna característica clave de Next.js son sus capacidades de obtención de datos. Recomendamos fuertemente leer la [documentación oficial](https://nextjs.org/docs/basic-features/data-fetching) para comprender cómo usar cada método y cómo difieren. `getServerSideProps` generalmente se desaconseja a menos que haya una buena razón para ello, debido al hecho de que es una llamada bloqueante y reducirá el rendimiento de tu sitio. La [regeneración estática incremental](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) es una gran alternativa a `getServerSideProps` cuando los datos son dinámicos y se pueden obtener incrementalmente.\n\n## Recursos útiles\n\n| Recurso                            | Enlace                             |\n| ---------------------------------- | ---------------------------------- |\n| Documentación de Next.js           | https://nextjs.org/docs            |\n| GitHub de Next.js                  | https://github.com/vercel/next.js  |\n| Blog de Next.js                    | https://nextjs.org/blog            |\n| Discord de Next.js                 | https://nextjs.org/discord         |\n| Twitter de Next.js                 | https://twitter.com/nextjs         |\n| Canal de Youtube de Vercel/Next.js | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/es/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Uso de Prisma\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\nPrisma es un ORM para TypeScript, que te permite definir el esquema de tu base de datos y los modelos en un archivo `schema.prisma`, y luego generar un cliente seguro en tipos que se puede usar para interactuar con tu base de datos desde tu backend.\n\n## Prisma Client\n\nUbicado en `/server/db/client.ts`, el Prisma Client se instancia como una variable global (como se recomienda como [mejor práctica](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) por el equipo de Prisma) y exportado para ser utilizado en tus rutas API. Incluimos el Prisma Client en el [contexto](/es/usage/trpc#-serverapitrpcts) de tRPC de forma predeterminada y recomendamos usar esto en lugar de importarlo por separado en cada archivo.\n\n## Esquema\n\nEncontrarás el archivo de esquema de Prisma en `/prisma/schema.prisma`. Este archivo es donde defines el esquema y los modelos de tu base de datos, y se usa al generar el cliente Prisma.\n\n### Con NextAuth.js\n\nCuando seleccionas NextAuth.js en combinación con Prisma, el archivo de esquema se genera y se configura para ti con los valores recomendados para los modelos `User`, `Session`, `Account` y `VerificationToken`, según la [documentación de NextAuth.js](https://next-auth.js.org/adapters/prisma).\n\n## Base de datos predeterminada\n\nLa base de datos predeterminada es una base de datos SQLite, que es excelente para el desarrollo y para crear rápidamente una prueba de concepto, pero no se recomienda para producción. Puede cambiar la base de datos a utilizar cambiando el `provider` en el bloque `datasource` a `postgresql` o` mysql`, y luego actualizando el string de conexión dentro de las variables de entorno para apuntar a tu base de datos.\n\n## Llenando (seeding) tu base de datos\n\n[Llenar (_seeding_) tu base de datos](https://www.prisma.io/docs/guides/database/seed-database) es una excelente manera de llenar (_seed_) rápidamente tu base de datos con datos de prueba para ayudarte a comenzar. Para configurar el llenado, deberás crear un archivo `seed.ts` en el directorio `/prisma`, y luego agregar un script `seed` a tu archivo `package.json`. También necesitarás algún corredor de TypeScript que pueda ejecutar el script de llenado. Recomendamos [tsx](https://github.com/esbuild-kit/tsx), que es un corredor de TypeScript muy optimizado que usa esbuild y que no requiere ninguna configuración de ESM, pero `ts-node` u otros corredores pueden funcionar también.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db/client\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nLuego, simplemente ejecuta `pnpm db-seed` (o `npm`/`yarn`) para llenar (_seed_) tu base de datos.\n\n## Recursos útiles\n\n| Recurso                           | Enlace                                                                                                                                            |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Documentación de Prisma           | https://www.prisma.io/docs/                                                                                                                       |\n| GitHub de Prisma                  | https://github.com/prisma/prisma                                                                                                                  |\n| Adaptador Prisma para NextAuth.JS | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| Guía de conexión de PlanetScale   | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/es/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Uso de Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\n## ¿Qué es Tailwind CSS?\n\nTailwind CSS es un pequeño framework, [_utility-first_](https://tailwindcss.com/docs/utility-first), de CSS para construir diseños personalizados, sin el cambio de contexto que requiere el CSS normal. Es puramente un framework de CSS y no proporciona componentes o lógica preconstruida, y proporciona [un conjunto muy diferente de beneficios](https://www.youtube.com/watch?v=CQuTF-bkOgc) en comparación con una librería de componentes como Material UI.\n\nHace que CSS sea increíblemente fácil y rápido de escribir, como se muestra en el siguiente ejemplo:\n\nViejo CSS:\n\n1. Escribir CSS, generalmente en un archivo separado\n\n```css\n.mi-clase {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Importar el CSS en tu componente\n\n```jsx\nimport \"./mi-clase.css\";\n```\n\n3. Agrega la clase a tu HTML\n\n```html\n<div class=\"mi-clase\">...</div>\n```\n\nEquivalente en Tailwind:\n\n1. Simplemente escribe clases en tu HTML\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nCuando se usa junto con los componentes de React, es extremadamente potente para construir UIs (_interfaces de usuario_) rápidamente.\n\nTailwind CSS tiene un hermoso sistema de diseño incorporado, que sale de la caja con una paleta de colores cuidadosamente elegida, patrones de dimensionamiento para estilos como width/height y padding/margin para un diseño uniforme, así como puntos de quiebre para crear diseños responsive. Este sistema de diseño se puede personalizar y extender para crear la caja de herramientas exacta de los estilos que necesita tu proyecto.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"Tru Narla: Building a design system in Next.js with Tailwind\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla mejor conocida como [mewtru](https://twitter.com/trunarla) dio una charla increíble de [cómo construir un sistema de diseño utilizando Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Uso\n\nAsegúrate de tener complementos de editor para Tailwind CSS instalados para mejorar tu experiencia escribiendo Tailwind.\n\n### Extensiones y complementos\n\n- [Extensión VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [Integración de JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formateo\n\nLas clases CSS de Tailwind pueden volverse un poco caóticas fácilmente, por lo que es imprescindible un formateo para las clases. [El complemento de Prettier de Tailwind CSS](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) clasifica las clases en el [orden recomendado](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) para que las clases coincidan con el paquete (_bundle_) CSS generado. Al seleccionar Tailwind CSS en la CLI, instalaremos y configuraremos esto para ti.\n\n### Aplicando clases condicionalmente\n\nAgregar condicionalmente clases con operadores ternarios puede ser muy desordenado y difícil de leer. Estos paquetes ayudan a organizar tus clases cuando se usa lógica condicional.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Recursos útiles\n\n| Recurso                          | Enlace                                                   |\n| -------------------------------- | -------------------------------------------------------- |\n| Documentación de Tailwind        | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet             | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss              | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Comunidad de Tailwind            | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Servidor Discord de Tailwind     | https://tailwindcss.com/discord/                         |\n| Canal de Youtube de TailwindLabs | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground              | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/es/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Uso de tRPC\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\ntRPC nos permite escribir APIs con seguridad de tipos de extremo a extremo sin ninguna generación de código o con un incremento en el tiempo de ejecución. Utiliza la increíble inferencia de TypeScript para inferir las definiciones de tipos de tu enrutador API y te permite llamar a tus procedimientos de API desde tu frontend con seguridad de tipos y con autocompletado. Al usar TRPC, tu backend y frontend se sienten más juntos que nunca, lo que permite una experiencia de desarrollo excepcional.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n   <span aria-hidden=\"true\">&quot;</span>I built tRPC to allow people to move faster by removing the need of a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creador de tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Archivos\n\ntRPC requiere una gran cantidad de archivos que `create-t3-app` genera para ti. Revisemos los archivos que se generan:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nEste es el punto de entrada para tu API y expone el enrutador tRPC. Normalmente, no tocarás mucho este archivo, pero si necesitas, por ejemplo, habilitar el middleware CORS o similar, es útil saber que el `createNextApiHandler` exportado es un [manejador API de Next.js](https://nextjs.org/docs/api-routes/introduction) que tiene un objeto de [solicitud](https://developer.mozilla.org/en-us/docs/web/api/request) y [respuesta](https://developer.mozilla.org/en-US/docs/Web/API/Response?retiredLocale=sv-SE). Esto significa que puedes envolver el `createNextApiHandler` en cualquier middleware que desees. Consulta a continuación un [fragmento de ejemplo](#habilitando-cors) de agregar CORS.\n\n### 📄 `server/trpc/context.ts`\n\nEste archivo es donde defines el contexto que se pasa a tus procedimientos tRPC. El contexto son datos a los que todos tus procedimientos tRPC tendrán acceso, y es un excelente lugar para poner cosas como conexiones de bases de datos, información de autenticación, etc. En create-t3-app, usamos dos funciones, para habilitar el uso de un subconjunto del contexto cuando no tenemos acceso al objeto de la solicitud.\n\n- `createContextInner`: aquí es donde defines el contexto que no depende de la solicitud, ejemplo: tu conexión de base de datos. Puedes usar esta función para [Pruebas de integración](#muestra-integración-test) o [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers) donde no tienes un objeto de solicitud.\n\n- `createContext`: Aquí es donde defines el contexto que depende de la solicitud, ejemplo: la sesión del usuario. Solicita la sesión usando el objeto `opts.req` y luego pasa la sesión a la función `createContextInner` para crear el contexto final.\n\n### 📄 `server/trpc/trpc.ts`\n\nAquí es donde inicializas tRPC y defines [procedimientos](https://trpc.io/docs/v10/procedures) reutilizables y [middlewares](https://trpc.io/docs/v10/middlewares). Por convención, no debes exportar todo el objeto `t`, sino crear procedimientos y middlewares reutilizables y exportarlos.\n\nNotarás que usamos `superjson` como [transformador de datos](https://trpc.io/docs/v10/data-transformers). Esto hace que tus tipos de datos se conserven cuando llegan al cliente, por lo que si por ejemplo envías un objeto `Date`, el cliente devolverá un `Date` y no una string, que es el caso para la mayoría de las APIs.\n\n### 📄 `server/trpc/router/*.ts`\n\nAquí es donde defines las rutas y procedimientos de tu API. Por convención, tu deberías [crear enrutadores separados](https://trpc.io/docs/v10/router) para procedimientos relacionados, luego [fusionar](https://trpc.io/docs/v10/merging-routers) todos ellos en un solo enrutador en `servidor/trpc/router/_app.ts`.\n\n### 📄 `utils/trpc.ts`\n\nEste es el punto de entrada frontend para tRPC. Aquí es donde importarás la definición de tipo **del enrutador** y crearás tu cliente tRPC junto con los hooks react-query. Dado que habilitamos `superjson` como nuestro transformador de datos en el backend, también debemos habilitarlo en el frontend. Esto se debe a que los datos serializados del backend están deserializados en la parte del frontend.\n\nDefinirás tus [enlaces](https://trpc.io/docs/v10/links) tRPC aquí, que determinan el flujo de la solicitud del cliente al servidor. Utilizamos el \"predeterminado\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpbatchlink) que habilita [solicitudes en conjunto](https://cloud.google.com/compute/docs/api/how-tos/batch), así como un [`loggerLink`](https://trpc.io/docs/v10/links/loggerlink) que genera registros de solicitudes útiles durante el desarrollo.\n\nPor último, exportamos un [tipo de ayuda](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) que puedes usar para inferir tus tipos en el frontend.\n\n## ¿Cómo uso tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nEl contribuidor de tRPC [trashh_dev](https://twitter.com/trashh_dev) dió [una charla en la Next.js conf](https://www.youtube.com/embed/2LYM8gf184U) sobre tRPC. Te recomendamos que lo veas si aún no lo has hecho.\n\nCon tRPC, escribes funciones TypeScript en tu backend y luego las llamas desde tu frontend. Un simple procedimiento de tRPC podría verse así:\n\n```ts:server/trpc/router/user.ts\nconst userRouter = t.router({\n  getById: t.procedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nEste es un procedimiento TRPC (equivalente a un manejador de ruta en un backend tradicional) que primero valida la entrada usando Zod (que es la misma librería de validación que utilizamos para las [variables de entorno](./env-variables)) - en este caso, se asegura de que la entrada sea un string. Si la entrada no es un string, enviará un error informativo en su lugar.\n\nDespués de la entrada, encadenamos una función de resolución que puede ser una [consulta](https://trpc.io/docs/v10/react-queries), [mutación](https://trpc.io/docs/v10/react-mutations), o una [suscripción](https://trpc.io/docs/v10/subscriptions). En nuestro ejemplo, la función de resolución llama a nuestra base de datos utilizando nuestro cliente [prisma](./prisma) y devuelve al usuario cuyo `id` coincide con el que pasamos.\n\nTu defines tus procedimientos en `routers` que representan una colección de procedimientos relacionados con un nombre compartido. Es posible que tengas un enrutador para `users`, uno para `posts` y otro para `messages`. Estos enrutadores se pueden fusionar en un único `appRouter` centralizado:\n\n```ts:server/trpc/router/_app.ts\nconst appRouter = t.router({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nTen en cuenta que solo necesitamos exportar las definiciones de tipo de nuestro enrutador, lo que significa que nunca estamos importando ningún código de servidor en nuestro cliente.\n\nAhora llamemos al procedimiento en nuestro frontend. tRPC proporciona un wrapper para `@tanstack/react-query` que te permite utilizar la potencia completa de los hooks que proporcionan, pero con el beneficio adicional de tener tus llamadas API seguras en tipos e inferidas. Podemos llamar a nuestros procedimientos desde nuestro frontend de la misma manera:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = trpc.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nInmediatamente notarás lo bueno que es el autocompletado y la seguridad tipos. Tan pronto como escribas `trpc.`, tus enrutadores aparecerán como sugerencias de autocompletado, y cuando selecciones un enrutador, tus procedimientos también aparecerán. También recibirás un error de TypeScript si tu entrada no coincide con el validador que se definió en el backend.\n\n## ¿Cómo llamo a mi API externamente?\n\nCon APIs regulares, puedes llamar a tus endpoints utilizando cualquier cliente HTTP como `curl`, `Postman`, `fetch` o directamente desde tu navegador. Con tRPC, es un poco diferente. Si deseas llamar a tus procedimientos sin el cliente tRPC, hay dos formas recomendadas de hacerlo:\n\n### Exponer un solo procedimiento externamente\n\nSi deseas exponer un solo procedimiento externamente, estás buscando [llamadas del lado del servidor](https://trpc.io/docs/v10/server-side-calls). Eso te permitirá crear un endpoint API normal Next.js, pero reutilizará la parte de la resolución de tu procedimiento tRPC.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Exponer cada procedimiento como endpoints REST\n\nSi deseas exponer cada procedimiento externamente, consulta el complemento construido por la comunidad [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Al proporcionar algunos metadatos adicionales a tus procedimientos, puedes generar una API REST compatible con OpenAPI desde tu enrutador tRPC.\n\n### Son solo solicitudes HTTP\n\ntRPC se comunica a través de HTTP, por lo que también es posible llamar a tus procedimientos tRPC utilizando solicitudes HTTP \"regulares\". Sin embargo, la sintaxis puede ser engorrosa debido al [protocolo RPC](https://trpc.io/docs/v10/RPC) que tRPC usa. Si tienes curiosidad, puedes verificar cómo se ven las solicitudes y respuestas de tRPC en la pestaña de red de tu navegador, pero sugerimos hacerlo solo como un ejercicio educativo y apegarse a una de las soluciones descritas anteriormente.\n\n## Comparación con un API endpoint de Next.js\n\nComparemos un API endpoint de Next.js con un procedimiento tRPC. Supongamos que queremos obtener un objeto de usuario de nuestra base de datos y devolverlo al frontend. Podríamos escribir un API endpoint Next.js como este:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db/client\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nCompara esto con el ejemplo de tRPC anterior, para poder ver algunas de las ventajas de tRPC:\n\n- En lugar de especificar una URL para cada ruta, que puede volverse molesto para depurar si mueves algo, todo tu enrutador es un objeto con autocompletado.\n- No necesitas validar qué método HTTP se utilizó.\n- No necesitas validar que la consulta de solicitud o el cuerpo contenga los datos correctos en el procedimiento, porque Zod se encarga de esto.\n- En lugar de crear una respuesta, puedes lanzar errores y devolver un valor u objeto como lo harías en cualquier otra función de TypeScript.\n- Llamar al procedimiento en el frontend proporciona autocompletado y seguridad de tipos.\n\n## Fragmentos útiles\n\nAquí hay algunos fragmentos que pueden ser útiles.\n\n### Habilitando CORS\n\nSi necesitas consumir tu API desde un dominio diferente, por ejemplo, en un monorepo que incluye una aplicación React Native, es posible que debas habilitar CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/trpc/router/_app\";\nimport { createContext } from \"~/server/trpc/context\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Habilita cors\n  await cors(req, res);\n\n  // Crea y llama al manejador tRPC\n  return createNextApiHandler({\n    router: appRouter,\n    createContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Actualizaciones optimistas\n\nLas actualizaciones optimistas son cuando actualizamos la interfaz de usuario antes de que la llamada API haya terminado. Esto le da al usuario una mejor experiencia porque no tiene que esperar a que la llamada API termine antes de que la interfaz de usuario refleje el resultado de tu acción. Sin embargo, las aplicaciones que valoran el estado correcto de los datos deben evitar actualizaciones optimistas, ya que no son una representación \"verdadera\" del estado del backend. Puede leer más en la documentación de [React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = trpc.post.list.useQuery();\n\n  const utils = trpc.useContext();\n  const postCreate = trpc.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancela las solicitudes de salida (para que no  sobrescriban nuestras actualizaciones optimistas)\n      await utils.post.list.cancel();\n\n      // Obtener los datos del queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimisticamente actualizamos los datos con nuestro nuevo post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Retornamos los datos previos para que podamos revertirlo si algo sale mal\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // Si la mutación falla, utilizar el valor del contexto de onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sincronizamos el servidor una vez la mutación se haya completado\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Prueba de integración de muestra\n\nAquí hay una prueba de integración de muestra que utiliza [Vitest](https://vitest.dev) para verificar que tu enrutador tRPC funcione como se esperaba, el analizador de entrada infiere el tipo correcto y que los datos devueltos coincidan con la salida esperada.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/router/_app\";\nimport { createContextInner } from \"~/server/router/context\";\n\ntest(\"example router\", async () => {\n  const ctx = await createContextInner({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n## Recursos útiles\n\n| Recurso                       | Enlace                                                  |\n| ----------------------------- | ------------------------------------------------------- |\n| Documentación de tRPC         | https://www.trpc.io                                     |\n| Un montón de ejemplos de tRPC | https://github.com/trpc/trpc/tree/next/examples         |\n| Documentación de React Query  | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/es/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Uso de TypeScript\nlayout: ../../../layouts/docs.astro\nlang: es\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creador del T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nYa sea que seas un desarrollador nuevo o experimentado, creemos que TypeScript es imprescindible. Al principio puede parecer intimidante, pero al igual que muchas herramientas, es algo de lo que muchos nunca miran hacia atrás después de comenzar a usarlo.\n\nProporciona comentarios en vivo a medida que escribes tu código definiendo los tipos de datos esperados, y proporciona un servicio automático útil en tu editor de código, o te dice con líneas rojas curveadas si estás intentando acceder a una propiedad que no existe o intentas pasar un valor del tipo incorrecto, que de otro modo tendrías que depurar más adelante.\n\nEs, tal vez, la herramienta que proporciona la mayor productividad a los desarrolladores; Proporciona documentación del código que estás escribiendo o consumiendo directamente en tu editor, y tener comentarios instantáneos a medida que inevitablemente cometes errores no tiene precio.\n\n## Inferencia de Tipos\n\nSi bien muchos desarrolladores de TypeScript nuevos se preocupan por _escribir_ TypeScript, muchos de sus beneficios en realidad no requieren que cambies tu código en absoluto, en particular la inferencia. La inferencia significa que si se escribe algo, ese tipo seguirá siendo el mismo durante todo el flujo de la aplicación sin tener que volver a declararlo en otros lugares.Esto significa que, por ejemplo, una vez que hayas definido los tipos de los argumentos que toma una función, el resto de la función generalmente será segura en tipos sin requerir ningún código más específico de TypeScript. Los desarrolladores de librerías pusieron un montón de trabajo en el mantenimiento de los tipos de sus librerías, lo que significa que nosotros, como desarrolladores de aplicaciones, podemos beneficiarnos tanto de la inferencia como de la documentación incorporada en tu editor de código que proporcionan estos tipos.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nEcha un vistazo al video de Theo sobre cómo [podrías estar usando TypeScript de manera incorrecta](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Usos poderosos de inferencia de tipos\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) es una librería de validación de esquema que se basa en TypeScript. Escribe un esquema que represente una sola fuente de verdad para tus datos, y Zod se asegurará de que tus datos sean válidos en toda tu aplicación, incluso a través de los límites de la red y las APIs externas.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) te ofrece consultas y mutaciones auto-gestionadas, siempre actualizadas, que mejoran directamente tu experiencia de desarrollo y usuario.\n\n## Recursos útiles\n\n| Recurso                                                       | Enlace                                                            |\n| ------------------------------------------------------------- | ----------------------------------------------------------------- |\n| Manual de TypeScript                                          | https://www.typescriptlang.org/docs/handbook/                     |\n| Tutorial de TypeScript para principiantes                     | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                               | https://github.com/type-challenges/type-challenges                |\n| Canal de Youtube de Rodney Mullen de TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/es/why.md",
    "content": "---\ntitle: ¿Por qué CT3A?\ndescription: ¿Por qué deberías elegir Create T3 App para tu siguiente proyecto?\nlayout: ../../layouts/docs.astro\nlang: es\n---\n\nEmpezamos create-t3-app porque [Theo](https://twitter.com/t3dotgg) se negó a hacer una plantilla de sus tecnologías favoritas. Inspirándose en create-next-app, [CLI de Astro](https://astro.build) y un amor general por la seguridad de tipos, el equipo de create-t3-app trabajó arduamente para crear el mejor punto de partida posible para los nuevos proyectos de T3 Stack.\n\nSi estás interesado en usar Next.js de forma segura, este es el lugar para comenzar. Si tienes curiosidad acerca de alguna de las opciones tecnológicas específicas que tomamos, sigue leyendo :)\n\n## ¿Por qué TypeScript?\n\nJavaScript es difícil. ¿Por qué agregar más reglas?\n\nCreemos firmemente que la experiencia que brinda TypeScript te ayudará a ser un mejor desarrollador. Proporciona retroalimentación en vivo a medida que escribes tu código definiendo los tipos de datos esperados, y proporciona un autocompletado útil en tu editor o te grita con líneas onduladas rojas si estás tratando de acceder a una propiedad que no existe o tratando de pasar un valor del tipo incorrecto, que de otro modo tendrías que depurar más adelante. Ya sea que seas nuevo en el desarrollo web o un profesional experimentado, el \"rigor\" de TypeScript te brindará una experiencia menos frustrante y más consistente que JS estándar.\n\nLa seguridad de tipos te hace más rápido. Si no estás convencido, [podrías estar usando TypeScript de forma incorrecta...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## ¿Por qué Next.js?\n\nNos encanta React. Ha hecho que el desarrollo de la interfaz de usuario sea accesible de maneras que nunca antes habíamos imaginado. También puede llevar a los desarrolladores por caminos difíciles.\n\nNext.js ofrece un enfoque ligeramente obstinado y muy optimizado para crear aplicaciones usando React. Desde el enrutamiento hasta las definiciones de API y la representación de imágenes, confiamos en Next.js para guiar a los desarrolladores hacia buenas decisiones.\n\n## ¿Por qué tRPC/Prisma/Tailwind/etc?\n\nSi bien creemos en mantener las cosas lo más simples posible, encontramos que estas piezas se utilizan en cada proyecto similar a una \"aplicación\" que construimos. `create-t3-app` hace un gran trabajo al permitirte adoptar las piezas que necesitas.\n\n### tRPC\n\ntRPC cumple con la promesa de GraphQL de un desarrollo de cliente sin interrupciones contra un servidor seguro en tipos sin todo lo repetitivo. Es un abuso inteligente de TypeScript que proporciona una experiencia de desarrollo increíble.\n\n### Prisma\n\nPrisma es para SQL lo que TypeScript es para JS. Creó una experiencia de desarrollo que no existía antes. Al generar tipos a partir de un esquema definido por el usuario compatible con [varias bases de datos](https://www.prisma.io/docs/concepts/database-connectors), Prisma garantiza la seguridad de tipos de extremo a extremo desde su base de datos hasta su aplicación.\n\nPrisma proporciona un [conjunto de herramientas](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) completo, facilitando las interacciones diarias con tu base de datos. En particular, Prisma Client es responsable de consultar y hacer que SQL sea tan fácil que apenas notarás que lo estás usando, y Prisma Studio es una GUI conveniente para tu base de datos que te permite leer y manipular sus datos rápidamente sin tener que escribir código.\n\n### Tailwind CSS\n\nTailwind se siente como \"CSS en modo zen\".\n\nAl proporcionar bloques de construcción en forma de buenos colores predeterminados, espaciado y otras primitivas, Tailwind facilita la creación de una aplicación atractiva. Y a diferencia de las librerías de componentes, no te detiene cuando deseas llevar tu aplicación al siguiente nivel y crear algo hermoso y único.\n\nAdemás, con su enfoque en línea, Tailwind te alienta a diseñar sin preocuparte por nombrar clases, organizar archivos o cualquier otro problema que no esté directamente relacionado con el problema que estás tratando de resolver.\n\n### NextAuth.js\n\nCuando desees un sistema de autenticación en tu aplicación NextJS, NextAuth.js es una excelente solución para incorporar la complejidad de la seguridad sin la molestia de tener que construirlo por tu cuenta. Viene con una extensa lista de proveedores para agregar rápidamente la autenticación OAuth y proporciona adaptadores para muchas bases de datos y ORM.\n"
  },
  {
    "path": "www/src/pages/fr/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Déploiement avec Docker\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\nVous pouvez containeriser cette stack et la déployer en tant que conteneur unique à l'aide de Docker, ou en tant que partie d'un ensemble de conteneurs en utilisant docker-compose. Voir [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) pour un exemple basé sur cette documentation.\n\n## Configuration du projet sous Docker\n\nVeuillez noter que Next.js nécessite des variables d’environnements qui sont différentes entre le processus de génération (celles-ci vont être disponible seulement côté navigateur, et sont préfixées par `NEXT_PUBLIC`) et dans l’environnement d’exécution, qui est côté serveur seulement. Dans cette démo nous utilisons deux variables. Prêtez attention à leurs positions dans les fichiers `Dockerfile`, `docker-compose.yml` et dans la ligne de commande.\n\n- `DATABASE_URL` (utiliser par le serveur)\n- `NEXT_PUBLIC_CLIENTVAR` (utiliser par le client)\n\n### 1. Configuration de Next\n\nDans votre fichier [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), ajouter l'entrée `output` avec comme valeur `standalone` [réduit la taille de l'image Docker en se basant sur la sortie du processus de génération](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Créer un fichier dockerignore\n\n<details>\n    <summary>\n      Cliquez ici et incluez le contenue dans votre <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Créer un fichier Dockerfile\n\n> Étant donné que nous ne récupérons pas les variables d'environnement du serveur dans notre conteneur, la [validation du schéma d'environnement](/fr/usage/env-variables) échouera. Pour éviter cela, nous devons ajouter l'argument `SKIP_ENV_VALIDATION=1` à la commande de génération afin que les schémas d'environnement ne soient pas validé à ce moment là.\n\n<details>\n    <summary>\n      Cliquez ici et incluez le contenue dans votre <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Notes_**\n>\n> - _L'émulation de `--platform=linux/amd64` n'est pas nécessaire à partir de Node 18._\n> - _Voir [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) pour comprendre pourquoi `libc6-compat` pourrait être nécessaire._\n> - _Next.js receuille [des données de télémétrie sur l'utilisation générale de façon anonyme](https://nextjs.org/telemetry). Décommentez la première occurrence de `ENV NEXT_TELEMETRY_DISABLED 1` pour désactiver la télémétrie durant le processus de génération. Décommentez la seconde occurence pour désactiver la télémétrie durant l'exécution._\n\n</div>\n</details>\n\n## Génération et exécution de l'image localement\n\nGénérer et exécuter l'image localement avec les commandes suivantes:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nOuvrez [localhost:3000](http://localhost:3000/) pour voir votre application s'exécuter.\n\n## Docker Compose\n\nVous pouvez également utiliser Docker Compose pour générer l'image et exécuter le conteneur.\n\n<details>\n    <summary>\n      Suivez les étapes 1 à 4 ci-dessus, cliquez ici et incluez le contenue dans votre <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nExécutez ceci à l'aide de la commande `docker compose up` :\n\n```bash\ndocker compose up\n```\n\nOuvrez [localhost:3000](http://localhost:3000/) pour voir votre application en cours d'exécution.\n\n</div>\n</details>\n\n## Déployer sur Railway\n\nVous pouvez utiliser un service de type PaaS comme [Railway's](https://railway.app) pour automatiser le déploiement de votre application [Voir Dockerfile sur railway](https://docs.railway.app/deploy/dockerfiles). Si vous avez [Railway CLI d'installer](https://docs.railway.app/develop/cli#install) vous pouvez déployer votre application en suivant les commandes suivantes:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nAllez dans \"Variables\" et rajoutez votre `DATABASE_URL`. Ensuite, allez dans \"Settings\" et sélectionnez \"Generate Domain.\". Pour voir un exemple qui fonctionne sur Railway, visitez [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Ressources utiles\n\n| Ressources                                       | Liens                                                                |\n| ------------------------------------------------ | -------------------------------------------------------------------- |\n| Dockerfile référence                             | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file version 3 référence                 | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI référence                             | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI référence                     | https://docs.docker.com/compose/reference/                           |\n| Next.js déploiement avec une image Docker        | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js dans Docker                              | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Next.js exemple avec Docker                      | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Créer une image Docker d'une application Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/fr/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Déploiement\",\n  layout: \"docs\",\n  description: \"Apprenez comment déployer votre app T3 en production.\",\n};\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/fr/deployment/netlify.mdx",
    "content": "---\ntitle: Netlify\ndescription: Déploiement sur Netlify\nlayout: ../../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nNetlify est un fournisseur de déploiement alternatif dans la même veine que Vercel. Voir [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) pour un exemple de dépôt basé sur ce document.\n\n## Pourquoi héberger sur Netlify\n\nLa sagesse conventionnelle dit que Vercel a un support Next.js supérieur parce que Vercel développe Next.js. Ils ont tout intérêt à s'assurer que la plate-forme est réglée pour des performances optimales et DX avec Next.js. Pour la majorité des cas d'utilisation, cela sera vrai et cela n'aura aucun sens de s'écarter du chemin standard.\n\nIl existe également un sentiment commun selon lequel de nombreuses fonctionnalités de Next.js ne sont prises en charge que sur Vercel. S'il est vrai que les nouvelles fonctionnalités Next.js seront testées et prises en charge sur Vercel au moment de leurs publications, il est également vrai que d'autres fournisseurs comme Netlify [implémenteront et publieront rapidement leur prise en charge](https://www.netlify.com/blog/deploy-nextjs-13/) pour les [fonctionnalités stables de Next.js](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nIl existe des avantages et des inconvénients relatifs pour chaque fournisseurs de déploiement, car aucun hébergeur ne peut avoir le meilleur support pour tous les cas d'utilisation. Par exemple, Netlify a construit son propre [environnement d'exécution Next.js personnalisé](https://github.com/netlify/next-runtime) pour les fonctions Edge de Netlify (qui s'exécutent sur Deno Deploy) et [maintient un middleware unique pour accéder et modifier les réponses HTTP](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n<Callout type=\"info\">\n  Pour suivre l'état des fonctionnalités instables de Next 13, consultez [Utilisation du répertoire \"app\" de Next 13 sur Netlify](https://github.com/netlify/next-runtime/discussions/1724).\n</Callout>\n\n## Configurer le projet\n\nIl existe de nombreuses façons de configurer vos instructions de build, y compris directement via la CLI Netlify ou le tableau de bord Netlify. Bien que cela ne soit pas obligatoire, il est conseillé de créer et d'inclure un fichier [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Cela garantit que les versions dérivées et clonées du projet seront plus faciles à déployer et de manière reproductible.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Utilisation du tableau de bord Netlify\n\n1. Transférez votre code vers un dépôt GitHub et inscrivez-vous à [Netlify](https://app.netlify.com/signup). Après avoir créé un compte, cliquez sur **Ajouter un nouveau site** puis sur **Importer un projet existant**.\n\n![Nouveau projet sur Netlify](/images/netlify-01-new-project.webp)\n\n2. Connectez votre fournisseur de dépôt.\n\n![Importation de votre dépôt](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Sélectionnez le dépôt de votre projet.\n\n![Sélectionnez le dépôt de votre projet.](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify détectera si vous avez un fichier `netlify.toml` et configurera automatiquement votre commande de build et votre répertoire de publication.\n\n![Paramètres de build de Nextjs](/images/netlify-04-configure-build-settings.webp)\n\n5. Cliquez sur **Afficher les paramètres avancés**, puis sur **Nouvelle variable** pour ajouter vos variables d'environnement.\n\n![Ajouter des variables d'environnement](/images/netlify-05-env-vars.webp)\n\n1. Cliquez sur **Déployer le site**, attendez la fin de la compilation, puis, affichez votre nouveau site.\n\n## Utilisation de la CLI Netlify\n\nPour déployer à partir de la ligne de commande, vous devez d'abord pousser votre projet vers un dépôt GitHub et [installer la CLI Netlify](https://docs.netlify.com/cli/get-started/). Vous pouvez installer `netlify-cli` en tant que dépendance de projet ou l'installer globalement sur votre machine avec la commande suivante :\n\n```bash\nnpm i -g netlify-cli\n```\n\nPour tester votre projet localement, exécutez la commande [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) et ouvrez [`localhost:8888 `](http://localhost:8888/) pour afficher votre application Netlify exécutée localement :\n\n```bash\nntl dev\n```\n\nExécutez la commande [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) pour configurer votre projet :\n\n```bash\nntl init\n```\n\nImportez les variables d'environnement de votre projet à partir de votre fichier `.env` avec [`ntl env:import`](https://cli.netlify.com/commands/env#envimport) :\n\n```bash\nntl env:import .env\n```\n\nDéployez votre projet avec [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Vous devrez passer l'indicateur `--build` pour exécuter la commande build avant le déploiement et l'indicateur `--prod` pour déployer sur l'URL principale de votre site :\n\n```bash\nntl deploy --prod --build\n```\n\nPour afficher un exemple d'exécution sur Netlify, visitez [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/fr/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Déploiement sur Vercel\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\nNous vous recommandons de déployer votre application sur [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Ce service facilite le déploiement d'application Next.js.\n\n## Configuration du projet\n\nVercel va certainement configurer les commandes de génération et publier le répertoire automatiquement. Cependant, vous pouvez également spécifier ces informations manuellement avec vos propres configurations en créant un fichier appelé [`vercel.json`](https://vercel.com/docs/project-configuration) et en incluant les informations suivantes. **La plus part des projets ne le requiert pas.**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Utilisation du tableau de bord Vercel\n\n1. Après avoir envoyer votre code sur GitHub, Inscrivez-vous sur [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) avec GitHub et cliquez ensuite sur **Add New Project**.\n\n![Nouveau projet sur Vercel](/images/vercel-new-project.webp)\n\n2. Importez votre projet GitHub.\n\n![Importation de votre projet](/images/vercel-import-project.webp)\n\n3. Ajoutez vos variables d'environnement.\n\n![Ajoutez vos variables d'environnement](/images/vercel-env-vars.webp)\n\n4. Cliquez sur **Deploy**. À partir de maintenant, à chaque fois que vous pousserez une modification, Vercel redéploiera automatiquement votre application !\n\n## Utilisation de Vercel CLI\n\nPour déployer à partir de la ligne de commande, vous devez d'abord [installer la CLI Vercel globalement](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nExécutez la commande [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) pour déployer votre projet.\n\n```bash\nvercel\n```\n\nAjoutez l'argument `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` pour ajouter une variable d'environnement comme la chaîne de connexion à la base de données. Utilisez `--yes` si vous souhaitez ignorer les questions lors des déploiements et donner une réponse par défaut.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nAprès le premier déploiement, cette commande déploiera sur une branche de prévisualisation. Vous deverez ajouter l'argument `--prod` pour pousser votre changement directement sur la production.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/fr/examples.mdx",
    "content": "---\ntitle: Exemples\ndescription: Exemples d'application actives\nlayout: ../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\nimport Form from \"../../components/docs/exampleOptionForm.astro\";\n\nVous pouvez essayer plusieurs combinaisons de technologies que create-t3-app offre.\n\n<Callout type=\"info\">\n  Vous ne pouvez pas sélectionner `prisma` et `drizzle` simultanément.\n</Callout>\n\n<Form />\n\n<Callout type=\"warning\">\n  Certaines fonctionnalités peuvent ne pas fonctionner à moins que vous créer un\n  fichier d'environnement\n</Callout>\n"
  },
  {
    "path": "www/src/pages/fr/faq.mdx",
    "content": "---\ntitle: FAQ\ndescription: Foire aux questions sur Create T3 App\nlayout: ../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nVoici quelques questions fréquemment posées sur Create T3 App.\n\n## Et après? Comment faire une application avec ça ?\n\nNous essayons de garder ce projet aussi simple que possible, afin que vous puissiez commencer uniquement avec la configuration que nous avons fait pour vous, et ajouter des éléments supplémentaires plus tard, lorsqu'ils deviennent nécessaires.\n\nSi vous n'êtes pas familier avec les différentes technologies utilisées dans ce projet, veuillez vous référer aux docs respectives. Si vous êtes toujours dans le brouillard, veuillez rejoindre notre [Discord](https://t3.gg/discord) et demander de l'aide.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## Quelles ressources d'apprentissage sont actuellement disponibles?\n\nBien que les ressources répertoriées ci-dessous soient parmi les meilleures qui existent pour la stack T3, la communauté (et [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) vous recommandent de commencer à utiliser la stack et d'apprendre en cours de route en codant avec elle.\n\nSi vous envisagez Create T3 App, il y a de fortes chances que vous ayez déjà utilisé certaines parties de la stack. Alors pourquoi ne pas simplement plonger la tête la première et apprendre les autres parties pendant que vous créez quelque chose ?\n\nMaintenant, nous comprenons que cette voie ne fonctionne pas pour tout le monde. Donc, si vous avez l'impression d'avoir suivi les recommandations et que vous êtes toujours en manque de ressources, ou si vous n'êtes tout simplement pas sûr de le faire vous-même et/ou si vous vous sentez dépassé par la stack, consultez ces tutoriels géniaux sur Create T3 App :\n\n### Articles\n\n- [Créez une application complète avec Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [Un premier aperçu de Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrer votre application T3 vers un Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Intégrer Stripe dans votre application T3](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Vidéos\n\n- [Créez un clone Twitter avec la stack T3 - tRPC, Next.js, Prisma, Tailwind et Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Créez un blog avec la stack T3 - tRPC, TypeScript, Next.js, Prisma et Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Créer une application de chat en direct avec la stack T3 - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [La stack T3 - Comment nous l'avons créez](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [Un aperçu de Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Pourquoi y a-t-il des fichiers `.js` dans le projet ?\n\nConformément à [T3-Axiom #3](/fr/introduction#la-sécurité-de-typage-nest-pas-facultative), nous traitons la sécurité de typage comme un citoyen de première classe. Malheureusement, tous les frameworks et plugins ne prennent pas en charge TypeScript, ce qui signifie que certains des fichiers de configuration doivent être des fichiers `.js`.\n\nNous essayons de souligner que ces fichiers sont JavaScript pour une raison, en déclarant explicitement le type de chaque fichier (`cjs` ou `mjs`) en fonction de ce qui est pris en charge par la librairie par laquelle il est utilisé. De plus, tous les fichiers `js` de ce projet sont vérifiés systématiquement à l'aide d'un commentaire `@ts-check` en début de fichier.\n\n## J'ai du mal à ajouter i18n à mon application. Y a-t-il une référence que je peux utiliser?\n\nNous avons décidé de ne pas inclure i18n par défaut dans `create-t3-app` car c'est un sujet très opiniâtre et il existe de nombreuses façons de l'implémenter.\n\nCependant, si vous avez du mal à l'implémenter et que vous souhaitez voir un projet de référence, nous avons un [repo de référence](https://github.com/juliusmarminge/t3-i18n) qui montre comment vous pouvez ajouter i18n à une application T3 en utilisant [next-i18next](https://github.com/i18next/next-i18next).\n\n## Pourquoi utilisons-nous `/pages` et non `/app` de Next.js 13 ?\n\nSelon [T3-Axiom #2](/fr/introduction#etre-responsable), nous aimons les trucs à la pointe de la technologie, mais nous apprécions la stabilité, l'entièreté de votre routeur est difficile à porter, [pas le meilleur lieu pour les technologies de pointes](https://youtu.be/mnwUbtieOuI?t=1662). Bien que `/app` soit [un aperçu du futur](https://youtu.be/rnsC-12PVlM?t=818), il n'est pas prêt pour la production ; L'API est en version bêta et devrait subir des modifications avec changements majeurs pouvant casser le code.\n\n<Callout type=\"info\">\n  Pour obtenir une liste des fonctionnalités prises en charge, planifiées et en cours de développement dans le répertoire `/app`, consultez la [documentation de la beta de Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n</Callout>\n"
  },
  {
    "path": "www/src/pages/fr/folder-structure-pages.mdx",
    "content": "---\ntitle: Structure des dossiers (Pages)\ndescription: Structure des dossiers d'une application T3 nouvellement créée\nlayout: ../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nVeuillez sélectionner vos packages pour voir la structure des dossiers d'une application nouvellement créée avec ces sélections. Plus bas, vous trouverez une description de chaque entrée.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nLe dossier `prisma` contient le fichier `schema.prisma` qui est utilisé pour configurer la connexion à la base de données et le schéma de la base de données. C'est également l'emplacement où stocker les fichiers de migration et/ou les scripts de départ, s'ils sont utilisés. Voir [Utilisation de Prisma](/fr/usage/prisma) pour plus d'informations.\n\n</div>\n<div>\n\n### `public`\n\nLe dossier \"public\" contient des fichiers statiques qui sont servis par le serveur Web. Le fichier `favicon.ico` en est un exemple.\n\n</div>\n<div>\n\n### `src/env`\n\nUtilisé pour la validation des variables d'environnement et les définitions de types - voir [Variables d'environnement](usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nLe dossier `pages` contient toutes les pages de l'application Next.js. Le fichier `index.tsx` dans le répertoire racine de `/pages` est la page d'accueil de l'application. Le fichier `_app.tsx` est utilisé pour envelopper l'application avec des fournisseurs. Voir [Documentation Next.js](https://nextjs.org/docs/basic-features/pages) pour plus d'informations.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nLe dossier `api` contient toutes les routes API de l'application Next.js. Le fichier `examples.ts` (avec Prisma) contient un exemple de route qui utilise la fonctionnalité [Next.js API route](https://nextjs.org/docs/api-routes/introduction) avec Prisma. Le fichier `restricted.ts` (avec Next-Auth) contient un exemple de route qui utilise la fonctionnalité [Next.js API route](https://nextjs.org/docs/api-routes/introduction) et est protégé par [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nLe fichier `[...nextauth].ts` est la route d'authentification NextAuth.js. Il est utilisé pour gérer les demandes d'authentification. Voir [utilisation de NextAuth.js](usage/next-auth) pour plus d'informations sur NextAuth.js, et la [documentation Next.js sur les routes dynamiques](https://nextjs.org/docs/routing/dynamic-routes) pour plus d'informations sur les routes fourre-tout / slug.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nLe fichier `[trpc].ts` est le point d'entrée de l'API tRPC. Il est utilisé pour gérer les requêtes tRPC. Voir [utilisation de tRPC](usage/trpc#-pagesapitrpctrpcts) pour plus d'informations sur ce fichier, et la [documentation Next.js sur les routes dynamiques](https://nextjs.org/docs/routing/dynamic-routes) pour plus d'informations sur les routes fourre-tout / slug.\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nLe dossier `server` est utilisé pour séparer clairement le code côté serveur du code côté client.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n### `src/server/auth.ts`\n\nContient des utilitaires d'authentification tels que la récupération de la session de l'utilisateur côté serveur. Voir [utilisation de NextAuth.js](usage/next-auth#utilisation-avec-trpc) pour plus d'informations.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nLe fichier `db.ts` est utilisé pour instancier le client Prisma au niveau global. Voir [Utilisation de Prisma](usage/prisma#prisma-client) et [meilleures pratiques pour utiliser Prisma avec Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) pour plus d'informations.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nLe dossier `api` contient le code côté serveur de tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nLe dossier `routers` contient tous vos sous-routeurs tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nLe fichier `example.ts` est un exemple de routeur tRPC utilisant le helper `publicProcedure` pour montrer comment créer une route tRPC publique.\n\nEn fonction des packages choisis, ce routeur contient plus ou moins de routes pour démontrer au mieux l'utilisation à vos besoins.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nLe fichier `trpc.ts` est le fichier de configuration principal de votre back-end tRPC. Ici, vous trouverez:\n\n1. La définissons du contexte utilisé dans les requêtes tRPC. Voir [utilisation de tRPC](usage/trpc#-serverapitrpcts) pour plus d'informations.\n2. Le helper de procédure d'exportation. Voir [utilisation de tRPC](usage/trpc#-serverapitrpcts) pour plus d'informations.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nLe fichier `root.ts` est utilisé pour fusionner les routeurs tRPC et les exporter en tant que routeur unique, ainsi que la définition du type de routeur. Voir [utilisation du tRPC](usage/trpc#-serverapirootts) pour plus d'informations.\n\n</div>\n<div>\n\n### `src/styles`\n\nLe dossier `styles` contient les styles globaux de l'application.\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/types`\n\nLe dossier `types` est utilisé pour stocker les types réutilisés ou les déclarations de type.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/types/next-auth.d.ts`\n\nLe fichier `next-auth.d.ts` est utilisé pour étendre le type de session par défaut NextAuth afin d'inclure l'ID utilisateur. Voir [utilisation de NextAuth.js](usage/next-auth#inclusion-de-userid-dans-la-session) pour plus d'informations.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nLe dossier `utils` est utilisé pour stocker les fonctions utilitaires couramment réutilisées.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nLe fichier `api.ts` est le point d'entrée frontal de tRPC. Voir [utilisation de tRPC](usage/trpc#-utilsapits) pour plus d'informations.\n\n</div>\n<div>\n\n### `.env`\n\nLe fichier `.env` est utilisé pour stocker les variables d'environnement. Voir [Variables d'environnement](usage/env-variables) pour plus d'informations. Ce fichier ne doit **pas** être commité dans l'historique de git.\n\n</div>\n<div>\n\n### `.env.example`\n\nLe fichier `.env.example` montre des exemples de variables d'environnement basées sur les librairies choisies. Ce fichier doit être commité dans l'historique de git.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nLe fichier `.eslintrc.cjs` est utilisé pour configurer ESLint. Voir la [documentation de ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) pour plus d'informations.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nLe fichier `next-env.d.ts` garantit que les types Next.js sont récupérés par le compilateur TypeScript. **Vous ne devez pas le supprimer ou le modifier car il peut changer à tout moment.** Voir la [documentation de Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) pour plus informations.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nLe fichier `next.config.mjs` est utilisé pour configurer Next.js. Voir la [documentation de Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) pour plus d'informations. Remarque : L'extension .mjs est utilisée pour autoriser les importations ESM.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nLe fichier `postcss.config.js` est utilisé pour l'utilisation de Tailwind PostCSS. Voir la [documentation de Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) pour plus d'informations.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nLe fichier `prettier.config.mjs` est utilisé pour configurer Prettier afin d'inclure le prettier-plugin-tailwindcss pour le formatage des classes CSS Tailwind. Consultez l'[article de blog Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) pour plus d'informations.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nLe fichier `tsconfig.json` est utilisé pour configurer TypeScript. Certaines valeurs autres que celles par défaut, telles que le `strict mode`, ont été activées pour garantir la meilleure utilisation de TypeScript pour Create T3 App et ses librairies. Voir la [documentation de TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) ou [Utilisation de TypeScript](usage/typescript) pour plus d'informations.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/fr/installation.mdx",
    "content": "---\ntitle: Installation\ndescription: Instructions d'installation pour Create T3 App\nlayout: ../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nPour configurer une application à l'aide de `create-t3-app`, exécutez l'une des trois commandes suivantes et répondez aux questions de l'invite de commande :\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nUne fois votre application configurée, consultez les [premières étapes](/fr/usage/first-steps) pour démarrer sur votre nouvelle application.\n\n## Utilisation avancée\n\n| Option            | Description                                                                                     |\n| ----------------- | ----------------------------------------------------------------------------------------------- |\n| `[dir]`           | Inclure un argument de répertoire avec un nom pour le projet                                    |\n| `--noGit`         | Dites explicitement à la CLI de ne pas initialiser un nouveau dépôt git dans le projet          |\n| `-y`, `--default` | Contourner la CLI et démarrer une nouvelle application t3 avec toutes les options sélectionnées |\n| `--noInstall`     | Générer un projet sans installer de dépendances                                                 |\n\n## Utilisation expérimentale\n\nPour notre CI, nous avons des options expérimentales qui vous permettent de configurer n'importe quelle application sans aucun invite. Si ce cas d'utilisation s'applique à vous, vous pouvez utiliser ces options. Veuillez noter que ces options sont expérimentales et peuvent changer à l'avenir sans suivre la version de Semver.\n\n| Flag         | Description                                     |\n| ------------ | ----------------------------------------------- |\n| `--CI`       | Faites savoir à la CLI que vous êtes en mode CI |\n| `--trpc`     | Inclure tRPC dans le projet                     |\n| `--prisma`   | Inclure Prisma dans le projet                   |\n| `--nextAuth` | Inclure NextAuth.js dans le projet              |\n| `--tailwind` | Inclure Tailwind CSS dans le projet             |\n\n<Callout type=\"warning\">\n  Si vous ne fournissez pas l'option \"CI\", le reste de ces options n'a aucun\n  effet.\n</Callout>\nVous n'avez pas besoin de vous désinscrire explicitement des packages que vous ne\nvoulez pas.Cependant, si vous préférez être explicite, vous pouvez passer `false`,\npar exemple `--nextAuth false`.\n\n### Exemple\n\nCe qui suit configurera une application T3 avec tRPC et Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/fr/introduction.md",
    "content": "---\ntitle: Introduction\ndescription: Introduction à la stack T3\nlayout: ../../layouts/docs.astro\nlang: fr\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"La meilleure stack pour votre prochain projet\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## La stack T3\n\nLa _\"T3 Stack\"_ est une stack de développement Web créée par [Theo](https://twitter.com/t3dotgg) axée sur la simplicité, la modularité et la sécurité de typage complète.\n\nLes éléments principaux sont [**Next.js**](https://nextjs.org/) et [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) est presque toujours inclus. Si vous faites quelque chose qui ressemble a du backend, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/) et [**NextAuth .js**](https://next-auth.js.org/) sont également d'excellents ajouts.\n\nVous avez peut-être remarqué qu'il y a beaucoup… beaucoup de pièces. C'est par conception. Échangez les pièces selon vos besoins - cette stack est modulaire à la base :)\n\n## Alors... qu'est-ce que create-t3-app ? Un modèle?\n\n`create-t3-app` est une CLI conçue par des développeurs chevronnés de T3 Stack pour rationaliser la configuration d'une application modulaire T3 Stack. Cela signifie que chaque pièce est facultative et que le \"modèle\" est généré en fonction de vos besoins spécifiques.\n\nAprès d'innombrables projets et de nombreuses années sur cette technologie, nous avons beaucoup d'opinions et d'idées. Nous avons fait de notre mieux pour les encoder dans cette CLI.\n\nCe n'est **PAS** un modèle tout compris. Nous **attendons** que vous apportiez vos propres librairies qui répondent aux besoins de **VOTRE** application. Bien que nous ne souhaitions pas prescrire de solutions à des problèmes plus spécifiques tels que la gestion de l'état et le déploiement, nous [avons quelques recommandations répertoriées ici](/fr/other-recs).\n\n## T3 Axioms\n\nNous allons être francs - c'est un _projet opiniâtre_. Nous partageons une poignée de croyances fondamentales autour de la création et nous les traitons comme la base de nos décisions.\n\n### Résoudre des problèmes\n\nIl est facile de tomber dans le piège de \"tout ajouter\" - nous ne voulons explicitement pas le faire. Tout ce qui est ajouté à \"create-t3-app\" devrait résoudre un problème spécifique qui existe dans les technologies de base incluses. Cela signifie que nous n'ajouterons pas des choses comme des librairies d'état (`zustand`, `redux`) mais nous ajouterons des choses comme NextAuth.js et intégrerons Prisma et tRPC pour vous.\n\n### Être responsable\n\nNous aimons notre technologie de pointe. La vitesse et honnêtement le fun qu'apportent de nouvelles choses est vraiment cool. Nous pensons qu'il est important d'être responsable, en utilisant des technologies plus risquées dans les parties les moins risquées. Cela signifie que nous ne parierions pas ⛔️ sur une nouvelle technologie de base de données risquée (SQL est génial !). Mais nous parions volontiers ✅ sur tRPC car ce ne sont que des fonctions triviales à déplacer.\n\n### La sécurité de typage n'est pas facultative\n\nL'objectif déclaré de Create T3 App est de fournir le moyen le plus rapide de démarrer une nouvelle application Web **typesafe** complète. Nous prenons la sécurité des caractères au sérieux dans ces parties, car elle améliore notre productivité et nous aide à expédier moins de bogues. Toute décision qui compromet la nature typesafe de Create T3 App est une décision qui doit être prise dans un projet différent.\n"
  },
  {
    "path": "www/src/pages/fr/other-recs.md",
    "content": "---\ntitle: Autres recommandations\ndescription: Librairies et services que nous recommandons pour de nombreux projets\nlayout: ../../layouts/docs.astro\nlang: fr\n---\n\nNous reconnaissons que les librairies incluses dans `create-t3-app` ne résolvent pas tous les problèmes. Bien que nous vous encourageons à commencer votre projet avec les éléments que nous fournissons, il viendra un moment où vous devrez ajouter d'autres librairies. Vous seul pouvez savoir ce dont votre projet a besoin, mais voici certaines choses que nous recommandons fréquemment.\n\nCe sont des recommandations de contributeurs individuels de Create T3 App et ne doivent pas être considérées comme des approbations \"officielles\" par l'équipe de Create T3 App ou T3-OSS. _**Veuillez faire vos propres recherches, surtout avant de vous engager dans des services payants**_.\n\n## State Management\n\n_**Note de l'éditeur**_: Les librairies de state management peuvent être excellentes, mais ne sont pas souvent nécessaires. Les hooks de React Query-tRPC devraient pouvoir prendre en charge le state de votre serveur. Pour le state du client, commencez par `useState` de React et utilisez l'une de ces options lorsque vous en avez besoin de plus.\n\n### Zustand\n\n**Pour ne plus jamais utiliser Redux**\n\nLe \"Redux moderne et simple\" dont vous ne saviez pas avoir besoin. On peut toujours faire confiance à [Poimandres](https://github.com/pmndrs). Vous pouvez tout créer, des applications d'appel vidéo aux jeux en passant par les serveurs avec cette petite librairie.\n\n- [Page d'accueil Zustand](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Pour ne plus jamais utiliser Context**\n\nPour une approche plus atomique, Jotai est difficile à battre. Toujours par [Poimandres](https://github.com/pmndrs), Jotai vous permet de définir des singletons qui ressemblent à un useState global. Une excellente option pour les comportements avec état qui n'ont pas encore besoin d'une machine d'état.\n\n- [Page d'accueil Jotai](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## Librairies de composants\n\nLa plupart des applications ont besoin de la même poignée de composants - boutons, menus déroulants, modaux, etc. Ces librairies fournissent d'excellents composants accessibles que vous pouvez utiliser et personnaliser à votre guise.\n\n### Librairies de composants sans style\n\nAussi connues sous le nom de librairies headless, elles fournissent d'excellents composants sans style et accessibles que vous pouvez personnaliser à votre guise. Voici quelques recommandations.\n\n- [Radix UI](https://www.radix-ui.com/) vous offre un ensemble puissant de primitives pratiques et accessibles que vous pouvez styliser avec du CSS vanilla ou Tailwind.\n\n- [Headless UI](https://headlessui.com/) créé par l'équipe Tailwind CSS fournit également des composants accessibles sans style qui s'intègrent de manière transparente avec Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) fournit des primitives d'interface utilisateur accessibles pour votre design. Leur composant Date Picker est de premier plan.\n\n### Librairies de composants stylisés\n\n**Pour quand vous voulez juste que votre application ait l'air OK**\n\nParfois, vous créez un projet où vous voulez juste que l'interface utilisateur ait l'air décente. Pour les tableaux de bord d'administration et d'autres projets similaires, n'importe laquelle de ces librairies de composants fera le travail.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n\n### Class Variance Authority\n\n**Pour créer des librairies d'interface utilisateur**\n\nCréez de manière déclarative une librairie d'interface utilisateur avec différentes variantes de couleur, de taille, etc. Lorsque votre projet atteint une échelle où vous souhaitez un ensemble normé de composants d'interface utilisateur avec plusieurs variantes utilisant Tailwind CSS, CVA est un excellent outil.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Animations\n\nLorsque vous avez besoin d'animations dans votre application, voici nos recommandations.\n\n### AutoAnimate\n\n**Pour les animations avec une seule ligne de code**\n\nLa plupart des librairies d'animation essaient de satisfaire tous les cas d'utilisation possibles et deviennent lourdes. AutoAnimate est un outil sans configuration qui vous apportera une amélioration significative de l'expérience utilisateur sans effort supplémentaire du développeur.\n\n- [Page d'accueil AutoAnimate](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [Extrait de composant AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Pour les animations complexes avec du code déclaratif**\n\nFramer Motion fournit une syntaxe déclarative simple et vous permet d'écrire moins de code pour tout créer, des animations complexes aux gestes uniformes.\n\n- [Page d'accueil Framer Motion](https://framer.com/motion)\n- [Documentation Framer Motion](https://www.framer.com/docs/)\n\n## Déploiements, Infrastructure, Bases de données et CI\n\n### Vercel\n\n**Pour héberger votre application**\n\nVercel a pris l'enfer des déploiements Web et en a fait une intégration GitHub prête à l'emploi. Nous sommes passés à des centaines de milliers d'utilisateurs sans problème. Alimenté par AWS, juste une meilleure interface :)\n\n- [Page d'accueil Vercel](https://vercel.com/)\n- [Guide de déploiement de Create T3 App sur Vercel](/fr/deployment/vercel)\n\n### PlanetScale\n\n**Pour des bases de données sans souci**\n\nPlanetScale est de loin la meilleure \"plate-forme de base de données serverless\" que nous ayons utilisée. À une échelle folle, excellente expérience de développeur et prix fantastiques. Si vous utilisez SQL (et, espérons-le, Prisma), c'est difficile à battre.\n\n- [Page d'accueil PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Pour héberger votre infrastructure**\n\n\"Heroku moderne\". Le moyen le plus simple de faire fonctionner un vrai serveur. Si Vercel et PlanetScale ne suffisent pas, Railway le sera probablement. Faites le pointer sur un dépôt GitHub et c'est parti.\n\n- [Page d'accueil Railway](https://railway.app/)\n\n### Upstash\n\n**Pour du Redis serverless**\n\nNous aimons Prisma et PlanetScale, mais certains projets nécessitent une solution plus performante. Upstash vous permet d'obtenir les performances en mémoire de Redis dans votre projet serverless, sans avoir à gérer l'infrastructure et à faire évoluer vous-même.\n\n- [Page d'accueil Upstash](https://upstash.com/)\n\n### Pusher\n\n**Pour les WebSockets serverless**\n\nSi WebSockets est l'objectif principal de votre projet, vous pouvez envisager un backend plus traditionnel tel que [Fastify](https://www.fastify.io/) (qui [fonctionne également avec tRPC !](https:// trpc.io/docs/v10/fastify)). Mais pour ajouter rapidement des WebSockets à une application T3, Pusher est un excellent choix.\n\n- [Page d'accueil Pusher](https://pusher.com/)\n\n### Soketi\n\nSoketi est une alternative à Pusher, auto-hébergée, simple et rapide. Il est entièrement compatible avec le SDK de Pusher que vous pouvez utiliser pour vous connecter au serveur. Soketi serverless est également en version bêta.\n\n- [Page d'accueil Soketi](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Analytics\n\nLes données utilisateur sont très précieuses lorsque vous créez une application. Voici quelques fournisseurs d'analyse que nous recommandons.\n\n### Plausible\n\nBesoin d'analyses ? Plausible est l'un des moyens les plus rapides de les obtenir. Super minime. Il a même un [plugin, simple, pour Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Page d'accueil Plausible](https://plausible.io/)\n\n### Umami\n\nUmami est une alternative open source à Google Analytics, auto-hébergée, simple, rapide et axée sur la confidentialité. Vous pouvez le déployer très facilement sur Vercel, Railway, etc. Avec PlanetScale comme base de données.\n\n- [Page d'accueil Umami](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n## Autre\n\n### Next Bundle Analyzer\n\nIl peut parfois être difficile de déterminer ce qui sera inclus dans la sortie de votre application générée. Next Bundle Analyzer est un moyen simple de visualiser et d'analyser les bundles JavaScript générés.\n\n- [@next/bundle-analyzer sur npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/fr/t3-collection.mdx",
    "content": "---\ntitle: Collection T3\ndescription: Projets open source sympas et d'entreprises utilisant la stack T3\nlayout: ../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nVous avez réalisé un projet à l'aide de la stack T3 et souhaitez le partager ? Ajoutez-le à la liste !\n\n## Applications Open Source créées à l'aide de la stack T3\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\n<OpenSourceAppList linkIntl=\"Lien\"/>\n\n## Entreprises utilisant la stack T3\n\nNous aimerions connaître les entreprises qui utilisent la stack T3 pour leurs applications. Votre entreprise utilise la stack T3 et souhaite la partager ? Ajoutez-le à la liste !\n\n<CompanyList linkIntl=\"Lien\"/>\n\n<Callout type=\"tip\">\n  Vous avez un projet sympa utilisant la stack T3 ? Faites une [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) et ajoutez-la ici !\n</Callout>\n"
  },
  {
    "path": "www/src/pages/fr/usage/env-variables.mdx",
    "content": "---\ntitle: Variables d'environnement\ndescription: Débuter avec Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App utilise son propre package [@t3-oss/env-nextjs](https://env.t3.gg), ainsi que [zod](https://zod.dev) en interne pour valider les variables d'environnement à l'exécution _et_ au moment du build, en fournissant une logique simple dans `src/env.js`.\n\n## env.js\n\n_Résumé : Si vous voulez ajouter une nouvelle variable d'environnement, vous devez ajouter un validateur pour celle-ci dans `src/env.js`, puis ajouter la paire CLEF/VALEUR dans `.env`._\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env introduit un nouveau concept à travers la fonction `createEnv`, qui est responsable de la création du schéma et inclura la logique de validation principale pour les variables d'environnement côté client et côté serveur.\n\n<Callout type=\"info\">\n  Pour plus d'informations sur le fonctionnement interne de `createEnv`,\n  consultez la documentation de [T3 Env](https://env.t3.gg/docs/introduction).\n</Callout>\n\n## Utilisation de variables d'environnement\n\nLorsque vous souhaitez utiliser vos variables d'environnement, vous pouvez les importer depuis `env.js` et les utiliser comme vous le feriez normalement. Si vous l'importez côté client et essayez d'accéder à une variable d'environnement du côté serveur, vous obtiendrez une erreur d'exécution.\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` is fully typesafe and provides autocompletion\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ This will throw a runtime error\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ This is fine\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nPuisque le fichier `.env` par défaut n'est pas enregistré dans le dépoôt de version, nous avons inclus un fichier `.env.example` dans lequel vous pouvez éventuellement conserver une copie de votre fichier `.env` sans les secrets. Cela n'est pas obligatoire, mais nous recommandons de maintenir le fichier exemple à jour pour faciliter autant que possible le démarrage des nouveaux contributeurs avec leur environnement.\n\nCertains frameworks et outils de build, comme Next.js, suggèrent de stocker les secrets dans un fichier `.env.local` et de commit les fichiers `.env` dans votre projet. Ceci n'est pas recommandé, car cela pourrait rendre facile de commit accidentellement des secrets dans votre projet. Au lieu de cela, nous recommandons de stocker les secrets dans le fichier `.env`, de rajouter votre fichier `.env` dans le fichier `.gitignore` et de ne commit que les fichiers `.env.example` dans votre projet.\n\n## Ajout des variables d’environnement\n\nPour vous assurer que votre build ne se termine jamais sans les variables d'environnement nécessaires au projet, vous devriez ajouter de nouvelles variables d'environnement dans **deux** emplacements:\n\n📄 `.env`: Entrez votre variable d'environnement comme vous le feriez normalement dans un fichier `.env`, c'est-à-dire `CLEF=VALEUR`\n\n📄 `env.js`: Ajoutez la logique de validation appropriée pour les variables d'environnement en définissant un schéma Zod à l'intérieur de `createEnv` pour chacune d'entre elles, par exemple `CLEF: z.string()`. En plus de cela, assurez-vous de la déstructuration dans l'option `runtimeEnv`, par exemple : `CLEF: process.env.CLEF`\n\n<Callout type=\"info\">\n  Pourquoi ai-je besoin de déstructurer la variable d'environnement dans\n  `runtimeEnv` ? Cela est dû à la façon dont Next.js rassemble les variables\n  d'environnement dans certains contextes d'exécution. En les déstructurant\n  manuellement, vous vous assurez que la variable ne sera jamais supprimée du\n  bundle.\n</Callout>\n\nEn option, vous pouvez également maintenir à jour le fichier `.env.example`:\n\n📄 `.env.example`: Entrez votre variable d'environnement, mais assurez-vous de ne pas inclure la valeur si elle est secrète, c'est-à-dire `CLEF=VALUE` ou `CLEF=`\n\n### Exemple\n\n_Je veux ajouter le jeton de l’API Twitter en tant que variable d’environnement côté serveur_\n\n1. Ajouter la variable d'environnement dans `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Ajouter la variable d'environnement dans `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n  runtimeEnv: {\n    // ...\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n\n3. facultatif : ajoutez la variable d'environnement à `.env.example`, mais n'incluez pas le jeton\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/fr/usage/first-steps.md",
    "content": "---\ntitle: Premiers pas\ndescription: Premiers pas avec votre nouvelle application T3\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\nVous venez de créer une nouvelle application T3 et vous êtes prêt à démarrer. Voici le strict minimum pour que votre application puisse fonctionner.\n\n## Base de données\n\nSi votre application inclut Prisma, assurez vous de lancer la commande `npx prisma db push` depuis la racine de votre application\nCette commande va synchroniser votre schéma Prisma avec votre base de données et va générer les types TypeScript sur lequel se base le client Prisma. Notez que vous devez redémarrer le serveur TypeScript afin qu'il puisse détecter les nouveaux types générés.\n\n## Authentification\n\nSi votre application inclut NextAuth.js, nous vous aidons à démarrer avec le `DiscordProvider`. C'est l'un des fournisseurs les plus simples proposés par NextAuth.js, mais il nécessite encore un peu de configuration initiale de votre part.\n\nBien sûr, si vous préférez utiliser un autre fournisseur d'authentification, vous pouvez également utiliser l'un des [nombreux fournisseurs](https://next-auth.js.org/providers/) proposés par NextAuth.js.\n\n1. Vous aurez besoin d'un compte Discord, créez-en un si vous ne l'avez pas déjà fait.\n2. Accédez à https://discord.com/developers/applications et cliquez sur \"New Application\" dans le coin supérieur droit. Nommez votre application et acceptez les conditions d'utilisation.\n3. Une fois votre application créée, accédez à \"Settings → OAuth2 → General\".\n4. Copiez le \"Client ID\" et ajoutez-le à votre `.env` en tant que `AUTH_DISCORD_ID`.\n5. Cliquez sur \"Reset Secret\", copiez le nouveau secret et ajoutez-le à votre `.env` en tant que `DISCORD CLIENT_SECRET`.\n6. Cliquez sur \"Add Redirect\" et saisissez `http://localhost:3000/api/auth/callback/discord`.\n   - Pour le déploiement en production, suivez les étapes précédentes pour créer une autre application Discord, mais cette fois remplacez `http://localhost:3000` par l'URL vers laquelle vous déployez.\n7. Sauvegarder les modifications.\n\nVous devriez maintenant pouvoir vous connecter.\n\n## Prochaines étapes\n\n- Si votre application inclut tRPC, consultez `src/pages/index.tsx` et `src/server/api/routers/post.ts` pour voir comment fonctionnent les requêtes tRPC.\n- Consultez la documentation Create T3 App, ainsi que la documentation des packages inclus dans votre application.\n- Rejoignez notre [Discord](https://t3.gg/discord) et donnez-nous une étoile sur [GitHub](https://github.com/t3-oss/create-t3-app) ! :)\n"
  },
  {
    "path": "www/src/pages/fr/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Utilisation\",\n  layout: \"docs\",\n  description:\n    \"Apprenez comment utiliser les différentes technologies de la stack T3.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/fr/usage/next-auth.mdx",
    "content": "---\ntitle: NextAuth.js\ndescription: Utilisation de NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: fr\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nLorsque vous souhaitez un système d'authentification dans votre application Next.js, NextAuth.js est une excellente solution pour apporter la sécurité sans avoir à le construire vous-même. Il vient avec une longue liste de fournisseurs pour ajouter rapidement de l'authentification OAuth et fournit des adaptateurs pour de nombreuses bases de données et ORM.\n\n## Context Provider\n\nDans le point d'entrée de votre application, vous verrez que votre application est encapsulée dans un [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider) :\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nCe fournisseur de contexte permet à votre application d'accéder aux données de session de n'importe où dans votre application, sans avoir à les transmettre en tant que props :\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Handle unauthenticated state, e.g. render a SignIn component\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Récupérer la session côté serveur\n\nParfois, vous souhaiterez demander la session côté serveur. Pour ce faire, prérécupérez la session à l'aide du helper `getServerAuthSession` fournie par `create-t3-app` et transmettez-le au client à l'aide de `getServerSideProps` :\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTE: `session` wont have a loading state since it's already prefetched on the server\n\n  ...\n}\n```\n\n## Inclusion de `user.id` dans la Session\n\nCreate T3 App est configuré pour utiliser le [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) dans la configuration NextAuth.js pour inclure l'ID de l'utilisateur dans le objet \"session\".\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nCeci est couplé avec un fichier de déclaration de type pour s'assurer que `user.id` est typé lors de l'accès à l'objet `session`. En savoir plus sur [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) sur la documentation de NextAuth.js.\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nLe même modèle peut être utilisé pour ajouter toute autre donnée à l'objet `session`, comme un champ `role`, mais **ne doit pas être utilisé à mauvais escient pour stocker des données sensibles** sur le client.\n\n## Utilisation avec tRPC\n\nLorsque vous utilisez NextAuth.js avec tRPC, vous pouvez créer des procédures réutilisables et protégées à l'aide de [middleware](https://trpc.io/docs/v10/middlewares). Cela vous permet de créer des procédures accessibles uniquement aux utilisateurs authentifiés. `create-t3-app` configure tout cela pour vous, vous permettant d'accéder facilement à l'objet de session dans des procédures authentifiées.\n\nCela se fait en deux étapes :\n\n1. Récupérez la session à partir des en-têtes de requête à l'aide de la fonction [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). L'avantage d'utiliser `getServerSession` au lieu de `getSession` est qu'il s'agit d'une fonction côté serveur uniquement et qu'elle ne déclenche pas d'appels de récupération inutiles. `create-t3-app` crée une fonction d'assistance qui résume cette API particulière.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await getServerSession(ctx.req, ctx.res, nextAuthOptions);\n};\n```\n\nEn utilisant cette fonction d'assistance, nous pouvons récupérer la session et la transmettre au contexte tRPC :\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Créez un middleware tRPC qui vérifie si l'utilisateur est authentifié. Nous utilisons ensuite le middleware dans une `protectedProcedure`. Tout appelant à ces procédures doit être authentifié, sinon une erreur sera générée qui pourra être gérée de manière appropriée par le client.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nL'objet de session est une représentation légère et minimale de l'utilisateur et ne contient que quelques champs. Lorsque vous utilisez les `protectedProcedures`, vous avez accès à l'identifiant de l'utilisateur qui peut être utilisé pour extraire plus de données de la base de données.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Utilisation avec Prisma\n\nFaire fonctionner NextAuth.js avec Prisma nécessite beaucoup de [configuration initiale](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` gère tout cela pour vous, et si vous sélectionnez à la fois Prisma et NextAuth.js, vous obtiendrez un système d'authentification entièrement fonctionnel avec tous les modèles requis préconfigurés. Nous démarrons votre application avec un fournisseur Discord OAuth préconfiguré, que nous avons choisi car c'est l'un des plus faciles à démarrer - fournissez simplement vos jetons dans le `.env` et vous êtes prêt à partir. Cependant, vous pouvez facilement ajouter d'autres fournisseurs en suivant la [documentation NextAuth.js](https://next-auth.js.org/providers/). Notez que certains fournisseurs exigent que des champs supplémentaires soient ajoutés à certains modèles. Nous vous recommandons de lire la documentation du fournisseur que vous souhaitez utiliser pour vous assurer que vous disposez de tous les champs obligatoires.\n\n### Ajout de nouveaux champs à vos modèles\n\nLors de l'ajout de nouveaux champs à l'un des modèles `User`, `Account`, `Session` ou `VerificationToken` (il vous suffira très probablement de modifier le modèle `User` seulement), vous devez garder à l'esprit que l'[Adaptateur Prisma](https://next-auth.js.org/adapters/prisma) crée automatiquement des champs sur ces modèles lorsque de nouveaux utilisateurs s'inscrivent et se connectent. Par conséquent, lors de l'ajout de nouveaux champs à ces modèles, vous devez leur fournir des valeurs par défaut, car l'adaptateur n'a pas connaissance de ces champs.\n\nSi, par exemple, vous souhaitez ajouter un `role` au modèle `User`, vous devrez fournir une valeur par défaut au champ `role`. Cela se fait en ajoutant une valeur `@default` au champ `role` dans le modèle `User` :\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Utilisation avec le middleware Next.js\n\nUtilisation de NextAuth.js avec le middleware Next.js [nécessite l'utilisation de la stratégie de session JWT](https://next-auth.js.org/configuration/nextjs#caveats) pour l'authentification. En effet, le middleware ne peut accéder au cookie de session que s'il s'agit d'un JWT. Par défaut, Create T3 App est configuré pour utiliser la stratégie de base de données **default**, en combinaison avec Prisma comme adaptateur de base de données.\n\n<Callout type=\"warning\">\n  L'utilisation de sessions en base de données est l'approche recommandée et\n  vous devriez vous informer sur les JWT (JSON Web Token) avant de passer à la\n  stratégie de session JWT, et ce, afin d'éviter tout problème de sécurité.\n</Callout>\n\nAprès avoir basculé vers la stratégie de session JWT, assurez-vous de mettre à jour le callback `session` dans `src/server/auth.ts`. L'objet `user` sera `undefined`. À la place, récupérez l'identifiant de l'utilisateur à partir de l'objet `token`.\nEx.:\n\n```diff:server/auth.ts\n  export const authOptions: NextAuthOptions = {\n+   session: {\n+     strategy: \"jwt\",\n+   },\n    callbacks: {\n-     session({ session, user }) {\n+     session({ session, token }) {\n-       if (session.user) {\n+       if (session.user && token.sub) {\n-         session.user.id = user.id;\n+         session.user.id = token.sub;\n        }\n        return session;\n      }\n    },\n  };\n```\n\n## Configuration du DiscordProvider par défaut\n\n1. Rendez-vous dans [la section Applications du portail des développeurs Discord](https://discord.com/developers/applications), et cliquez sur \"New Application\"\n1. Dans le menu des paramètres, allez dans \"OAuth2 => General\"\n\n- Copiez l'ID client et collez-le dans `AUTH_DISCORD_ID` dans `.env`.\n- Sous Client Secret, cliquez sur \"Reset Secret\" et copiez cette chaîne de caractères dans `DISCORD CLIENT_SECRET` dans `.env`. Soyez prudent car vous ne pourrez plus voir ce secret et le réinitialiser entraînera l'expiration du secret existant.\n- Cliquez sur \"Add Redirect\" et collez `<app url>/api/auth/callback/discord` (exemple pour le développement local : <code class=\"break-all\">http://localhost:3000/api/auth/rappel/discord</code>)\n- Enregistrez vos modifications\n- Il est possible, mais non recommandé, d'utiliser la même application Discord pour le développement et la production. Vous pouvez également envisager [moquer le fournisseur](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) pendant le développement.\n\n## Ressources utiles\n\n| Ressource                         | Lien                                    |\n| --------------------------------- | --------------------------------------- |\n| Documentation NextAuth.js         | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/fr/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Utilisation de Next.js\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\nNext.js est un framework backend pour vos applications React.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js est un framework backend\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nDécouvrez [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw) pour mieux comprendre ce qu'est Next.js et son fonctionnement.</p>\n\n## Pourquoi devrais-je l'utiliser ?\n\nNous aimons React. Il a rendu le développement des interfaces utilisateur accessible d'une manière que nous n'aurions jamais imaginée auparavant. Cela peut également conduire les développeurs sur des chemins difficiles. Next.js offre une approche légèrement opiniâtre et fortement optimisée pour créer des applications à l'aide de React. Du routage aux définitions d'API en passant par le rendu d'image, nous faisons confiance à Next.js pour guider les développeurs vers de bonnes décisions.\n\nL'association de Next.js avec [Vercel](https://vercel.com/) facilite plus que jamais le développement et le déploiement d'applications Web. Leur offre gratuite est extrêmement généreuse et leurs interfaces sont super intuitives, fournissant une solution pointer-cliquer pour déployer votre site (Nous ❤️ Vercel)\n\n## Get Static/Server Props\n\nUne des caractéristique clé de Next.js sont ses capacités de récupération de données. Nous vous recommandons vivement de lire la [documentation officielle](https://nextjs.org/docs/basic-features/data-fetching) pour comprendre comment utiliser chaque méthode et en quoi elles diffèrent. `getServerSideProps` est généralement déconseillé à moins qu'il n'y ait une bonne raison, car il s'agit d'un appel bloquant qui ralentira votre site. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) est une excellente alternative à `getServerSideProps` lorsque les données sont dynamiques et peuvent être récupérées de manière incrémentielle.\n\n## Ressources utiles\n\n| Ressource                      | Lien                               |\n| ------------------------------ | ---------------------------------- |\n| Next.js Documentation          | https://nextjs.org/docs            |\n| Next.js GitHub                 | https://github.com/vercel/next.js  |\n| Next.js Blog                   | https://nextjs.org/blog            |\n| Next.js Discord                | https://nextjs.org/discord         |\n| Next.js Twitter                | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/fr/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Utilisation de Prisma\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\nPrisma est un ORM pour TypeScript, qui vous permet de définir votre schéma et vos modèles de base de données dans un fichier `schema.prisma`, puis de générer un client de type sécurisé qui peut être utilisé pour interagir avec votre base de données à partir de votre backend.\n\n## Prisma Client\n\nSitué dans `/server/db.ts`, le client Prisma est instancié en tant que variable globale (cette façon est recommandé comme [meilleure pratique](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) par l'équipe de Prisma) et exporté pour être utilisé dans vos routes API. Nous incluons le client Prisma dans le [Context](/fr/usage/trpc#-serverapitrpcts) par défaut et recommandons de l'utiliser au lieu de l'importer séparément dans chaque fichier.\n\n## Schéma\n\nVous trouverez le fichier de schéma Prisma dans `/prisma/schema.prisma`. Ce fichier est l'endroit où vous définissez votre schéma et vos modèles de base de données, et est utilisé lors de la génération du client Prisma.\n\n### Avec NextAuth.js\n\nLorsque vous sélectionnez NextAuth.js en combinaison avec Prisma, le fichier de schéma est généré et configuré pour vous avec les valeurs recommandées pour les modèles `User`, `Session`, `Account` et `VerificationToken`, conformément à la [documentation de NextAuth .js](https://next-auth.js.org/adapters/prisma).\n\n## Base de données par défaut\n\nLa base de données par défaut est une base de données SQLite, idéale pour le développement et la mise en place rapide d'une preuve de concept, mais n'est pas recommandée pour la production. Vous pouvez changer de type de base de données à utiliser en changeant le `provider` dans le bloc `datasource` en `postgresql` ou `mysql`, puis en mettant à jour la chaîne de connexion dans les variables d'environnement pour pointer vers votre base de données.\n\n## Amorçage de votre base de données\n\n[L'amorçage de votre base de données](https://www.prisma.io/docs/guides/database/seed-database) est un excellent moyen de remplir rapidement votre base de données avec des données de test pour vous aider à démarrer. Afin de configurer l'amorçage, vous devrez créer un fichier `seed.ts` dans le répertoire `/prisma`, puis ajouter un script `seed` à votre fichier `package.json`. Vous aurez également besoin d'un exécuteur TypeScript capable d'exécuter le script de départ. Nous recommandons [tsx](https://github.com/esbuild-kit/tsx), qui est un exécuteur TypeScript très performant qui utilise esbuild et ne nécessite aucune configuration ESM, mais `ts-node` ou d'autres exécuteurs le feront fonctionner aussi parfaitement.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nEnsuite, exécutez simplement `pnpm db-seed` (ou `npm`/`yarn`) pour amorcer votre base de données.\n\n## Ressources utiles\n\n| Ressource                          | Lien                                                                                                                                              |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Documentation Prisma               | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                      | https://github.com/prisma/prisma                                                                                                                  |\n| Adaptateur Prisma pour NextAuth.JS | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| Guide de connexion à PlanetScale   | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/fr/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Utilisation de Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\n## Qu'est-ce que Tailwind CSS ?\n\nTailwind CSS est une toute petite librairie CSS, [utilitaire d'abord](https://tailwindcss.com/docs/utility-first), permettant de créer des designs personnalisées, sans le changement de contexte requis par le CSS classique. Il s'agit purement d'une librairie CSS et ne fournit aucun composant ou logique prédéfini, elle offre [un ensemble d'avantages très différent](https://www.youtube.com/watch?v=CQuTF-bkOgc) par rapport à une librairie de composants comme Material UI.\n\nCela rend le CSS incroyablement facile et rapide à écrire, comme le montre l'exemple suivant :\n\nAncien CSS :\n\n1. Écrire du CSS, souvent dans un fichier séparé\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Importer le CSS dans votre composant\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Ajouter la classe à votre code HTML\n\n```jsx\n<div class=\"my-class\">...</div>\n```\n\nÉquivalent dans Tailwind :\n\n1. Écrivez simplement des classes dans votre HTML\n\n```jsx\n<div class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\">\n  ...\n</div>\n```\n\nLorsqu'elle est utilisé avec des composantes React, cela permet de créer des interfaces utilisateur de façon extrêmement puissant et rapidement.\n\nTailwind CSS dispose d'un magnifique système de conception intégré, qui sort de l'oeuf avec une palette de couleurs soigneusement choisie, des modèles de dimensionnement pour des styles tels que la width/height et le padding/margin pour une conception uniforme, ainsi que des points d'arrêt (breaking points) pour créer des mises en page. Ce système de conception peut être personnalisé et étendu pour créer la boîte à outils exacte de styles dont votre projet a besoin.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla mieux connu sous le nom de [mewtru](https://twitter.com/trunarla) a donné une conférence étonnante sur [la construction d'un système de conception à l'aide de Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Utilisation\n\nAssurez-vous d'avoir installé des plugins pour Tailwind dans votre éditeur de code afin d'améliorer votre expérience d'écriture avec Tailwind.\n\n### Extensions et plugins\n\n- [Extension VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [Integration avec JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formatage\n\nLes classes CSS Tailwind peuvent facilement devenir un peu désordonnées, donc un formateur pour les classes est indispensable. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) trie les classes dans [l'ordre recommandé](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) afin que les classes correspondent au bundle CSS généré. Lorsque vous sélectionnez Tailwind dans la ligne de commande, nous l'installons et le configurons pour vous.\n\n### Appliquez les classes de façon conditionnelle\n\nL'ajout conditionnel de classes à l'aide de ternaires peut devenir très compliqué et difficile à lire. Ces packages vous aident à organiser vos classes lorsque vous utilisez une logique conditionnelle.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Ressources utiles\n\n| Ressource                       | Lien                                                     |\n| ------------------------------- | -------------------------------------------------------- |\n| Documentation Tailwind          | https://tailwindcss.com/docs/editor-setup/               |\n| Feuille de triche pour Tailwind | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss             | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Communauté Tailwind             | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord Server         | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube Channel    | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground             | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/fr/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: utilisation de tRPC\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\ntRPC nous permet d'écrire des API fortement typées de bout en bout sans aucune génération de code ni surcharge d'exécution. Il utilise l'inférence de TypeScript pour déduire les définitions de type de votre routeur d'API et vous permet d'appeler vos procédures d'API à partir de votre client avec une sécurité de type complète et une saisie semi-automatique dans votre éditeur de code. Lorsque vous utilisez tRPC, vous sentirez votre frontend et votre backend plus proches que jamais, ce qui permet une expérience de développement exceptionnelle.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>J'ai écrit tRPC pour permettre aux gens de coder plus rapidement en supprimant le besoin d'une couche API traditionnelle, tout en ayant la certitude que nos applications ne se briseront pas lorsque nous itérerons rapidement.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - créateur de tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Comment utiliser tRPC ?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Créer des APIs typesafe facilement avec tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nLe contributeur de tRPC [trashh_dev](https://twitter.com/trashh_dev) a fait [une présentation de malade à la Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) à propos de tRPC. Nous vous recommandons fortement de la regarder si vous ne l'avez pas déjà fait.\n\nAvec tRPC, vous écrivez des fonctions TypeScript sur votre backend, puis vous les appelez depuis votre frontend. Une procédure tRPC simple pourrait ressembler à ceci :\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nIl s'agit d'une procédure tRPC (équivalente à un gestionnaire de route dans un backend traditionnel) qui valide d'abord l'entrée à l'aide de Zod (qui est la même bibliothèque de validation que nous utilisons pour les [variables d'environnement] (./env-variables)) - dans ce cas , il s'assure que l'entrée est une chaîne de caractères. Si l'entrée n'en est pas une, elle renverra une erreur informative à la place.\n\nAprès l'entrée, nous enchaînons une fonction de résolveur qui peut être soit une [query](https://trpc.io/docs/v10/react-queries), [mutation](https://trpc.io/docs/v10/react-mutations), ou une [subscription](https://trpc.io/docs/v10/subscriptions). Dans notre exemple, le résolveur appelle notre base de données à l'aide de notre client [prisma](./prisma) et renvoie l'utilisateur dont l'`id` correspond à celui que nous avons transmis.\n\nVous définissez vos procédures dans des \"routeurs\" qui représentent une collection de procédures liées avec un espace de noms partagé. Vous pouvez avoir un routeur pour les `utilisateurs`, un pour les `posts` et un autre pour les `messages`. Ces routeurs peuvent ensuite être fusionnés en un seul `appRouter` centralisé :\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nNotez que nous n'avons besoin d'exporter que les définitions de type de notre routeur, ce qui signifie que nous n'importons jamais de code serveur sur notre client.\n\nMaintenant appelons la procédure sur notre frontend. tRPC fournit un wrapper pour `@tanstack/react-query` qui vous permet d'utiliser toute la puissance des hooks qu'il fournit, avec l'avantage supplémentaire d'avoir vos appels d'API typés. Nous pouvons appeler nos procédures depuis notre frontend comme ceci :\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nVous remarquerez immédiatement à quel point la saisie semi-automatique et la sécurité de typage sont bonnes. Dès que vous écrivez `trpc.`, vos routeurs s'affichent en saisie semi-automatique et lorsque vous sélectionnez un routeur, ses procédures s'affichent également. Vous obtiendrez également une erreur TypeScript si votre entrée ne correspond pas au validateur que vous avez défini du côté backend.\n\n## Fichiers\n\ntRPC nécessite beaucoup de configuration que `create-t3-app` fait pour vous. Passons en revue les fichiers générés :\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nIl s'agit du point d'entrée de votre API et expose le routeur tRPC. Normalement, vous ne toucherez pas beaucoup à ce fichier, mais si vous devez, par exemple, activer le middleware CORS ou similaire, il est utile de savoir que le `createNextApiHandler` exporté est un [gestionnaire d'API Next.js](https://nextjs.org/docs/api-routes/introduction) qui prend une [requête](https://developer.mozilla.org/en-US/docs/Web/API/Request) et [réponse](https://developer.mozilla.org/en-US/docs/Web/API/Response). Cela signifie que vous pouvez envelopper le `createNextApiHandler` dans n'importe quel middleware de votre choix. Voir ci-dessous pour un [exemple] (#enabling-cors) d'ajout de CORS.\n\n### 📄 `server/api/trpc.ts`\n\nCe fichier est divisé en deux parties, la création du contexte et l'initialisation de tRPC :\n\n1. Nous définissons le contexte qui est passé à vos procédures tRPC. Le contexte sont des données auxquelles toutes vos procédures tRPC auront accès, et c'est un endroit idéal pour mettre des choses comme les connexions à la base de données, les informations d'authentification, etc. Dans create-t3-app, nous utilisons deux fonctions, pour activer l'utilisation d'un sous-ensemble du contexte lorsque nous n'avons pas accès à l'objet de requête.\n\n- `createInnerTRPCContext` : c'est ici que vous définissez le contexte qui ne dépend pas de la requête, par ex. votre connexion à la base de données. Vous pouvez utiliser cette fonction pour les [tests d'intégration](#exemple-de-test-dintégration) ou [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers) où vous n'avez pas d'objet de requête .\n\n- `createTRPCContext` : c'est ici que vous définissez le contexte qui dépend de la requête, par ex. la session de l'utilisateur. Vous demandez la session à l'aide de l'objet `opts.req`, puis transmettez la session à la fonction `createInnerTRPCContext` pour créer le contexte final.\n\n1. Nous initialisons tRPC et définissons des [procédures](https://trpc.io/docs/v10/procedures) et des [middlewares](https://trpc.io/docs/v10/middlewares) réutilisables. Par convention, vous ne devriez pas exporter l'intégralité de l'objet `t`, mais plutôt de créer des procédures et des middlewares réutilisables et de les exporter.\n\nVous remarquerez que nous utilisons `superjson` comme [transformateur de données](https://trpc.io/docs/v10/data-transformers). Cela fait en sorte que vos types de données sont préservés lorsqu'ils atteignent le client, donc si vous envoyez par exemple un objet `Date`, le client renverra une `Date` et non une chaîne, ce qui est le cas pour la plupart des API.\n\n### 📄 `server/api/routers/*.ts`\n\nC'est ici que vous définissez les routes et les procédures de votre API. Par convention, vous [créez des routeurs séparés](https://trpc.io/docs/v10/router) pour les procédures associées.\n\n### 📄 `server/api/root.ts`\n\nIci, nous [fusionnons](https://trpc.io/docs/v10/merging-routers) tous les sous-routeurs définis dans `routers/**` en un seul routeur d'application.\n\n### 📄 `utils/api.ts`\n\nIl s'agit du point d'entrée frontend pour tRPC. C'est ici que vous allez importer la **définition de type** du routeur et créer votre client tRPC avec les hooks de react-query. Depuis que nous avons activé `superjson` comme transformateur de données sur le backend, nous devons également l'activer sur le frontend. En effet, les données sérialisées du backend sont désérialisées sur le frontend.\n\nVous définirez ici vos [liens](https://trpc.io/docs/v10/links) tRPC, qui détermine le flux de requêtes du client vers le serveur. Nous utilisons le [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink) \"par défaut\" qui active [le traitement par lot des requêtes](https://cloud.google.com/compute/docs/api/how-tos/batch), ainsi qu'un [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) qui génère des journaux de requêtes utiles pendant le développement.\n\nEnfin, nous exportons un [helper de type](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) que vous pouvez utiliser pour déduire vos types sur le frontend.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nLe contributeur de Create T3 App [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) a réalisé [une vidéo sur les flux de données dans tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Cette vidéo est recommandée si vous avez utilisé tRPC mais que vous ne savez toujours pas comment cela fonctionne.\n\n## Comment puis-je appeler mon API en externe ?\n\nAvec les API classiques, vous pouvez appeler vos points de terminaison à l'aide de n'importe quel client HTTP tel que `curl`, `Postman`, `fetch` ou directement depuis votre navigateur. Avec tRPC, c'est un peu différent. Si vous souhaitez appeler vos procédures sans le client tRPC, il existe deux méthodes recommandées :\n\n### Exposez une seule procédure vers l'extérieur\n\nSi vous souhaitez exposer une seule procédure vers l'extérieur, vous cherchez des [appels côté serveur](https://trpc.io/docs/v10/server-side-calls). Cela vous permettrait de créer un point de terminaison API Next.js normal, et de réutiliser la partie résolveur de votre procédure tRPC.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Exposer chaque procédure en tant que point de terminaison REST\n\nSi vous souhaitez exposer chaque procédure vers l'extérieur, consultez le plugin créer par la communauté [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). En fournissant des métadonnées supplémentaires à vos procédures, vous pouvez générer une API REST compatible OpenAPI à partir de votre routeur tRPC.\n\n### Ce ne sont que des requêtes HTTP\n\ntRPC communique via HTTP, il est donc également possible d'appeler vos procédures tRPC à l'aide de requêtes HTTP \"régulières\". Cependant, la syntaxe peut être fastidieuse en raison du [protocole RPC](https://trpc.io/docs/v10/rpc) utilisé par tRPC. Si vous êtes curieux, vous pouvez regarder à quoi ressemblent les demandes et les réponses tRPC dans l'onglet réseau de votre navigateur, mais nous vous suggérons de le faire uniquement à titre d'exercice pédagogique et de vous en tenir à l'une des solutions décrites ci-dessus.\n\n## Comparaison avec un endpoint d'API Next.js\n\nComparons un endpoint d'API Next.js à une procédure tRPC. Disons que nous voulons récupérer un objet utilisateur de notre base de données et le renvoyer au frontend. Nous pourrions écrire un endpoint d'API Next.js comme ceci :\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nComparez cela à l'exemple tRPC ci-dessus et vous pouvez voir certains des avantages de tRPC :\n\n- Au lieu de spécifier une url pour chaque route, ce qui peut devenir fastidieux à déboguer si vous déplacez quelque chose, votre routeur entier est un objet avec saisie semi-automatique.\n- Vous n'avez pas besoin de valider la méthode HTTP utilisée.\n- Vous n'avez pas besoin de valider que la requête ou le corps de la requête contient les données correctes dans la procédure, car Zod s'en charge.\n- Au lieu de créer une réponse, vous pouvez générer des erreurs et renvoyer une valeur ou un objet comme vous le feriez dans n'importe quelle autre fonction TypeScript.\n- L'appel de la procédure sur le frontend fournit l'auto-complétion et la sécurité de typage.\n\n## Extraits de code utiles\n\nVoici quelques extraits de code qui pourraient être utiles.\n\n### Activation de CORS\n\nSi vous avez besoin de consommer votre API à partir d'un domaine différent, par exemple dans un monorepo qui inclut une application React Native, vous devrez peut-être activer CORS :\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Mises à jour optimistes\n\nLes mises à jour optimistes se produisent lorsque nous mettons à jour l'interface utilisateur avant la fin de l'appel d'API. Cela donne à l'utilisateur une meilleure expérience car il n'a pas à attendre la fin de l'appel d'API pour que l'interface utilisateur reflète le résultat de son action. Cependant, les applications qui accordent une grande importance à l'exactitude des données doivent éviter les mises à jour optimistes car elles ne sont pas une \"véritable\" représentation de l'état du backend. Vous pouvez en savoir plus sur la [documentation de React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Exemple de test d'intégration\n\nVoici un exemple de test d'intégration qui utilise [Vitest](https://vitest.dev) pour vérifier que votre routeur tRPC fonctionne comme prévu, que l'analyseur d'entrée déduit le type correct et que les données renvoyées correspondent à la sortie attendue.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n## Ressources utiles\n\n| Ressource                 | Lien                                                    |\n| ------------------------- | ------------------------------------------------------- |\n| Documentation tRPC        | https://www.trpc.io                                     |\n| Un tas d'exemples de tRPC | https://github.com/trpc/trpc/tree/next/examples         |\n| Documentation React Query | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/fr/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Utilisation de TypeScript\nlayout: ../../../layouts/docs.astro\nlang: fr\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Construisez des filets de sécurité, pas des garde-fous<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - auteur de la T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nQue vous soyez un développeur débutant ou chevronné, nous pensons que TypeScript est indispensable. Cela peut sembler intimidant au début, mais tout comme beaucoup d'outils, c'est quelque chose dont beaucoup ne garderont de mauvais souvenirs après avoir commencé à l'utiliser.\n\nIl fournit des commentaires en direct lorsque vous écrivez votre code en définissant les types de données attendus, et fournit soit une saisie semi-automatique dans votre éditeur de code, soit vous crie dessus avec des lignes ondulées rouges si vous essayez d'accéder à une propriété qui n'existe pas ou essayez de passez une valeur du mauvais type, que vous auriez sinon à déboguer plus tard, en ligne.\n\nC'est peut-être l'outil qui offre le plus de productivité aux développeurs. Il fournit la documentation de votre code lorsque vous l'écrivez ou le consommez dans votre éditeur en vous donnant une information directe car vous pouvez faire des erreurs et ceci est absolument inestimable.\n\n## Inférence de type\n\nAlors que de nombreux nouveaux développeurs TypeScript sont concernés par _écrire_ du TypeScript, bon nombre de ses avantages ne vous obligent pas à modifier votre code, en particulier l'inférence. L'inférence signifie que si quelque chose est typé, ce type le suivra tout au long du flux de l'application sans avoir à être redéclaré à d'autres endroits. Cela signifie que, par exemple, une fois que vous avez défini les types d'arguments qu'une fonction prend, le reste de la fonction sera généralement typesafe sans nécessiter d'autre code spécifique à TypeScript. Les développeurs de librairies consacrent une tonne de travail à la maintenance des types de celles-ci, ce qui signifie que nous, en tant que développeurs d'applications, pouvons bénéficier à la fois de l'inférence et de la documentation intégrée dans notre éditeur de code grâce aux types que fournissent ces librairies.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"Vous utilisez peut-être mal TypeScript\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nRegardez la vidéo de Theo sur la façon dont [vous utilisez peut-être mal TypeScript](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Utilisations puissantes de l'inférence de type\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) est une librairie de validation de schéma construite avec TypeScript. Écrivez un schéma qui représente une source unique de vérité pour vos données, et Zod s'assurera que vos données sont valides dans toute votre application, même au-delà des limites du réseau et des API externes.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) vous propose des requêtes et des mutations déclaratives, toujours à jour et autogérées, qui améliorent directement votre expériences de développeur et d'utilisateur.\n\n## Ressources utiles\n\n| Ressource                                                 | Lien                                                              |\n| --------------------------------------------------------- | ----------------------------------------------------------------- |\n| Manuel TypeScript                                         | https://www.typescriptlang.org/docs/handbook/                     |\n| Tutoriel TypeScript pour débutants                        | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Défis de Type                                             | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/fr/why.md",
    "content": "---\ntitle: Pourquoi CT3A?\ndescription: Pourquoi devriez-vous choisir Create T3 App pour votre prochain projet\nlayout: ../../layouts/docs.astro\nlang: fr\n---\n\nNous avons lancé Create T3 App parce que [Theo](https://twitter.com/t3dotgg) a refusé de créer un modèle de ses technologies préférées. Inspirée par create-next-app, [Astro's CLI](https://astro.build) avec un amour pour la sécurité des types, l'équipe de Create T3 App a travaillé dur pour créer le meilleur point de départ possible pour les nouveaux projets T3 Stack.\n\nSi vous souhaitez utiliser Next.js de manière sécurisée, c'est ici qu'il faut commencer. Si vous voulez en savoir plus sur l'un des choix technologiques spécifiques que nous avons faits, lisez la suite :)\n\n## Pourquoi TypeScript ?\n\nJavaScript est difficile. Pourquoi ajouter plus de règles ?\n\nNous croyons fermement que l'expérience fournie par TypeScript vous aidera à devenir un meilleur développeur. Il fournit des commentaires en direct lorsque vous écrivez votre code en définissant les types de données attendus, et fournit soit une saisie semi-automatique utile dans votre éditeur, soit vous crie dessus avec des lignes ondulées rouges si vous essayez d'accéder à une propriété qui n'existe pas ou essayez de passer une valeur du mauvais type, que vous auriez sinon à déboguer plus loin. Que vous soyez nouveau dans le développement Web ou un professionnel chevronné, la \"strictité\" de TypeScript fournira une expérience moins frustrante et plus cohérente que Vanilla JS.\n\nLa sécurité de type vous rend plus rapide. Si vous n'êtes pas convaincu, vous [utilisez peut-être mal TypeScript...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Pourquoi Next.js ?\n\nNous aimons React. Il a rendu le développement d'interface utilisateur accessible d'une manière que nous n'avions jamais imaginé auparavant. Cela peut également conduire les développeurs sur des chemins difficiles.\n\nNext.js offre une approche légèrement opiniâtre et fortement optimisée pour créer des applications à l'aide de React. Du routage aux définitions d'API en passant par le rendu d'image, nous faisons confiance à Next.js pour guider les développeurs vers de bonnes décisions.\n\n## Pourquoi tRPC/Prisma/Tailwind/etc?\n\nBien que nous croyions qu'il faut garder les choses aussi simples que possible, nous constatons que ces éléments sont utilisés dans chaque \"application\" comme projet que nous créons. `create-t3-app` fait un excellent travail en vous permettant d'adopter les éléments dont vous avez besoin.\n\n### tRPC\n\ntRPC tient la promesse de GraphQL d'un développement client transparent par rapport à un serveur typesafe sans tout le passe-partout. C'est un abus intelligent de TypeScript qui offre une expérience de développement incroyable.\n\n### Prisma\n\nPrisma est à SQL ce que TypeScript est à JS. Il a créé une expérience de développement qui n'existait pas auparavant. En générant des types à partir d'un schéma défini par l'utilisateur compatible avec [plusieurs bases de données](https://www.prisma.io/docs/concepts/database-connectors), Prisma garantit la sécurité des types de bout en bout, de votre base de données à votre application.\n\nPrisma fournit toute une [suite d'outils](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) facilitant les interactions quotidiennes avec votre base de données. Notamment, Prisma Client est chargé d'interroger et de rendre SQL si simple que vous remarquerez à peine que vous l'utilisez, et Prisma Studio est une interface graphique pratique pour votre base de données qui vous permet de lire et de manipuler vos données rapidement sans avoir à écrire de code.\n\n### Tailwind CSS\n\nTailwind ressemble à un \"CSS en mode zen\".\n\nEn fournissant des blocs de construction sous la forme de bonnes couleurs par défaut, d'un espacement et d'autres primitives, Tailwind facilite la création d'une belle application. Et contrairement aux librairies de composants, cela ne vous retient pas lorsque vous souhaitez faire passer votre application au niveau supérieur et créer quelque chose de beau et d'unique.\n\nDe plus, avec son approche en ligne, Tailwind vous encourage à styliser sans vous soucier de nommer les classes, d'organiser les fichiers ou de tout autre problème non directement lié au problème que vous essayez de résoudre.\n\n### NextAuth.js\n\nLorsque vous souhaitez un système d'authentification dans votre application NextJS, NextAuth.js est une excellente solution pour apporter la complexité de la sécurité sans avoir à le coder vous-même. Il est livré avec une longue liste de fournisseurs pour ajouter rapidement l'authentification OAuth et fournit des adaptateurs pour de nombreuses bases de données et ORM.\n"
  },
  {
    "path": "www/src/pages/index.astro",
    "content": "---\nimport About from \"../components/landingPage/about.astro\";\nimport Banner from \"../components/landingPage/banner.astro\";\nimport Community from \"../components/landingPage/community/community.astro\";\nimport Features from \"../components/landingPage/stack/stack.astro\";\nimport LandingPage from \"../layouts/landingPage.astro\";\n---\n\n<LandingPage>\n  <Banner />\n  <About />\n  <Features />\n  <Community />\n</LandingPage>\n"
  },
  {
    "path": "www/src/pages/ja/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Dockerへのデプロイ\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\nこのスタックをコンテナ化し、Docker を使用して単一のコンテナとしてデプロイすることができます。または、 docker-compose を使用して複数のコンテナのグループの一部としてデプロイすることもできます。このドキュメントに基づいたサンプルリポジトリは [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) をご覧ください。\n\n## Docker プロジェクトの設定\n\nNext.js では、ビルド時の変数（フロントエンドで利用可能、接頭辞は`NEXT_PUBLIC`）と実行環境の変数（サーバサイドのみ）が異なる処理を必要とすることに注意してください。このデモでは 2 つの変数を使用しています。`Dockerfile`、コマンドライン引数、`docker-compose.yml`の中での位置に注意してください：\n\n- `DATABASE_URL` (サーバーが使用する)\n- `NEXT_PUBLIC_CLIENTVAR`（クライアントが使用する）\n\n### 1. Next の設定\n\n[`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js) に、[出力ファイルのトレースを自動的に活用してイメージサイズを小さくする](https://nextjs.org/docs/advanced-features/output-file-tracing)ための`standalone`出力オプション設定を追加してください：\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. .dockerignore ファイルの作成\n\n<details>\n    <summary>\n      Click here and include contents in <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Dockerfile の作成\n\nサーバ環境変数をコンテナに取り込んでいないため、[環境スキーマの検証](/en/usage/env-variables)が失敗します。これを防ぐために、ビルド時に環境スキーマが検証されないように、ビルドコマンドに `SKIP_ENV_VALIDATION=1` フラグを追加する必要があります。\n\n<details>\n    <summary>\n      Click here and include contents in <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-alpine3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-alpine3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-alpine3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_備考_**\n>\n> - _Node 18 への移行後は、`--platform=linux/amd64`のエミュレーションが不要になる場合があります。_\n> - _なぜ `libc6-compat` が必要なのかについては [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) を参照してください。._\n> - _[Alpine 3.17 ベースのイメージを使用すると、Prisma で問題が発生することがあります](https://github.com/t3-oss/create-t3-app/issues/975)。`engineType=\"binary\"`を設定すると、Alpine 3.17 の問題は解決されますが、[ただし、関連するパフォーマンスコストが発生します](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js は[一般的な使用方法に関する匿名のテレメトリーデータ](https://nextjs.org/telemetry)を収集します。ビルド時にテレメトリを無効にするには、`ENV NEXT_TELEMETRY_DISABLED 1` の最初のインスタンスのコメントを外してください。実行時にテレメトリを無効にするには、2 番目のインスタンスのコメントを外してください。_\n\n</div>\n</details>\n\n## ローカルでイメージをビルドし、実行する\n\n以下のコマンドでこのイメージをローカルでビルドして実行します：\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\n[localhost:3000](http://localhost:3000/)を開き、実行中のアプリケーションを確認します。\n\n## Docker Compose\n\nまた、Docker Compose でイメージを構築し、コンテナを実行することもできます。\n\n<details>\n    <summary>\n      Follow steps 1-4 above, click here, and include contents in <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nこれを `docker compose up` コマンドで実行します：\n\n```bash\ndocker compose up\n```\n\n[localhost:3000](http://localhost:3000/)を開き、実行中のアプリケーションを確認します。\n\n</div>\n</details>\n\n## Railway へのデプロイ\n\nアプリケーションのデプロイには、[Railway](https://railway.app)のような自動化された[Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles) などの PaaS を使用することができます。[Railway CLI をインストールしている場合](https://docs.railway.app/develop/cli#install)は、以下のコマンドでアプリケーションをデプロイすることができます：\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\n\"Variables\"に行ってあなたの`DATABASE_URL`を指定します。その後、\"Settings\" に行き、\"Generate Domain\" を選択します。Railway 上での実行例を見るには[ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/)にアクセスしてください。\n\n## お役立ち情報\n\n| リソース                               | リンク                                                               |\n| -------------------------------------- | -------------------------------------------------------------------- |\n| Dockerfile のリファレンス              | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file バージョン 3 リファレンス | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI リファレンス                | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI リファレンス        | https://docs.docker.com/compose/reference/                           |\n| Next.js の Docker イメージでのデプロイ | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js in Docker                      | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Docker での Next.js の例               | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Next.js アプリの Docker イメージの作成 | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/ja/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Deployment\",\n  layout: \"docs\",\n  description: \"Learn how to deploy your T3 app to production.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/ja/deployment/netlify.mdx",
    "content": "---\ntitle: Netlify\ndescription: Netlifyへのデプロイ\nlayout: ../../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nNetlify は Vercel の代替となり得る同系統のデプロイメントプロバイダです。本ドキュメントに基づいたサンプルリポジトリは [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) を参照してください。\n\n## Netlify でホスティングする理由\n\n従来からの知識では、Vercel では Next.js のサポートが優れているとされています。これは Vercel が Next.js を開発しているためで、Next.js の最適なパフォーマンスと DX のためのチューニングに Vercel プラットフォームは大きな関心をもっています。多くのユースケースではそのとおりであり、この「標準的な道筋」から逸脱しても意味がありません。\n\nまた一般に、多くの Next.js の機能が Vercel でのみサポートされているという意見もあります。確かに新しい Next.js の機能はリリース時にデフォルトで Vercel でテストされサポートされることは事実ですが、Netlify のような他のプロバイダも、[安定した Next.js 機能](https://docs.netlify.com/integrations/frameworks/next-js/overview/)に対して[すぐに実装およびリリースサポート](https://www.netlify.com/blog/deploy-nextjs-13/)を提供することがあります。\n\n結局のところ、すべてのデプロイメントプロバイダーには相対的な長所と短所があり、一つのホストがすべてのユースケースに対して最高のサポートを提供できるわけではありません。例えば、Netlify では、Netlify のエッジファンクション（Deno Deploy 上で動作）用に、独自の[カスタム Next.js ランタイム](https://github.com/netlify/next-runtime)を構築し、[HTTP レスポンスにアクセスへのアクセスと変更のための独自のミドルウェアをメンテナンス](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify)しています。\n\n<Callout type=\"info\">\n  no-stableのNext 13の機能のステータスを追跡するには、[Next 13の`app`\n  ディレクトリをNetlify上で使う](https://github.com/netlify/next-runtime/discussions/1724)を参照してください。\n</Callout>\n\n## プロジェクトの設定\n\nビルド手順を設定する方法は、Netlify CLI や Netlify ダッシュボードを使って直接ビルド命令を設定するなど、たくさんあります。必須ではありませんが、[`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/)ファイルを作成して含めることをお勧めします。これにより、プロジェクトのフォークやクローン版を再現性をもって簡単にデプロイすることができます。\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Netlify Dashboard の使用方法\n\n1. コードを GitHub リポジトリにプッシュし、[Netlify](https://app.netlify.com/signup)にサインアップしてください。アカウントを作成したら、**Add new site** から **Import an existing project** をクリックします。\n\n![Netlify の新プロジェクト](/images/netlify-01-new-project.webp)\n\n2. Git プロバイダーを接続します。\n\n![リポジトリのインポート](/images/netlify-02-connect-to-git-provider.webp)\n\n3. プロジェクトのリポジトリを選択します。\n\n![プロジェクトのリポジトリを選択する](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify は `netlify.toml` ファイルがあるかどうかを検出し、ビルドコマンドと公開ディレクトリを自動的に設定します。\n\n![Nextjs のビルド設定](/images/netlify-04-configure-build-settings.webp)\n\n5. 「**Show advanced**」→「**New variable**」をクリックして、環境変数を追加します。\n\n![環境変数の追加](/images/netlify-05-env-vars.webp)\n\n6. 「**Deploy site**」をクリックし、ビルドが完了するのを待ち、新しいサイトを表示します。\n\n## Netlify CLI の使用方法\n\nコマンドラインからデプロイするには、まずプロジェクトを GitHub のリポジトリにプッシュし、[Netlify CLI をインストール](https://docs.netlify.com/cli/get-started/) する必要があります。`netlify-cli` はプロジェクトの依存関係としてインストールするか、以下のコマンドでマシンにグローバルにインストールすることができます：\n\n```bash\nnpm i -g netlify-cli\n```\n\nローカルでプロジェクトをテストするには、[`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) コマンドを実行し、[`localhost:8888`](http://localhost:8888/) を開いてローカルで動いている Netlify アプリを表示します：\n\n```bash\nntl dev\n```\n\n[`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment)コマンドを実行してプロジェクトを設定します：\n\n```bash\nntl init\n```\n\n`.env` ファイルからプロジェクトの環境変数を [`ntl env:import`](https://cli.netlify.com/commands/env#envimport) でインポートしてください：\n\n```bash\nntl env:import .env\n```\n\n[`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys)でプロジェクトをデプロイします。デプロイ前にビルドコマンドを実行するには `--build` フラグを、サイトのメイン URL にデプロイするには `--prod` フラグを渡す必要があります：\n\n```bash\nntl deploy --prod --build\n```\n\nNetlify での実行例は、[ct3a.netlify.app](https://ct3a.netlify.app/)でご覧ください。\n"
  },
  {
    "path": "www/src/pages/ja/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Vercelへのデプロイ\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\nアプリケーションは[Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss)にデプロイすることをお勧めします。Next.js のアプリケーションを超簡単にデプロイすることができます。\n\n## プロジェクト構成\n\nVercel はビルドコマンドの設定とディレクトリの公開を自動的にうまくやってくれる場合が多いでしょう。しかし、[`vercel.json`](https://vercel.com/docs/project-configuration)というファイルを作成し、以下のコマンドを含めることで、他の設定も含めてこれらの情報を明示指定することもできます。**これはほとんどのプロジェクトでは必要ありません**。\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Vercel ダッシュボードを使う\n\n1. コードを GitHub のリポジトリにプッシュした後、GitHub で[Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss)にサインアップし、**Add New Project**をクリックします。\n\n![Vercel の新プロジェクト](/images/vercel-new-project.webp)\n\n2. GitHub のリポジトリをプロジェクトと一緒にインポートします。\n\n![インポートリポジトリ](/images/vercel-import-project.webp)\n\n3. 環境変数を追加します。\n\n![環境変数を追加する](/images/vercel-env-vars.webp)\n\n4. **Deploy**をクリックします。これで、リポジトリに変更をプッシュするたびに、Vercel は自動的にアプリケーションを再デプロイするようになります！\n\n## Vercel CLI を使う\n\nコマンドラインからデプロイするには、まず [Vercel CLI をグローバルにインストール](https://vercel.com/docs/cli#installing-vercel-cli) する必要があります。\n\n```bash\nnpm i -g vercel\n```\n\n[`vercel`](https://vercel.com/docs/cli/deploying-from-cli) コマンドを実行してプロジェクトをデプロイします。\n\n```bash\nvercel\n```\n\nデータベース接続文字列などの環境変数には、`--env DATABASE_URL=YOUR_DATABASE_URL_HERE`を含めるようにします。デプロイの質問を省略し、それぞれにデフォルトの回答を与えたい場合は `--yes` を使用します。\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\n最初のデプロイの後、このコマンドは preview ブランチにデプロイされます。将来のデプロイのために、変更をライブサイトに直接プッシュするには、`--prod`を含める必要があります。\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/ja/faq.mdx",
    "content": "---\ntitle: FAQ\ndescription: T3 Appについてのよくある質問(FAQ)\nlayout: ../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nCreate T3 App について、よくあるご質問をご紹介します。\n\n## 次に何をしたら良いですか？これでアプリケーションを作るにはどうすればいい？\n\nCT3A はできる限りシンプルにしたものなので、CT3A で生成した初期構成から始め、後で必要なものが出てきたらその時点で追加していくのが良いでしょう。\n\nこのプロジェクトで使用されているさまざまな技術に精通していない場合、それぞれのドキュメントを参照してください。それでも漠然としている場合は、私たちの[Discord](https://t3.gg/discord)に参加し質問してください。\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## アプリケーションを最新の状態に保つにはどうすればよいですか？\n\nCreate T3 App はフレームワークではなく、初期構成を生成するツールです。このことは、一度アプリケーションを初期化したなら、それはあなたのものになることを意味します。インストール後には、最新版へ追随するのを助けてくれる CLI ツールのようなものはありません。もし、私たちがテンプレートに加えた改良を追っていきたいのであれば、私たちのリポジトリで[リリースを通知できるようにする](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository)と良いでしょう。とはいえ、私たちがテンプレートに加えたすべての変更を、あなたのアプリケーションに反映させる必要はないでしょう。\n\n## 現在、どのような学習リソースがありますか？\n\n下記のリソースは T3 Stack のために存在する最高のものの一部ですが、コミュニティ（および[Theo](https://youtu.be/rzwaaWH0ksk?t=1436)）としては、まずはスタックを使い始め、それを使って開発をしながら学んでいくことをお奨めします。\n\nもしあなたが Create T3 App を検討しているなら、スタックの構成要素のいくつかをすでに使っているかもしれません。そうなら、思い切って飛び込んで、何かを作りながら他の構成要素を学んでいってみてはいかがでしょうか？\n\nとはいえ、この方法が誰にとってもうまくいくわけではないことも理解しています。もしあなたが、推奨される方法を試した上でもっとリソースが欲しいと感じたり、自分でやる自信がなかったり、スタックに圧倒されていると感じたら、Create T3 App に関する以下の素晴らしいチュートリアルをチェックしてみてください：\n\n### 記事一覧\n\n- [Create T3 App でフルスタックアプリを作る](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [初めての Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [T3 アプリを Turborepo に移行する](https://www.jumr.dev/blog/t3-turbo)\n- [T3 アプリに Stripe を組み込む](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### 動画\n\n- [T3 Stack チュートリアル - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(recommended)**\n- [Jack Herrington - T3 Stack でメモ帳アプリを作る](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [T3 Stack で Twitter クローンを作る - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [T3 スタックでブログを作る - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [T3 スタックによるライブチャットアプリケーションの構築 - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [T3 Stack - どのように作ったか](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [Create T3 App の概要（Next、Typescript、Tailwind、tRPC、Next-Auth）](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## なぜプロジェクトに `.js` ファイルがあるのですか？\n\n[T3-原則#3](/ja/introduction#型安全は必須)にあるように、私たちは型安全性を第一級市民として扱っています。しかし残念ながら、すべてのフレームワークやプラグインが TypeScript をサポートしているわけではないので、設定ファイルの一部は `.js` ファイルでなければならないのです。\n\nこれらのファイルが JavaScript であることを強調するために、各ファイルの種別（`cjs`または`mjs`）を、それを使用するライブラリによってサポートするものに応じて明示的に宣言するように努めています。また、このプロジェクトのすべての `js` ファイルは、コンパイラ (tsconfig) の checkJs オプションを使用して型チェックが行われています。\n\n## アプリケーションを国際化対応するのに苦労しています。参考にできるものはありますか？\n\n`create-t3-app` にデフォルトで i18n を含めないことにした理由は、非常に意見が分かれるトピックであり、実装方法も多岐にわたるためです。\n\nしかし、実装するのに苦労していて参考プロジェクトを見たい場合は、[next-i18next](https://github.com/i18next/next-i18next)を使って T3 アプリケーションに i18n を追加する方法を紹介する[参考リポジトリ](https://github.com/juliusmarminge/t3-i18n)があります。\n\n## Next.js 13 の /app ではなく、なぜ /pages を使っているのですか？\n\n[T3 原則 2](/ja/introduction#問題を解決する)の通り、私たちは最先端のものが大好きですが、安定性を重視しており、ルーター全体を移植するのは難しく、[血を流すのには適切なところではない](https://youtu.be/mnwUbtieOuI?t=1662)とみなしています。`/app` ディレクトリは [未来への一端を垣間見せてくれる](https://youtu.be/rnsC-12PVlM?t=818)ものではありますが、まだ本番環境には適していません。API はベータ版であり、破壊的な変更が予想されています。\n\n<Callout type=\"info\">\n  `/app`ディレクトリでサポートされている機能、計画されている機能、作業中の機能の一覧は[ベータ版Next.js\n  ドキュメント](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features)をご覧ください。\n</Callout>\n"
  },
  {
    "path": "www/src/pages/ja/folder-structure-pages.mdx",
    "content": "---\ntitle: フォルダ構造 (Pages)\ndescription: 初期構成として新規に生成されたT3 Appのフォルダ構造\nlayout: ../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\n以下でパッケージを選択してみてください。すると、その選択したパッケージで新たに初期構成を生成したアプリケーションのフォルダ構造が表示されます。もっと下には各エントリーの説明があります。\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\n`prisma` フォルダには、データベース接続とデータベーススキーマの設定に使用する `schema.prisma` ファイルが格納されています。\nまた、マイグレーションファイルやシードスクリプトを格納する場所でもあります（もし使用する場合）。\n詳しくは、[Prisma の使い方](/ja/usage/prisma)を参照してください。\n\n</div>\n<div>\n\n### `public`\n\n`public`フォルダには、Web サーバが提供する静的アセットが格納されています。`favicon.ico`ファイルは静的アセットの一例です。\n\n</div>\n<div>\n\n### `src/env`\n\n環境変数の検証や型定義に使用します。[環境変数](usage/env-variables)を参照。\n\n</div>\n<div>\n\n### `src/pages`\n\n`pages`フォルダには、Next.js アプリケーションのすべてのページが格納されます。`pages`ディレクトリの直下にある `index.tsx` ファイルは、アプリケーションのホームページとなります。`_app.tsx`ファイルは、アプリケーションを各種プロバイダでラップするために使用されます。詳しくは、[Next.js ドキュメント](https://nextjs.org/docs/basic-features/pages)を参照してください。\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\n`api`フォルダには、Next.js アプリケーションのすべての API ルーティングが格納されています。API ルートについては、[Next.js Api Routes Docs](https://nextjs.org/docs/api-routes/introduction)を参照してください。\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\n`[...nextauth].ts`ファイルは、NextAuth.js の認証スラッグルートです。認証リクエストを処理するために使用されます。NextAuth.js の詳細については [NextAuth.js usage](usage/next-auth) を、キャッチオール／スラッグルートについては [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) を参照してください。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\n`[trpc].ts`ファイルは、tRPC API のエントリポイントです。このファイルは、tRPC リクエストを処理するために使用されます。このファイルの詳細については[tRPC の使い方](usage/trpc#-pagesapitrpctrpcts)を、キャッチオール/スラッグルートの情報については[Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) を参照してください。\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\n`server`フォルダは、サーバサイドのコードとクライアントサイドのコードを明確に分けるために使用されます。\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nサーバーサイドの認証ロジックのメインエントリポイントです。\nここでは、NextAuth.js の[設定オプション](usage/next-auth)、[モジュール拡張](usage/next-auth#inclusion-of-userid-on-the-session) と、サーバサイドでユーザのセッションを取得するなどの認証に関する DX ユーティリティを提供しています。詳しくは [NextAuth.js usage](usage/next-auth#usage-with-trpc) をご覧ください。\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\n`db.ts`ファイルは、グローバルスコープで Prisma クライアントをインスタンス化するために使用されます。詳しくは、[Prisma の使い方](usage/prisma#prisma-client)と[Next.js で Prisma を使うためのベストプラクティス](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices)をご覧ください。\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\n`api`フォルダには、tRPC のサーバーサイドのコードが格納されています。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\n`routers`フォルダには、すべての tRPC サブルーターが格納されています。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\n`example.ts`ファイルは、`publicProcedure`ヘルパーを利用した tRPC ルーターの例で、public な tRPC ルートを作成する方法を示しています。\n\nこのルーターには、あなたがどのパッケージを選択したかに応じて増減させたルーターが含められており、あなたが必要とする使用方法を示しています。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\n`trpc.ts`ファイルは、tRPC バックエンドのメイン設定ファイルです。この中で私たちは：\n\n1. tRPC リクエストで使用するコンテキストを定義しています。詳しくは[tRPC の使い方](usage/trpc#-serverapitrpcts)を参照してください。\n2. プロシージャヘルパーをエクスポートしています。詳しくは、[tRPC usage](usage/trpc#-serverapitrpcts) を参照してください。\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\n`root.ts` ファイルは、ルータの型定義と同様に、tRPC ルータをマージして 1 つのルータとしてエクスポートするために使用されます。詳しくは[tRPC の使い方](usage/trpc#-serverapirootts)を参照してください。\n\n</div>\n<div>\n\n### `src/styles`\n\n`styles`フォルダには、アプリケーションのグローバルスタイルが格納されます。\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\n`utils`フォルダは、よく再利用されるユーティリティ関数を置いておくために使用されます。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\n`api.ts`ファイルは、tRPC のフロントエンドのエントリポイントです。詳しくは[tRPC の使い方](usage/trpc#-utilsapits)を参照してください。\n\n</div>\n<div>\n\n### `.env`\n\n`.env`ファイルは、環境変数を格納するために使用されます。詳しくは [環境変数](usage/env-variables) を参照してください。このファイルは、git 履歴にコミットする必要はありません。\n\n</div>\n<div>\n\n### `.env.example`\n\n`.env.example` ファイルは、選択したライブラリに基づく環境変数の例を示しています。このファイルは git 履歴にコミットしておく必要があります。\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\n`.eslintrc.cjs`ファイルは、ESLint の設定に使用されます。詳しくは[ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files)を参照してください。\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\n`next-env.d.ts`ファイルは、Next.js の型が TypeScript コンパイラに拾われるようにするためのファイルです。**いつでも変化し得るものなので、削除や編集はしないでください。** 詳細は [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects) をご覧ください。\n\n</div>\n<div>\n\n### `next.config.mjs`\n\n`next.config.mjs`ファイルは、Next.js を設定するためのものです。詳しくは[Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction)を参照してください。注： .mjs という拡張子は、ESM でのインポートができるようにするために使用されます。\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nTailwind の PostCSS の利用には、`postcss.config.js`ファイルが使用されます。詳しくは[Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss)を参照してください。\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\n`prettier.config.mjs`ファイルは、Tailwind CSS クラスをフォーマットするために prettier-plugin-tailwindcss を含めるように Prettier を設定するために使用します。詳しくは [Tailwind CSS ブログポスト](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) を参照してください。\n\n</div>\n<div>\n\n### `tsconfig.json`\n\n`tsconfig.json`ファイルは、TypeScript を設定するために使用されます。Create T3 App とそのライブラリの TypeScript を最適に利用するために、`strict mode`のようないくつかの非デフォルトが有効になっています。詳細については、[TypeScript ドキュメント](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) または [使用法の TypeScript](usage/typescript) を参照してください。\n\n</div>\n"
  },
  {
    "path": "www/src/pages/ja/installation.mdx",
    "content": "---\ntitle: インストール\ndescription: Create T3 Appによるインストール手順\nlayout: ../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\n`create-t3-app`を使用してアプリケーションの初期構成を生成するには、以下の 3 つのコマンドのいずれかを実行し、コマンドプロンプトの質問に答えてください：\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nアプリケーションの初期構成が生成されたら、[ファーストステップ](/ja/usage/first-steps) をチェックして、新しいアプリケーションを開始しましょう。\n\n## 高度な使用法\n\n| オプション/フラグ | 説明文                                                                           |\n| ----------------- | -------------------------------------------------------------------------------- |\n| `[dir]`           | ディレクトリ引数にプロジェクト名を含める                                         |\n| `--noGit`         | プロジェクト内に新しい git リポジトリを初期化しないよう CLI に明示的に指示する   |\n| `-y`, `--default` | CLI の確認をバイパスして、すべてのオプションを選択した新しい t3-app を立ち上げる |\n| `--noInstall`     | 依存関係をインストールせずにプロジェクトを生成する                               |\n\n## 実験的な使い方\n\nCI 用として、プロンプトなしで任意のアプリケーションの初期構成を生成できる実験的なフラグをいくつか用意しています。\nこのユースケースがあなたに当てはまるなら、これらのフラグを使用することができます。これらのフラグは実験的なものであり、semver のバージョニングに従わずに将来的に変更されるかもしれないことに注意してください。\n\n| フラグ       | 説明文                                |\n| ------------ | ------------------------------------- |\n| `--CI`       | CI モードであることを CLI に知らせる  |\n| `--trpc`     | プロジェクト内に tRPC を含める        |\n| `--prisma`   | Prisma をプロジェクトに組み込む       |\n| `--nextAuth` | NextAuth.js をプロジェクトに含める    |\n| `--tailwind` | Tailwind CSS をプロジェクトに組み込む |\n\n<Callout type=\"warning\">\n  `CI`フラグを指定しない場合、その他のフラグは効果を持ちません。\n</Callout>\n\n不要なパッケージを明示的にオプトアウトする必要はありません。しかし、明示的にそうしたい場合は、`--nextAuth false` のように `false` を渡すことができます。\n\n### 例\n\n以下は、tRPC と Tailwind CSS を使った T3 App の初期構成を生成します。\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/ja/introduction.md",
    "content": "---\ntitle: イントロダクション\ndescription: T3 Stackの紹介\nlayout: ../../layouts/docs.astro\nlang: ja\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\n「T3 Stack」は、[Theo](https://twitter.com/t3dotgg)が作った Web 開発スタックで、シンプルさ、モジュール性、フルスタックに渡っての型安全性に焦点を当てています。\n\n核となるのは[**Next.js**](https://nextjs.org/)と[**TypeScript**](https://typescriptlang.org/)です。また、[**Tailwind CSS**](https://tailwindcss.com/)は、ほぼ必ず含まれています。バックエンドに近いことをするのであれば、[**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), [**NextAuth.js**](https://next-auth.js.org/) も素晴らしい追加要素になるでしょう。\n\nお気づきかもしれませんが、構成要素の数が多いのですが、意図的にそうしており、必要に応じて構成要素を入れ替えることができます。このスタックはモジュール式です。:）\n\n## さて、create-t3-app とは何でしょう？テンプレート？\n\n一種そのようなものです。`create-t3-app`は、モジュール式の T3 Stack アプリケーションのセットアップを効率化するために、経験豊富な T3 Stack 開発者によって作られた CLI です。つまり、各パーツはオプションであり、「テンプレート」があなたの特定のニーズに基づいて生成されることを意味します。\n\n長年の間、数え切れないほどのプロジェクトにおいてこの技術に携わってきた私たちには、たくさんの意見や洞察があります。私たちは、それらをこの CLI に反映させるために最善を尽くしました。\n\nただしこれは、すべてを網羅したテンプレートでは**ありません**。私たちは、あなたが **あなたの**アプリケーションのニーズを解決する独自のライブラリを持ってくることを**期待しています**。状態管理やデプロイメントなど、より具体的な問題に対する解決策を規定するつもりはありませんが、私たちは[ここにいくつかの推奨事項を挙げています](/en/other-recs).\n\n## T3 原則\n\n率直に言って、T3 Stack は「_主張の強い_」プロジェクトです。私たちは、開発に関する一握りの核となる信念を共有し、私たちの判断基準としています。\n\n### 問題を解決する\n\n「何でもかんでも追加してしまう」という罠に容易に陥りがちですが、わたしたちは明示的にそれを避けます。`create-t3-app` に追加するものはすべて、その領域における固有の問題を解決している必要があります。したがって状態管理ライブラリ(Zustand、Redux 等)は含めませんが、NextAuth.js などは追加し、Prisma や tRPC などを統合します。\n\n### 責任を負って血を流す\n\n私たちは、最先端の技術が大好きです。正直なところ、新しい技術から生まれる開発速度と楽しさは本当に素晴しいものです。ただし、責任を持って血を流すことが重要です。リスクが低い領域では高リスク技術を採用しつつ、冒険的な新しいデータベース技術は採用しません(SQL は偉大なり！)。しかし、tRPC は単なる関数であり、問題があれば簡単に交換できるので、私たちは喜んでそれに賭けるのです。\n\n### 型安全は必須\n\nCreate T3 App の目標は、**型安全な**フルスタック Web アプリケーションを新規開発するための最も迅速な方法を提供することです。生産性を高め、バグの少ない製品を提供するのに役立つので、型安全性を真剣に考えています。Create T3 App の型安全性を損なうような妥協は他のプロジェクトで行うべき決定です。\n"
  },
  {
    "path": "www/src/pages/ja/other-recs.md",
    "content": "---\ntitle: その他のオススメ\ndescription: 多くのプロジェクトに推奨しているライブラリ・サービス\nlayout: ../../layouts/docs.astro\nlang: ja\n---\n\n私たちは、`create-t3-app`に含まれるライブラリがすべての問題を解決するわけではないことを認識しています。私たちの提供物でプロジェクトを始めることをお勧めしますが、他パッケージの導入が必要となる時も来るでしょう。あなたのプロジェクトに必要なものを知っているのはあなただけです。ここでは、私たちが頻繁に推奨しているものをいくつか紹介します。\n\nこれらは、個々の Create T3 App の貢献者による推奨であり、Create T3 App チームまたは T3-OSS による「公式」推奨とみなされるものではありません。 _**特に有料サービスを利用する前にはご自身で調査してください**_。\n\n## 状態管理\n\n_**編注**_：tRPC の React Query フックでサーバー状態を管理することができるでしょう。クライアントの状態管理については、React の`useState`から始め、不足を感じた時になってからこれらの選択肢のいずれかを使用すれば良いでしょう。\n\n### Zustand\n\n**もう二度と Redux を使わないために**\n\nあなたが知らない「モダンでシンプルな Redux」。[Poimandres](https://github.com/pmndrs)はいつも信頼できます。この小さなライブラリで、ビデオ通話アプリからゲーム、サーバーまで、あらゆるものを作れます。\n\n- [Zustand ホームページ](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**もう二度と Context を使わないために**\n\nよりアトミックなアプローチでは、Jotai が勝るとも劣りません。Zustand と同じく、[Poimandres](https://github.com/pmndrs)から提供される Jotai は、グローバルな useState のような感覚でシングルトンを定義することができます。ステートマシンまでは必要としないステートフルな振舞いに最適なオプションです。\n\n- [Jotai ホームページ](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## コンポーネントライブラリ\n\nほとんどのアプリケーションは、トグルボタン、ドロップダウンメニュー、モーダルなど、同じ一握りのコンポーネントを必要とします。これらのライブラリは、あなたの好みに合わせてカスタマイズできる、アクセスしやすい優れたコンポーネントを提供しています。\n\n### スタイル付けされていない(Unstyled)コンポーネントライブラリ\n\n「ヘッドレスライブラリ」とも呼ばれ、スタイルにとらわれず、自分好みにカスタマイズできるアクセス性の高い素晴らしいコンポーネントが提供されています。ここでは、おすすめのものをいくつか紹介します。\n\n- [Radix UI](https://www.radix-ui.com/) は、バニラまたは Tailwind CSS でスタイルを設定できる、便利でアクセスしやすいプリミティブの強力なセットを提供します。\n\n- Tailwind CSS チームによって作られた[Headless UI](https://headlessui.com/)も、Tailwind CSS とシームレスに統合された、スタイルのないアクセシビリティを考慮したコンポーネント群を提供しています。\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/)は、アクセシビリティを考慮した UI プリミティブをあなたのデザインシステムに提供します。彼らの Date Picker コンポーネントはトップクラスです。\n\n### スタイル付けされた(Styled)コンポーネントライブラリ\n\n**アプリケーションを見た目良くしたいだけの場合**\n\nプロジェクトでは、UI がすぐに格好良く見えるようにしたい場合があります。管理者用ダッシュボードや、他の類似のプロジェクトでは、以下のコンポーネントライブラリのいずれかを使用すれば、目的を達成できます。\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**UI ライブラリ構築用**\n\n色やサイズなどのバリエーションを持った UI ライブラリを宣言的に構築します。プロジェクトが大規模になり、複数のバリエーションがある 標準化した Tailwind CSS ベースの UI コンポーネントのセットが必要になったとき、CVA は素晴らしいツールになります。\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## アニメーション\n\nアニメーションが必要なときのおすすめを紹介します。\n\n### AutoAnimate\n\n**1 行のコードでアニメーションを作成する場合**\n\n多くのアニメーションライブラリはありとあらゆるユースケースを満たそうとするため、結果的に不格好になっています。AutoAnimate は設定不要のツールであり、開発者の労力を増やすことなく UX を大幅に向上させることができます。\n\n- [AutoAnimate のホームページ](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [AutoAnimate コンポーネントスニペット](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**宣言的なコードで複雑なアニメーションを実現する**。\n\nFramer Motion は、シンプルで宣言的なシンタックスを提供し、複雑なアニメーションからジェスチャーまで、より少ないコードで作成できるようにします。\n\n- [Framer Motion ホームページ](https://framer.com/motion)\n- [Framer Motion ドキュメント](https://www.framer.com/docs/)\n\n## デプロイメント、インフラ、データベース、CI\n\n### Vercel\n\n**アプリケーションのホスティング用**\n\nVercel は、デプロイ作業のひどいつらみを巻き取ってくれ、GitHub 連携を設定すれば放っておいてもよしなにやってくれます。また、数十万人もいる利用者に何の問題もなくプロダクトを展開できました。AWS の力も得て、インターフェイスもはるかに優れています :)\n\n- [Vercel のホームページ](https://vercel.com/)\n- [Create T3 App Vercel デプロイメントガイド](/ja/deployment/vercel)\n\n### PlanetScale\n\n**心配いらずのデータベースのために**\n\nPlanetScale は、これまで使った中で最も優れた「サーバーレスデータベースプラットフォーム」です。驚異的なスケーラビリティ、優れた開発者体験、そして素晴しい価格設定が魅力です。SQL（できれば Prisma）を使っているのであれば、これに勝るものはありません。\n\n- [PlanetScale ホームページ](https://planetscale.com/)\n\n### Railway\n\n**インフラのホスティングに最適**\n\n一言で言えば「モダンな Heroku」。本格的なサーバーを立ち上げる最も簡単な方法です。Vercel と PlanetScale だけでは十分でない場合、Railway がおそらくそれに対応します。GitHub のリポジトリを指定して実行してみてください。\n\n- [Railway ホームページ](https://railway.app/)\n\n### Upstash\n\n**サーバーレス Redis 用**\n\n私たちは Prisma と PlanetScale が大好きですが、より高性能なソリューションが必要なプロジェクトもあります。Upstash を使うと、インフラとスケーリングを自分で管理することなく、サーバーレスプロジェクトで Redis のインメモリ性能を得ることができます。\n\n- [Upstash ホームページ](https://upstash.com/)\n\n### Pusher\n\n**サーバーレス WebSockets 用**\n\nWebSocket がプロジェクトの主な焦点である場合、[Fastify](https://www.fastify.io/) (これは[tRPC でも動作する!](https://trpc.io/docs/v10/fastify))のようなもっと伝統的なバックエンドを検討することをお勧めします。しかし、T3 アプリに WebSocket を素早く追加するには、Pusher は優れた選択です。\n\n- [Pusher ホームページ](https://pusher.com/)\n\n### Soketi\n\nSoketi は Pusher の代替となる、セルフホスティング可能でシンプルかつ高速なソフトウェアです。サーバーに接続するために使用できる Pusher SDK と完全に互換性があります。Soketi のサーバーレスもベータ版です。\n\n- [Soketi ホームページ](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## アナリティクス(分析)\n\nアプリケーションを開発していく上で、ユーザーデータはとても貴重です。ここでは、私たちがおすすめするアナリティクスプロバイダーをご紹介します。\n\n### Plausible\n\nアナリティクスが必要ですか？Plausible は、それを得るための最も迅速な方法の 1 つです。非常にミニマムで、[Next.js 用のシンプルなプラグイン](https://plausible.io/docs/proxy/guides/nextjs)もあります。\n\n- [Plausible ホームページ](https://plausible.io/)\n\n### Umami\n\nUmami は、Google アナリティクスの代替であり、オープンソースでセルフホスティング可能、シンプルで高速、プライバシーに重点を置いたソフトウェアです。PlanetScale をデータベースとして、Vercel や Railway などに実に簡単にデプロイすることができます。\n\n- [Umami ホームページ](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n# その他\n\n### Next Bundle Analyzer\n\nアプリケーションのビルド出力に何が含まれるかを判断するのが難しい場合があります。Next Bundle Analyzer は、生成される JavaScript バンドルを視覚化し分析する簡単な方法です。\n\n- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/ja/t3-collection.mdx",
    "content": "---\ntitle: T3 コレクション\ndescription: T3 Stackを使用するクールなOSSプロジェクトと企業\nlayout: ../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\nT3 スタックを使用したプロジェクトを作成し、それを共有したいですか？リストに追加してください！\n\n## T3 Stack を使用して作られたオープンソースのアプリケーション\n\n<OpenSourceAppList />\n\n## T3 Stack を利用している企業\n\nアプリケーション開発に T3 スタックを使用している企業をぜひ教えてください。あなたの会社は T3 スタックを使っていることを共有したいですか？リストに追加してください！\n\n<CompanyList />\n\n<Callout type=\"tip\">\nT3 スタックを使ったクールなプロジェクトをお持ちですか？[プルリクエスト](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)を作成し、ここに追加してください！\n\n</Callout>\n"
  },
  {
    "path": "www/src/pages/ja/usage/env-variables.mdx",
    "content": "---\ntitle: 環境変数\ndescription: Create T3 Appを始めるにあたって\nlayout: ../../../layouts/docs.astro\nlang: ja\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App は [Zod](https://github.com/colinhacks/zod) を使用して、`src/env.js`にいくつかの追加ロジックを提供することにより、実行時*および*構築時に環境変数の検証を行います。\n\n## env.js\n\n_要約; 環境変数を追加する場合は、`.env`に追加するとともに、`src/env.js`にバリデーターを定義する必要があります。_\n\nこのファイルは、スキーマと、オブジェクトの検証ロジックおよび再構築の、2 つの部分に分かれています。検証ロジックは触る必要がありません。\n\n```ts:env.js\nconst server = z.object({\n  NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n});\n\nconst client = z.object({\n  // NEXT_PUBLIC_CLIENTVAR: z.string(),\n});\n\nconst processEnv = {\n  NODE_ENV: process.env.NODE_ENV,\n  // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\n};\n```\n\n### サーバースキーマ\n\nサーバーサイドの環境変数スキーマをここで定義します。\n\n<Callout type=\"warning\">\n  重要なシークレットがクライアント側に漏れないようにするため、ここでのキーには\n  `NEXT_PUBLIC` の接頭辞をつけないようにしてください。\n</Callout>\n\n### クライアントスキーマ\n\nクライアント側の環境変数のスキーマをここで定義します。\n\nクライアントに公開するには接頭辞 `NEXT_PUBLIC` を付ける必要があります。接頭辞を付けない場合、検証が失敗するので不正な構成を検出できます。\n\n### processEnv オブジェクト\n\nここで `process.env` を再構築します。\n\nZod スキーマを解析できる JavaScript オブジェクトが必要で、Next.js が環境変数を扱う方法のため、通常のオブジェクトのように process.env を再構築できません。そのため、手動で行う必要があります\n\nTypeScript は、両方のスキーマからすべてのキーを再構築したことを確認するのに役立ちます。\n\n```ts\n// ❌ This doesn't work, we need to destruct it manually\nconst schema = z.object({\n  NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nconst validated = schema.parse(process.env);\n```\n\n### バリデーションロジック\n\n_興味のある読者のために:_\n\n<details>\n<summary>高度な話題: バリデーションロジック</summary>\n\n環境（サーバーまたはクライアント）に応じて、両方のスキーマが検証されるのか、クライアントのスキーマだけが検証されるのかが決まります。つまり、サーバーの環境変数が未定義であっても、バリデーションが失敗することはありません。つまり、環境変数のエントリーポイントを 1 つにすることができます。\n\n```ts\n// src/env.js\n\nconst isServer = typeof window === \"undefined\";\n\nconst merged = server.merge(client);\nconst parsed = isServer\n  ? merged.safeParse(processEnv) // <-- on server, validate all\n  : client.safeParse(processEnv); // <-- on client, validate only client\n\nif (parsed.success === false) {\n  console.error(\n    \"❌ Invalid environment variables:\\n\",\n    ...formatErrors(parsed.error.format()),\n  );\n  throw new Error(\"Invalid environment variables\");\n}\n```\n\nそして、プロキシオブジェクトを使って、クライアントでサーバーサイドの環境変数にアクセスしようとすると、エラーを投げるようにしています。\n\n```ts\n// src/env.js\n\n// proxy allows us to remap the getters\nexport const env = new Proxy(parsed.data, {\n  get(target, prop) {\n    if (typeof prop !== \"string\") return undefined;\n    // on the client we only allow NEXT_PUBLIC_ variables\n    if (!isServer && !prop.startsWith(\"NEXT_PUBLIC_\"))\n      throw new Error(\n        \"❌ Attempted to access serverside environment variable on the client\",\n      );\n    return target[prop]; // <-- otherwise, return the value\n  },\n});\n```\n\n</details>\n\n## 環境変数の使用\n\n環境変数を使いたいときは、`env.js`からインポートして、通常と同じように使うことができます。これをクライアントでインポートして、サーバー側の環境変数にアクセスしようとすると、ランタイムエラーが発生します。\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` is fully typesafe and provides autocompletion\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ This will throw a runtime error\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ This is fine\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nデフォルトの `.env` ファイルはバージョンコントロールにコミットされないので、初期構成プロジェクトには`.env.example` ファイルも用意しました。このファイルは、シークレット情報が削除された `.env` ファイルのコピーを保存しておくことができます。これは必須ではありませんが、貢献者が自分の環境をできるだけ簡単に立ち上げられるようにするために、example を最新に保つことをお勧めします。\n\nNext.js などのいくつかのフレームワークやビルドツールでは、シークレット情報を `.env.local` ファイルに保存し、 `.env` ファイルをプロジェクトにコミットすることを推奨するものがあります。しかしこれだと誤ってプロジェクトにシークレット情報をコミットしてしまうかもしれないため、あまりお勧めできません。その代わりに、シークレット情報を `.env` に保存し、 `.env` ファイルを `.gitignore` に保存し、 `.env.example` ファイルのみをプロジェクトにコミットすることを推奨します。\n\n## 環境変数を追加する\n\nプロジェクトが必要とする環境変数がない状態でビルドが完了しないようにするために、**2 箇所** に新しい環境変数を追加する必要があります：\n\n📄 `.env`: 通常の`.env`ファイルに入力するように、環境変数を入力します（例：`KEY=VALUE`）。\n\n📄 `env.js`：Zod スキーマを定義することで、環境変数に適切な検証ロジックを追加します。（例：`KEY: z.string()` ）。そして、環境変数を `process.env` から `processEnv` オブジェクトに再構築します（例：`KEY: process.env.KEY` ）。\n\nオプションで、`.env.example`を最新化しておいても良いでしょう：\n\n📄 `.env.example`：環境変数を入力します。ただし、シークレット値は含めないように注意してください。(例： `KEY=VALUE` or `KEY=`)\n\n### 例\n\n_サーバーサイドの環境変数として、Twitter API Token を追加したい_。\n\n1. 環境変数を `.env` に追加する：\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. 環境変数を `env.js` に追加する：\n\n```ts\nexport const server = z.object({\n  // ...\n  TWITTER_API_TOKEN: z.string(),\n});\n\nexport const processEnv = {\n  // ...\n  TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n};\n```\n\n3. _オプション:_ 環境変数を `.env.example` に追加しますが、トークン値自体は含めないようにします。\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/ja/usage/first-steps.md",
    "content": "---\ntitle: はじめの一歩\ndescription: 新しいT3アプリを使い始める\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\n新しい T3 アプリのために初期構成を生成し、準備ができたとして、ここではアプリを動作させるために必要な最低限の手順を説明します。\n\n## データベース\n\nアプリケーションに Prisma を含めた場合には、アプリケーションのルートディレクトリから`npx prisma db push`を実行してください。このコマンドは Prisma スキーマをデータベースと同期させ、スキーマに基づいて Prisma クライアントの TypeScript 型を生成します。なお、このコマンドを実行した後、生成された型を検出できるように [TypeScript サーバーを再起動する](https://tinytip.co/tips/vscode-restart-ts/) 必要があることに注意して下さい。\n\n## 認証\n\nアプリケーションに NextAuth.js を含めた場合、まず`DiscordProvider`から始めます。これは NextAuth.js が提供するプロバイダの中で最もシンプルなものの一つですが、初期設定が少し必要です。\n\nもちろん、別の認証プロバイダを使いたい場合は、NextAuth.js が提供する[多数のプロバイダ](https://next-auth.js.org/providers/)から選んで利用することができます。\n\n1. Discord のアカウントが必要になりますので、まだの方は登録してください。\n2. https://discord.com/developers/applications に移動し、右上の「New Application」をクリックします。アプリケーションの名前を付け、利用規約に同意してください。\n3. アプリケーションの作成が完了したら、「Settings → OAuth2 → General」に移動してください。\n4. 「Client ID」をコピーし、`AUTH_DISCORD_ID`として`.env`に追加します。\n5. 「Reset Secret」をクリックし、新しいシークレット情報をコピーし、`AUTH_DISCORD_SECRET`として`.env`に追加します。\n6. 「Add Redirect」をクリックし、`http://localhost:3000/api/auth/callback/discord`と入力します。\n\n   - 本番環境でのデプロイの場合は、前述の手順で別の Discord アプリケーションを作成しますが、今回は`http://localhost:3000`をデプロイ先の URL で置き換えてください。\n\n7. 変更を保存します。\n\nこれでログインできるようになります。\n\n## エディターの設定\n\n開発者体験を最適にするために、以下の拡張機能を推奨します。以下のリンクは、それぞれのエディター用のプラグインサポートを提供します。\n\n- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)\n- [Prettier Extension](https://prettier.io/docs/en/editors.html)\n\n## 次のステップへ\n\n- もしあなたのアプリケーションが tRPC を含んでいるならば、`src/pages/index.tsx` と `src/server/api/routers/post.ts` をチェックして、tRPC クエリがどのように動作するかを見てください。\n- Create T3 App のドキュメントや、あなたのアプリケーションに含まれるパッケージのドキュメントを見てみてください。\n- [Discord](https://t3.gg/discord)に参加し、[GitHub](https://github.com/t3-oss/create-t3-app)でスターを付けてください！:)\n"
  },
  {
    "path": "www/src/pages/ja/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Usage\",\n  layout: \"docs\",\n  description: \"Learn how to use the different technology from the T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/ja/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: NextAuth.jsの使い方\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\nNext.js アプリケーションが認証システムを必要とするとき、NextAuth.js は、自分で構築する手間をかけずに、複雑なセキュリティを導入できる優れたソリューションです。NextAuth.js には OAuth 認証をすばやく追加するための豊富なプロバイダーの一覧が付属しており、多くのデータベースや ORM のためのアダプターを提供しています。\n\n## コンテクストプロバイダー\n\nアプリケーションのエントリーポイントでは、アプリケーションが [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider)でラップされていることがわかります：\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nこのコンテキストプロバイダーによって、アプリケーションはセッションデータを props として渡すことなく、アプリケーションのどこからでもアクセスできるようになります：\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Handle unauthenticated state, e.g. render a SignIn component\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## サーバーサイドでセッションを取得する\n\n時には、サーバー上でセッションを要求したいこともあるかもしれません。そのためには、`create-t3-app`が提供するヘルパー関数 `getServerAuthSession` を使ってセッションをプリフェッチし、`getServerSideProps` を使ってクライアントに渡します：\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTE: `session` wont have a loading state since it's already prefetched on the server\n\n  ...\n}\n```\n\n## セッションに `user.id` を含める\n\nCreate T3 App は、NextAuth.js の設定にある[session callback](https://next-auth.js.org/configuration/callbacks#session-callback)を利用して、ユーザー ID を`session`オブジェクトに含めるように設定します。\n\n```ts:server/auth.ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nこれは、`session`オブジェクトにアクセスしたときに `user.id` が型付けされることを確認するために型宣言ファイルと組合せて使用されます。詳細については NextAuth.js のドキュメントにある [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) を参照ください。\n\n```ts:server/auth.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\n同じパターンを使って、`role`フィールドのような他のデータを`session`オブジェクトに追加することができますが、**クライアントに機密データを保存するために使用してはなりません**。\n\n## tRPC との併用\n\nNextAuth.js を tRPC で利用する場合、[ミドルウェア](https://trpc.io/docs/v10/middlewares) を使って、再利用可能で保護されたプロシージャを作成することができます。これにより、認証されたユーザーのみがアクセスできるプロシージャを作成することができます。`create-t3-app`は、認証されたプロシージャの中でセッションオブジェクトに簡単にアクセスできるように、すべてセットアップしてくれます。\n\nこれは、2 段階のプロセスで行われます：\n\n1. [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession) 関数を使用して、リクエストヘッダーからセッションを取得します。通常の `getSession`の代わりに`getServerSession` を使用する利点は、サーバーサイドのみの関数であるため、不要なフェッチ呼び出しが発生しないことです。`create-t3-app`は、この特殊な API を抽象化するヘルパー関数を作成するので、セッションにアクセスするたびに、NextAuth.js のオプションと`getServerSession` 関数の両方をインポートする必要がありません。\n\n```ts:server/auth.ts\nexport const getServerAuthSession = (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nこのヘルパー関数を使って、セッションを取得し、tRPC コンテキストに渡すことができます：\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. ユーザーが認証されているかどうかをチェックする tRPC ミドルウェアを作成します。そして、そのミドルウェアを `protectedProcedure` で使用します。これらのプロシージャの呼び出し元はすべて認証されていなければなりません。そうでなければ、エラーが投げられるので、クライアントで適切にエラー処理を行えます。\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nセッションオブジェクトは、ユーザーの軽くて最小限の表現であり、いくつかのフィールドしか含んでいません。`protectedProcedures`を使用するとユーザー id にアクセスでき、データベースからさらにデータを取得するのに使用できます。\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Prisma との併用法\n\nNextAuth.js を Prisma と共に動作させるには、多くの[初期設定](https://authjs.dev/reference/adapter/prisma/)が必要ですが、`create-t3-app` はこのすべてを処理します。`create-t3-app` の実行において Prisma と NextAuth.js の両方を選択すると、必要なモデルがすべて設定された、完全に動作する認証システムを手に入れることができます。初期構成として生成されたアプリケーションには、Discord OAuth プロバイダがあらかじめ設定されています。これを使っているのは一番簡単に始められるからで、`.env`にトークンを設定するだけで準備完了です。しかし、[NextAuth.js ドキュメント](https://next-auth.js.org/providers/) に従えば、簡単に他のプロバイダを追加することもできます。なお、プロバイダによっては、特定のモデルに余分のフィールドを追加しなければならない場合があります。利用したいプロバイダのドキュメントを読んで、必要なフィールドがすべて揃っていることを確認することをお勧めします。\n\n### モデルに新しいフィールドを追加する\n\n`User`、`Account`、`Session`、`VerificationToken`のいずれかのモデルに新しいフィールドを追加する場合（ほとんどの場合、変更する必要があるのは`User`モデルのみです）、[Prisma アダプター](https://next-auth.js.org/adapters/prisma) が新しいユーザーのサインアップやログイン時に自動的にこれらのモデル上にフィールドを作成することを念頭に置いておく必要があります。したがって、これらのモデルに新しいフィールドを追加する場合は、デフォルト値を指定する必要があります。\n\n例えば、`User`モデルに `role` を追加したい場合、`role` フィールドにデフォルト値を指定する必要があります。これは `User` モデルの `role` フィールドに `@default` 値を追加することで実現できます：\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Next.js ミドルウェアを使った利用法\n\nNextAuth.js を Next.js ミドルウェアで利用する場合、認証に [JWT セッション戦略](https://next-auth.js.org/configuration/nextjs#caveats)を利用する必要があります。これは、ミドルウェアが JWT である場合にのみ、セッションクッキーにアクセスすることができるためです。デフォルトでは、Create T3 App は、データベースアダプターとして Prisma と組み合わせて、**default**データベースストラテジーを使用するように構成されています。\n\n## デフォルトの DiscordProvider を設定する\n\n1. [Discord Developer Portal の Application セクション](https://discord.com/developers/applications)に向かい「New Application」をクリックします。\n2. 設定メニューの 「OAuth2 ⇒ General」に行きます\n\n- Client ID をコピーして、`.env`の`AUTH_DISCORD_ID`に貼り付けます。\n- Client Secret の下にある 「Reset Secret」をクリックし、その文字列を`.env`の`AUTH_DISCORD_SECRET`にコピーしてください。このシークレット情報は二度と表示されないことと、リセットすると既存のシークレット情報は失効してしまうことについて注意してください。\n- 「Add Redirect」をクリックし、`<app url>/api/auth/callback/discord` を貼り付ける(ローカル開発サーバの場合の例：<code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- 変更を保存します\n- 開発用と本番用で同じ Discord Application を使用できますが、推奨はしません。また、開発時には[プロバイダをモックする](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts)こと検討するのもよいでしょう。\n\n## お役立ち情報\n\n| リソース                                  | リンク                                  |\n| ----------------------------------------- | --------------------------------------- |\n| NextAuth.js ドキュメント                  | https://next-auth.js.org/               |\n| NextAuth.js GitHub                        | https://github.com/nextauthjs/next-auth |\n| tRPC キッチンシンク - NextAuth と併用して | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/ja/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Next.jsの使い方\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\nNext.js は、React アプリケーションのためのバックエンドフレームワークです。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n[Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw) をチェックして、Next.js とは何であり、どのように機能するのかをより深く理解しましょう。</p>\n\n## なぜ Next.js を使う必要があるの？\n\n私たちは React が大好きです。これまで想像もしなかったような方法で UI 開発を身近なものにしてくれました。しかし、その反面、開発者を険しい道へ導くこともあります。Next.js は、React を使ったアプリケーションを作成するための、思想に拘りすぎず、かつ強力に最適化されたアプローチを提供します。ルーティングから API 定義、画像レンダリングに至るまで、私たちは Next.js が開発者を正しい判断に導いてくれると信じています。\n\nNext.js と[Vercel](https://vercel.com/)を組み合わせることで、これまで以上に簡単に Web アプリケーションの開発とデプロイができるようになります。非常に寛大な無料利用枠と直感的なインターフェイスが、「ポイント&クリック」でサイト公開を行えるソリューションを提供します（We ❤️ Vercel）。\n\n## Static/Server Props を取得する\n\nNext.js の大きな特徴はデータフェッチ機能です。各メソッドの使い方や違いを理解するために、[公式ドキュメント](https://nextjs.org/docs/basic-features/data-fetching)を一読することを強くお勧めします。`getServerSideProps`は、ブロッキングする同期呼び出しであり、サイトの速度を低下させるため、特別な理由がない限りは基本的には非推奨です。データが動的でインクリメンタルに取得できる場合、[Incremental Static Regeneration(インクリメンタルな静的再生成)](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration)は`getServerSideProps`に代わる素晴らしい方法です。\n\n## お役立ち情報\n\n| リソース                          | リンク                             |\n| --------------------------------- | ---------------------------------- |\n| Next.js ドキュメント              | https://nextjs.org/docs            |\n| Next.js GitHub                    | https://github.com/vercel/next.js  |\n| Next.js ブログ                    | https://nextjs.org/blog            |\n| Next.js Discord                   | https://nextjs.org/discord         |\n| Next.js Twitter                   | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube チャンネル | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/ja/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Prismaの使用方法\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\nPrisma は TypeScript のための ORM で、`schema.prisma`ファイルでデータベーススキーマとモデルを定義し、バックエンドからデータベースとやり取りするための型安全なクライアントを生成することができます。\n\n## Prisma Client\n\n`src/server/db.ts`にある Prisma Client は、グローバル変数としてインスタンス化され（Prisma チームが[ベストプラクティス](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem)として推奨）、API ルートで使用するためにエクスポートされます。Prisma クライアントは、デフォルトで [コンテキスト](/ja/usage/trpc#-serverapitrpcts) に含まれており、各ファイルで個別にインポートするのではなく、こちらを使用することを推奨します。\n\n## スキーマ\n\nPrisma のスキーマファイルは、`/prisma/schema.prisma`にあります。このファイルでデータベーススキーマとモデルを定義し、Prisma クライアントを生成する際に使用されます。\n\n### NextAuth.js と組み合わせた場合\n\nNextAuth.js と Prisma を組み合わせて選択すると、`User`, `Session`, `Account`, `VerificationToken`モデルの推奨値が[NextAuth.js ドキュメント](https://next-auth.js.org/adapters/prisma)に従って設定されてスキーマファイルが生成されます。\n\n## デフォルトのデータベース\n\nデフォルトのデータベースは SQLite データベースで、開発や PoC(概念実証) を素早く行うのには適していますが、本番環境での使用はお勧めできません。使用するデータベースを変更するには、`datasource` ブロックの `provider` を `postgresql` または `mysql` に変更し、環境変数内の接続文字列でデータベースを指定します。\n\n## データベースのシーディング\n\n[データーベースのシーディング](https://www.prisma.io/docs/guides/database/seed-database)(訳註: データベース構築時にダミーデータや初期データを投入すること)は、データベースに素早くテストデータを投入して開始するのにとても役立ちます。シーディングを設定するには、`/prisma`ディレクトリに `seed.ts` ファイルを作成し、シードスクリプトを `package.json` ファイルに追加する必要があります。また、シードスクリプトを実行できる TypeScript ランナーも必要です。TypeScript ランナーには、esbuild を使用し、ESM 設定を必要としない非常にパフォーマンスの高い [tsx](https://github.com/esbuild-kit/tsx) をお勧めしますが、`ts-node`やその他のランナーも使えます。\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nその後、`pnpm db-seed` (または `npm`/`yarn`) を実行して、データベースへのシーディングを実行します。\n\n## お役立ち情報\n\n| リソース                                | リンク                                                                                                                                            |\n| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Prisma ドキュメント                     | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                           | https://github.com/prisma/prisma                                                                                                                  |\n| Prisma マイグレーションプレイグラウンド | https://playground.prisma.io/guides                                                                                                               |\n| NextAuth.JS Prisma アダプタ             | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| PlanetScale 接続ガイド                  | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/ja/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Tailwind CSSの使い方\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\n## Tailwind CSS とは何ですか？\n\nTailwind CSS は、通常の CSS では必要になるコンテキスト切り替え無しで、カスタムデザインを構築するための小さな[ユーティリティファースト](https://tailwindcss.com/docs/utility-first) CSS フレームワークです。純粋な CSS フレームワークであり、あらかじめ構築されたコンポーネントやロジックを提供しません。また、Material UI のようなコンポーネントライブラリと比較して、[全く異なる一連の利点](https://www.youtube.com/watch?v=CQuTF-bkOgc)を提供します。\n\nこれにより、以下の例のように、CSS が驚くほど簡単に、素早く書けるようになります：\n\n従来の CSS の場合：\n\n1. CSS を（多くの場合別ファイルで）書く。\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. CSS をコンポーネントにインポートする\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. HTML にクラス名を追加する\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nTailwind で同じことをするとこうなります：\n\n1. HTML にクラス名を書く、以上。\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nTailwind CSS は React Components と併用することで、UI を素早く構築するのに究極の威力を発揮します。\n\nTailwind CSS には美しい組込みのデザインシステムが備わっており、厳選されたカラーパレット、均一なデザインを実現する width/height や padding/margin などのスタイルのサイズのパターン、レスポンシブなレイアウトを作成するためのメディアブレークポイントなどがすぐに使える状態で提供されています。このデザインシステムはカスタマイズや拡張を行うことができ、プロジェクトが必要とするスタイルのツールボックスを正確に作成することができます。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla better known as [mewtru](https://twitter.com/trunarla) gave an amazing talk on [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n[mewtru](https://twitter.com/trunarla)として知られる Tru Narla は、[Tailwind CSS を使ったデザインシステムの構築](https://www.youtube.com/watch?v=T-Zv73yZ_QI)について素晴らしい講演をしました。\n\n## 使用方法\n\nTailwind の書き味を向上させるために、Tailwind 用のエディタプラグインがインストールされていることを確認してください。\n\n### 拡張機能およびプラグイン\n\n- [VSCode 拡張](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains 拡張](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### 書式設定\n\nTailwind CSS のクラス名は、少し乱雑になりやすいので、クラス名のフォーマッタは必需品です。[Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) は、出力される css バンドルとクラス名が一致するように、クラス名を[推奨順序](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted)でソートします。CLI で Tailwind を選択すると、これをインストール・設定します。\n\n### 条件付きでクラスを適用する\n\n三項演算子を使った条件分岐を伴うクラス名の追加は、非常に面倒で読みにくいものになります。以下のパッケージは、条件付きロジックを使用する際に、クラス名を整理するのに役立ちます。\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## お役立ち情報\n\n| リソース                        | リンク                                                   |\n| ------------------------------- | -------------------------------------------------------- |\n| Tailwind ドキュメント           | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind チートシート           | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss             | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind コミュニティ           | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord サーバー       | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube チャンネル | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind プレイグラウンド       | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/ja/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: tRPCの使い方\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\ntRPC では、コード生成やランタイムの肥大化なしで、エンドツーエンドの型安全な API を書くことができます。TypeScript の優れた型推論機能を利用して API ルーターの型定義を推論し、フロントエンドから 完全に型安全かつ自動補完で API プロシージャを呼び出すことができます。tRPC を使用すると、フロントエンドとバックエンドがより近しいものに感じられ、極上の開発者体験を得ることができます。\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>私は、従来の API レイヤーの必要性を排除することによって、迅速なイテレーションを回してもアプリケーションが壊れないという自信を持ちつつ、人々がより速く動けるようにするために tRPC を開発しました。\"\n<span aria-hidden=\"true\"></span>\n\n</p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - tRPCの開発者</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## tRPC の使い方\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC のコントリビューターである[trash_dev](https://twitter.com/trashh_dev)が tRPC について[Next.js Conf での決定的な講演](https://www.youtube.com/watch?v=2LYM8gf184U)を作成しました。未見の方はぜひご覧ください。\n\ntRPC では、バックエンドで TypeScript の関数を書き、それをフロントエンドから呼び出します。単純な tRPC プロシージャは次のようなものです：\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nこれは tRPC プロシージャ（従来のバックエンドのルートハンドラに相当）で、まず Zod を使って入力の検証を行います（これは[環境変数の検証](./env-variables)に使っているのと同じ検証ライブラリです）。この場合、入力が文字列であることを確認しています。入力が文字列でない場合は、代わりに情報提供のためのエラー情報をレスポンスとして送信します。\n\n入力の後、[query](https://trpc.io/docs/v10/react-queries)、[mutation](https://trpc.io/docs/v10/react-mutations)、[subscription](https://trpc.io/docs/v10/subscriptions)のいずれかであるリゾルバー関数を連鎖させます。この例では、リゾルバは[prisma](./prisma)クライアントを使用してデータベースを呼び出し、渡された`id`と一致するユーザを返します。\n\n名前空間を共有する一連のプロシージャをまとめた`routers`を定義できます。例えば、`users`のルータ、`posts`のルータ、`messages`のルータがあるとして、これらのルータは、単一の集約された `appRouter` にマージすることができます：\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nルーターの型定義だけをエクスポートすれば良く、クライアントでサーバーサイドのコードをインポートすることは決してないことに注意してください。\n\nさて、フロントエンドからプロシージャを呼び出してみましょう、tRPC は `@tanstack/react-query` のラッパーを提供しており、API 呼び出しが型付けされ推論されるという利点のもとで、TanStack Query が提供する Hooks のフルパワーを活用することができます。以下のように、フロントエンドからプロシージャを呼び出すことができます：\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\n自動補完と型安全の優秀さがすぐに分かるはずです。`api.`と入力するや否や自動補完でルータ一覧が表示され、選択するとそのルータのプロシージャ一覧も表示されます。また、入力したものがバックエンドで定義したバリデータと一致しない場合は、TypeScript のエラーが表示されます。\n\n## エラーを推論する\n\nデフォルトで、`create-t3-app`はバックエンドで検証エラーが発生した場合に、Zod エラーを推論できるようにする[エラーフォーマッタ](https://trpc.io/docs/error-formatting)を設定します。\n\n使用例：\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` returned with an error on the `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## ファイル\n\ntRPC は、`create-t3-app`が設定するかなり多くのボイラープレートを必要とします。生成されるファイルを見ていきましょう：\n\n### 📄 `pages/api/trpc/[trpc].ts`.\n\nこれは API のエントリポイントであり、tRPC ルータを公開しています。通常、このファイルに触れることはあまりありませんが、たとえば CORS ミドルウェアなどを有効にする必要がある場合、エクスポートされた `createNextApiHandler` は [Next.js API ハンドラ](https://nextjs.org/docs/api-routes/introduction) であり、 [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) と [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) オブジェクトを受け取ることを知っていれば便利です。つまり、`createNextApiHandler`を任意のミドルウェアでラッピングすることができます。CORS を追加する[コードスニペットの例はこちら](#cors-の有効化)です。\n\n### 📄 `server/api/trpc.ts`\n\nこのファイルは、コンテキスト作成と tRPC 初期化の 2 つに分かれています：\n\n1. tRPC プロシージャに渡されるコンテキストを定義しています。コンテキストは、すべての tRPC プロシージャがアクセスできるデータであり、データベース接続、認証情報などが置かれるのに最適な場所です。create-t3-app では、リクエストオブジェクトにアクセスできない場合にコンテキストの一部を使用できるようにするために、2 つの関数を使用しています。\n\n- `createInnerTRPCContext`：これは、リクエストに依存しないコンテキストを定義している場所です。例えば、データベース接続などです。この関数は、リクエストオブジェクトがない [統合テスト](#統合テストの例) や [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers) で使用できます。\n\n- `createTRPCContext`：これは、リクエストに依存するコンテキストを定義している場所です。例えば、ユーザのセッションです。`opts.req`オブジェクトを使ってセッションをリクエストし、そのセッションを `createInnerTRPCContext` 関数に渡して最終的なコンテキストを作成します。\n\n2. tRPC を初期化し、再利用可能な[手続き](https://trpc.io/docs/v10/procedures)と[ミドルウェア](https://trpc.io/docs/v10/middlewares)を定義しています。慣例として、`t`オブジェクト全体をエクスポートするのではなく、再利用可能な手続きとミドルウェアを作成し、それらをエクスポートするようにしてください。\n\n[データトランスフォーマー](https://trpc.io/docs/v10/data-transformers)として `superjson` を使用していることにお気づきでしょう。これにより、データがクライアントに到達したときにもデータ型が保持されるため、例えば`Date`オブジェクトを送信すると、クライアントは文字列ではなく`Date`を返します。他の API のほとんどではこうならないでしょう。\n\n### 📄 `server/api/routers/*.ts`.\n\nここでは、API のルート群とプロシージャ群を定義します。慣例として、関連する一連のプロシージャごとに[個別のルータ](https://trpc.io/docs/v10/router)を作成します。\n\n### 📄 `server/api/root.ts`.\n\nここでは、`routers/**`で定義されたすべてのサブルータを 1 つの app ルータに[マージ](https://trpc.io/docs/v10/merging-routers)しています。\n\n### 📄 `utils/api.ts`\n\nこれは tRPC のフロントエンドのエントリポイントです。ここでルーターの**型定義**をインポートし、tRPC クライアントと react-query フックを作成します。バックエンドでデータトランスフォーマーとして `superjson` を有効にしたので、フロントエンドでも有効にする必要があります。これは、バックエンドからのシリアライズされたデータが、フロントエンドでデシリアライズされるようにするためです。\n\nここでは tRPC の[リンク](https://trpc.io/docs/v10/links)を定義し、クライアントからサーバーへのリクエストフローを決定します。ここでは、デフォルトとして [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink) が指定されており、[リクエストバッチ](https://cloud.google.com/compute/docs/api/how-tos/batch) が有効になっています。また、開発中に役立つリクエストログを出力する [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) も使用しています。\n\n最後に、フロントエンドで型を推論するために使える[ヘルパー型](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type)をエクスポートします。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCreate T3 App のコントリビューターである[Christopher Ehrlich](https://twitter.com/ccccjjjjeeee)が[tRPC のデータフローに関するビデオ](https://www.youtube.com/watch?v=x4mu-jOiA0Q)を作成しました。このビデオは、tRPC を使ったことがあるけれども、まだ仕組みがよくわからないと感じる方におすすめです。\n\n## API を外部から呼び出せるようにするには\n\n通常の API では、`curl`、`Postman`、`fetch`などの HTTP クライアントを使用してエンドポイントを呼び出したり、ブラウザから直接呼び出すことができます。しかし、tRPC の場合は少し違います。tRPC クライアントを使わずにプロシージャを呼び出したい場合、2 つの方法が推奨されます：\n\n### 単一のプロシージャを外部に公開する\n\n単一のプロシージャを外部に公開したい場合は、[サーバーサイドコール](https://trpc.io/docs/v10/server-side-calls)を探すことになります。これなら、通常の Next.js の API エンドポイントを作成しつつ、tRPC プロシージャのリゾルバ部分を再利用することができます。\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### すべてのプロシージャを REST エンドポイントとして公開する\n\nもし、すべてのプロシージャを外部に公開したい場合は、コミュニティが作ったプラグイン [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master) をチェックアウトしてください。プロシージャにいくつかの特別なメタデータを追加することで、tRPC ルータから OpenAPI 準拠の REST API を生成することができます。\n\n### 単なる HTTP Requests として\n\ntRPC は HTTP で通信するため、通常の HTTP リクエストとして tRPC プロシージャを呼び出すこともできます。ただし、tRPC が使用している[RPC プロトコル](https://trpc.io/docs/v10/rpc)のため、構文が煩雑になる可能性があります。もし興味があれば、ブラウザのネットワークタブで tRPC のリクエストとレスポンスがどのように見えるかを確認することができます。ただ、これはあくまで教育的な練習として行い、上記の解決策のいずれかを採用することをお勧めします。\n\n## Next.js API エンドポイントとの比較\n\nNext.js API エンドポイントと tRPC プロシージャを比較してみましょう。たとえば、データベースからユーザーオブジェクトを取得して、フロントエンドに返したいとします。Next.js API のエンドポイントは、次のように書きます：\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nこれを前掲した tRPC の例と比較すると、tRPC の利点がわかると思います：\n\n- 各ルートに url を指定する代わりに、ルーター全体が自動補完を持つオブジェクトになります。\n- どの HTTP メソッドが使われたかを検証する必要はありません。\n- リクエストのクエリやボディがプロシージャの中で正しいデータを含んでいるかどうかを検証する必要はありません、Zod がそれを行なっているからです。\n- レスポンスを作成する代わりに、他の TypeScript 関数と同じように、エラーを投げたり、値やオブジェクトを返したりすることができます。\n- フロントエンドでプロシージャを呼び出すと、自動補完と型安全性が提供されます。\n\n## 便利なスニペット\n\n以下、便利そうなスニペットを紹介していきます。\n\n### CORS の有効化\n\nReact Native アプリを含むモノレポなどで、異なるドメインから API を呼び出す必要がある場合、CORS の有効化が必要かもしれません：\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### 楽観的な更新\n\n楽観的な更新とは、API コールが終了する前に UI を更新することです。API コールの終了を待たずに UI に反映されるため、ユーザーにとってより良い体験になります。しかし、データの正確性を重視するアプリケーションでは、バックエンドの状態を「真に」反映していないため、楽観的な更新は避けるべきでしょう。詳しくは、[React Query ドキュメント](https://tanstack.com/query/v4/docs/guides/optimistic-updates)をご覧ください。\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### 統合テストの例\n\nここでは、[Vitest](https://vitest.dev)を使用して、tRPC ルーターが期待通りに動作しているか、入力パーサーが正しい型を推論しているか、返されたデータが期待通りの出力と一致しているかをチェックする統合テストのサンプルを紹介します。\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\nprotected なプロシージャを呼び出す場合は、コンテキストを作成するときにモックした `session` オブジェクトを渡すことができます：\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n\n  // ...\n});\n```\n\n## お役立ち情報\n\n| リソース                 | リンク                                                  |\n| ------------------------ | ------------------------------------------------------- |\n| tRPC ドキュメント        | https://www.trpc.io                                     |\n| tRPC のサンプル集        | https://github.com/trpc/trpc/tree/next/examples         |\n| React Query ドキュメント | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/ja/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: TypeScriptの使用方法\nlayout: ../../../layouts/docs.astro\nlang: ja\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>ガードレールではなく、セーフティネットを作る<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creator of the T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n新人開発者であれ、熟練した開発者であれ、TypeScript は必須の要素だと考えています。最初はとっつきにくいかもしれませんが、多くのツールがそうであるように、使い始めたら元に戻りたいと思うことはないでしょう。\n\nTypeScript は、コードを書く際に、期待されるデータ型を定義することでリアルタイムなフィードバックを提供します。つまりコードエディタで便利な自動補完を提供したり、存在しないプロパティにアクセスしようとしたり、間違った型の値を渡そうとした場合に赤い波線で注意喚起を行います。これがなかったら、あなたは先の段階でその行のバグ取りを行う羽目になっていたでしょう。\n\nあなたが今まさに書いているコードや、のめり込んで集中しているコードに対して、ドキュメントをエディター中で直接表示し、避けられないミスを犯したときに即座にフィードバックが得られるのですから、TypeScript はおそらく、開発者に最も生産性をもたらすツールです。\n\n## 型推論\n\n多くの新しい TypeScript 開発者は、TypeScript の「_記述_」に関心がありますが、そのメリットの多くは実はコードを一切変更せずとも、型推論で得られるのです。型推論とは、何かが型付けされた場合、その型はアプリケーションのフロー全体を通じ、他の場所で再度型宣言することなしで、その型への適合が追従することを意味します。例えばある関数が受け取る引数の型を定義してしまえば、その関数の本体では通常、さらなる TypeScript 特有のコードを必要とせずに型安全になることを意味します。また、ライブラリの開発者は、ライブラリの型を維持するために多大な労力を費やしています。つまり、アプリケーション開発者は、型推論が提供する型と、ビルトインのドキュメントが提供する型の両方からエディタ上で恩恵を受けることができるのです。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n[TypeScript の使い方が間違っているかもしれない](https://www.youtube.com/watch?v=RmGHnYUqQ4k)という Theo のビデオをチェックしてみてください。\n\n## 型推論の強力な活用法\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod)は、TypeScript の上に構築されたスキーマ検証ライブラリです。データの「唯一の真実の情報源」を表すスキーマを書くと、Zod は、ネットワーク境界や外部 API を越えても、アプリケーション全体でデータが有効であることを保証します。\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) は、宣言的で、常にデータが最新化される自動管理されたクエリとミューテーションを提供し、開発者体験と利用者体験の両方を直接改善します。\n\n## お役立ち情報\n\n| リソース                                                       | リンク                                                            |\n| -------------------------------------------------------------- | ----------------------------------------------------------------- |\n| TypeScript ハンドブック                                        | https://www.typescriptlang.org/docs/handbook/                     |\n| TypeScript 初心者向けチュートリアル                            | https://github.com/total-typescript/beginners-typescript-tutorial |\n| タイプチャレンジ                                               | https://github.com/type-challenges/type-challenges                |\n| TypeScript の Rodney Mullen (Matt Pocock)の Youtube チャンネル | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/ja/why.md",
    "content": "---\ntitle: CT3A を選ぶ理由\ndescription: なぜあなたは次のプロジェクトで Create T3 App を選ぶべきなのか\nlayout: ../../layouts/docs.astro\nlang: ja\n---\n\n私たちが Create T3 App の開発を始めたのは、[Theo](https://twitter.com/t3dotgg)が自分の好みの技術のテンプレートを作ることを拒んだからです。create-next-app や[Astro's CLI](https://astro.build)、そして型安全性への全面的な愛に触発されて、Create T3 App チームは新しく T3 Stack プロジェクトを始めるための最高の出発点を作るために懸命に働きました。\n\nNext.js を型安全な方法で使うことに興味があるなら、こここそが始めるべき場所です。私たちが選択した技術的選択について興味がある方は、引き続きお読みください :)\n\n## なぜ TypeScript なのか？\n\nJavaScript は難しいですよね。なんだってこれ以上ルールを増やすのでしょうか？\n\n私たちは、TypeScript が提供する体験が、より優れた開発者になるのに役立つと確信しています。TypeScript は、期待されるデータ型を定義することで、コードを書きながらのリアルタイムのフィードバックを提供し、存在しないプロパティにアクセスを試みたり、間違った型の値を渡そうとすると、エディタで役立つ自動補完を提供したり、赤い波線で警告を発してくれます。Web 開発の初心者であれ、熟練したプロであれ、TypeScript の「厳密さ」は、「バニラ JS」よりもフラストレーションが少なく、一貫した体験を提供してくれるでしょう。\n\n型安全性はあなたをより速くします。もし納得できないなら、あなたは[TypeScript の使い方を間違っているかもしれません...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)。\n\n## なぜ Next.js なのか？\n\n私たちは React が大好きです。React はこれまで想像もしなかったような方法で UI 開発を身近なものにしてくれました。しかし、その反面、開発者を険しい道へ導くこともあります。\n\nNext.js は、React を使ったアプリケーションを作成するための、思想に拘りすぎず、かつ強く最適化したアプローチを提供します。Next.js は、ルーティングから API 定義、画像レンダリングに至るまで、開発者が良い判断ができるように導いてくれると私たちは信じています。\n\n## なぜ tRPC/Prisma/Tailwind/etc なのか？\n\n私たちは物事をできるだけシンプルに保つべきだと信じてやってきましたが、これらの構成要素は私たちが作ってきた、「アプリ」っぽいすべてのプロジェクトで使ってきたことがわかりました。`create-t3-app`は、必要とする構成要素を導入できるように、すばらしく良い仕事をしてくれます。\n\n### tRPC\n\ntRPC は GraphQL が実現してくれるはずのもの、「サーバーに対するシームレスで型安全なクライアント開発」を、定型文を一切使わずに実現するものです。これは TypeScript を巧みに利用したもので、極上の開発体験が得られます。\n\n### Prisma\n\nSQL に対する Prisma は 「JS に対する TypeScript」のようなものです。Prisma はこれまでにない開発者体験を作り出しました。[複数のデータベース](https://www.prisma.io/docs/concepts/database-connectors)と互換性のあるユーザー定義スキーマから型を生成することで、Prisma はデータベースからアプリケーションまでのエンドツーエンドの型安全性を保証します。\n\nPrisma は、データベースの日常的な操作をより簡単にするための[ツール群](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows)を提供しています。特に Prisma Client は、クエリの実行と SQL の使用をほとんど意識しないで済むぐらい簡単にします。Prisma Studio は、データベースの便利な GUI で、コードを書くことなくデータを素早く表示したり操作したりすることができます。\n\n### Tailwind CSS\n\nTailwind は「禅モードの CSS」みたいなものです。\n\nTailwind は、優れたデフォルトの色、間隔(spacing)、その他のプリミティブという形でビルディングブロックを提供することで、見栄えの良いアプリケーションを簡単に作成することができます。また、コンポーネントライブラリとは異なり、アプリケーションを次のレベルまで引き上げようとしたり、美しくユニークなものを作ろうとしたときに、足かせとなってにっちもさっちもいかなくなったりするようなことは Tailwind では起きません。\n\nまた、Tailwind ではインラインスタイルのような書きっぷりをするのですが、クラス名やファイルの編成など、「解決しようとしている問題には直接関係しないことがら」を気にせずにスタイリングできます。\n\n### NextAuth.js\n\nNextJS アプリケーションに認証システムを導入したいとき、NextAuth.js は、がんばって自分で構築する手間をかけずに、複雑なセキュリティ条件下に導入できる優れたソリューションです。NextAuth.js は、OAuth 認証をすばやく追加するための豊富なプロバイダーリストと、多くのデータベースや ORM のためのアダプターを提供しています。\n"
  },
  {
    "path": "www/src/pages/no/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Utrulling med Docker\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nStakken kan rulles ut med Docker. Enten som en enkel kontainer eller som en gruppe kontainere ved hjelp av `docker-compose`. Se [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) for et eksempel-_repo_ som er basert på denne dokumentasjonen.\n\n## Docker-prosjektkonfigurasjon\n\nVær klar over at Next.js krever forskjellig håndtering av variabler som er satt til \"build time\" (tilgjengelig i frontend, prefikset av `NEXT_PUBLIC`) og variabler som bare skal være tilgjengelige på serversiden under kjøring. I denne demonstrasjonen bruker vi to variabler. Så vær oppmerksom på rekkefølgen på kommandolinjeargumentene i `Dockerfile` og i `docker-compose.yml`-filen.\n\n- `DATABASE_URL` (brukes av serveren)\n- `NEXT_PUBLIC_CLIENTVAR` (brukes av klienten)\n\n### 1. Next.js-konfigurasjon\n\nI [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), legg til _output_-alternativet `standalone` for å redusere størrelsen på Docker-_imaget_ ved å benytte [\"Output File Tracing\"](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Lag en dockerignore-fil\n\n<details>\n     <summary>\n     Klikk her og kopier innholdet til <code>.dockerignore</code>:\n     </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Lag Dockerfile\n\n> Siden vi ikke drar serverens miljøvariabler inn i kontaineren, vil [skjema for validering av miljøvariabler](/no/usage/env-variables) feile. For å forhindre dette må vi legge til `SKIP_ENV_VALIDATION=1` i byggkommandoen slik at miljøvariabelskjemaene ikke valideres ved \"build time\".\n\n<details>\n     <summary>\n     Klikk her og kopier innholdet til <code>Dockerfile</code>:\n     </summary>\n<div class=\"content\">\n\n```docker\n##### AVHENGIGHETER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl\nWORKDIR /app\n\n# Installer Prisma-klienten - Fjern denne linjen hvis du ikke bruker Prisma\n\nCOPY prisma ./\n\n# Installer avhengigheter basert på foretrukket pakkebehandler\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Notater_**\n>\n> - _Emulering av `--platform=linux/amd64` er kanskje ikke lenger nødvendig dersom man bruker Node 18._\n> - \\_Se [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) for å forstå hvorfor `libc6-compat` kan være nødvendig.\n> - _Next.js samler inn [anonym bruksdata](https://nextjs.org/telemetry). I `Dockerfile` ovenfor er det allerede to kommenterte linjer med kommandoen `ENV NEXT_TELEMETRY_DISABLED 1`. Fjern kommentarer på den første linjen for å deaktivere datainnsamling under bygging. Den andre linjen deaktiverer datainnsamling under kjøring._\n\n</div>\n</details>\n\n## Bygg og Kjør Bildet Lokalt\n\nBygg og start opp bildet lokalt med følgende kommandoer:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_her\" ct3a-docker\n```\n\nÅpne [localhost:3000](http://localhost:3000/) for å se programmet som kjøres.\n\n## Docker Compose\n\nDu kan også bruke Docker Compose for å bygge bildet og kjøre det i kontaineren.\n\n<details>\n    <summary>\n       Følg trinn 1-4 ovenfor, klikk her og lim inn innholdet i <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_her\n```\n\nKjør kommandoen `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nÅpne [localhost:3000](http://localhost:3000/) for å se programmet som kjører.\n\n</div>\n</details>\n\n## Rull ut til Railway\n\nDu kan bruke en PaaS slik som [Railways](https://railway.app) automatiserte [Dockerfile-utrullinger](https://docs.railway.app/deploy/dockerfiles) for å rulle ut applikasjonen din. Hvis du har installert [Railway CLI](https://docs.railway.app/develop/cli#install), kan du rulle ut applikasjonen din med følgende kommandoer:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nGå til \"Variables\" og lim inn `DATABASE_URL`. Gå deretter til \"Settings\" og velg \"Generate Domain\". For å se et kjørende eksempel på Railway, besøk [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Nyttige Ressurser\n\n| Ressurser                              | Link                                                                 |\n| -------------------------------------- | -------------------------------------------------------------------- |\n| Dockerfile-referanse                   | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file versjon 3-Referanse       | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI-referanse                   | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI-referanse           | https://docs.docker.com/compose/reference/                           |\n| Rulle ut Next.js med Docker Image      | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js i Docker                       | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Next.js med Docker-Eksempel            | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Lag et Docker-bilde fra en Next.js-app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/no/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Utrulling\",\n  layout: \"docs\",\n  description:\n    \"Lær hvordan man ruller ut T3-applikasjonen til produksjonsmiljø.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/no/deployment/netlify.md",
    "content": "---\ntitle: Netlify\ndescription: Utrulling med Netlify\nlayout: ../../../layouts/docs.astro\n---\n\nNetlify er en alternativ distribusjonsleverandør på samme måte som Vercel. Se [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) for et eksempel-repo basert på dette dokumentet.\n\n## Hvorfor hoste på Netlify\n\nKonvensjonell visdom tilsier at Vercel har en overlegen støtte for Next.js fordi Vercel utvikler Next.js. De har en egeninteresse i å sikre at plattformen er innstilt for optimal ytelse og best utvikleropplevelse med Next.js. For de fleste brukstilfeller vil dette være sant, og det vil ikke være fornuftig å avvike fra standardbanen.\n\nDet er også en felles oppfatning at mange Next.js-funksjoner kun støttes på Vercel. Selv om det er sant at nye Next.js-funksjoner vil bli testet og støttet på Vercel på utgivelsestidspunktet som standard, er det også slik at andre leverandører som Netlify raskt vil [implementere og gi ut støtte](https://www.netlify.com/blog/deploy-nextjs-13/) for [stabile Next.js-funksjoner](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nDet er noen fordeler og ulemper for alle distribusjonsleverandører siden ingen enkelt leverandør kan ha den beste støtten for alle brukstilfeller. For eksempel bygde Netlify sin egen [tilpassede Next.js kjøretid](https://github.com/netlify/next-runtime) for Netlifys Edge-funksjoner (som kjører på Deno Deploy) og [opprettholder unik mellomvare for å få tilgang til og endre HTTP-responser](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n> _MERK: For å følge statusen til ustabile Next 13-funksjoner, se [Bruk av Next 13 `app` -katalogen på Netlify](https://github.com/netlify/next-runtime/discussions/1724)._\n\n## Prosjektkonfigurasjon\n\nDet er mange måter å konfigurere byggeinstruksjonene på, inkludert direkte gjennom Netlify CLI- eller Netlify-dashbordet. Selv om det ikke er nødvendig, er det tilrådelig å opprette og inkludere en [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) fil. Dette sikrer at forka og klonede versjoner av prosjektet blir enklere å rulle ut på en reproduserbar måte.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Bruk av Netlify-dashbordet\n\n1. Push koden din til et GitHub-repo og registrer deg for [Netlify](https://app.netlify.com/signup). Etter at du har opprettet en konto, klikker du på **Add new site** og deretter **Import an existing project**.\n\n![Nytt prosjekt på Netlify](/images/netlify-01-new-project.webp)\n\n2. Koble til Git-leverandøren din.\n\n![Importer repository](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Velg prosjektets repository.\n\n![Velg prosjektets repository](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify vil oppdage om du har en `netlify.toml`-fil og automatisk konfigurere build-kommandoen og publiseringskatalogen.\n\n![Nextjs byggeinnstillinger](/images/netlify-04-configure-build-settings.webp)\n\n5. Klikk **Show advanced** og deretter **New variable** for å legge til miljøvariablene dine.\n\n![Legg til miljøvariabler](/images/netlify-05-env-vars.webp)\n\n6. Klikk på **Deploy site**, vent til bygget er fullført, og se det nye nettstedet ditt.\n\n## Bruk av Netlify CLI\n\nFor å rulle ut fra kommandolinjen må du først pushe prosjektet til et GitHub-repo og [installere Netlify CLI](https://docs.netlify.com/cli/get-started/). Du kan installere `netlify-cli` som en prosjektavhengighet eller installere den globalt på maskinen din med følgende kommando:\n\n```bash\nnpm i -g netlify-cli\n```\n\nFor å teste prosjektet ditt lokalt, kjør [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) kommando og åpne [`localhost:8888`](http://localhost:8888/) for å se din lokalt kjørende Netlify-app:\n\n```bash\nntl dev\n```\n\nKjør [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) kommando for å konfigurere prosjektet:\n\n```bash\nntl init\n```\n\nImporter prosjektets miljøvariabler fra `.env`-filen din med [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nRull ut prosjektet ditt med [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Du må ha med `--build`-flagget for å kjøre build-kommandoen før utrullingen og `--prod`-flagget for å rulle ut til nettstedets hoved-URL:\n\n```bash\nntl deploy --prod --build\n```\n\nFor å se et kjørende eksempel på Netlify, besøk [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/no/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Utrulling med Vercel\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nVi anbefaler at du ruller ut applikasjonen din til [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Det gjør det superenkelt å rulle ut Next.js-applikasjoner.\n\n## Prosjektkonfigurasjon\n\nVercel vil mest sannsynlig automatisk konfigurere byggekommandoen og publisere katalogen din. Du kan imidlertid også spesifisere dette, i tillegg til andre konfigurasjoner, i en fil som heter [`vercel.json`](https://vercel.com/docs/project-configuration) og inkludere følgende kommandoer:\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Bruk av Vercel Dashboard\n\n1. Etter å ha pushet koden til et GitHub-repo, logger du på [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) med GitHub og klikker på **Add New Project**.\n\n![Nytt prosjekt på Vercel](/images/vercel-new-project.webp)\n\n2. Importer GitHub-repoet med prosjektet du vil rulle ut.\n\n![Importer repository](/images/vercel-import-project.webp)\n\n3. Legg til miljøvariablene dine.\n\n![Legg til miljøvariabler](/images/vercel-env-vars.webp)\n\n4. Klikk på **Deploy**. Hvis du nå _pusher_ repoet ditt vil Vercel automatisk rulle ut applikasjonen din på nytt!\n\n## Bruke Vercel CLI\n\nFor å rulle ut applikasjonen din fra kommandolinjen, må du først [installere](https://vercel.com/docs/cli#installing-vercel-cli) Vercel CLI globalt.\n\n```bash\nnpm i -g vercel\n```\n\nKjør kommandoen [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) for å rulle ut prosjektet ditt.\n\n```bash\nvercel\n```\n\nLegg til `--env DATABASE_URL=DIN_DATABASE_URL_HER` for miljøvariabler slik som strengen for databasetilkobling. Bruk `--yes` hvis du vil hoppe over spørsmålene rundt utrullingen og angi standardsvaret for hvert spørsmål.\n\n```bash\nvercel --env DATABASE_URL=DIN_DATABASE_URL_HER --yes\n```\n\nEtter den første utrullingen vil denne kommandoen rulle ut til en forhåndsvisnings-_branch_. Du må legge til `--prod` for å _pushe_ endringer direkte til produksjonmiljøet.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/no/faq.md",
    "content": "---\ntitle: FAQ\ndescription: Ofte stilte spørsmål om Create T3 App\nlayout: ../../layouts/docs.astro\nlang: no\n---\n\nHer er noen ofte stilte spørsmål om \"create-t3-app\".\n\n## Hva nå? Hvordan lager jeg en app med dette?\n\nVi prøver å holde dette prosjektet så enkelt som mulig, slik at du kan starte med bare det grunnleggende rammeverket vi har laget for deg. Du kan legge til flere ting senere etter hvert som de blir nødvendige.\n\nHvis du ikke er kjent med de forskjellige teknologiene som brukes i dette prosjektet, vennligst se den relevante dokumentasjonen. Hvis du har flere spørsmål kan du bli med i vår [Discord](https://t3.gg/discord) og be om hjelp.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## Hvilke læringsressurser er tilgjengelige for øyeblikket?\n\nSelv om ressursene som er oppført nedenfor, er noen av de beste som finnes for T3-Stakken, anbefaler vårt samfunn (og [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) at du bare begynner å bruke stakken og bygger med den mens du lærer.\n\nHvis du vurderer \"create-t3-app\", er sjansen stor for at du allerede har brukt noen av delene av stakken. Så hvorfor ikke bare hoppe inn i det og lære de andre delene mens du bygger noe?\n\nNå har vi forståelse for at denne metoden ikke fungerer for alle. Så hvis du føler at du har prøvd anbefalingen og fortsatt vil ha noen ressurser, eller du bare ikke er sikker på hvordan å gjøre det selv og/eller føler deg overveldet av stakken, så sjekk ut disse fantastiske veiledningene på `create-t3-app `:\n\n### Artikler\n\n- [Bygg en full stakk-app med create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [En første titt på create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrering av T3-applikasjonen din til et Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrering av Stripe i T3-applikasjonen din](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Videoer\n\n- [Bygg en Twitter-klone med T3-stakken - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n  – [Bygg en Blogg Med T3-stakken – tRPC, TypeScript, Next.js, Prisma og Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Bygg en Live Chat-applikasjon med T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [T3-stakken - Hvordan Vi Bygget Den](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [En oversikt over create-T3-app (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Hvorfor er det `.js`-filer i prosjektet?\n\nI henhold til [3. T3-Prinsipp](/no/introduction#typesafety-isnt-optional), anser vi _typesafety_ som en førsteklasses borger. Dessverre støtter ikke alle rammeverk og plugins TypeScript, noe som betyr at noen av konfigurasjonsfilene nødvendigvis må være `.js`-filer.\n\nVi forsøker å understreke at disse filene er JavaScript for en grunn, ved å eksplisitt deklarere hver filtype (`cjs` eller `mjs`) avhengig av hva som støttes av biblioteket den brukes av. Dessuten er alle `js`-filene i dette prosjektet fortsatt typesjekket ved bruk av checkJs alternativet i kompilatoren (tsconfig).\n\n## Jeg sliter med å legge til i18n i applikasjonen min. Er det noen referanse jeg kan bruke?\n\nVi har bestemt oss for å ikke inkludere i18n som standard i `create-t3-app` fordi det er et emne omgitt av mange meninger og det er mange måter å implementere det på.\n\nMen hvis du sliter med å implementere det og ønsker å se et referanseprosjekt, så har vi et [referanserepo](https://github.com/juliusmarminge/t3-i18n) som viser hvordan du kan legge til i18n i en T3-app ved å bruke [next-i18next](https://github.com/i18next/next-i18next).\n\n## Hvorfor bruker vi `/pages` og ikke `/app` fra Next.js 13?\n\nI henhold til [2. T3-Prinsipp](/no/introduction#bleed-responsibly), elsker vi ny teknologi, men verdsetter stabilitet. Det er vanskelig flytte hele ruteren og det er ikke en god idé å ta disse risikoene der, [se: Moderne og Ansvarsbevisst](https://youtu.be/mnwUbtieOuI?t=1662). Mens `/app` er [et glimt inn i fremtiden](https://youtu.be/rnsC-12PVlM?t=818), er det ikke klart for produksjon; API-et er i beta og forventes å ha _breaking changes_.\n\nFor en liste over støttede, planlagte og funksjoner under arbeid i `/app`-katalogen, gå til [beta Next.js docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n"
  },
  {
    "path": "www/src/pages/no/folder-structure-pages.mdx",
    "content": "---\ntitle: Mappestruktur (Pages)\ndescription: Mappestrukturen til en nylig opprettet T3 App\nlayout: ../../layouts/docs.astro\nlang: no\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nVelg pakkene dine for å se mappestrukturen til en app med disse valgene. Lenger ned finner du en beskrivelse av hver oppføring.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\n`prisma`-mappen inneholder `schema.prisma`-filen som brukes til å konfigurere databasetilkoblingen og databaseskjemaet. Det er også stedet for å lagre migreringsfiler og/eller _seedscript_, dersom de brukes. Se [Bruk av Prisma](/no/usage/prisma) for mer informasjon.\n\n</div>\n<div>\n\n### `public`\n\n`public`-mappen inneholder statiske ressurser som betjenes av _webserveren_. `favicon.ico`-filen er et eksempel på en statisk ressurs.\n\n</div>\n<div>\n\n### `src/env`\n\nBrukes for validering av miljøvariabler og typedefinisjoner - se [Miljøvariabler](usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\n`pages`-mappen inneholder alle sidene til Next.js-applikasjonen. `index.tsx`-filen i rotkatalogen til `/pages` er hjemmesiden til applikasjonen. Filen `_app.tsx` brukes til å pakke applikasjonen sammen med _providers_. Se [Next.js-dokumentasjon](https://nextjs.org/docs/basic-features/pages) for mer informasjon.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nMappen `api` inneholder alle API-rutene til Next.js-applikasjonen. Filen `examples.ts` inneholder et eksempel på en rute som bruker [Next.js API-rute](https://nextjs.org/docs/api-routes/introduction)-funksjonaliteten sammen med Prisma. `restricted.ts`-filen inneholder et eksempel på en rute som bruker [Next.js API-rute](https://nextjs.org/docs/api-routes/introduction)-funksjonaliteten, og er beskyttet av [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\n`[...nextauth].ts`-filen håndterer autentiseringslug ruter for NextAuth.js. Den brukes til å håndtere autentiseringsforespørsler. Se [Bruk av NextAuth.js](usage/next-auth) for mer informasjon om NextAuth.js, og [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for informasjon på catch-all/slug-ruter.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\n`[trpc].ts`-filen er inngangspunktet for tRPC-APIet. Den brukes til å håndtere tRPC-forespørsler. Se [Bruk av tRPC](usage/trpc#-pagesapitrpctrpcts) for mer informasjon om denne filen, og [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for informasjon om catch-all/slug-ruter.\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\n`server`-mappen brukes til å tydelig skille serverside-kode fra klientside-kode.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nHovedinngangspunktet for autentiseringslogikk på serversiden. Her setter vi opp NextAuth.js [konfigurasjonsalternativer](usage/next-auth), utfører [modulforstørrelse](usage/next-auth#inclusion-of-userid-on-the-session) samt gir utvikleropplevelsesverktøy for autentisering som for eksempel å hente brukerens økt på serversiden. Se [Bruk av NextAuth.js](usage/next-auth#usage-with-trpc) for mer informasjon.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\n`db.ts` filen brukes til å instansiere Prisma-klienten i globalt omfang. Se [Bruk av Prisma](usage/prisma#prisma-client) og [beste fremgangsmåter for bruk av Prisma med Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for mer informasjon.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\n`api`-mappen inneholder tRPC serverside-koden.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\n`routers`-mappen inneholder alle dine tRPC-underrutere.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\n`example.ts`-filen er et eksempel på en tRPC-ruter som bruker `publicProcedure`-hjelperen for å demonstrere hvordan du oppretter en offentlig tRPC-rute.\n\nBasert på dine valgte pakker inneholder denne ruteren flere eller færre ruter for best mulig å demonstrere bruken til dine behov.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\n`trpc.ts`-filen er hovedkonfigurasjonsfilen for din tRPC-backend. Her inne vi:\n\n1. Definerer kontekst brukt i tRPC-forespørsler. Se [Bruk av tRPC](usage/trpc#-serverapitrpcts) for mer informasjon.\n2. Eksporter prosedyre hjelpere. Se [Bruk av tRPC](usage/trpc#-serverapitrpcts) for mer informasjon.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\n`root.ts`-filen brukes til å slå sammen tRPC-rutere og eksportere dem som en enkelt ruter, så vel som ruterens typedefinisjon. Se [Bruk av tRPC](usage/trpc#-serverapirootts) for mer informasjon.\n\n</div>\n<div>\n\n### `src/styles`\n\n`stiler`-mappen inneholder det globale stilsettet til applikasjonen.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\n`utils`-mappen brukes til å lagre ofte gjenbrukte verktøyfunksjoner.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\n`api.ts`-filen er frontendinngangspunktet til tRPC. Se [Bruk av tRPC](usage/trpc#-utilsapits) for mer informasjon.\n\n</div>\n<div>\n\n### `.env`\n\n`.env`-filen brukes til å lagre miljøvariabler. Se [Miljøvariabler](usage/env-variables) for mer informasjon. Denne filen skal **ikke** _commites_ til git-historikk.\n\n</div>\n<div>\n\n### `.env.example`\n\n`.env.example`-filen viser noen eksempler på miljøvariabler basert på valgte bibliotek. Denne filen skal _commites_ til git-historikk.\n\n</div>\n<div>\n\n### `.eslintrc.json`\n\n`.eslintrc.json`-filen brukes til å konfigurere ESLint. Se [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for mer informasjon.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\n`next-env.d.ts`-filen sikrer at Next.js-typer blir plukket opp av TypeScript-kompilatoren. **Du bør ikke fjerne den eller redigere den, da den kan endres når som helst.** Se [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects) for mer informasjon.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\n`next.config.mjs`-filen brukes til å konfigurere Next.js. Se [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for mer informasjon. Merk: .mjs-utvidelsen brukes for å tillate ESM-import.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\n`postcss.config.js`-filen er for bruk av Tailwind PostCSS. Se [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for mer informasjon.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\n`prettier.config.mjs`-filen brukes til å konfigurere Prettier slik at prettier-plugin-tailwindcss inkluderes for formatering av Tailwind CSS-klasser. Se [Tailwind CSS-blogginnlegget](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for mer informasjon.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nFilen `tsconfig.json` brukes til å konfigurere TypeScript. Noen ikke-standardinnstillinger, som for eksempel `strict mode`, har blitt aktivert for å sikre best mulig bruk av TypeScript i create-t3-app og tilhørende biblioteker. Se [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) eller [TypeScript Usage](usage/typescript) for mer informasjon.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/no/installation.mdx",
    "content": "---\ntitle: Installasjon\ndescription: Installasjonsveiledning for Create T3 App\nlayout: ../../layouts/docs.astro\nlang: no\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nFor å lage en app med `create-t3-app`, kjør en av følgende tre kommandoer og svar på spørsmålene i veiviseren:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nEtter at applikasjonen din har blitt opprettet, sjekk ut [første steg](/no/usage/first-steps) for å begynne å utvikle den nye applikasjonen.\n\n## Avansert bruk\n\n| Alternativ/Flagg  | Beskrivelse                                                                            |\n| ----------------- | -------------------------------------------------------------------------------------- |\n| `[dir]`           | Inkluder et mappeargument med navnet på prosjektet                                     |\n| `--noGit`         | Eksplisitt be CLI om ikke å initialisere et nytt git-repo i prosjektet                 |\n| `-y`, `--default` | CLI vil bli hoppet over og en ny t3-app vil bli opprettet med alle alternativene valgt |\n| `--noInstall`     | Bygger prosjektet uten å installere avhengigheter                                      |\n\n## Eksperimentell bruk\n\nFor vår CI (Kontinuerlig Integrasjon) har vi noen eksperimentelle flagg som lar deg opprette skjelett for hvilken som helst app uten noen spørsmål. Hvis denne _use casen_ gjelder deg, kan du bruke disse flaggene. Vær oppmerksom på at disse flaggene er eksperimentelle og kan bli endret i fremtiden uten å følge noen semver-versjonering.\n\n| Flagg        | Beskrivelse                        |\n| ------------ | ---------------------------------- |\n| `--CI`       | La CLI vite at du er i CI-modus    |\n| `--trpc`     | Inkluder tRPC i prosjektet         |\n| `--prisma`   | Inkluder Prisma i prosjektet       |\n| `--nextAuth` | Inkluder NextAuth.js i prosjektet  |\n| `--tailwind` | Inkluder Tailwind CSS i prosjektet |\n\n<Callout type=\"warning\">\n  Hvis du utelater CI-flagget har resten flaggene ingen effekt.\n</Callout>\n\nDu trenger ikke å eksplisitt velge bort pakkene du ikke vil ha. Men hvis du vil være eksplisitt, kan du sende `false`, f.eks. `--nextAuth false`.\n\n### Eksempel\n\nFølgende vil lage en T3-app med både tRPC og Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/no/introduction.md",
    "content": "---\ntitle: Introduksjon\ndescription: Introduksjon til T3-stakken\nlayout: ../../layouts/docs.astro\nlang: no\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The BEST Stack For Your Next Project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3-Stakken\n\n_\"T3-Stakken\"_ er en webutviklingsstakk inspirert av [Theo](https://twitter.com/t3dotgg) som fokuserer på enkelhet, modularitet og full typesikkerhet.\n\nI kjernen består den av [**Next.js**](https://nextjs.org/) og [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) brukes også nesten alltid. Dersom backend-funksjonalitet er nødvendig så er [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/) og [**NextAuth.js**](https://next-auth.js.org/) også gode tillegg.\n\nDu har kanskje lagt merke til at T3-stakken har mange komponenter. Det er med vilje. Bytt ut delene hvis du trenger dem - stakken er modulær i kjernen :)\n\n## Så... hva er create-t3-app? En mal?\n\nPå en måte? `create-t3-app` er en CLI utviklet av erfarne T3-stakk-utviklere som forenkler oppsett av en modulær T3-stakk-app. Dette betyr at hver komponent er valgfri og \"malen\" lages basert på dine spesifikke krav.\n\nEtter å ha jobbet med mange prosjekter og mange år med denne teknologien, har vi mange meninger og mye innsikt. Vi har gjort vårt beste for inkludere dette i CLI-et.\n\nDette er **IKKE** en altomfattende mal. Vi **forventer** at du tar inn dine egne biblioteker som oppfyller behovene til **DIN** applikasjon. Selv om vi ikke ønsker å foreskrive løsninger for mer spesifikke problemer som _state_-administrasjon og utrulling, har vi [laget en liste over noen anbefalinger her](/no/other-recs).\n\n## T3-Prinsipper\n\nVi skal være ærlige - Dette prosjektet ble designet i henhold til _våre ideer_. Vi deler et sett med oppfatninger om å bygge webapplikasjoner og bruker disse som grunnlag for våre beslutninger.\n\n### Løs Problemer\n\nDet er lett å gå i fellen med \"å legg til alt\" – det ønsker vi spesifikt _ikke_ å gjøre. Alt som legges til 'create-t3-app' bør løse et spesifikt problem som finnes innenfor de inkluderte kjerneteknologiene. Dette betyr at vi ikke vil legge til ting som state-biblioteker (`zustand`, `redux`). Vi vil imidlertid integrere ting som NextAuth.js, Prisma og tRPC.\n\n### Moderne og Ansvarsbevisst\n\nVi elsker moderne teknologi. Arbeidshastigheten og, ærlig talt, hvor moro det er å jobbe med disse teknologiene er fantastisk. Imidlertid synes vi det er viktig å være ansvarsbevisst når det gjelder å bruke noe risikofylte teknologier i de mindre risikofylte delene av stakken. Dette betyr at vi ikke ⛔️ stoler på risikable nye databaseteknologier (SQL er flott!). Men vi liker å ✅ stole på tRPC da det kun gjelder funksjonalitet som er trivielt å endre.\n\n### Typesikkerhet er ikke valgfritt\n\nDet uttalte målet med `create-t3-app` er å gi den raskeste ruten til en ny, **typesikker** fullstakk-webapplikasjon. Vi tar typesikkerhet på alvor fordi det forbedrer produktiviteten vår og hjelper oss å sende færre feil ut i produksjonsmiljø. Enhver beslutning som svekker typesikkerheten til `create-t3-app` er en beslutning som bør tas i et annet prosjekt.\n"
  },
  {
    "path": "www/src/pages/no/other-recs.md",
    "content": "---\ntitle: Flere anbefalinger\ndescription: Biblioteker og tjenester som vi anbefaler til mange prosjekter\nlayout: ../../layouts/docs.astro\nlang: no\n---\n\nVi er klar over at bibliotekene som er inkludert i `create-t3-app` ikke løser alle problemer.\nSelv om vi oppfordrer deg til å starte prosjektet med tingene vi tilbyr, vil det garantert komme en tid da du må inkludere andre pakker. Bare du kan vite hva prosjektet ditt trenger, men her er noen ting vi ofte anbefaler å bruke.\n\nDisse anbefalingene er gitt av individuelle create-t3-app-bidragsytere og skal ikke tas som \"offisielle\" godkjenninger gitt av create-t3-app-teamet eller T3-OSS. _**Vennligst gjør din egen undersøkelse, spesielt før du velger betaltingstjenester**_.\n\n## Statehåndtering\n\n_**Merk**_: Statehåndteringsbiblioteker kan være flotte, men er ofte ikke nødvendige. tRPCs React Query Hooks skal kunne håndtere serverstaten din. For state på klientsiden bør du starte med Reacts `useState` og vurdere ett av disse alternativene hvis du trenger noe mer omfattende.\n\n### Zustand\n\n**For aldri å måtte bruke Redux igjen**\n\nDen \"moderne, enkle Reduxen\" du ikke visste du trengte. [Poimandres](https://github.com/pmndrs) kan du alltid stole på. Med dette lille biblioteket kan du bygge alt fra videokonferanseapper til spill og servere.\n\n- [Zustand Hjemmeside](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**For aldri å måtte bruke Context igjen**\n\nJotai er vanskelig å slå når en atomær tilnærming er foretrukket. Også av [Poimandres](https://github.com/pmndrs). Jotai lar deg definere _singletons_ som føles som global `useState`. Et flott alternativ for stateful adfærd som ennå ikke trenger en statemaskin.\n\n- [Jotai Hjemmeside](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## Komponentbibliotek\n\nDe fleste applikasjoner krever den samme håndfullen komponenter – toggleknapper, dropdownmenyer, modaler osv. Disse bibliotekene gir flotte, tilgjengelige komponenter som du kan bruke og tilpasse etter dine egne behov.\n\n### Ustilte Komponentbiblioteker\n\nSlike biblioteker er også kjent som hodeløse biblioteker. De tilbyr flotte, ustilte og tilgjengelige komponenter som du kan tilpasse etter din smak. Her er noen anbefalinger.\n\n- [Radix UI](https://www.radix-ui.com/) tilbyr deg et kraftig sett med praktiske og tilgjengelige primitive komponenter som du kan style med vanilla CSS eller Tailwind CSS.\n\n– [Headless UI](https://headlessui.com/) ble opprettet av Tailwind CSS-teamet og tilbyr også ustilte, tilgjengelige komponenter som enkelt kan lages med Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) en stor samling av React-hooks for å lage tilgjengelige komponenter. Datovelgeren deres er aldeles toppnivå.\n\n### Stylede Komponentbiblioteker\n\n**Hvis du bare vil ha en app som ser helt OK ut**\n\nNoen ganger vil du lage et prosjekt der brukergrensesnittet ser helt ordinært ut. Dette kan være tilfelle med f.eks. admin dashboards eller lignende prosjekter. For slike prosjekter er alle disse komponentbibliotekene gode valg.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n\n### Class Variance Authority\n\n**For å lage UI-biblioteker**\n\nLar deg deklarativt lage et brukergrensesnittbibliotek med forskjellige varianter av farger, størrelser osv. Hvis prosjektet ditt har nådd en størrelse der du vil ha et standardisert sett med UI-komponenter med flere varianter enn ved å bruke Tailwind CSS, er CVA et flott verktøy.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Animasjoner\n\nHer er våre anbefalinger hvis du trenger animasjoner i applikasjon din.\n\n### AutoAnimate\n\n**For animasjoner med bare én kodelinje**\n\nDe fleste animasjonsbiblioteker forsøker å oppfylle alle mulige brukstilfeller og blir dermed uhåndterlig. AutoAnimate er et nullkonfigurasjonsverktøy som gir deg betydelige UX-forbedringer uten ytterligere utviklerinnsats.\n\n- [AutoAnimate Hjemmeside](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [AutoAnimate Komponentkodebit](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**For komplekse animasjoner med deklarativ kode**\n\nFramer Motion tilbyr en enkel, deklarativ syntaks og lar deg lage komplekse animasjoner og til og med gestikuleringer med bare noen få linjer kode.\n\n- [Framer Motion Hjemmeside](https://framer.com/motion)\n- [Framer Motion Dokumentasjon](https://www.framer.com/docs/)\n\n## Implementeringer, Infrastruktur, Databaser og CI\n\n### Vercel\n\n**For å hoste applikasjonen din**\n\nVercel har gjort web-app-hosting til en lek. Vi har skalert applikasjonen vår til hundretusenvis av brukere, og vi har aldri støtt på noen problemer. Vercel bruker AWS-teknologi, og tilbyr et mye bedre brukergrensesnitt enn mange andre tjenester.\n\n- [Vercels Hjemmeside](https://vercel.com/)\n- [Create T3 App Vercel-utrullingsveiledning](/no/deployment/vercel)\n\n### PlanetScale\n\n**For databaser uten å måtte bekymre deg**\n\nPlanetScale er den beste \"serverløse databaseplattformen\" vi har brukt så langt. Vanvittig skalerbarhet, meget utviklervennlig og fantastiske priser. Hvis du bruker SQL (og forhåpentligvis Prisma) er dette vanskelig å slå.\n\n- [PlanetScale Hjemmeside](https://planetscale.com/)\n\n### Railway\n\n**For å hoste infrastrukturen din**\n\n\"Den moderne Heroku\". Den enkleste måten å starte en ekte server på. Hvis Vercel og PlanetScale ikke er nok, er Railway sannsynligvis det beste alternativet. Bare pek på et GitHub-repo og kom i gang.\n\n- [Railway Homepage](https://railway.app/)\n\n### Upstash\n\n**For serverløse Redis**\n\nVi elsker Prisma og PlanetScale, men enkelte prosjekter tremger noen ganger en mer effektiv løsning. Upstash lar deg bruke minneytelsen til Redis i ditt serverløse prosjekt uten å måtte bekymre deg for infrastruktur og skalering.\n\n- [Upstash hjemmeside](https://upstash.com/)\n\n### Pusher\n\n**For serverløse WebSockets**\n\nHvis WebSockets er hovedfokuset for prosjektet ditt, kan det være lurt å vurdere en mer tradisjonell backend-løsning som [Fastify](https://www.fastify.io/) (som [også fungerer med tRPC!](https://trpc.io/docs/v10/fastify)). For raskt å legge til WebSockets i en T3-app er Pusher et utmerket valg.\n\n- [Pusher Hjemmeside](https://pusher.com/)\n\n### Soketi\n\nSoketi er et selvhostende, enkelt og raskt alternativ til Pusher. Det er helt kompatibel med Pusher SDK, som du kan bruke til å koble til serveren. Soketi serverless er fortsatt i beta.\n\n- [Soketi Hjemmeside](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Analytics\n\nBrukerdata er svært verdifullt når du skal utvikle en app. Her er noen analyseleverandører vi anbefaler.\n\n### Plausible\n\nTrenger du analyser? Plausibel er en av de raskeste måtene. Superminimal. Og den har til og med en [enkel plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Plausible Hjemmeside](https://plausible.io/)\n\n### Umami\n\nUmami er et åpen kilde, selvhostende, enkelt, raskt og personvernvennlig alternativ til Google Analytics. Du kan hoste det veldig enkelt på Vercel, Railway, osv. med PlanetScale som database.\n\n- [Umami Hjemmeside](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n## Annet\n\n### Neste Bundle Analyzer\n\nNoen ganger er det vanskelig å finne ut hvilken kode som inkluderes i byggeutdataen til applikasjonen din. Next Bundle Analyzer er en enkel måte å visualisere og analysere JavaScript-bundler på.\n\n- [@next/bundle-analyzer på npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/no/t3-collection.mdx",
    "content": "---\ntitle: T3-Kolleksjon\ndescription: Kule open source-prosjekter og selskaper som bruker T3-stakken\nlayout: ../../layouts/docs.astro\nlang: no\nisMdx: true\n---\n\nHar du laget et prosjekt med T3-stakken og ønsker å dele det? Legg det til lista!\n\n## Open source-prosjekter bygget med T3-stakken\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\n\n<OpenSourceAppList descriptionIntl=\"Beskrivelse\"/>\n\n## Selskaper som bruker T3-stakken\n\nVi vil gjerne vite hvilke selskaper som bruker T3-stakken for applikasjonene sine. Bruker du T3-stakken og vil dele den? Legg den til lista!\n\n<CompanyList companyIntl=\"Bedrift\"/>\n\n_Har du et kult prosjekt som bruker T3-stakken? Opprett en [Pull Request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) og legg den til her!_\n"
  },
  {
    "path": "www/src/pages/no/usage/env-variables.md",
    "content": "---\ntitle: Miljøvariabler\ndescription: Introduksjon til create-t3-app\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\n`create-t3-app` bruker [Zod](https://github.com/colinhacks/zod) for å validere miljøvariablene dine ved kjøretid _og_ ved byggetidspunkt. Ytterligere filer er angitt i `env`-katalogen for dette formålet:\n\n📁 src/env\n\n┣ 📄 client.mjs\n\n┣ 📄 schema.mjs\n\n┣ 📄 server.mjs\n\nInnholdet i disse filene kan virke skummelt til å begynne med, men ikke til bekymring, det er ikke så komplisert som det ser ut til. La oss se på disse en etter en og på hvordan du legger til flere miljøvariabler.\n\n_TLDR; Hvis du vil legge til en ny miljøvariabel, må du definere den i både `.env` og `env/schema.mjs`._\n\n## schema.mjs\n\nEndringene skjer i denne filen. Den inneholder to skjemaer, ett for servermiljøvariabler og ett for klientmiljøvariabler, og et `clientEnv`-objekt.\n\n```ts:env/schema.mjs\nexport const serverSchema = z.object({\n  // DATABASE_URL: z.string().url(),\n});\n\nexport const serverEnv = {\n  // DATABASE_URL: process.env.DATABASE_URL,\n};\n\nexport const clientSchema = z.object({\n  // NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nexport const clientEnv = {\n  // NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,\n};\n```\n\n### Oppsett av Serverskjema\n\nDefiner skjemaet for servermiljøvariablene her.\n\nPass på at du _ikke_ bruker nøkler med prefikset `NEXT_PUBLIC` her. Validering vil mislykkes hvis du gjør dette for å hjelpe deg med å oppdage en ugyldig konfigurasjon.\n\n### Oppsett av Klientskjema\n\nDefiner ditt skjema for klientmiljøvariabeler her.\n\nFor å gjøre dem tilgjengelige for klienten, _må_ du prefiksere dem med `NEXT_PUBLIC`. Validering vil mislykkes hvis du ikke gjør det, for å hjelpe deg med å oppdage en ugyldig konfigurasjon.\n\n### clientEnv-Objektet\n\nI denne filen må vi få tilgang til verdiene fra `process.env`-objektet.\n\nVi trenger et JavaScript-objekt som vi kan analysere gjennom Zod-skjemaene og på grunn av måten Next.js håndterer miljøvariabler kan vi ikke destrukturere `process.env`-objektet som et normalt objekt. Derfor må vi gjøre det manuelt.\n\nTypeScript vil hjelpe deg med å sørge for at du legger nøklene i både `clientEnv` og `clientSchema`.\n\n```ts\n// ❌ Dette fungerer ikke. Vi må destrukturere den manuelt.\nconst schema = z.object({\n  NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nconst validated = schema.parse(process.env);\n```\n\n## server.mjs & client.mjs\n\nHer foregår valideringen og de validerte objektene eksporteres. Du bør ikke redigere disse filene.\n\n## Bruk Miljøvariabler\n\nHvis du vil bruke miljøvariablene dine, kan du importere dem fra `env/client.mjs` eller `env/server.mjs` avhengig av hvor du vil bruke dem:\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` er helt typesikker og tillater autofullføring\nconst dbUrl = env.DATABASE_URL;\n```\n\n## .env.example\n\nSiden standard `.env`-filen ikke er versjonert, har vi også inkludert en `.env.example`-fil der du eventuelt kan lagre en kopi av `.env`-filen din med eventuelle hemmeligheter fjernet. Dette er ikke nødvendig, men vi anbefaler å holde eksempelfilen oppdatert for å gjøre det så enkelt som mulig for bidragsytere å få miljøet sitt i gang.\n\n## Legg til Miljøvariabler\n\nFor å sikre at _builden_ aldri fullføres uten miljøvariablene som prosjektet trenger, må du legge til nye miljøvariabler **to** steder:\n\n📄 `.env`: Skriv miljøvariabelen din her slik du vanligvis ville gjort i en `.env`-fil, f.eks. `KEY=VALUE`\n\n📄 `schema.mjs`: Legg til riktig valideringslogikk for miljøvariabelen ved å definere et Zod-skjema, f.eks. `KEY: z.string()`\n\nI tillegg kan du også oppdatere `.env.example`:\n\n📄 `.env.example`: Legg til miljøvariabelen din, men ikke glem å fjerne verdien hvis den er hemmelig, for eksempel `KEY=VALUE` eller `KEY=`\n\n### Eksempel\n\n_Jeg vil legge til min Twitter API-token som en servermiljøvariabel_\n\n1. Legg til miljøvariabelen i filen \".env\":\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Legg til miljøvariabelen i `schema.mjs`:\n\n```ts\nexport const serverSchema = z.object({\n  // ...\n  TWITTER_API_TOKEN: z.string(),\n});\n\nexport const serverEnv = {\n  // ...\n  TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n};\n```\n\n3. Valgfritt: Inkluder miljøvariabelen i `.env.example`, men ikke glem å fjerne verdien\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/no/usage/first-steps.md",
    "content": "---\ntitle: Komme i gang\ndescription: De første stegene med din nye T3-app\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nDu har nettopp opprettet en ny T3-app, og du er klar til å sette i gang. Her er det minste du må gjøre for å få applikasjonen din til å kjøre.\n\n## Database\n\nHvis applikasjonen din bruker Prisma, må du kjøre `npx prisma db push` fra rotmappen av applikasjonen. Denne kommandoen synkroniserer Prisma-skjemaet til databasen og genererer TypeScript-typene for Prisma-klienten basert på skjemaet ditt. Merk at du må [starte TypeScript-serveren på nytt](https://tinytip.co/tips/vscode-restart-ts/) etter denne handlingen for at de genererte typene skal gjenkjennes.\n\n## Autentisering\n\nHvis applikasjonen din bruker NextAuth.js, starter vi med `DiscordProvider`. Dette er en av de enkleste leverandørene som NextAuth.js tilbyr, men det krever fortsatt litt oppsett fra din side.\n\nHvis du foretrekker en annen autentiseringsleverandør, kan du også bruke en av de [mange leverandørene](https://next-auth.js.org/providers/) som NextAuth.js tilbyr.\n\n1. Du trenger en Discord-konto. Meld deg på hvis du ikke har en ennå.\n2. Naviger til https://discord.com/developers/applications og klikk \"New Application\" øverst til høyre. Gi applikasjonen din et navn og godta vilkårene for bruk.\n3. Når applikasjonen din er opprettet, naviger til \"Settings → OAuth2 → General\".\n4. Kopier \"Client ID\" og lim den inn i `.env` som `AUTH_DISCORD_ID`.\n5. Klikk \"Reset Secret\", kopier den nye hemmeligheten og lim inn verdien i `.env` som `AUTH_DISCORD_SECRET`.\n6. Klikk \"Add Redirect\" og skriv inn `http://localhost:3000/api/auth/callback/discord`.\n   - For utrulling i produksjonsmiljø må de foregående trinnene følges på nytt for å lage en annen Discord-applikasjon. Denne gangen erstatt `http://localhost:3000` med URL-en du publiserer til.\n7. Lagre endringene.\n\nDu skal nå kunne logge på.\n\n## Editor Setup\n\nFølgende utvidelser anbefales for en optimal utvikleropplevelse. Linkene nedenfor gir støtte for redigeringsprogram utvidelser.\n\n- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)\n- [Prettier Extension](https://prettier.io/docs/en/editors.html)\n\n## Neste Steg\n\n- Hvis applikasjonen din bruker tRPC, ta en titt på `src/pages/index.tsx` og `src/server/api/routers/post.ts` for å se hvordan tRPC-spørringer fungerer.\n- Ta en titt på dokumentasjonen for `create-t3-app` samt dokumentasjonen for pakkene applikasjonen din inkluderer.\n- Bli med i [Discord](https://t3.gg/discord) og gi oss en stjerne på [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/no/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Bruk\",\n  layout: \"docs\",\n  description:\n    \"Lær hvordan man bruker de forskjellige teknologiene i T3-stakken.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/no/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: Bruk av NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nHvis du vil ha et autentiseringssystem i Next.js-applikasjonen din, er NextAuth.js en utmerket løsning for å unngå kompleksiteten med å bygge det selv. Den kommer med en omfattende liste leverandører for raskt å legge til OAuth-autentisering og tilbyr adaptere for mange databaser og ORM-er.\n\n## Kontekstleverandør\n\nI applikasjonens inngangspunkt vil du se at applikasjonen er pakket inn av en [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider).\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nDenne kontekstleverandøren lar applikasjonen din få tilgang til din `session`-data fra hvor som helst i applikasjonen din uten å måtte sende dem som _props_:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Håndter uautentisert state f.eks. ved å vise en påloggingskomponent\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Henting av session på serversiden\n\nNoen ganger vil du kanskje be om _session_ på serveren. For å gjøre dette, prefetch'er du session ved å bruke `getServerAuthSession`-hjelperfunksjonen som `create-t3-app` gir, sender den videre til klienten ved å bruke `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport type { GetServerSideProps } from \"next\";\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\nconst User = () => {\n  const { data: session } = useSession();\n  // MERK: `session` vil ikke ha en lastestatus siden den allerede er prefetched på serveren\n  ...\n}\n```\n\n## Inkluder `user.id` i din Session\n\n`create-t3-app` er konfigurert til å bruke [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) i NextAuth.js-konfigurasjonen for å inkludere bruker-ID i 'session'-objektet.\n\n```ts:server/auth.ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nDette er kombinert med en typedeklarasjonsfil for å sikre at `user.id` er riktig typet når du får tilgang til `session`-objektet. Les mer om [`\"Module Augmentation\"`](https://next-auth.js.org/getting-started/typescript#module-augmentation) i NextAuth.js-dokumentasjonen.\n\n```ts:server/auth.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nDet samme mønsteret kan brukes til å legge til flere data til `session`-objektet, som f.eks et `role`-felt, men **skal ikke misbrukes til å lagre sensitive data på klienten**.\n\n## Bruk med tRPC\n\nHvis du bruker NextAuth.js med tRPC, kan du opprette gjenbrukbare beskyttede prosedyrer med [middlewares](https://trpc.io/docs/v10/middlewares). Dette lar deg lage prosedyrer som bare er tilgjengelige for autentiserte brukere. `create-t3-app` gir deg allerede dette, slik at du enkelt kan få tilgang til session-objektet i autentiserte prosedyrer.\n\nDette skjer i to trinn:\n\n1. Få tilgang til sesjonen fra _request-headerne_ ved å bruke funksjonen [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Fordelen med `getServerSession` sammenlignet med `getSession` er at det er en funksjon på serversiden og medfører ikke unødvendige kall. `create-t3-app` lager en hjelpefunksjon som abstraherer dette særegne API-et, slik at du ikke trenger å importere både NextAuth.js-alternativene dine så vel som `getServerSession`-funksjonen hver gang du trenger tilgang til sesssion.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nMed denne hjelpefunksjonen kan vi hente sesjonen og sende den videre til tRPC-konteksten:\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Lag en tRPC-middleware som sjekker om brukeren er autentisert. Vi bruker deretter middlewaren i en `protectedProcedure`. Hvert kall av disse prosedyrene må autentiseres, ellers kastes en feilmelding, som kan håndteres av klienten.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // inferer `session` som ikke-nullbar\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n}));\n```\n\n`Session`-objektet er en minimal representasjon av brukeren og inneholder bare noen få felt. Hvis du bruker `protectedProcedures`, har du tilgang til brukerens ID, som kan brukes til å hente ut mer data fra databasen.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Bruk med Prisma\n\nMye [førstegangsoppsett](https://authjs.dev/reference/adapter/prisma/) kreves for å bruke NextAuth.js med Prisma. `create-t3-app` vil gjøre dette for deg, og hvis du velger både Prisma og NextAuth.js, får du et fullt funksjonelt autentiseringssystem med alle nødvendige modeller forhåndskonfigurert. Vi oppretter applikasjonen din med en forhåndskonfigurert Discord OAuth-leverandør, som vi valgte siden den er en av de enkleste leverandørene å komme i gang med – du trenger bare å legge inn tokens i `.env`-filen og du er i gang. Du kan imidlertid enkelt legge til flere leverandører ved å følge [NextAuth.js-dokumentasjonen](https://next-auth.js.org/providers/). Vær oppmerksom på at enkelte leverandører krever at du legger til flere felt i enkelte modeller. Vi anbefaler å lese dokumentasjonen for leverandøren du planlegger å bruke for å sikre at alle obligatoriske felt er til stede.\n\n### Legge til nye felt i modellene dine\n\nHvis du legger til nye felt i noen av modellene `User`, `Account`, `Session` eller `VerificationToken` (du trenger sannsynligvis bare å justere `User`-modellen), må du huske på at [Prisma-adapteren](https://next-auth.js.org/adapters/prisma) automatisk legger til felt i disse modellene når nye brukere registrerer seg og logger på. Så når du legger til nye felt i disse modellene, må du oppgi standardverdier for dem fordi adapteren ikke vet om disse feltene.\n\nHvis du for eksempel vil legge til et `role`-felt i `User`-modellen, må du angi en standardverdi for feltet. Dette oppnås ved å legge til en `@default`-verdi i `role`-feltet i `User`-modellen:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Bruk med Next.js middleware\n\nBruk av NextAuth.js med Next.js middleware [krever bruk av \"JWT session strategy\"](https://next-auth.js.org/configuration/nextjs#caveats) for autentisering. Dette er fordi middlewaren bare kan få tilgang til session-informasjonskapslene når den er en JWT. Som standard er `create-t3-app` konfigurert til å bruke **default**-databasestrategien, i kombinasjon med Prisma som databaseadapter.\n\n## Oppsett av DiscordProvider (standard)\n\n1. Naviger til [Applications-delen i Discord Developer Portal](https://discord.com/developers/applications) og klikk på \"New Application\"\n\n2. Bytt til \"OAuth2 => Generelt\" i settings-menyen\n\n- Kopier klient-ID-en og lim den inn i `AUTH_DISCORD_ID` i `.env`.\n- Under Client Secret, klikk på \"Reset Secret\" og kopier denne strengen til `AUTH_DISCORD_SECRET` i `.env`. Vær forsiktig siden du ikke lenger vil kunne se denne hemmeligheten og tilbakestilling av den vil føre til at den eksisterende hemmeligheten utløper.\n- Klikk på \"Add Redirect\" og lim inn `<app url>/api/auth/callback/discord` (eksempel for utvikling i lokal miljø: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Lagre endringene dine\n- Det er mulig, men ikke anbefalt, å bruke samme Discord-applikasjon for utvikling og produksjon. Du kan også vurdere å [Mocke leverandøren](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) under utviklingen.\n\n## Nyttige Ressurser\n\n| Ressurser                        | Link                                    |\n| -------------------------------- | --------------------------------------- |\n| NextAuth.js Dokumentasjon        | https://next-auth.js.org/               |\n| NextAuth.js GitHub               | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - med NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/no/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Bruk av Next.js\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nNext.js er et backend-rammeverk for dine React-applikasjoner.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nSe [Theos Next.js Conf-prat](https://www.youtube.com/watch?v=W4UhNo3HAMw) for å bedre forstå hva Next.js er og hvordan det fungerer.\n\n## Hvorfor skal jeg bruke det?\n\nVi elsker React. Det har gjort UI-utvikling tilgjengelig på måter vi aldri kunne ha forestilt oss før. Det kan også lede utviklere ned noen vanskelige veier. De som utvikler Next.js har noen klare meninger om hvordan de ønsker at ting skal gjøres, samtidig som de tilbyr en svært optimalisert tilnærming til hvordan å bygge React-applikasjoner. Fra ruting til API-definisjoner til bilde-rendering stoler vi på at gjenge i Next.js dirigerer oss utviklere til gode beslutninger.\n\nNext.js kombinert med [Vercel](https://vercel.com/) gjør utvikling og utrulling av webapplikasjoner enklere enn noen gang. Deres ekstremt sjenerøse free-tier og superintuitive grensesnitt lar deg publisere nettstedet ditt i løpet av noen få klikk. (Vi ❤️ Vercel)\n\n## Get Static/Server Props\n\nEn nøkkelfunksjon i Next.js er hvordan man henter data. Vi anbefaler på det sterkeste å lese den [offisielle dokumentasjonen](https://nextjs.org/docs/basic-features/data-fetching) for å forstå hvordan disse funksjonene fungerer og hvordan de er forskjellige. `getServerSideProps` anbefales vanligvis bare når det er en god grunn til å bruke det, da det er et blokkerende anrop og fordi det gjør siden tregere. [Inkrementell statisk regenerering (ISR)](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) er et godt alternativ til `getServerSideProps` når dataen er dynamiske og kan hentes trinnvis.\n\n## Nyttige Ressurser\n\n| Ressurser                    | Link                               |\n| ---------------------------- | ---------------------------------- |\n| Next.js Dokumentasjon        | https://nextjs.org/docs            |\n| Next.js GitHub               | https://github.com/vercel/next.js  |\n| Next.js Blogg                | https://nextjs.org/blog            |\n| Next.js Discord              | https://nextjs.org/discord         |\n| Next.js Twitter              | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube-kanal | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/no/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Bruk av Prisma\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\nPrisma er en ORM (Object Relational Mapper) for TypeScript, som gir deg muligheten til å definere databasens skjema og modeller i en schema.prisma-fil. Deretter genereres en typesikker klient som kan brukes til å kommunisere med databasen din fra backend. Dette gir en enklere og mer sikker måte å utvikle databaserelaterte applikasjoner med TypeScript på.\n\n## Prisma Client\n\nPrisma-klienten blir instansiert i `/server/db.ts` og eksporteres som en global variabel. Som anbefalt av Prisma-teamet som [beste praksis](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem). Vi angir, som standard, Prisma-klienten i [context](/no/usage/trpc#-serverapitrpcts). Vi anbefaler å bruke klienten via konteksten i stedet for å importere klienten i hver fil.\n\n## Skjema\n\nPrisma-skjemafilen finner du i `/prisma/schema.prisma`. I denne filen definerer du databasens skjema og modeller. Denne filen brukes til å generere Prisma-klienten.\n\n### Med NextAuth.js\n\nHvis du velger å bruke NextAuth.js sammen med Prisma, vil skjemafilen bli generert for deg og satt opp med de anbefalte verdiene for modellene `User`, `Session`, `Account` og `VerificationToken` i henhold til [NextAuth. js-dokumentasjonen](https://next-auth.js.org/adapters/prisma).\n\n## Standard Database\n\nStandarddatabasen er en SQLite-database, som er meget godt egnet for utvikling og rask oppretting av et proof-of-concept. Imidlertid anbefaler vi ikke å bruke SQLite i produksjonsmiljøer. Du kan endre databasen ved å endre `provider` i `datasource`-blokken til `postgresql` eller `mysql` og deretter justere URL for database i miljøvariablene slik at den peker på databasen din.\n\n## Fyll Databasen (\"Seeding\")\n\n[\"Seeding\"](https://www.prisma.io/docs/guides/database/seed-database) er en god måte å fylle databasen med testdata. For å konfigurere fyllingen må du lage en `seed.ts`-fil i `/prisma`-katalogen og deretter legge inn et `seed`-skript i `package.json`-filen. Du trenger også en TypeScript runner som kan kjøre startskriptet. Vi anbefaler [tsx](https://github.com/esbuild-kit/tsx) som er en meget effektiv TypeScript-runner som bruker esbuild og ikke trenger noen ESM-konfigurasjon. `ts-node` eller andre runners vil også fungere.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db/client\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nDeretter kan du kjøre `pnpm db-seed` (eller `npm`/`yarn`) for å fylle inn databasen.\n\n## Nyttige Ressurser\n\n| Ressurser                         | Link                                                                                                                                              |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Prisma Dokumentasjon              | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                     | https://github.com/prisma/prisma                                                                                                                  |\n| Prisma Migrate Playground         | https://playground.prisma.io/guides                                                                                                               |\n| NextAuth.JS Prisma Adapter        | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| PlanetScale Tilkoblingsveiledning | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/no/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Bruk av TailwindCSS\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\n## Hva er Tailwind CSS?\n\nTailwind CSS er et lite, [utility first](https://tailwindcss.com/docs/utility-first) CSS-rammeverk for å lage tilpassede temaer uten å måtte bytte mellom ulike kontekster. Det er et rent CSS-rammeverk og tilbyr ingen forhåndsbygde komponenter eller logikk. Det tilbyr også [et helt annet sett med fordeler](https://www.youtube.com/watch?v=CQuTF-bkOgc) sammenlignet med et komponentbibliotek som Material UI.\n\nDet gjør det utrolig enkelt og raskt å skrive CSS, som vist i eksemplet nedenfor:\n\nGammel CSS:\n\n1. Skriv CSS (ofte i en egen fil)\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Importer CSS til komponenten din\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Legg til klassen i HTML-koden din\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nTilsvarende i Tailwind:\n\n1. Bare skriv klassen i HTML-koden din\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nReact-komponenter er en sterk kombinasjon for å raskt lage brukergrensesnitt.\n\nTailwind CSS har et veldig fint innebygd temasystem som kommer med en nøye utvalgt fargepalett, dimensjonsstiler for bredde/høyde og padding/margin, og mediabrytepunkter for responsive layouter. Dette designsystemet kan tilpasses og utvides for å lage nøyaktig det settet med stiler som prosjektet ditt trenger.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla, bedre kjent som [mewtru](https://twitter.com/trunarla), har en flott presentasjon om hvordan å [bygge et temasystem med Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Bruk\n\nSørg for at du har installert editor-plugins for Tailwind for å forbedre utvikleropplevelsen.\n\n### Utvidelser og plugins\n\n- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains-integrasjon](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formatering\n\nTailwind CSS-klasser kan fort bli forvirrende, så en klasseformaterer er et must. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sorterer klassene i [anbefalt rekkefølge](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) slik at klassene samsvarer med utdata-CSS-bundlen. Hvis du velger Tailwind i CLI, vil vi installere og konfigurere det for deg.\n\n### Betinget Bruk av Klasser\n\nÅ legge til klasser under forhold med \"ternærer\" kan bli veldig rotete og vanskelig å lese. Disse pakkene hjelper deg med å organisere klassene dine når du bruker betinget logikk.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Nyttige Ressurser\n\n| Ressurser                  | Link                                                     |\n| -------------------------- | -------------------------------------------------------- |\n| Tailwind Dokumentasjon     | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet       | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss        | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community         | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord-server    | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube-kanal | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground        | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/no/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Bruk av tRPC\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\ntRPC lar oss skrive ende-til-ende typesikre APIer, helt uten kodegenerering eller runtime-bloat.\ntRPC bruker TypeScripts _inferens_ for å automatisk utlede API-ruterens typedefinisjoner og lar deg kalle API-prosedyrene dine fra frontend med full typesikkerhet og autofullføring. Når du bruker tRPC, føles frontend og backend nærmere enn noen gang, noe som resulterer i en enestående utvikleropplevelse.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>\"Jeg bygde tRPC for å forbedre hastigheten på utviklingen av applikasjoner ved å fjerne behovet for et tradisjonelt API-lag. Samtidig kan vi fortsatt stole på at de vil være stabile når man itererer raskt.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creator of tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Hvordan bruker jeg tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC-bidragsyter [trashh_dev](https://twitter.com/trashh_dev) holdt [en flott tale på Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) om tRPC. Vi anbefaler deg å se den hvis du ikke allerede har gjort det.\n\nMed tRPC skriver du TypeScript-funksjoner i backend, og kaller dem deretter fra frontend. En enkel tRPC-prosedyre kan se slik ut:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nDette er tRPC-prosedyre (tilsvarer en rutebehandler i en tradisjonell backend) som først validerer inndataene ved å bruke Zod (som er det samme valideringsbiblioteket vi bruker for [miljøvariablene](./env-variables)) - i dette tilfellet forsikres det at _input_ er en streng. Hvis input ikke er en streng, returneres en detaljert feil.\n\nEtter input følger en resolver-funksjon som enten utfører en [query](https://trpc.io/docs/v10/react-queries), [mutasjon](https://trpc.io/docs/v10/react-mutations) eller en [subscription](https://trpc.io/docs/v10/subscriptions). I vårt eksempel kaller resolver-funksjonen vår database med vår [prisma](./prisma)-klient og returnerer brukeren hvis `id` samsvarer med den vi sendte inn.\n\nDu definerer prosedyrene dine i `rutere` som er en samling av relaterte prosedyrer innenfor et felles _namespace_. Du kan ha en ruter for `users`, en for `posts` og en for `messages`. Disse ruterne kan deretter slås sammen til en enkelt, sentral `appRouter`:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nMerk at vi bare trenger å eksportere vår ruters typedefinisjoner, noe som betyr at vi aldri importerer noen serverkode i klienten vår.\n\nLa oss nå påkalle prosedyren i frontenden vår. tRPC tilbyr en _wrapper_ for `@tanstack/react-query` hvor det er definert noen hooks som gjør at du kan påkalle ditt API med definerte typer som er \"inferred\", det vil at TypeScript-kompilatoren automatisk har utledet hvilken type API-kallene dine har. Vi kan kalle prosedyrene våre fra vår frontend slik:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nDu vil umiddelbart legge merke til hvor god autofullføringen og typesikkerheten er. Så snart du skriver inn `api.` vil ruterne dine automatisk bli foreslått. Hvis du nå velger en ruter, vil prosedyrene også vises. Hvis inndataene dine ikke samsvarer med validatoren du definerte i backend, får du en TypeScript-feil.\n\n## Filer\n\ntRPC krever mye _boilerplate_, som `create-t3-app` setter opp for deg. La oss gå gjennom filene som vil bli opprettet:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nDette er inngangspunktet for API-et ditt og eksponerer tRPC-ruteren. Normalt vil du ikke være borti denne filen så ofte. Men hvis du f.eks. trenger en _middleware_ for CORS eller lignende, er det nyttig å vite at den eksporterte funksjonen `createNextApiHandler` er en [Next.js API-Handler](https://nextjs.org/docs/api-routes/introduction) som mottar et [request-](https://developer.mozilla.org/en-US/docs/Web/API/Request) og et [response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-objekt. Dette betyr at du kan _wrappe_ `createNextApiHandler` med hvilken som helst middleware. Se under for et [eksempel](#aktivering-av-cors) for å legge til CORS.\n\n### 📄 `server/api/trpc.ts`\n\nDenne filen er delt opp i to deler, kontekstoppretting og tRPC-initialisering:\n\n1. Vi definerer konteksten som videresendes til tRPC-prosedyrene dine. Kontekst er data som alle dine tRPC-prosedyrer vil ha tilgang til, og er et flott sted å plassere ting som databaseforbindelser, autentiseringsinformasjon, osv. I create-t3-app bruker vi to funksjoner, for å muliggjøre bruk av en undergruppe av konteksten når vi ikke har tilgang til forespørselsobjektet.\n\n- `createInnerTRPCContext`: Det er her du definerer konteksten som ikke avhenger av forespørselen, f.eks. databasetilkoblingen din. Du kan bruke denne funksjonen til [integrasjonstesting](#sample-integration-test) eller [ssg-hjelpere](https://trpc.io/docs/v10/ssg-helpers) der du ikke har et forespørselsobjekt.\n\n- `createTRPCContext`: Det er her du definerer konteksten som avhenger av forespørselen, f.eks. brukerens økt. Du ber om økten ved å bruke `opts.req`-objektet, og sender deretter økten ned til `createInnerTRPCContext`-funksjonen for å lage den endelige konteksten.\n\n2. Vi initialiserer tRPC og definerer gjenbrukbare [prosedyrer](https://trpc.io/docs/v10/procedures) og [middlewares](https://trpc.io/docs/v10/middlewares). Av konvensjon bør du ikke eksponere hele `t`-objektet, men i stedet lage gjenbrukbare prosedyrer og middleware og eksportere de.\n\nDu har sikkert lagt merke til at vi bruker `superjson` som [datatransformator](https://trpc.io/docs/v10/data-transformers). Dette sikrer at datatypene dine blir bevart når de når klienten, så hvis du for eksempel sender et `Date`-objekt til klienten så returneres et `Date`-objekt og ikke en streng slik de fleste API gjør.\n\n### 📄 `server/api/routers/*.ts`\n\nDet er her du definerer ruterne og prosedyrene for API-et din. Konvensjon tilsier at du bør [opprette separate rutere](https://trpc.io/docs/v10/router) for relaterte prosedyrer.\n\n### 📄 `server/api/root.ts`\n\nHer slår vi sammen alle underruterne definert i `routers/**` [merge](https://trpc.io/docs/v10/merging-routers) til et enkelt app-ruter.\n\n### 📄 `utils/api.ts`\n\nDette er inngangspunktet for tRPC på klientsiden. Her importerer du ruterens **typedefinisjonen** og oppretter tRPC-klienten, samt hooks for react-query. Ettersom vi har aktivert `superjson` som vår datatransformator på serversiden, må vi aktivere den på klientsiden også. Dette er fordi serialisert data fra _backend_ blir deserialisert på _frontend_.\n\nDu definerer tRPC [lenker](https://trpc.io/docs/v10/links) her, som kartlegger request-flyten fra klienten til serveren. Vi bruker \"standard\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink) som muliggjør [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), samt en [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) som gir ut request-logger som kan være nyttige under utviklingsprosessen.\n\nTil slutt eksporterer vi en [hjelpertype](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) som du kan bruke til å utlede typene dine på klientsiden.\n\n## Hvordan påkaller jeg API-et mitt eksternt?\n\nMed vanlige API-er kan du bruke hvilken som helst HTTP-klient som `curl`, `Postman`, `fetch` eller bare nettleseren din. Med tRPC er det litt annerledes. Hvis du vil kalle opp prosedyrene dine uten tRPC-klienten, er det to anbefalte måter:\n\n### Gjør en enkelt prosedyre tilgjengelig eksternt\n\nHvis du ønsker å eksponere en enkel prosedyre eksternt, er du avhengig av [server-side-kall](https://trpc.io/docs/v10/server-side-calls). Dette vil tillate deg å opprette et normalt Next.js API-endepunkt, men gjenbruke resolver-delen av tRPC-prosedyren.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Vis alle prosedyrer som et REST-endepunkt\n\nHvis du vil gjøre hver enkelt prosedyre tilgjengelig eksternt, sjekk ut den community-skapte plugin-modulen [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Den lar deg generere et OpenAPI-kompatibelt REST API fra tRPC-ruteren din, ved å legge til ytterligere metadata i prosedyrene dine.\n\n### Dette er kun HTTP-requests\n\ntRPC kommuniserer via HTTP, så det er også mulig å starte tRPC-prosedyrene dine med \"normale\" HTTP-requests. Syntaksen kan imidlertid være vanskelig på grunn av [RPC-protokollen](https://trpc.io/docs/v10/rpc) som tRPC bruker. Hvis du er nysgjerrig, sjekk nettleserens nettverksfane for å se hvordan tRPC-requestene og -responsene ser ut. Vi anbefaler imidlertid dette kun for pedagogiske formål og vil råde deg til generelt å bruke en av løsningene ovenfor.\n\n## Sammenligning med et Next.js API-endepunkt\n\nLa oss sammenligne et Next.js API-endepunkt med en tRPC-prosedyre. Anta at vi ønsker å hente et brukerobjekt fra databasen vår og returnere det til frontend. Vi kan skrive et Next.js API-endepunkt slik:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nHvis vi nå sammenligner dette med tRPC-eksemplet fra lenger opp i dokumentasjonen, kan følgende fordeler med tRPC sees:\n\n- I stedet for å spesifisere en URL for hver rute, som kan forårsake feil ved endring av prosjektets struktur, er hele ruteren et objekt med autofullføring.\n- Du trenger ikke å validere hvilken HTTP-metode som ble brukt.\n- Du trenger ikke å validere at request eller _body_ inneholder riktige data i prosedyren, fordi Zod tar seg av dette.\n- I stedet for å opprette en response, kan du kaste en error og returnere en verdi eller et objekt som du ville gjort i en hvilken som helst annen TypeScript-funksjon.\n- Å kalle prosedyren på frontend gir autofullføring og typesikkerhet.\n\n## Nyttige Kodeutdrag\n\nHer er noen kodesnutter som kan hjelpe deg.\n\n### Aktivering av CORS\n\nHvis du trenger å konsumere API-et ditt fra et annet domene, for eksempel i en monorepo som inneholder en React Native-app, må du antageligvis aktivere CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Aktiver cors\n  await cors(req, res);\n\n  // Oprett og påkall tRPC-handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Optimistiske oppdateringer\n\nOptimistiske oppdateringer er oppdateringer vi gjør før API-forespørselen fullføres. Dette gir en bedre opplevelse for brukeren siden de ikke trenger å vente på at API-forespørselen skal fullføres før brukergrensesnittet reflekterer resultatet av handlingen deres. Imidlertid bør applikasjoner som verdsetter riktigheten av dataen unngå optimistiske oppdateringer, da de ikke gjenspeiler de \"sanne\" dataene til backend. Du kan lese mer om det i [React Query-dokumentasjonen](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n   const listPostQuery = api.post.list.useQuery();\n\n   const utils = api.useContext();\n   const postCreate = api.post.create.useMutation({\n     async onMutate(newPost) {\n       // Avbryt utgående henting (slik at de ikke overskriver vår optimistiske oppdatering)\n       vent utils.post.list.cancel();\n\n       // Få dataene fra queryCache\n       const prevData = utils.post.list.getData();\n\n       // Oppdater dataene optimistisk med vårt nye innlegg\n       utils.post.list.setData(udefinert, (gammel) => [...gammel, nyinnlegg]);\n\n       // Returner forrige data slik at vi kan gå tilbake hvis noe går galt\n       return { prevData };\n     },\n     onError(err, newPost, ctx) {\n       // Hvis mutasjonen mislykkes, bruk kontekstverdien fra onMutate\n       utils.post.list.setData(udefinert, ctx.prevData);\n     },\n     onSettled() {\n       // Synkroniser med server når mutasjonen er fullført\n       utils.post.list.invalidate();\n     },\n   });\n};\n```\n\n### Eksempel på Integrasjonstest\n\nHer er et eksempel på en integrasjonstest som bruker [Vitest](https://vitest.dev) for å bekrefte at tRPC-ruteren din fungerer som forventet, at input-parseren _inferrer_ riktig type, og at returnert data samsvarer med forventet output.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n## Nyttige Ressurser\n\n| Ressurser                 | Link                                                    |\n| ------------------------- | ------------------------------------------------------- |\n| tRPC Dokumentasjon        | https://www.trpc.io                                     |\n| Noen tRPC-eksempler       | https://github.com/trpc/trpc/tree/next/examples         |\n| React Query Dokumentasjon | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/no/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Bruk av TypeScript\nlayout: ../../../layouts/docs.astro\nlang: no\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Bygg sikkerhetsnett, ikke rekkverk<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n<cite className=\"flex items-center justify-end pr-4 pb-2\">\n  <img\n      alt=\"Avatar av @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\"text-sm font-semibold\">Theo – skaperen av T3-stakken</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nEnten du er en ny eller erfaren utvikler, synes vi at TypeScript er et must. Det kan virke skremmende i begynnelsen, men som mange verktøy, når du først begynner å bruke det, er det noe du ikke vil være foruten.\n\nDet tilbyr live tilbakemeldinger mens du skriver koden din. De forventede datatypene er definert, og vi får nyttig autofullføring i koderedigeringsprogrammet vårt. Dersom det er et problem får man rød understrek, for eksempel når vi prøver å få tilgang til en attributt som ikke eksisterer eller når vi prøver å angi en verdi av feil type. Dette lar oss identifisere og fikse feil tidlig uten å måtte feilsøke etterpå.\n\nDet er uten tvil verktøyet i stakken som mest øker utvikleres produktivitet; man får dokumentasjon på at koden man skriver er riktig direkte i editoren og man får umiddelbar tilbakemelding når man uunngåelig gjør noen feil. Dette er helt uvurderlig.\n\n## Typeinferens\n\nMange nye TypeScript-utviklere blir veldig opptatt av å _skrive_ TypeScript, men mange av fordelene med TypeScript kommer av at man ikke trenger å endre koden sin i det hele tatt. Spesielt vha. typeinferens. Typeinferens betyr at når noe er definert med type, så vil den typen følge med gjennom hele applikasjonen uten å måtte redeklareres andre steder. Dette betyr at, for eksempel, når du har definert typene av en funksjons argumenter, er resten av funksjonen typesikker, uten ekstra TypeScript-spesifikk kode. Bibliotekutviklere legger mye arbeid i å vedlikeholde typene eksponert i bibliotekene deres, noe som betyr at vi som brukere kan dra nytte av inferens og den innebygde dokumentasjonen i koderedigeringsprogrammet som tilbys av disse typene.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nSe videoen av Theo, hvorfor [det kan hende at du bruker TypeScript feil](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Gode bruksområder for typeinferens\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) er et skjemavalideringsbibliotek bygd på TypeScript. Skriv et skjema som representerer den eneste kilden til sannhet (\"single source of truth\") for din data, og Zod vil sørge for at din data er gyldig gjennom hele applikasjonenen. Selv på tvers av nettverksgrenser og eksterne API.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) gir deg deklarative, alltid oppdaterte, automatisk administrerte `queries` og `mutations` som direkte forbedrer utvikler- og brukeropplevelsen.\n\n## Nyttige Ressurser\n\n| Ressurser                                                | Link                                                              |\n| -------------------------------------------------------- | ----------------------------------------------------------------- |\n| TypeScript håndbok                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| TypeScript opplæring for nybegynnere                     | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type-utfordringer                                        | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen fra TypeScript (Matt Pocock) Youtube-kanal | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/no/why.md",
    "content": "---\ntitle: Hvorfor CT3A?\ndescription: Hvorfor du bør velge Create T3 App for ditt neste prosjekt\nlayout: ../../layouts/docs.astro\nlang: no\n---\n\nVi startet create-t3-app fordi [Theo](https://twitter.com/t3dotgg) ikke ønsket å lage en mal for favoritteknologiene sine. Inspirert av create-next-app, [Astro's CLI](https://astro.build) og en forkjærlighet for typesikkerhet, har create-t3-app-teamet jobbet hardt for å skape et best mulig utgangspunkt for nye T3-stakkprosjekter.\n\nHvis du er interessert i å bruke Next.js på en typesikker måte, er dette det rette stedet å starte. Hvis du er interessert i hvorfor vi tok visse spesifikke teknologivalg, les videre :)\n\n## Hvorfor TypeScript?\n\nJavaScript er vanskelig. Hvorfor legge til enda flere regler?\n\nVi er overbevist om at opplevelsen som TypeScript gir vil gjøre deg til en bedre utvikler.\nMan mottar umiddelbar tilbakemelding når man skriver koden sin. De forventede datatypene er definert, og enten får vi nyttig autofullføring i kodeeditoren, eller røde understrekinger som varsler oss om et problem, for eksempel når vi prøver å få tilgang til en attributt som ikke eksisterer eller når vi prøver å angi en verdi av feil type. Dette lar oss identifisere og fikse feil tidlig uten å måtte feilsøke etterpå. Enten du er helt ny på webutvikling eller en erfaren proff, vil TypeScripts \"strenghet\" gi deg en mindre frustrerende, mer konsekvent opplevelse enn vanilla JS.\n\nTypesikkerhet gjør deg raskere. Hvis du ikke er overbevist, [kan det hende du bruker TypeScript feil...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Hvorfor Next.js?\n\nVi elsker React. Det har gjort UI-utvikling tilgjengelig på måter vi aldri kunne ha forestilt oss før. Det kan også lede utviklere ned noen vanskelige veier.\n\nNext.js, som har noen enkle, tydelige meninger, tilbyr en svært optimalisert tilnærming til å bygge applikasjoner med React. Fra ruting til API-definisjoner til bilde-rendering stoler vi på at Next.js dirigerer utviklere til gode beslutninger.\n\n## Hvorfor tRPC/Prisma/Tailwind/osv?\n\nSelv om vi ønsker å holde ting så enkelt som mulig, så opplever vi at disse delene kan brukes i så og si alle applikasjonene vi lager. `create-t3-app` gjør det enkelt for deg å legge til delene du trenger.\n\n### tRPC\n\ntRPC bygger på GraphQLs løfte om sømløs klientsideutvikling opp mot en typesikker server uten å generere mye _boilerplate_. Det er en smart utnyttelse av TypeScript som tilbyr en utrolig utvikleropplevelse.\n\n### Prisma\n\nPrisma er for SQL det TypeScript er for JS. Det skaper en utvikleropplevelse som ikke har eksistert før.\nPrisma garanterer ende-til-ende typesikkerhet fra databasen til applikasjonen din ved å generere typer fra et brukerdefinert skjema som er kompatible med [forskjellige databaser](https://www.prisma.io/docs/concepts/database-connectors).\n\nPrisma tilbyr et helt [sett med verktøy](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) som gjør det daglige arbeidet med databasen enklere. Spesielt å merke seg er Prisma-klienten, som utfører spørringer og gjør SQL så enkelt at du knapt vil legge merke til at du bruker det. Prisma Studio er et nyttig GUI for databasen din som lar deg raskt lese og manipulere dataene dine uten å måtte skrive noen kode.\n\n### Tailwind CSS\n\nTailwind føles som \"zen-modus CSS\".\n\nTailwind lar deg lage en tydelig beskrevet applikasjon ved å gi deg grunnleggende byggeklosser i form av gode standardfarger, mellomrom og andre primitiver. I motsetning til komponentbiblioteker, blir du ikke holdt tilbake hvis du ønsker å ta applikasjonen din til det neste nivået og skape noe ekstraordinært og unikt.\n\nI tillegg betyr Tailwinds \"inline\"-tilnærming at du ikke trenger å bekymre deg for klassenavn, mappestruktur eller andre problemer som ikke er direkte relatert til problemet du ønsker å løse.\n\n### NextAuth.js\n\nHvis du vil ha et autentiseringssystem i Next.js-applikasjonen din, er NextAuth.js en utmerket løsning for å unngå kompleksiteten innebært i å bygge det selv. Den kommer med en omfattende liste over _providers_ for å raskt legge til OAuth-autentisering og tilbyr adaptere for mange databaser og ORM-er.\n"
  },
  {
    "path": "www/src/pages/og.ts",
    "content": "import { Resvg } from \"@resvg/resvg-js\";\nimport { type APIRoute } from \"astro\";\nimport satori from \"satori\";\n\nimport OpenGraph from \"../components/openGraph\";\nimport { SITE } from \"../config\";\nimport { getIsRtlFromLangCode, getLanguageFromURL } from \"../languages\";\nimport { getFont } from \"../utils/ogFont\";\nimport { SITE_URL } from \"../utils/siteUrl\";\n\nconst removeEndingSlash = (str: string) => str.replace(/\\/$/, \"\");\n\nexport const get: APIRoute = async (request) => {\n  const params = request.url.searchParams;\n  const title = params.get(\"title\") ?? SITE.title;\n  const description = params.get(\"description\") ?? SITE.description;\n  const pagePath = params.get(\"pagePath\") ?? \"\";\n\n  // Used for most languages\n  const inter = await getFont({\n    family: \"Inter\",\n    weights: [400, 700] as const,\n  });\n\n  // Used for arabic text\n  const bonaNova = await getFont({\n    family: \"Bona Nova\",\n    weights: [400, 700] as const,\n  });\n\n  // Used for chinese\n  const notoSans = await getFont({\n    family: \"Noto Sans SC\",\n    weights: [400, 700] as const,\n  });\n\n  const hostname = request.site?.hostname.replace(/^https?:\\/\\//, \"\");\n  const pageLang = getLanguageFromURL(pagePath);\n\n  const svg = await satori(\n    OpenGraph({\n      title,\n      description,\n      imageBase: SITE_URL,\n      pageUrl: `${hostname}${removeEndingSlash(pagePath)}`,\n      rtl: getIsRtlFromLangCode(pageLang),\n    }),\n    {\n      width: 1200,\n      height: 630,\n      fonts: [\n        { name: \"Inter\", data: inter[400], weight: 400 },\n        { name: \"Inter\", data: inter[700], weight: 700 },\n        { name: \"Noto Sans SC\", data: notoSans[400], weight: 400 },\n        { name: \"Noto Sans SC\", data: notoSans[700], weight: 700 },\n        { name: \"Bona Nova\", data: bonaNova[400], weight: 400 },\n        { name: \"Bona Nova\", data: bonaNova[700], weight: 700 },\n      ],\n      debug: import.meta.env.DEBUG_OG === \"true\",\n    },\n  );\n\n  const resvg = new Resvg(svg, {});\n  const pngData = resvg.render();\n  const pngBuffer = pngData.asPng();\n\n  return new Response(pngBuffer, {\n    headers: {\n      \"Content-Type\": \"image/png\",\n      \"cache-control\": \"public, max-age=31536000, immutable\",\n    },\n  });\n};\n"
  },
  {
    "path": "www/src/pages/pl/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Deployment with Docker\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nStack ten możesz skonteneryzować i zdeploy'ować jako pojedynczy kontener korzystając z Dockera, czy też jako część grupy kontenerów korzystając z docker-compose. Po przykładowe repozytorium bazowane na tym dokumencie, zobacz [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker).\n\n## Konfiguracja Projektu z Dockerem\n\nNależy pamiętać, że Next.js wymaga innego procesu na czas budowania (dostępnego na frontendzie, z prefiksem `NEXT_PUBLIC`) a innego dla środowiska na czas działania, tylko po stronie serwera, oraz zmiennych. W poniższym demo korzystamy z dwóch zmiennych, zwróć uwagę na ich umiejscowienie w pliku `Dockerfile`, argumenty w konsoli i plik `docker-compose.yml`:\n\n- `DATABASE_URL` (używany przez serwer)\n- `NEXT_PUBLIC_CLIENTVAR` (używany przez klienta)\n\n### 1. Konfiguracja Next.js\n\nW swoim pliku [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), dodaj opcję konfiguracji outputu `standalone` aby [zredukować rozmiar zdjęć poprzez automatyczne wykorzystanie danych wyjściowych](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Stwórz plik dockerignore\n\n<details>\n    <summary>\n      Kliknij tutaj i dodaj poniższą zawartość do pliku <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Stwórz plik Dockerfile\n\n> Jako iż nie pobieramy serwerowych zmiennych środowiskowych do naszego kontenera, [walidacja zmiennych środowiskowych](/pl/usage/env-variables) wyrzuci błąd. Aby mu zapobiec, musimy dodać flagę `SKUP_ENV_VALIDATION=1` do komendy budowania projektu - schemat zmiennych środ. nie zostanie wtedy sprawdzony podczas budowania.\n\n<details>\n    <summary>\n      Kliknij tutaj i dodaj poniższą zawartość do pliku <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Uwagi_**\n>\n> - _Emulacja platformy z flagą `--platform=linux/amd64` może nie być potrzebna podczas korzystania z Node'a w wersji 18._\n> - _Aby zrozumieć, dlaczego `libc6-compat` może być potrzebny, zobacz [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine)._\n> - _Korzystanie z obrazów bazujących na Alpine 3.17 [może powodować problemy z Prismą](https://github.com/t3-oss/create-t3-app/issues/975). Ustawienie `engineType = \"binary\"` rozwiązuje ten problem, [niestety kosztem wydajności](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js zbiera [anonimowe dane telemetryczne o ogólnym użyciu](https://nextjs.org/telemetry). Odkomentuj pierwsze wystąpienie `ENV NEXT_TELEMETRY_DISABLED 1` aby wyłączyć telemetrię podczas budowania. Odkomentuj drugie wystąpienie, aby wyłączyć telemetrię w produkcie końcowym._\n\n</div>\n</details>\n\n## Zbuduj oraz Uruchom Obraz Lokalnie\n\nZbuduj i uruchom ten obraz lokalnie korzystając z następujących komend:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nOtwórz [localhost:3000](http://localhost:3000/) aby zobaczyć uruchomioną aplikację.\n\n## Docker Compose\n\nMożesz także skorzystać z narzędzia Docker Compose, aby zbudować obraz i uruchomić kontener.\n\n<details>\n    <summary>\n      Podążaj za krokami 1-4 powyżej, kliknij tutaj i dodaj poniższą zawartość do pliku <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nUruchom aplikację za pomocą komendy `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nOtwórz [localhost:3000](http://localhost:3000/) aby zobaczyć uruchomioną aplikację.\n\n</div>\n</details>\n\n## Deployment na Railway'a\n\nMożesz użyć usługi PaaS (\"platforma jako usługa\"), takiej jak [zautomatyzowany deployment Dockerfile'a](https://docs.railway.app/deploy/dockerfiles) od [Railway'a](https://railway.app), aby zdeploy'ować swoją aplikację. Jeżeli zainstalowałeś [CLI Railway'a](https://docs.railway.app/develop/cli#install), możesz zdeploy'ować aplikację korzystając z poniższych komend.\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nPrzejdź do zakładki \"Zmienne\" (\"Variables\") i dodaj tam swój `DATABASE_URL`. Następnie przejdź do ustawień (\"Settings\") i wybierz opcję \"Wygeneruj Domenę.\" (\"Generate Domain.\"). Aby zobaczyć działający przykład na Railway, odwiedź stronę [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Przydatne Zasoby\n\n| Nazwa odnośnika                               | Link                                                                 |\n| --------------------------------------------- | -------------------------------------------------------------------- |\n| Odnośnik do pików Dockerfile                  | https://docs.docker.com/engine/reference/builder/                    |\n| Odnośnik do plików \"Compose file\" w wersji 3  | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Odnośnik do Docker CLI                        | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Odnośnik do Docker Compose CLI                | https://docs.docker.com/compose/reference/                           |\n| Wdrażanie aplikacji Next.js z obrazem Dockera | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js z Dockerem                            | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Przykład Next.js z Dockerem                   | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Stwórz obraz Dockera aplikacji Next.js        | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/pl/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Deployment\",\n  layout: \"docs\",\n  description: \"Naucz się deploy'ować produkcyjną wersję swojej aplikacji T3.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/pl/deployment/netlify.md",
    "content": "---\ntitle: Netlify\ndescription: Deployment na platformie Netlify\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nNetlify, to alternatywny provider do deploymentu z podobnym założeniem do Vercela. Po przykładowe repozytorium bazujące na tej stronie, zobacz [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify).\n\n## Dlaczego hostować na Netlify'u?\n\nRacjonalizm podpowiadać może, iż Vercel ma znakomite wsparcie dla Next.js, ponieważ to właśnie on jest jego twórcą. Vercel ma duży biznes w zapewnianiu optymalnego doświadczenia i wydajności z Next.js na swojej platformie. W większości przypadków będzie to prawda i zmiana ścieżki z Vercelem nie będzie miała sensu.\n\nCzęsto powtarzane jest także to, iż wiele funkcji z Next.js ma wsparcie jedynie na Vercelu. Chociaż prawdą jest to, iż nowe funkcje Next.js testowane i wspierane będą na Vercelu od razu po wydaniu, warto pamiętać, iż inni dostawcy, tacy jak Netlify, [szybko implementują i wdrażają wsparcie](https://www.netlify.com/blog/deploy-nextjs-13/) dla [stabilnych funkcji Next.js](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nZależnie od tego, co dana aplikacja potrzebuje, każda strona od deploymentu posiada swoje wady i zalety - żadna strona nie jest w stanie rozwiązać wszystkich problemów. Przykładowo, Netlify zbudował swój własny [runtime Next.js](https://github.com/netlify/next-runtime) dla własnych Edge Functions (które działają na Deno Deploy) i [utrzymuje unikalny middleware pozwalający na dostęp i modyfikację odpowiedzi HTTP](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n> _UWAGA: Aby obserwować status niestabilnych funkcji Next.js, zobacz [Korzystanie z folderu `app` od Next 13 na Netlify](https://github.com/netlify/next-runtime/discussions/1724)._\n\n## Konfiguracja Projektu\n\nJest wiele sposobów na konfigurację sposobu budowania aplikacji bezpośrednio poprzez narzędzie CLI od Netlify, czy też dashboard Netlify. Choć nie jest to wymagane, polecamy stworzyć i dołączyć plik [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Zapewnia to, iż system budowania sklonowanych i zforkowanych wersji twojego projektu będzie łatwiejszy w odwzorowaniu.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Korzystanie z Dashboardu Netlify\n\n1. Wrzuć swój kod do repozytorium GitHuba i zarejestruj się na stronie [Netlify](https://app.netlify.com/signup). Po stworzeniu konta, kliknij na **Add new site** (dodaj nową stronę) a następnie na **Import an existing project** (zaimportuj istniejący projekt).\n\n![Nowy projekt na Netlify](/images/netlify-01-new-project.webp)\n\n2. Połącz swojego dostawcę Gita.\n\n![Importowanie repozytorium](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Wybierz repozytorium swojego projektu.\n\n![Wybierz repozytorium swojego projektu](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify wykryje, czy posiadasz plik `netlify.toml` i automatycznie skonfiguruje polecenia budowania i publikowany folder.\n\n![Ustawienia budowania Next.js](/images/netlify-04-configure-build-settings.webp)\n\n5. Kliknij na **Show advanced** (pokaż zaawansowane) a następnie na **New variable** (nowa zmienna), aby dodać swoje zmienne środowiskowe.\n\n![Dodaj zmienne środowiskowe](/images/netlify-05-env-vars.webp)\n\n6. Kliknij na **Deploy site** (opublikuj stronę), poczekaj aż budowanie się zakończy i otwórz swoją nową stronę.\n\n## Korzystanie z nadzędzia CLI Netlify\n\nAby wrzucić stronę z konsoli, musisz najpierw opublikować swój projekt do repozytorium na GitHubie i [zainstalować narzędzie CLI od Netlify](https://docs.netlify.com/cli/get-started/). Możesz zainstalować `netlify-cli` jako zależność projektu, lub globalnie na swoim urządzeniu korzystając z polecenia:\n\n```bash\nnpm i -g netlify-cli\n```\n\nAby przetestować lokalnie swój projekt, uruchom polecenie [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) i otwórz [`localhost:8888`](http://localhost:8888/), aby zobaczyć lokalnie odpaloną aplikację Netlify.\n\n```bash\nntl dev\n```\n\nUruchom polecenie [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) aby skonfgurować swój projekt:\n\n```bash\nntl init\n```\n\nZaimportuj zmienne środowiskowe swojego projektu z pliku `.env` poleceniem [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nWrzuć do sieci swój projekt korzystając z polecenia [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Aby zbudować projekt przed jego publikacją, będziesz musiał dodać flagę `--build`. Aby wrzucić projekt pod główny URL aplikacji, dodaj flagę `--prod`:\n\n```bash\nntl deploy --prod --build\n```\n\nAby zobaczyć działający przykład na Netlify, odwiedź stronę [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/pl/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Deployment na platformie Vercel\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nPolecamy wykonywać deployment twojej aplikacji na platformę [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Pozwala ona w bardzo prosty sposób wrzucać do sieci aplikacje Next.js.\n\n## Konfiguracja Projektu\n\nVercel prawdopodobnie automatycznie skonfiguruje za Ciebie komendy budowania i folder publikacji aplikacji. Jeśli jednak chcesz, możesz skonfigurować projekt tworząc plik [`vercel.json`](https://vercel.com/docs/project-configuration) zawierający poniższą treść. **Nie jest to wymagane przy większości projektów.**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Korzystanie z Dashboardu Vercela\n\n1. Po wrzuceniu kodu do repozytorium GitHuba, zarejestruj się na stronie [Vercela](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) z tym kontem GitHub i kliknij na **Dodaj Nowy Projekt**.\n\n![Nowy projekt na stronie Vercel](/images/vercel-new-project.webp)\n\n2. Importuj repozytorium z GitHuba z projektem.\n\n![Importuj repozytorium](/images/vercel-import-project.webp)\n\n3. Dodaj zmienne środowiskowe.\n\n![Dodaj zmienne środowiskowe](/images/vercel-env-vars.webp)\n\n4. Kliknij **Deploy**. Od teraz, kiedykolwiek wrzucisz zmianę w kodzie w repozytorium, Vercel automatycznie opublikuje twoją aplikację!\n\n## Korzystanie z Vercel CLI\n\nAby wykonać deploy z konsoli, musisz najpierw [zainstalować Vercel CLI globalnie](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nUruchom komendę [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) aby opublikować swój projekt.\n\n```bash\nvercel\n```\n\nDołącz `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` aby dodać zmienne środowiskowe, jakie jak link do bazy danych. Użyj `--yes`, jeżeli chcesz pominąć pytania podczas publikowania projektu i pozostawić ustawienia domyślne dla każdego z nich.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nPo pierwszym opublikowaniu, komenta ta publikować będzie do gałęzi poglądowej. Będziesz musiał dołączyć `--prod`, aby wrzucić zmiany bezpośrednio do aktywnej strony.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/pl/examples.mdx",
    "content": "---\ntitle: Przykłady\ndescription: Przykłady różnych aplikacji na żywo\nlayout: ../../layouts/docs.astro\nlang: pl\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\nimport Form from \"../../components/docs/exampleOptionForm.astro\";\n\nMożesz wypróbować różne kombinacje technologii, które oferuje create-t3-app.\n\n<Callout type=\"info\">\n  Nie można wybrać `prisma` i `drizzle` jednocześnie.\n</Callout>\n\n<Form />\n\n<Callout type=\"warning\">\n  Niektóre funkcje mogą nie działać, chyba że utworzysz plik env\n</Callout>"
  },
  {
    "path": "www/src/pages/pl/faq.md",
    "content": "---\ntitle: FAQ\ndescription: Najczęściej zadawane pytania dotyczące Create T3 App\nlayout: ../../layouts/docs.astro\nlang: pl\n---\n\nTu znajdziesz najczęściej zadawane pytania dotyczące Create T3 App.\n\n## Co dalej? Jak mam napisać aplikację?\n\nStaramy się, aby projekt ten był jak najprostszy - możesz zacząć już korzystać z zawartego w nim szablonu a następnie stopniowo dodawać potrzebne Ci rzeczy.\n\nJeżeli nie znasz poszczególnych technologi użytych w projekcie, skorzystaj z odnośników do odpowiednich stron z dokumentacjami. Jeżeli dalej nie jesteś co do nich pewien, możesz dołączyć do naszego [serwera Discord](https://t3.gg/discord) i poprosić o pomoc.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n- [Drizzle](https://orm.drizzle.team/docs/overview)\n\n## Jak sprawić, by aplikacja była ciągle aktualna?\n\nCreate T3 App to narzędzie do tworzenia szablonu, a nie framework. Oznacza to, że po inicjalizacji aplikacji jest ona już twoja. Nie istnieje żadne narzędzie CLI do wykorzystania po instalacji aplikacji, które utrzymałoby twoją aplikację aktualną. Jeżeli chcesz być na bieżąco z wprowadzanymi przez nas zmianami do szablonu, możesz [włączyć powiadomienia nowych wersji](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) dla naszego repozytorium. Pamiętaj jednak, że wprowadzanie każdej zmiany z naszego szablonu nie jest wcale wymagane.\n\n## Jakie zasoby do nauki są dostępne?\n\nPoniższe elementy to jedne z najlepszych zasobów dla stacka T3, jednak społeczność oraz [Theo](https://youtu.be/rzwaaWH0ksk?t=1436) polecają Ci zacząć po prostu z niego korzystać. W ten sposób podczas pisania aplikacji zdobędziesz potrzebną wiedzę.\n\nJeżeli zastanawiasz się nad korzystaniem z Create T3 App, mogłeś już używać poszczególnych jego składowych w przeszłości. W takim przypadku spróbuj wskoczyć na głęboką wodę i nauczyć się innych jego części po drodze!\n\nZdajemy sobie sprawę z tego, iż opisany wyżej sposób nie jest dla każdego najlepszy. Jeżeli więc w dalszym ciągu czujesz potrzebę skorzystania z innych źródeł (lub jeżeli nie jesteś wystarczająco pewny siebie / czujesz się przytłoczony stackiem), sprawdź te poradniki dotyczące Create T3 App (pamiętaj, że są one w języku angielskim):\n\n### Artykuły\n\n- [Zbuduj aplikację full stack z Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [Pierwsze spojrzenie na Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrowanie aplikacji T3 do Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrowanie Stripe'a z Aplikacją T3](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Filmy\n\n- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(recommended)**\n- [Jack Herrington - Zbuduj aplikację do sporządzania notatek z T3 Stackiem](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [Zbuduj klon Twittera z T3 Stackiem - tRPC, Next.js, Prisma, Tailwind oraz Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Zbuduj blog z T3 Stackiem - tRPC, TypeScript, Next.js, Prisma i Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Zbuduj live chat z T3 Stackiem - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [T3 Stack - Jak go zbudowaliśmy](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [Przegląd Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Dlaczego w projekcie są pliki `.js`?\n\nTak jak opisano w [aksjomacie #3](/pl/introduction#typesafety-nie-jest-opcjonalne), traktujemy typesafety za pierwszorzędną rzecz. Niestety nie wszystkie frameworki i pluginy posiadają wsparcie do TypeScripta, dlatego też niektóre pliki konfiguracyjne muszą mieć powyższe rozszerzenie.\n\nStaramy się podkreślić, iż pliki te korzystają z TypeScripta nie bez powodu. Wyraźnie określamy rozszerzenia plików jako `cjs` lub `mjs`, zależnie od wsparcia przez daną bibliotekę. Dodatkowo, wszystkie pliki `.js` w naszym projekcie są w dalszym ciągu sprawdzane pod kątem poprawności typów - korzystamy do tego opcji `checkJs` w kompilatorze (tsconfig).\n\n## Mam problem z dodaniem i18n do aplikacji. Czy istnieje jakiś projekt, do którego mógłbym się odnieść przy jej budowaniu?\n\nZdecydowaliśmy się nie umieszczać i18n w `create-t3-app`, ponieważ jest to bardzo kontrowersyjny temat i istnieje wiele sposobów, aby element ten zaimplementować.\n\nJeżeli jednak nie wiesz jak wygląda poprawna interpretacja internacjonalizacji i chciałbyś zobaczyć przykładowy projekt, sprawdź [to repozytorium](https://github.com/juliusmarminge/t3-i18n) - ukazuje ono jak możesz dodać i18n do aplikacji T3 korzystając przy tym z [next-i18next](https://github.com/i18next/next-i18next).\n\n## Dlaczego korzystamy z folderu `/pages` a nie `/app` z Next.js 13?\n\nTak jak opisano w [aksjomacie #2](/pl/introduction#bleed-responsibly-korzystaj-rozważnie-z-nowych-technologii), kochamy technologie \"bleeding edge\", jednak ważna jest dla nas stabilność. Ciężko jest zmienić cały `router` w aplikacji ([not a great place to bleed](https://youtu.be/mnwUbtieOuI?t=1662)). Folder `/app` to [wgląd na przyszłość](https://youtu.be/rnsC-12PVlM?t=818), jednak nie jest on gotowy na wersję produkcyjną. API jest w becie i oczekiwać można zmian wpływających na działanie całej aplikacji (niekoniecznie pozytywnie!).\n\nŻeby poznać listę wspieranych, zaplanowanych i tych, nad którymi prace trwają funkcji, odwiedź [dokumentację Next.js beta](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n"
  },
  {
    "path": "www/src/pages/pl/folder-structure-pages.mdx",
    "content": "---\ntitle: Struktura projektu (Pages)\ndescription: Struktura projektu nowej aplikacji T3\nlayout: ../../layouts/docs.astro\nlang: pl\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nWybierz paczkę, aby zobaczyć strukturę folderów nowo utworzonej z nią aplikacji. Poniżej znajdziesz opis każdego elementu.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nFolder `prisma` zawiera plik `schema.prisma`, który używany jest do konfiguracji połączenia z bazą danych i struktury tej bazy. Jest to także miejsce, w którym przechowywać można pliki migracji i/lub skrypty \"seedowania\" (jeżeli z nich korzystasz). Po więcej informacji, zobacz [korzystanie z Prismy](/pl/usage/prisma).\n\n</div>\n<div>\n\n### `public`\n\nFolder `public` zawiera zasoby statyczne, które \"serwowane\" są przez serwer webowy. Plik `favicon.ico` jest przykładem jednego z takich zasobów.\n\n</div>\n<div>\n\n### `src/env`\n\nUżywany do walidacji zmiennych środowiskowych i definiowania ich typów - zobacz [zmienne środowiskowe](/pl/usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nFolder `pages` zawiera wszystkie strony aplikacji Next.js. Plik `index.tsx` w głównym folderze zawierającym folder `/pages` to strona główna twojej aplikacji. Plik `_app.tsx` dostarcza aplikacji odpowiednie \"providery\". Po więcej informacji, zobacz [dokumentację Next.js](https://nextjs.org/docs/basic-features/pages).\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nFolder `api` zawiera wszystkie route'y twojej aplikacji Next.js. Po więcej informacji o api route'ach, zobacz [ich dokumentację od Next.js](https://nextjs.org/docs/api-routes/introduction).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nPlik `[...nextauth].ts` jest slug routem używanym do uwierzytelniania (\"authentication\") poprzez NextAuth.js. Pomaga on przetwarzać zapytania o uwierzytelnianie. Po więcej informacji o kolejno NextAuth.js i slug route'ach, zobacz [korzystanie z NextAuth.js](/pl/usage/next-auth) oraz [dokumentację dynamicznych route'ów Next.js](https://nextjs.org/docs/routing/dynamic-routes).\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nPlik `[trpc].ts` to punkt wejścia dla API (tRPC). Pomaga on przetwarzać zapytania wykonane z tRPC. Po więcej informacji o kolejno tRPC i slug route'ach, zobacz [korzystanie z tRPC](/pl/usage/trpc#-pagesapitrpctrpcts) oraz [dokumentację dynamicznych route'ów Next.js](https://nextjs.org/docs/routing/dynamic-routes).\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nFolder `server` używany jest do stworzenia wyraźnego podziału między kodem działającym na serwerze, a tym po stronie klienta.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n### `src/server/auth.ts`\n\nJest to główny punkt wejścia dla systemu uwierzytelniania po stronie serwera. Ustawiamy tutaj [opcje konfiguracji](/pl/usage/next-auth), [dostosowujemy model użytkownika](/pl/usage/next-auth#inclusion-of-userid-on-the-session) oraz zapewniamy narzędzia DX dla uwierzytelniania, takie jak funkcja pobierania sesji użytkownika po stronie serwera. Po więcej informacji, zobacz [korzystanie z NextAuth.js](/pl/usage/next-auth#korzystanie-z-trpc).\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nPlik `db.ts` jest używany do tworzenia instancji klienta Prismy z globalnym zakresie. Po więcej informacji, zobacz [korzystanie z Prismy](/pl/usage/prisma#prisma-client) oraz [polecane korzystanie z Prismy wraz z Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices).\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nFolder `api` zawiera kod tRPC po stronie serwera.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nFolder `routers` zawiera wszystkie \"sub-routery\" tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nPlik `example.ts` zawiera przykład routera tRPC wykorzystującego funkcję pomocniczą `publicProcedure` do zaprezentowania, jak stworzyć publiczny route tRPC.\n\nZależnie od wybranych paczek, router ten zawiera więcej lub mniej route'ów, aby najlepiej zaprezentować jego sposób użycia.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nPlik `trpc.ts` jest głównym plikiem konfiguracyjnym dla tRPC po stronie serwera. W pliku tym:\n\n1. Definiujemy kontekst używany w zapytaniach tRPC. Po więcej informacji, zobacz [korzystanie z tRPC](usage/trpc#-serverapitrpcts).\n2. Eksportujemy funkcje pomocnicze helperów. Po więcej informacji, zobacz [korzystanie z tRPC](usage/trpc#-serverapitrpcts).\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nPlik `root.ts` jest używany do scalenia routerów tRPC i eksportowania ich jako pojedynczego routera, a także eksportowania jego definicji typów. Po więcej informacji, zobacz [korzystanie z tRPC](/pl/usage/trpc#-serverapirootts).\n\n</div>\n<div>\n\n### `src/styles`\n\nFolder `styles` zawiera globalne style aplikacji.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nFolder `utils` jest używany do przechowywania często powielanych funkcji pomocniczych.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nPlik `api.ts` to plik wejścia tRPC od strony klienta. Po więcej informacji, zobacz [korzystanie z tRPC](/pl/usage/trpc#-utilsapits).\n\n</div>\n<div>\n\n### `.env`\n\nPlik `.env` jest używany do przechowywania zmiennych środowiskowych. Po więcej informacji, zobacz [Zmienne Środowiskowe](usage/env-variables). Plik ten **nie** powinien być commitowany do historii gita.\n\n</div>\n<div>\n\n### `.env.example`\n\nPlik `.env.example` pokazuje przykładowe zmienne środowiskowe bazując na wybranych bibliotekach. Plik ten powinien być commitowany do historii gita.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nPlik `.eslintrc.cjs` jest używany do konfigurowania ESLinta. Po więcej informacji, zobacz [dokumentację ESLinta](https://eslint.org/docs/latest/user-guide/configuring/configuration-files).\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nPlik `next-env.d.ts` gwarantuje korzystanie z typów Next.jsa przez kompilator TypeScripta. \\*\\*Nie powinieneś go usuwać ani modyfikować, ponieważ może on zmienić się w każdym momencie. Po więcej informacji, zobacz [dokumentację Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects).\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nPlik `next.config.mjs` jest używany do konfigurowania Next.js. Po więcej informacji, zobacz [dokumentację Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction). Uwaga: Rozszerzenie .mjs pozwala korzystać z importów ESM.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nPlik `postcss.config.js` jest używany przez Tailwind PostCSS. Po więcej informacji, zobacz [dokumentację Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss).\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nPlik `prettier.config.mjs` jest używany do konfigurowania Prettiera. Dołącza on plugin `prettier-plugin-tailwindcss` formatujący klasy CSS Tailwinda. Po więcej informacji, zobacz [post na blogu Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier).\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nPlik `tsconfig.json` jest używany do konfigurowania TypeScripta. Niektóre ustawienia zostały włączone (takie jak `strict mode`), aby zapewnić najlepsze użycie TypeScripta do Create T3 App i jej bibliotek. Po więcej informacji, zobacz [dokumentację TypeScripta](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) albo [korzystanie z TypeScripta](/pl/usage/typescript).\n\n</div>\n<div>\n\n### `drizzle.config.ts`\n\nPlik `drizzle.config.ts` jest używany do konfigurowania Drizzle kit. Po więcej informacji przeczytaj [ich dokumentację](https://orm.drizzle.team/kit-docs/config-reference)\n\n</div>\n"
  },
  {
    "path": "www/src/pages/pl/installation.mdx",
    "content": "---\ntitle: Instalacja\ndescription: Instrukcje instalacji dla Create T3 App.\nlayout: ../../layouts/docs.astro\nlang: pl\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nAby zacząć używać szablonu `create-t3-app`, uruchom którąkolwiek z poniższych trzech komend i odpowiedz na pytania w konsoli:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nPo tym, jak szablon aplikacji zostanie utworzony, sprawdź [pierwsze kroki](/pl/usage/first-steps) aby zacząć budować swoją nową aplikację.\n\n## Zaawansowane użycie\n\n| Opcja/Flaga       | Opis                                                                                 |\n| ----------------- | ------------------------------------------------------------------------------------ |\n| `[dir]`           | Argument z nazwą dla projektu                                                        |\n| `--noGit`         | Wyraźnie poinformuj narzędzie, aby nie inicjalizować nowego repozytorium w projekcie |\n| `-y`, `--default` | Pomiń CLI i stwórz nową aplikację z wszystkimi wybranymi opcjami                     |\n| `--noInstall`     | Wygeneruj projekt bez instalowania zależności (npm)                                  |\n\n## Eksperymentalne użycie\n\nZ powodu naszej integracji CI, posiadamy eksperymentalne flagi pozwalające skorzystać z szablonu bez żadnych informacji w konsoli. Jeżeli przemawia do Ciebie któraś z poniższych opcji, możesz z jakiejś flagi skorzystać. Pamiętaj, że są to opcje eksperymentalne - mogą się one zmienić bez względu na system wersji semver.\n\n| Flaga        | Opis                                        |\n| ------------ | ------------------------------------------- |\n| `--CI`       | Poinformuj narzędzie, że jesteś w trybie CI |\n| `--trpc`     | Zawrzyj tRPC w projekcie                    |\n| `--prisma`   | Zawrzyj Prisma w projekcie                  |\n| `--nextAuth` | Zawrzyj NextAuth.js w projekcie             |\n| `--tailwind` | Zawrzyj Tailwind CSS w projekcie            |\n\n<Callout type=\"warning\">\n  Jeżeli nie podasz flagi `CI`, pozostałe flagi nie zostaną użyte.\n</Callout>\nNie musisz wyraźnie wskazywać paczek, z których nie chcesz korzystać. Jeżeli jednak\nwolisz jasno wskazać czego używasz, możesz podać wartość `false` - np. `--nextAuth\nfalse`.\n\n### Przykład\n\nPoniższy przykład stworzy aplikację T3 z bibliotekami tRPC oraz Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/pl/introduction.md",
    "content": "---\ntitle: Wstęp\ndescription: Wstęp do stacka T3\nlayout: ../../layouts/docs.astro\nlang: pl\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\n_\"T3 Stack\"_, to stack do web developmentu stworzony przez [Theo](https://twitter.com/t3dotgg) i mający na celu prostotę, modularność oraz typesafety całego projektu.\n\nJego głównymi elementami są [**Next.js**](https://nextjs.org/) oraz [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) również jest prawie zawsze dołączony. Jeżeli budujesz cokolwiek wspólnego z backendem, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/) oraz [**NextAuth.js**](https://next-auth.js.org/) mogą być dobrymi dodatkami.\n\nMogłeś dostrzec już, iż jest tu... dużo elementów. Jest to celowe. Zmieniaj elementy jak tylko chcesz - stack ten jest tak modularny, jak to tylko możliwe.\n\n## A więc... co to Create T3 App? Jakiś szablon?\n\nMoże? Create T3 App to narzędzie CLI zbudowane przez doświadczonych deweloperów stacka T3 aby usprawnić zakładanie w nim nowych, modularnych projektów. Oznacza to, iż każdy element jest opcjonalny a \"szablon\" generowany jest bazując na twoich szczegółowych potrzebach.\n\nPo niezliczonych projektach i wielu latach w tej technologii, nabyliśmy wiele opinii i wewnętrznych doświadczeń. Zrobiliśmy, co tylko się dało, aby zawrzeć je w naszym CLI.\n\n**NIE** jest to szablon all-inclusive. **Oczekujemy** od Ciebie trochę wkładu, dodając biblioteki rozwiązujące problemy, które posiada **TWOJA** aplikacja. Nie chcemy zapisywać rozwiązań na bardziej specyficzne problemy, takie jak state management lub deployment. [Mamy jednak tutaj parę rekomendacji](/pl/other-recs).\n\n## Aksjomaty T3\n\nBędziemy z tobą szczerzy - jest to _kontrowersyjny_ projekt. Posiadamy garść założeń dotyczących budowania aplikacji i traktujemy je jako bazę naszych decyzji.\n\n### Rozwiązuj Problemy\n\nŁatwo jest wpaść w pułapkę \"dodawania wszystkiego\" - wyraźnie nie chcemy tego robić. Wszystko dodane do Create T3 App powinno rozwiązywać konkretny problem który istnieje w dołączonych technologiach. Znaczy to, że nie dodamy rzeczy, takich jak biblioteki do state managementu (`zustand`, `redux`) ale dodamy elementy takie jak NextAuth.js, Prisma i tRPC.\n\n### \"Bleed Responsibly\" (Korzystaj Rozważnie z Nowych Technologii)\n\nKochamy technologie \"bleeding edge\". Uzyskana prędkość oraz szczerze mówiąc, zabawa, jaka wynika z ich zastosowania - jest naprawdę super. Uważamy jednak za ważne odpowiedzialne korzystanie z powyższych elementów. Oznacza to, iż nie ⛔️ postawimy na nowy rodzaj bazy danych (SQL jest dobry!). Z radością ✅ stawiamy jednak na tRPC - są to tylko funkcje, które łatwo można zamienić na coś innego.\n\n### Typesafety NIE Jest Opcjonalne\n\nCelem Create T3 App jest zapewnienie jak najszybszego sposobu na stworzenie nowego projektu full-stack z pełnym **typesafety**. Typesafety traktujemy poważnie - pozwala ono poprawić naszą produktywność i pomaga nam w dostarczaniu mniejszej ilości bugów. Jakakolwiek decyzja, która naraża naturę typesafety jest decyzją, która powinna zostać podjęta w innym projekcie.\n"
  },
  {
    "path": "www/src/pages/pl/other-recs.md",
    "content": "---\ntitle: Inne Rekomendacje\ndescription: Biblioteki i usługi, które polecamy dla wielu projektów\nlayout: ../../layouts/docs.astro\nlang: pl\n---\n\nZdajemy sobie sprawę z tego, że biblioteki które zawiera Create T3 App nie są lekarstwem na wszystko. Polecamy zaczynać projekty z rzeczami, które są już dołączone - przyjdzie jednak czas, kiedy będziesz musiał dodać swoje paczki. Tylko ty wiesz, czego twój projekt potrzebuje. Polecamy przejrzeć jednak poniższą listę naszych rekomendacji.\n\nSą to rekomendacje pojedynczych kontrybutorów i nie powinny być postrzegane jako \"oficjalne\" sposoby na rowiązywanie danych problemów od zespołu Create T3 App czy też T3-OSS.\n_**Zrób swój research, szczególnie zanim skorzystasz z płatnych usług**_.\n\n## State Management\n\n_**Informacja**_: Biblioteki do state managementu mogą być niezłe, jednak często nie są one potrzebne. Hooki od tRPC (a dokładniej od React Query) powinny być w stanie zarządzać statem od strony serwera. W przypadku state'a klienta, zacznij od hooka `useState` oferowanego przez Reacta i skorzystaj z poniższych opcji jeśli będziesz potrzebować czegoś więcej.\n\n### Zustand\n\n**Aby nigdy więcej nie używać Reduxa**\n\n\"Nowoczesny, prosty Redux\", o którym nie wiedziałeś, że go potrzebujesz. [Poimandresowi](https://github.com/pmndrs) zawsze można zaufać. Zbudować możesz wszystko, począwszy od aplikacji do rozmów wideo a skończywszy na grach czy też serwerach.\n\n- [Strona główna Zustanda](https://zustand-demo.pmnd.rs/)\n- [GitHub Zustanda](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Aby nigdy więcej nie używać kontekstu**\n\nPrzy bardziej \"niepodzielnym\" podejściu, ciężko jest pobić Jotai. Także wykonana przez [Poimandres](https://github.com/pmndrs), Jotai pozwala ci definiować singletony które sprawiają wrażenie, jakby były globalnym hookiem `useState`. Świetna opcja do zachowań wymagających zachowania ze statem i takich, które jeszcze nie potrzebują maszyny state'a.\n\n- [Strona główna Jotai](https://jotai.org/)\n- [GitHub Jotai](https://github.com/pmndrs/jotai)\n\n## Biblioteki Komponentów\n\nWiele aplikacji wymaga tej samej garści komponentów - przełączników, dropdownów czy też modali. Biblioteki te zaopatrzą cię w znakomite i przystępne komponenty, z których możesz korzystać, i które możesz dostosowywać jak tylko chcesz.\n\n### Biblioteki Komponentów Bez Narzuconych Stylów\n\nZnane także jako biblioteki \"headless\", zapoatrzą cię w znakomite, przystępne komponenty bez narzuconych stylów, które będziesz mógł dostosować jak tylko chcesz. Tu znajdziesz kilka rekomendacji.\n\n- [Radix UI](https://www.radix-ui.com/) zaopatrzy cię w olbrzymi zestaw praktycznych i przystępnych prymitywów, które będziesz mógł dostosować do swoich potrzeb z czystym CSSem lub Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) wykonane przez zespół stojący za Tailwind CSS, przekazuje ci przystępne komponenty bez narzuconych stylów, które bezproblemowo integrują się z Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) zaopatrzy cię w przystępne prymitywy do UI dla twojego design systemu.\n\n### Biblioteki Komponentów Z Gotowymi Stylami\n\n**W przypadku, kiedy chcesz żeby twoja aplikacja wyglądała OK**\n\nCzasem budując projekt, chcesz aby Ui wyglądało po prostu przyzwoicie. Do projektów takich jak panele administratora i podobnych, każda z tych bibliotek da sobie doskonale radę.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**Gdy budujesz własną bibliotekę UI**\n\nZbuduj bibliotekę UI z różnymi kolorami, rozmiarami, wariantami itp. Gdy twój projekt osiągnie skalę na tyle dużą, że będziesz musiał skorzystać z ustandaryzowanego zestawu komponentów z wieloma wariantami (korzystając przy tym z Tailwind CSS), CVA stanie się doskonałym narzędziem.\n\n- [GitHub Class Variance Authority](https://github.com/joe-bell/cva)\n\n## Animacje\n\nRekomendacje na sytuacje, kiedy w aplikacji potrzebować będziesz animacji :)\n\n### AutoAnimate\n\n**Aby animacje były pojedynczą linią kodu**\n\nWiele bibliotek od animacji stara się rozwiązać każdy możliwy problem, stając się przy tym uciężałe i niezbyt praktyczne. AutoAnimate to narzędzie niewymagające konfiguracji, które pozwoli ci uzyskać znaczącą poprawę w UX twojej aplikacji bez dodatkowego wysiłku.\n\n- [Strona główna AutoAnimate](https://auto-animate.formkit.com/)\n- [GitHub AutoAnimate](https://github.com/formkit/auto-animate)\n- [Snippet komponentu AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Złożone animacje z deklaratywnym kodem**\n\nFramer Motion pozwala Ci w prosty sposób i z deklaratywną składnią napisać mało kodu, a w zamian zaopatrzy twoją aplikację w złożone animacje, czy nawet reakcje na gesty.\n\n- [Strona główna Framer Motion](https://framer.com/motion)\n- [Dokumentacja Framer Motion](https://www.framer.com/docs/)\n\n## Wdrażanie, Infrastruktura, Bazy Danych i CI\n\n### Vercel\n\n**Aby zhostować swoją aplikację**\n\nVercel zamienił prawdziwe piekło deploymentu aplikacji w łatwą integrację z GitHubem. Przeskalowaliśmy się do setek tysięcy użytkowników bez problemu. Napędzany przez AWS, o wiele lepszy interfejs :)\n\n- [Strona główna Vercel](https://vercel.com/)\n- [Poradnik deploymentu aplikacji T3 z Vercelem](/pl/deployment/vercel)\n\n### PlanetScale\n\n**Bazy danych bez obaw**\n\nPlanetScale to najlepsza platforma \"serverless\" do baz danych, z której kiedykolwiek korzystaliśmy. Znakomicie się skaluje, dostarcza świetny DX, zawiera doskonałe ceny. Jeżeli korzystasz z SQLa (i miejmy nadzieję z Prismy), ciężko jest tą usługę pobić.\n\n- [Strona główna PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Aby hostować swoją infrastrukturę**\n\n\"Nowoczesne Heroku\". Najłatwiejszy sposób aby uzyskać prawdziwy działający serwer. Jeżeli Vercel i PlanetScale nie są dla Ciebie wystarczające, prawdopodobnie Railway będzie. Połącz go z repozytorium GitHuba i gotowe.\n\n- [Strona główna Railway](https://railway.app/)\n\n### Upstash\n\n**Redis dla aplikacji \"serverless\"**\n\nKochamy Prismę i PlanetScale, ale niektóre projekty wymagają bardziej wydajnego rozwiązania. Upstash pozwala na prędkość bliską tej przy bezpośrednim odczycie z pamięci w twoim projekcie \"serverless\", przy tym nie obciążając Cię zarządzaniem infrastruktury i skalowania.\n\n- [Strona główna Upstash](https://upstash.com/)\n\n### Pusher\n\n**WebSockety \"serverless\"**\n\nJeżeli WebSockety stanowią główną część projektu, możesz chcieć rozważyć bardziej tradycyjny backend taki jak [Fastify](https://www.fastify.io/) ([który również działa z tRPC!](https://trpc.io/docs/v10/fastify)). Jesli jednak chcesz szybko dodać WebSockety do aplikacji T3, Pusher to doskonały wybór.\n\n- [Strona głowna Pushera](https://pusher.com/)\n\n### Soketi\n\nSoketi to prosta w użyciu alternatywa do Pushera, którą hostuje się samemu. Jest w pełni kompatybilna z SDK Pushera, z którego możesz korzystać, aby połączyć się z serwerem. Wersja \"serverless\" Soketi jest w becie.\n\n- [Strona główna Soketi](https://soketi.app)\n- [GitHub Soketi](https://github.com/soketi/soketi)\n\n## Statystyki Stron (Analytics)\n\nBudując aplikację, dane użytkowników są bardzo cenne. Znajdziesz tu parę serwisów do ich zbierania, które polecamy.\n\n### Plausible\n\nPotrzebujesz zbierać statystyki? Plausible to jedna z najszybszych opcji aby to zrobić. Bardzo minimalna. Posiada nawet [prosty plugin dla Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Strona główna Plausible](https://plausible.io/)\n\n### Umami\n\nUmami to prosta w użyciu, open-source, szybka i skupiająca się na prywatności alternatywa dla Google Analytics, którą hostuje się samemu. Możesz go zdeploy'ować dzięki serwisom, takim jak Vercel, Railway itp., korzystając przy tym z PlanetScale jako bazy danych.\n\n- [Strona główna Umami](https://umami.is/)\n- [GitHub Umami](https://github.com/umami-software/umami)\n\n## Inne\n\n### Next Bundle Analyzer\n\nOkreślenie co znajdzie się w finalnym buildzie aplikacji może czasem stanowić problem. Next Bundle Analyzer to łatwy sposób na wizualizację i analizę kodu JavaScript, który zostaje wygenerowany.\n\n- [@next/bundle-analyzer na npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/pl/t3-collection.mdx",
    "content": "---\ntitle: Kolekcja T3\ndescription: Ciekawe projekty open source oraz firmy korzystające ze stacka T3\nlayout: ../../layouts/docs.astro\nlang: pl\nisMdx: true\n---\n\nZrobiłeś projekt korzystając z T3 stacka i chcesz się nim podzielić? Dodaj go do listy!\n\n## Aplikacje open source wykonane z T3 Stackiem\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\n\n<OpenSourceAppList descriptionIntl=\"Opis\" repoIntl=\"Repozytorium\"/>\n\n\n## Firmy korzystające ze stacka T3\n\nBardzo chcielibyśmy poznać firmy korzystające ze stacka T3 do budowania swoich aplikacji. Czy twoja firma korzysta ze stacka T3 i chciałaby się tym podzielić? Dodaj tą informację do listy poniżej!\n\n<CompanyList companyIntl=\"Firma\"/>\n\n_Posiadasz ciekawy projekt korzystający ze stacka T3? Zrób [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) i dodaj go tutaj!_\n"
  },
  {
    "path": "www/src/pages/pl/usage/env-variables.md",
    "content": "---\ntitle: Zmienne Środowiskowe\ndescription: Jak zacząć z Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nCreate T3 App korzysta z paczki [Zod](https://github.com/colinhacks/zod) w celu walidacji twoich zmiennych środowiskowych podczas runtime'u _oraz_ budowania aplikacji. Dołączane są z tego powodu dodatkowe narzędzia w pliku `src/env.js`.\n\n## env.js\n\n_TLDR; Jeżeli chcesz dodać nową zmienną środowiskową, musisz dodać ją zarówno do pliku `.env`, jak i zdefiniować jej walidator w pliku `src/env.js`._\n\nPlik ten podzielony jest na dwie części - schemat zmiennych i wykorzystywanie obiektu `process.env`, jak i logika walidacji. Logika ta nie powinna być zmieniana.\n\n```ts:env.js\nconst server = z.object({\n  NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n});\n\nconst client = z.object({\n  // NEXT_PUBLIC_CLIENTVAR: z.string(),\n});\n\nconst processEnv = {\n  NODE_ENV: process.env.NODE_ENV,\n  // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,\n};\n```\n\n### Schemat Dla Serwera\n\nZdefiniuj tutaj zmienne środowiskowe dla serwera.\n\nKoniecznie **nie** prefixuj tutejszych kluczy `NEXT_PUBLIC_`, aby przypadkiem nie ujawnić ich do klienta.\n\n### Schemat Dla Klienta\n\nZdefiniuj tutaj zmienne środowiskowe dla klienta.\n\nAby ujawnić zmienne dla klienta dodaj prefix `NEXT_PUBLIC`. Jeżeli tego nie zrobisz, walidacja nie zadziała, pomagając ci w wykryciu niewłaściwej konfiguracji.\n\n### Obiekt `processEnv`\n\nWykorzystaj destrukturyzację obiektu `process.env`.\n\nPotrzebny jest nam obiekt, który parse'ować możemy z naszymi schematami Zoda, a z powodu sposobu w jaki Next.js przetwarza zmienne środowiskowe, nie możesz destrukturyzować obiektu `process.env` tak jak zwykłego obiektu - trzeba to zrobić manualnie.\n\nTypeScript zapewni poprawność destrukturyzacji obiektu i zapobiegnie sytuacji, w której zapomnisz o jakimś kluczu.\n\n```ts\n// ❌ To nie zadziała, musimy ręcznie \"rozbić\" `process.env`\nconst schema = z.object({\n  NEXT_PUBLIC_WS_KEY: z.string(),\n});\n\nconst validated = schema.parse(process.env);\n```\n\n### Logika Walidacji\n\n_Dla zainteresowanego czytelnika:_\n\n<details>\n<summary>Zaawansowane: Logika walidacji</summary>\n\nW zależności od środowiska (serwer lub klient) walidujemy albo oba schematy, albo tylko schemat klienta. Oznacza to, iż nawet jeśli zmienne środowiskowe serwera nie będą zdefiniowane, nie zostanie wyrzucony błąd walidacji - możemy więc mieć jeden punkt odniesienia do naszych zmiennych.\n\n```ts:env.js\nconst isServer = typeof window === \"undefined\";\n\nconst merged = server.merge(client);\nconst parsed = isServer\n  ? merged.safeParse(processEnv)  // <-- na serwerze, sprawdź oba schematy\n  : client.safeParse(processEnv); // <-- na kliencie, sprawdź tylko zmienne klienta\n\nif (parsed.success === false) {\n  console.error(\n    \"❌ Invalid environment variables:\\n\",\n    ...formatErrors(parsed.error.format()),\n  );\n  throw new Error(\"Invalid environment variables\");\n}\n```\n\nNastępnie korzystamy z obiektu proxy, aby wyrzucać błędy, jeśli chcesz skorzystać z serwerowych zmiennych środowiskowych na kliencie.\n\n```ts:env.js\n// proxy pozwala na zmianę gettera\nexport const env = new Proxy(parsed.data, {\n  get(target, prop) {\n    if (typeof prop !== \"string\") return undefined;\n    // na kliencie pozwalamy jedynie na zmienne NEXT_PUBLIC_\n    if (!isServer && !prop.startsWith(\"NEXT_PUBLIC_\"))\n      throw new Error(\n        \"❌ Attempted to access serverside environment variable on the client\",\n      );\n    return target[prop]; // <-- w przeciwnym razie, zwróć wartość\n  },\n});\n```\n\n</details>\n\n## Korzystanie Ze Zmiennych Środowiskowych\n\nJeżeli chcesz skorzystać ze swoich zmiennych środowiskowych, możesz zaimportować je z pliku `env.js` i skorzystać z nich tak, jak normalnie byłoby to możliwe. Jeżeli zaimportujesz obiekt ten na kliencie i spróbujesz skorzystać ze zmiennych serwera, wystąpi błąd runtime.\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` jest w pełni typesafe i zapewnia autouzupełnianie\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ Wyrzuci to błąd runtime\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ To jest ok\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nPonieważ plik `.env` nie jest wrzucany na system kontroli wersji, dołączamy także plik `.env.example`, w którym - jesli chcesz - możesz zawrzeć kopię pliku `.env` z usuniętymi secretami. Nie jest to wymagane, jednak polecamy trzymać aktualną kopię przykładowego pliku, aby ułatwić potencjalnym kontrybutorom rozpoczęcie pracy w ich środowisku.\n\nNiektóre frameworki i narzędzia do budowania, takie jak Next.js, zalecają przechowywanie sekretnych wartości w pliku `.env.local` i commitowanie plików `.env` do projektu. Nie jest to przez nas jednak rekomendowane, ponieważ może to łatwo prowadzić do przypadkowego ujawnienia tych wartości. Polecamy natomiast przechowywanie sekretnych wartości w pliku `.env`, trzymanie pliku tego w `.gitignore` i commitowanie jedynie plików `.env.example`.\n\n## Dodawanie Zmiennych Środowiskowych\n\nAby upewnić się, że twój projekt nie zbuduje się bez wymaganych zmiennych środowiskowych, będziesz musiał dodać nową zmienną w **dwóch** miejscach:\n\n📄 `.env`: Wprowadź swoją zmienną środ. tak, jak to zwykle robisz (np. `KLUCZ=WARTOŚĆ`)\n\n📄 `env.js`: Dodaj odpowiadającą jej logikę walidacji definiując schemat Zod, np. `KLUCZ: z.string()`. Następnie wykorzystaj obiekt `process.env` w `processEnv`, np. `KEY: process.env.KEY`.\n\nOpcjonalnie możesz zaktualizować plik `.env.example`:\n\n📄 `.env.example`: Wprowadź swoją zmienną środowiskową, upewnij się jednak że nie nie posiada ona wartości, która jest sekretna, np. `KLUCZ=WARTOŚĆ` lub `KLUCZ=`\n\n### Przykład\n\n_Chcę dodać mój token do API Twittera jako zmienną środowiskową po stronie serwera_\n\n1. Dodaj zmienną środ. do pliku `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Dodaj zmienną środowiskową do pliku `env.js`:\n\n```ts\nexport const server = z.object({\n  // ...\n  TWITTER_API_TOKEN: z.string(),\n});\n\nexport const processEnv = {\n  // ...\n  TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n};\n```\n\n3. opcjonalnie: Dodaj zmienną środowiskową do `.env.example`. Usuń jednak token.\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/pl/usage/first-steps.md",
    "content": "---\ntitle: Pierwsze Kroki\ndescription: Jak zacząć pracę z nową aplikacją T3\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nSkorzytałeś właśnie z szablonu aplikacji T3 i jesteś gotowy, aby zacząć z nim pracę. Tu znajdziesz minimalny setup, jaki powinieneś wykonać, aby uruchomić aplikację.\n\n## Baza Danych\n\n### Prisma\n\nJeżeli twoja aplikacja zawiera Prismę, koniecznie uruchom `npx prisma db push` z głównego folderu projektu. Komenda ta zsynchronizuje twój schemat Prismy z bazą danych i wygeneruje typy TypeScripta dla \"Prisma Client\" bazując na tym schemacie. Uwaga: po wygenerowaniu typów Prismy prawdopodobnie będziesz musiał [zrestartować serwer TypeScripta](https://tinytip.co/tips/vscode-restart-ts/), aby był on w stanie je wykryć.\n\n### Drizzle\n\nJeżeli twoja aplikacja zawiera Drizzle, sprawdź plik `.env` po instrukcje jak stworzyć swój `DATABASE_URL`. Po dodaniu `DATABASE_URL` do pliku `.env` uruchom `pnpm db:push` ( lub odpowiednik dla innych menedżerów pakietów) - dokonana zostanie synchronizacja schematów twojej bazy danych.\n\n## Uwierzytelnianie\n\nJeżeli twoja aplikacja zawiera NextAuth.js, posiadasz przygotowany już przez nas `DiscordProvider`. Jest to jeden z najprostszych providerów oferowanych przez NextAuth.js, w dalszym ciągu wymaga on jednak trochę setupu po twojej części.\n\nOczywiście, jeżeli wolisz korzystać z innego, możesz użyć jednego z [wielu providerów](https://next-auth.js.org/providers/) oferowanych przez NextAuth.js.\n\n1. Potrzebować będziesz konta Discord, więc utwórz je, jeśli jeszcze tego nie zrobiłeś.\n2. Przejdź do strony https://discord.com/developers/applications i kliknij \"New Appliction\" w prawym górnym rogu. Nazwij ją i wyraź zgodę na warunki korzystania z serwisu.\n3. Po stworzeniu aplikacji, przejdź do \"Settings → OAuth2 → General\".\n4. Skopiuj \"Client ID\" i dodaj go do pliku `.env` pod kluczem `AUTH_DISCORD_ID`.\n5. Kliknij \"Reset Secret\", skopiuj nowy secret i dodaj go do pliku `.env` pod kluczem `AUTH_DISCORD_SECRET`.\n6. Kliknij \"Add Redirect\" i wpisz `http://localhost:3000/api/auth/callback/discord`.\n\n- Dla deploymentu w wersji produkcyjnej, podążaj za powyższymi krokami aby stworzyć nową aplikację Discord, ale tym razem zamień `http://localhost:3000` na URL, na który wrzucasz swój projekt.\n\n1. Zapisz zmiany\n2. Ustaw `AUTH_SECRET` w pliku `.env`. W wersji rozwojowej zadziała byle co, w wersji produkcyjnej zobacz uwagę w pliku `.env`, która mówi, jak wygenerować bezpieczny secret.\n\nPowinieneś być w stanie się zalogować.\n\n## Konfiguracja Edytora\n\nNastępujące rozszerzenia są przez nas polecane dla optymalnego DX'u. Poniższe linki dostarczają pluginy dla odpowiednich edytorów.\n\n- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)\n- [Prettier Extension](https://prettier.io/docs/en/editors.html)\n\n## Następne Kroki\n\n- Jeżeli twoja aplikacja zawiera tRPC, sprawdź pliki `src/pages/index.tsx` i `src/server/api/routers/post.ts` aby dowiedzieć się, jak działają zapytania wykonywane przez tRPC.\n- Rozejrzyj się po dokumentacji Create T3 App oraz dokumentacji paczek, z których korzysta twój projekt.\n- Dołącz do naszego serwera [Discord](https://t3.gg/discord) i dodaj gwiazdkę na repozytorium [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/pl/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Korzystanie z technologii\",\n  layout: \"docs\",\n  description:\n    \"Naucz się, jak korzystać z poszczególnych technologii w T3 Stacku.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/pl/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: Korzystanie z NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nKiedy chcesz dodać system kont do swojej aplikacji Next.js, NextAuth.js to znakomite rozwiązanie. Pozwala ono wdrożyć złożone systemy bezpieczeństwa nie zmuszając Cię przy tym do pisania ich własnoręcznie. NextAuth.js zawiera rozległą listę providerów, które zapewnią Ci szybki sposób na dodanie OAutha. Paczka ta posiada również wiele adapterów dla baz danych i ORMów.\n\n## Context Provider\n\nW pliku `pages/_app.tsx` zobaczyć możesz, iż twoja aplikacja znajduje się w [SessionProviderze](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nTen oto provider kontekstu pozwala twojej aplikacji na dostęp do danych sesji z każdego miejsca, bez potrzeby przesyłania ich po \"propsach\":\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Obsłuż status nie bycia zalogowanym, np. wyświetl komponent `SignIn`\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Otrzymywanie sesji po stronie serwera\n\nCzasem możesz chcieć otrzymać sesję na serwerze. Aby to zrobić, pobierz sesję korzystając z funkcji pomocniczej `getServerAuthSession` dostarczanej przez Create T3 App a następnie prześlij ją do klienta korzystając z `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\nconst User = () => {\n  const { data: session } = useSession();\n  // UWAGA: obiekt `session` nie będzie miał stanu ładowania, ponieważ jest już pobrany na serwerze\n  ...\n}\n```\n\n## Dołączanie `user.id` do sesji\n\nCreate T3 App jest skonfigurowany tak, aby wykorzystać [callback `session`](https://next-auth.js.org/configuration/callbacks#session-callback) w konfiguracji NextAuth.js do dodania ID użytkownika do obiektu `session`.\n\n```ts:server/auth.ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nŁączy się to z plikiem deklaracji typów, aby zapewnić odpowiednie typy obiektu `session` - musi on zawierać powyższe pole `user.id`. Więcej o zmianie typów poczytać możesz w rozdziale [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) dokumentacji NextAuth.js.\n\n```ts:server/auth.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nTen sam sposób wykorzystany może zostać do dodania większej ilości danych na obiekcie `session`, takich jak pole `role` (rola). **Nie powinien być on jednak wykorzystany do zapisywania wrażliwych danych** dla klienta.\n\n## Korzystanie wraz z tRPC\n\nJeżeli używasz NextAuth.js oraz tRPC, stworzyć można zabezpieczone procedury (z możliwością wielokrotnego użycia) korzystając z [middleware'ów](https://trpc.io/docs/v10/middlewares). Pozwala to na umieszczenie procedur, które zainicjowane być mogą jedynie przez autoryzowanych użytkowników. `create-t3-app` wszystko to dla Ciebie konfiguruje, dając ci możliwość łatwego dostępu do obiektu sesji wśród autoryzowanych procedur.\n\nKonfiguracja ta zachodzi w dwóch krokach:\n\n1. Pobierz sesję z headerów zapytania korzystając z funkcji [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Zaletą korzystania z `getServerSession` zamiast `getSession` jest fakt, iż jest to funkcja wywoływana jedynie po stronie serwera i nie inicjuje ona żadnych niepotrzebnych zapytań. `create-t3-app` tworzy funkcję pomocniczą, która ułatwia korzystanie z `getServerSession` - nie musisz więc importować zarówno opcji NextAuth.js jak i funkcji `getServerSession` za każdym razem, kiedy chcesz otrzymać sesję.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nKorzystając z tej funkcji pomocniczej, możemy otrzymać sesję i przesłać ją do kontekstu tRPC:\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../common/get-server-auth-session\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Stwórz middleware tRPC, który sprawdza, czy użytkownik jest autoryzowany. Wykorzystamy następnie stworzony middleware w `protectedProcedure` - specjalnej, zabezpieczonej procedurze. Każda osoba wywołująca ją będzie musiała spełniać warunki autoryzacji - w przeciwnym razie wystąpi błąd, który w odpowiedni sposób będzie mógł zostać obsłużony po stronie klienta.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // inferer `session` som ikke-nullbar\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n}));\n```\n\nObiekt `session` to minimalna i lekka reprezentacja użytkownika zawierająca jedynie parę pól. Jeśli korzystasz z procedur `protectedProcedure`, masz dostęp do ID użytkownika, które może zostać wykorzystane do pobrania większej ilości danych z bazy.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Korzystanie wraz z Prismą\n\nPrzygotowanie NextAuth.js do pracy z Prismą wymaga wiele [wstępnej konfiguracji](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` zajmuje się nią za Ciebie, a jeśli wybierzesz zarówno Prismę i NextAuth.js, otrzymasz w pełni działający system uwierzytelniania, wraz z wszystkimi potrzebnymi modelami bazy danych. Szablon aplikacji, który dostarczamy, zawiera domyślnie provider OAuth Discorda, który wybraliśmy z powodu bycia jednym z łatwiejszych do obsługiwania - jedyne, co musiz zrobić, to podać tokeny w pliku `.env`... i gotowe! Jeżeli jednak chcesz skorzystać z czegoś innego, możesz w łatwy sposób dołączyć inne providery opierając się na [dokumentacji NextAuth.js](https://next-auth.js.org/providers/). Uwaga - niektóre z providerów wymagają większej ilości pól na modelach w bazie danych. Polecamy Ci przeczytać dokumentację providera, z którego chciałbyś skorzystać aby upewnić się, iż posiadasz wszystko, czego potrzebujesz.\n\n### Dodawanie nowych pól do modeli\n\nKiedy dodajesz nowe pola do któregokolwiek z modeli - `User`, `Account`, `Session` lub `VerificationToken` (prawdopodobnie będziesz chciał zmieniać jedynie model `User`) - pamiętać musisz, iż [adapter dla Prismy](https://next-auth.js.org/adapters/prisma) automatycznie tworzy pola na powyższych modelach w przypadku rejestracji kont i logowania na nie. Z tego też powodu, dodając nowe pola do tychże modeli, zaopatrzyć musisz je w wartości domyślne - adapter nie jest ich świadomy.\n\nJeżeli przykładowo chcesz dodać pole `role` (roli) do modelu `User` (użytkownika), musisz pamiętać o dołączeniu wartości domyślnej tego pola. Zrobisz to za pomocą wartości `@default` w modelu `User`:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Korzystanie wraz z middlewarem Next.js\n\nWykorzystanie middleware'a Next.js [wymaga od Ciebie skorzystania ze strategii JWT](https://next-auth.js.org/configuration/nextjs#caveats) do autoryzacji. Dzieje się tak, ponieważ middleware jest w stanie pobierać ciasteczko sesji jedynie, gdy jest ono JWT. Create T3 App jest skonfigurowany tak, by wykorzystać **domyślną** strategię bazy danych, wraz z Prismą jako jej adapterem.\n\n## Konfigurowanie domyślnego providera Discord (`DiscordProvider`)\n\n1. Przejdź do [sekcji Aplikacje w Panelu Discord Developer Portal](https://discord.com/developers/applications), a następnie kliknij na \"New Application\"\n2. W menu ustawień, przejdź do \"OAuth2 => General\"\n\n- Skopiuj Client ID i wklej go do pliku `.env` pod kluczem `AUTH_DISCORD_ID`.\n- Pod Client Secret, kliknij \"Reset Secret\" i skopiuj podany tekst do pliku `.env` pod kluczem `AUTH_DISCORD_SECRET`. Uważaj - nie będziesz mógł ponownie zobaczyć tego klucza, a jego reset spowoduje wygaśnięcie aktualnego.\n- Dodaj \"Add Redirect\" i wklej tam `<app url>/api/auth/callback/discord` (przykładowo dla lokalnej aplikacji: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Zapisz zmiany\n- Jest możliwość (nie jest ona jednak polecana), aby wykorzystać tą samą aplikację Discorda dla zarówno aplikacji lokalnej i tej w wersji produkcyjnej. Możesz także wykorzystać [mockowanie providera](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) podczas rozwoju aplikacji.\n\n## Przydatne Zasoby\n\n| Zasób                               | Link                                    |\n| ----------------------------------- | --------------------------------------- |\n| Dokumentacja NextAuth.js            | https://next-auth.js.org/               |\n| GitHub NextAuth.js                  | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - wraz z NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/pl/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Korzystanie z Next.js\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nNext.js to backend framework dla aplikacji React.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nZapoznaj się z [rozmową Theo na konferencji Next.js](https://www.youtube.com/watch?v=W4UhNo3HAMw) aby lepiej zrozumieć, czym jest i jak działa Next.js.</p>\n\n## Dlaczego powinienem go używać?\n\nKochamy Reacta. Zmienił on sposób tworzenia interfejsów na niewyobrażalnie bardziej przystępny. Może on także prowadzić dewelopera za rękę w miejscach, mogących sprawiać problemy. Next.js oferuje lekko kontrowersyjne, bardzo zoptymalizowane podejście do tworzenia aplikacji z pomocą Reacta. Od routingu, przez API, do renderowania zdjęć, ufamy Next.js i wierzymy, że prowadzi nas do dobrych decyzji.\n\nPołączenie Next.js z [Vercelem](https://vercel.com/) sprawia, iż pisanie i deploy applikacji staje się łatwieszy niż kiedykolwiek. Ich bardzo hojny darmowy tier i bardzo intuicyjny interfejs zaopatruje Cię w rozwiązanie \"point and click\", dzięki któremu z łatwością opublikujesz swoją stronę (Kochamy ❤️ Vercela).\n\n## Get Static/Server Props\n\nKluczową funkcją Next.jsa są jego możliwości fetchowania danych. Bardzo polecamy przejrzenie jego [oficjalnej dokumentacji](https://nextjs.org/docs/basic-features/data-fetching), aby zrozumieć jak korzystać z każdej z tych metod i poznać ich różnice. `getServerSideProps` jest ogólnie odradzane (chyba, że jest dla metody tej BARDZO dobry argument za), z powodu blokowania renderu strony - i przez to jej spowalniania. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) to dobra anternatywa dla `getServerSideProps`, jeżeli dane są dynamiczne i mogą być pobierane \"przyrostowo\".\n\n## Przydatne Zasoby\n\n| Zasób                         | Link                               |\n| ----------------------------- | ---------------------------------- |\n| Dokumentacja Next.js          | https://nextjs.org/docs            |\n| GitHub Next.js                | https://github.com/vercel/next.js  |\n| Blog Next.js                  | https://nextjs.org/blog            |\n| Discord Next.js               | https://nextjs.org/discord         |\n| Twitter Next.js               | https://twitter.com/nextjs         |\n| Kanał YouTube Vercela/Next.js | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/pl/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Korzystanie z Prismy\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\nPrisma to ORM dla TypeScripta, który pozwala na definiowanie schematu bazy danych i modeli w pliku `schema.prisma`, a następnie generuje klikenta będącego typesafe, którego wykorzystasz w interakcjach z bazą danych ze swojego backendu.\n\n## Prisma Client\n\nZlokalizowany w pliku `src/server/db.ts`, Prisma Client to globalna zmienna (tak jak rekomendowane na stronie z [najlepszymi sposobami](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) przez zespół Prismy) wyeksportowana i gotowa do użycia w twoich route'ach API. Prisma Client dołączany jest przez nas w [kontekście tRPC](/en/usage/trpc#-serverapitrpcts). Polecamy tą metodę, zamiast importowania go osobno w każdym pliku.\n\n## Schema (Schemat)\n\nZnajdziesz schemat Prismy w pliku `/prisma/schema.prisma`. Plik ten to miejsce, gdzie definiuje się schemat bazy danych i modele. Jest on także wykorzystywany podczas generowania Prisma Clienta.\n\n### Z NextAuth.js\n\nJeżeli wybierzesz NextAuth.js w połączeniu z Prismą, plik shcematu generowany jest wraz z rekomendowanymi wartościami dla modeli `User`, `Session`, `Account`, czy też `VerificationToken` - tak jak opisano to w [dokumentacji NextAuth.js](https://next-auth.js.org/adapters/prisma).\n\n## Domyślna Baza Danych\n\nDomyślna baza danych to baza SQLite, która jest znakomita do szybkiego pisania aplikacji, takich jak \"weryfikacja konceptu\" (\"proof-of-concept\"), lecz nie jest ona polecana do pisania produkcyjnych wersji projektów. Typ bazy danych zmienić możesz poprzez edycję pola `provider` w bloku `database`, na `postgresql` lub `mysql`. Następnie, aktualizując string połączenia z bazą w pliku `.env` na taki, który skieruje Prismę do twojej bazy danych.\n\n## Seedowanie Bazy Danych\n\n[Seedowanie bazy danych](https://www.prisma.io/docs/guides/database/seed-database) to dobry sposób na szybkie uzupełnienie bazy danych testową zawartością. Aby rozpocząć seedowanie, będziesz musiał stworzyć plik `seed.ts` w folderze `/prisma`, a następnie dodać skrypt `seed` do pliku `package.json`. Będziesz musiał także skorzystać z jakiegoś środowiska uruchomieniowego dla TypeScripta. Polecamy [tsx](https://github.com/esbuild-kit/tsx), który jest bardzo szybkim środowiskiem korzystającym z esbuilda i niewymagającym żadnej konfiguracji ESM. Runnery, takie jak `ts-node`, także zadziałają.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db/client\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nNastępnie uruchom po prostu `pnpm db-seed` (lub `npm`/`yarn`) aby wykonać seedowanie bazy danych.\n\n## Przydatne Zasoby\n\n| Zasób                             | Link                                                                                                                                              |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Dokumentacja Prismy               | https://www.prisma.io/docs/                                                                                                                       |\n| GitHub Prismy                     | https://github.com/prisma/prisma                                                                                                                  |\n| Prisma Migrate Playground         | https://playground.prisma.io/guides                                                                                                               |\n| Adapter NextAuth.JS dla Prismy    | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| Poradnik Połączenia z PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/pl/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Korzystanie z Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\n## Co to Tailwind CSS?\n\nTailwindCSS to mały, [\"utility first\"](https://tailwindcss.com/docs/utility-first) framework CSS służący do budowania własnych designów, nie wymagając przy tym zmiany kontekstu, tak jak to robi zwykły CSS. Jest to tylko i wyłącznie framework CSS, który nie oferuje gotowych komponentów czy też logiki. Zawiera on natomiast [wiele różnych benefitów](https://www.youtube.com/watch?v=CQuTF-bkOgc) w porównaniu do biblioteki komponentów, takiej jak Material UI.\n\nSprawia on, iż pisanie CSSa staje się wyjątkowo łatwe i szybkie, jak widać z resztą na poniższym przykładzie:\n\nStary CSS:\n\n1. Napisz kod CSSa, często w osobnym pliku\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Zaimportuj CSSa do swojego komponentu\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Dodaj klasę do swojego kodu HTMLa\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nOdpowiednik z Tailwindem:\n\n1. Po prostu dodaj klasy do HTMLa\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nKiedy korzystasz z Tailwinda w połączeniu z komponentami Reacta, staje się on niezwykle silnym sposobem na szybkie pisanie interfejsów użytkownika (UI).\n\nTailwind CSS posiada piękny, wbudowany design system, który zawiera uważnie dobraną paletę kolorów, wzorce rozmiarów dla stylów, takich jak wysokość i szerokość czy też padding i margines. Zawiera też breakpointy pomocne przy tworzeniu responsywnego layoutu. Design system może być dostosowywany i poszerzany, aby stworzyć dokładnie ten zestaw narzędzi i stylów, którego twój projekt potrzebuje.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla, lepiej znana jako [mewtru](https://twitter.com/trunarla), wygłosiła niezwykłą rozmowę na temat [budowania design systemu korzystając z Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Korzystanie z Tailwinda\n\nUpewnij się, że zainstalowałeś pluginy dla Tailwinda. Zwięszą one komfort pisania kodu korzystając z tego narzędzia.\n\n### Rozszerzenia i Pluginy\n\n- [Rozszerzenie dla VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formatowanie\n\nKlasy Tailwinda mogą łatwo stać się nieczytelne, więc formater to \"must-have\". [Prettier Plugin dla Tailwind CSS](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sortuje klasy używając [rekomendowanej kolejności](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) tak, że kolejność klas jest zgodna z ich kolejnością w zbudowanej aplikacji. Wybierając Tailwind w naszym CLI, automatycznie zainstalujemy i skonfigurujemy plugin za Ciebie.\n\n### Warunkowe Dodawanie Klas\n\nWarunkowe dodawanie klas korzystając z \"ternary operators\" może stać się nieczytelne i niechlujne. Paczki te pomogą w organizowaniu twoich klas korzystając z logiki warunkowej.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Przydatne Zasoby\n\n| Zasób                      | Link                                                     |\n| -------------------------- | -------------------------------------------------------- |\n| Dokumentacja Tailwinda     | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet       | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss        | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community         | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Serwer Discrod Tailwinda   | https://tailwindcss.com/discord/                         |\n| Kanał Youtube TailwindLabs | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground        | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/pl/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Korzystanie z tRPC\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\ntRPC pozwala nam pisanie API będących w pełni typesafe bez żadnego generowania kodu czy też zaśmiecania runtime'u. Korzysta on ze świetnego type inference od Typecripta aby przekazywać definicje routerów oraz pozwala Ci na korzystanie z procedur API na frontendzie z pełnym tyepsafety i autouzupełnianiem. Jeśli korzystasz z tRPC, twój frontend i backend będą sprawiały wrażenie bycia bardziej połączonymi niż kiedykolwiek, pozwalając na niespotykany DX (developer experience).\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Zbudowałem tRPC aby umożliwić każdemu szybsze robienie postępów, usuwając przy tym potrzebę korzystania z tradycyjnej wartswy API oraz zachowując pewność, iż nasze aplikacje nie zepsują się nadążając za własnym rozwojem.<span aria-hidden=\"true\">&quot;</span>\n      <br />\n      <span className=\"text-xs opacity-70\"><span aria-hidden=\"true\">&quot;</span>Oryginał: I built tRPC to allow people to move faster by removing the need of a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span></span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 mr-4 rounded-full bg-neutral-500\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - twórca tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Jak korzystać z tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nKontrybutor tRPC [trashh_dev](https://twitter.com/trashh_dev) zrobił [znakomity występ na Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) właśnie o tRPC. Jeżeli jeszcze się z nim nie zapoznałeś, bardzo polecamy Ci to zrobić.\n\nZ tRPC, piszesz funkcje w TypeScript'cie na backendzie a następnie wywołujesz je z frontendu. Prosta procedura tRPC wyglądać może tak:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nJest to procedura (odpowiednik handlera route'a w tradycyjnym API), która najpierw waliduje wejście/input korzystając z biblioteki Zod (jest to ta sama biblioteka, z której korzystamy podczas sprawdzania [zmiennych środowiskowych](./env-variables)) - w tym przypadku zapewnia ona, iż dane przesłane do API są w formie tekstu (stringa). Jeżeli jednak nie jest to prawda, API wyśle informatywny błąd.\n\nPo sprawdzeniu wejścia, dołączamy funkcję, która może być albo [query](https://trpc.io/docs/v10/react-queries), albo [mutacją](https://trpc.io/docs/v10/react-mutations), albo [subscrypcją](https://trpc.io/docs/v10/subscriptions). W naszym przykładzie, funkcja ta (zwana \"resolverem\") wysyła zapytanie do bazy danych korzystając z naszego klienta [prisma](./prisma) i zwraca użytkownika z pasującym do wysłanego `id`.\n\nSwoje procedury definiujesz w folderze `routers`, który reprezentuje kolekcję pasujących procedur ze wspólnej przestrzeni. Możesz mieć router `users`, router `posts` i router `messages`. Routery te mogą zostać następnie połączone w jeden, scentralizowany `appRouter`:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nZwróć uwagę na to, iż musimy eksportować jedynie definicje typów tego routera - oznacza to, iż nigdy nie importujemy kodu serwera po stronie klienta.\n\nWywołajmy teraz procedurę na naszym frontendzie. tRPC dostarcza nam wrapper dla paczki `@tanstack/react-query`, który pozwala ci wykorzystać pełną moc hooków. Dodatkowo, zapytania API dostajesz w pełni \"otypowane\". Zapytanie do naszych procedur możemy wykonać w następujący sposób:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nNatychmiast zauważysz, jak dobrze działa type-safety i autouzupełnianie. Jak tylko napiszesz `trpc.`, twoje routery automatycznie pojawią się w opcjach autopodpowiedzi a kiedy tylko wybierzesz router, również znajdą się tam jego procedury. Otrzymasz także błąd TypeScripta, jeżeli wejście (input) nie będzie zgadzać się z tym, podanym do systemu walidacji na backendzie.\n\n## Korzystanie z błędów biblioteki Zod\n\nDomyślnie `create-t3-app` konfiguruje [error formatter](https://trpc.io/docs/error-formatting), który pozwala pobierać błędy z biblioteki Zod, jeśli na backendzie wystąpią błędy walidacji.\n\nPrzykładowe użycie:\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` returned with an error on the `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## Pliki\n\ntRPC wymaga dużo boilerplate'u, który `create-t3-app` przygotowuje za Ciebie. Przejdźmy więc po kolei po plikach, które są generowane:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nJest to właściwy punkt początkowy dla twojego API - to on ujawnia dla reszty aplikacji twój router od tRPC. Prawdopodobnie nie będziesz musiał edytować tego pliku, ale jeżeli zajdzie taka potrzeba (np. do włączenia CORSa), warto wiedzieć o tym, iż eksportowany `createNextApiHandler` to [Next.js API handler](https://nextjs.org/docs/api-routes/introduction), który pobiera obiekt [zapytania](https://developer.mozilla.org/en-US/docs/Web/API/Request) i [odpowiedzi](https://developer.mozilla.org/en-US/docs/Web/API/Response) serwera. Oznacza to, iż możesz zawrzeć `createNextApiHandler` w middleware, w jakim tylko chcesz. Poniżej znajdziesz [przykładowy kod](#aktywacja-cors), dzięki któremu dodasz CORS.\n\n### 📄 `server/api/trpc.ts`\n\nPlik ten podzielony jest na dwie części - tworzenie kontekstu oraz inicjalizacji tRPC:\n\n1. Definiujemy kontekst przesyłany do procedur tRPC. Kontekst, to dane do których dostęp mają wszystkie twoje procedury tRPC. Jest to doskonałe miejsce do umieszczenia rzeczy, takich jak połączenia z bazą danych, informacje o uwierzytelnianiu, itp. W Create T3 App korzystamy z dwóch funkcji, aby umożliwić korzystanie z części kontekstu bez dostępu do obiektu zapytania.\n\n- `createInnerTRPCContext`: Tutaj definiujesz kontekst, który nie zależy od obiektu zapytania, np. połączenie z bazą danych. Możesz wykorzystać tą funkcję do [testów integracji](#przykładowy-test-integracji) oraz [funkcji pomocniczych SSG](https://trpc.io/docs/v10/ssg-helpers), gdzie nie posiadasz obiektu zapytania.\n\n- `createTRPCContext`: Tutaj definiujesz kontekst, który zależny jest od zapytania, np. sesja użytkownika. Otrzymujesz sesję korzystając z obiektu `opts.req`, a następnie posyłasz ją do funkcji `createInnerTRPCContext` w celu utworzenia finalnego kontekstu.\n\n2. Inicjalizujemy tRPC i definiujemy [procedury](https://trpc.io/docs/v10/procedures) oraz [middleware](https://trpc.io/docs/v10/middlewares). Umownie, nie powinieneś eksportować całego obiektu `t` a jedynie poszczególne procedury i middleware.\n\nZwróć uwagę, iż korzystamy z paczki `superjson` jako [transformera danych](https://trpc.io/docs/v10/data-transformers). Umożliwia on na zachowanie typów danych, które otrzymuje klient - przykładowo, posyłając obiekt `Date`, klient również otrzyma obiekt `Date` - a nie tekst, w przeciwieństwie do wielu innych API.\n\n### 📄 `server/api/routers/*.ts`\n\nTutaj definiujesz routery i procedury swojego API. Umownie, powinieneś tworzyć [osobne routery](https://trpc.io/docs/v10/router) dla odpowiadających im procedur.\n\n### 📄 `server/api/root.ts`\n\nTutaj [łączymy](https://trpc.io/docs/v10/merging-routers) wszystkie \"sub-routery\" zdefiniowane w folderze `routers/**` w jeden router aplikacji.\n\n### 📄 `utils/api.ts`\n\nJest to punkt startowy tRPC po stronie frontendu. To tutaj importować będziesz wszystkie **definicje typów** i tworzyć będziesz swój client tRPC razem z hookami od react-query. Ponieważ korzystamy z paczki `superjson` jako transformera danych na backendzie, musimy go uruchomić również na frontendzie. Dzieje się tak, ponieważ dane serializowane w API muszą być dekodowane właśnie na frontendzie.\n\nZdefiniujesz tu także [linki](https://trpc.io/docs/v10/links) tRPC, które decydują o całym flow zapytania - od klienta do serwera. My korzystamy z \"domyślnego\" linku [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink), który umożliwia [\"request batching\"](https://cloud.google.com/compute/docs/api/how-tos/batch). Korzystamy też z linku [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink), pozwalającego na wyświetlanie przydatnych podczas pisania aplikacji logów.\n\nNa koniec eksportujemy [pomocniczy typ](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type), którego użyć możesz do dziedziczenia typów na frontendzie.\n\n## Jak wykonać zewnętrzne zapytania do mojego API?\n\nKorzystając z regularnego API, zapytania takie możesz wykonać korzystając z klientów HTTP takich jak `curl`, `Postman`, `fetch`, czy tez bezpośrednio z przeglądarki. Z tRPC sprawa wygląda jednak inaczej. Jeżeli chcesz wykonać takie zapytania bez klienta tRPC, możesz skorzystać z jedngo z dwóch polecanych na to sposobów:\n\n### Ujawnianie zewnętrznie pojedynczej procedury tRPC\n\nJeżeli chcesz ujawnić zewnętrznie pojedynczą procedurę, powinieneś skorzystać z [zapytań po stronie serwera](https://trpc.io/docs/v10/server-side-calls). Pozwoli Ci to na wykonanie standardowego endpointa Next.js, ale użyje części \"resolvera\" twojej procedury tRPC.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Ujawnianie wszystkich procedur tRPC jako endpointów REST\n\nJeżeli chcesz ujawnić zewnętrznie wszystkie procedury tRPC, sprawdź rozszerzenie stworzone przez społeczność - [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Dostarczając dodatkowych metadanych do twoich procedur, wygenerować możesz REST API zgodne z OpenAPI ze swoich routerów tRPC.\n\n### To tylko zapytania HTTP\n\ntRPC komunikuje się za pomocą HTTP, więc masz także możliwość wykonywania zapytań do swoich procedur korzystając właśnie z \"regularnych\" zapytań HTTP. Składnia może wydawać się jednak nieporęczna z powodu wykorzystywanego przez tRPC [protokołu RPC](https://trpc.io/docs/v10/rpc). Jeżeli jesteś ciekawy jak on działa, możesz zobaczyć jak wyglądają zapytania tRPC w zakładce \"sieć\" w swojej przeglądarce - polecamy robić to jednak tylko w celach edukacyjnych i skorzystać z jednego z rozwiązań przedstawionych powyżej.\n\n## Porównanie do endpointu API Next.js\n\nPorównajmy endpoint API Next.js z procedurą tRPC. Powiedzmy, że chcemy pobrać ubiekt użytkownika z naszej bazy danych i zwrócić go na frontend. Endpoint API Next.js napisać moglibyśmy w następujący sposób>+:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nPorównaj to do powyższego przykładu z tRPC - zobaczysz zalety korzystanie właśnie z tego sposobu:\n\n- Zamiast precyzować url dla każdego route'a (co może stać się uciążliwe do debugowania, jeśli coś przeniesiesz), twój cały router jest obiektem z autouzupełnianiem.\n- Nie musisz walidować użytej metody HTTP.\n- Nie musisz walidować zawartości zapytania pod kątem pooprawności zawartych danych - zajmuje się tym Zod.\n- Zamiast tworzyć obiekt \"response\", możesz wyrzucać błędy i zwracać wartości lub obiekty tak, jak robiłbyś to w zwykłej funkcji TypeScripta.\n- Wywoływanie procedury na frontendzie dostarcza Ci autouzupełniania i type-safety.\n\n## Przydatne fragmenty\n\nZnajdziesz tutaj fragmenty kodu, które mogą Ci się przydać.\n\n### Aktywacja CORS\n\nJeżeli chcesz korzystać z API z różnych domen, np. w monorepo zawierającym aplikację React Native, możesz chcieć włączyć CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Włącz cors\n  await cors(req, res);\n\n  // Stwórz i wywołaj handler tRPC\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### \"Optimistic updates\"\n\nAktualizacje danych zwane \"Optimistic updates\" zachodzą wtedy, kiedy aktualizujemy UI, zanim zapytanie API zostanie ukończone. Dostarcza to lepsze doświadczenie użytkownika, ponieważ nie musi on czekać na ukończenie zapytania API, aby zobaczyć odzwierciedlenie zmian w interfejsie aplikacji. Pamiętaj jednak, że aplikacje, które cenią sobie poprawność danych, powinny za wszelką cenę unikać aktualizacji \"optimisic updates\" - nie są one \"poprawną\" reprezentacją stanu backendu. Więcej na ich temat możesz poczytać w [dokumentacji React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Anuluj wychodzące zapytania (aby nie nadpisały one \"optimistic update'u\")\n      await utils.post.list.cancel();\n\n      // Otrzymaj dane z queryCache\n      const prevData = utils.post.list.getData();\n\n      // Zaktualizuj dane z naszego nowego postu\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Zwróć poprzednie dane, aby w razie błędu można było z nich przywrócić stan aplikacji\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // Jeżeli mutacja wyrzuci błąd, skorzystaj z wartości kontekstu z onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Zsynchronizuj z serwerem po ukończonej mutacji\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Przykładowy Test Integracji\n\nTu znajdziesz przykładowy test integracji korzystający z paczki [Vitest](https://vitest.dev), aby sprawdzić, czy router tRPC działa poprawnie, czy parser danych wejściowych dziedziczy odpowiedni typ, oraz czy zwracane dane pasują do oczekiwanego outputu.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\nJeżeli twoja procedura jest chroniona, możesz przesłać stworzony obiekt `session` tworząc kontekst:\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n  // ...\n});\n```\n\n## Przydatne Zasoby\n\n| Zasób                    | Link                                                    |\n| ------------------------ | ------------------------------------------------------- |\n| Dokumentacja tRPC        | https://www.trpc.io                                     |\n| Parę przykładów z tRPC   | https://github.com/trpc/trpc/tree/next/examples         |\n| Dokumentacja React Query | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/pl/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Korzystanie z TypeScripta\nlayout: ../../../layouts/docs.astro\nlang: pl\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Buduj siatki bezpieczeństwa, nie barierki<span aria-hidden=\"true\">&quot;</span>\n      <br />\n      <span className=\"text-xs opacity-70\"><span aria-hidden=\"true\">&quot;</span>Oryginał: Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span></span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 mr-4 rounded-full bg-neutral-500\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - twórca stacka T3</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nBez względu na to, czy jesteś nowym deweloperem, czy doświadczonym programistą, uważamy, iż TypeScript jest w tych czasach obowiązkiem. Początkowo może wyglądać strasznie, ale tak jak z większością narzędzi, z czasem nie będziesz chciał już z niego z rezygnować.\n\nZaopatruje Cię on w feedback na żywo definiując oczekiwane typy danych. Dostarcza także pomocnego autouzupełniania w edytorze lub krzyczy na ciebie czerwonymi podkreśleniami, jeżeli próbujesz uzyskać dostęp do właściwości, która nie istnieje, lub jesli próbujesz przesłać wartość złego typu - co skutkowałoby dłuższym debugowaniem w razie błędu.\n\nJest to prawdopodobnie narzędzie, które pozwala na największy wzrost produktywności dewelopera; dostarczanie dokumentacji kodu który piszesz, czy też z którego bezpośrednio korzystasz, a także posiadanie nagłego feedbacku w razie nieuniknionych błędów jest bezcenne.\n\n## Type Inference\n\nPodczas gdy wielu nowych deweloperów korzystających z TypeScripta martwi się o mus jego _pisania_, wiele benefitów wynikających z korzystania z tego języka, nie wymaga od ciebie praktycznie żadnej zmiany w kodzie - jednym z tych benefitów jest tzw. \"inference\". Oznacza to, iż jeśli coś posiada własny typ, typ ten przechodzić będzie przez całe flow aplikacji bez potrzeby jego ponownego definiowania w innych jej miejscach. Jeżeli na przykład zdefiniujesz w jednym miejscu typy argumentów przyjmowanych przez daną funkcję, reszta funkcji będzie typesafe bez potrzeby pisania kodu specyficznego dla TypeScripta. Deweloperzy tworzący biblioteki wkładają dużo wysiłku w utrzymywanie typów dla swoich projektów, co skutkuje tym, iż twórcy aplikacji mogą benefitować zarówno z type inference, jak i z wbudowanej dokumentacji w edytorze kodu, którą typy te dostarczają.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nSprawdź film od Theo - [korzystasz z TypeScripta źle...](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Wykorzystanie mocnych stron type inference w projektach\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) to biblioteka walidacji bazująca na schematach, zbudowana z pomocą TypeScripta. Napisz schemat reprezentujący pojedyncze źródło prawdy, a Zod zapewni poprawność danych w całej aplikacji - nawet wśród zapytań do zewnętrznych API.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) dostarcza deklaratywne, zawsze aktualne automatycznie zarządzane zapytania i mutacje, które bezpośrednio wspomagają zarówno Ciebie jako dewelopera i UX.\n\n## Przydatne Zasoby\n\n| Zasób                                                     | Link                                                              |\n| --------------------------------------------------------- | ----------------------------------------------------------------- |\n| TypeScript Handbook                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| Poradnik TypeScripta dla Początkujących                   | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                           | https://github.com/type-challenges/type-challenges                |\n| Kanał YouTube - Rodney Mullen of TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/pl/why.md",
    "content": "---\ntitle: Dlaczego CT3A?\ndescription: Dlaczego powinieneś wybrać Create T3 App dla swojego następnego projektu\nlayout: ../../layouts/docs.astro\nlang: pl\n---\n\nStworzyliśmy Create T3 App, ponieważ [Theo](https://twitter.com/t3dotgg) nie chciał przygotować szablonu składającego się ze swoich ulubionych technologii. Zainspirowany przez create-next-app, [CLI od Astro](https://astro.build) oraz ogólne zamiłowanie do typesafety, zespół Create T3 App ciężko pracował budując najlepszy możliwy punkt startowy dla nowych projektów korzystających ze stacka T3.\n\nJeżeli jesteś zainteresowany korzystaniem z Next.jsa w sposób, w który nie stracisz na typesafety, jest to znakomite miejsce, aby zacząć. Jeśli jesteś ciekawy co do poszczególnych technologii wybranych przez nas dla tego narzędzia, czytaj dalej :)\n\n## Dlaczego TypeScript?\n\nJavaScript jest ciężki. Dlaczego dodajemy więcej zasad?\n\nStanowczo wierzymy, że TypeScript pomoże ci być lepszym deweloperem. Zaopatruje Cię on w feedback na żywo definiując oczekiwane typy danych. Dostarcza także pomocnego autouzupełniania w edytorze lub krzyczy na ciebie czerwonymi podkreśleniami, jeżeli próbujesz uzyskać dostęp do właściwości, która nie istnieje, lub jesli próbujesz przesłać wartość złego typu - co skutkowałoby dłuższym debugowaniem w razie błędu. Bez względu na to, czy jesteś nowy w świecie web developmentu, czy też doświadczonym programistą, \"surowość\" jaką daje ci TypeScript pozwala na mniej frustrujące i bardziej konsekwentne doświadczenie niż czysty JS.\n\nTypesafety pozwala ci być szybszym. Jeżeli dalej nie jesteś przekonany, może się okazać, że [korzystasz z TypeScripta źle...](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Dlaczego Next.js?\n\nKochamy Reacta. Zmienił on sposób tworzenia interfejsów na niewyobrażalnie bardziej przystępny. Może on także prowadzić dewelopera za rękę z miejscach, mogących sprawiać problemy.\n\nNext.js oferuje lekko kontrowersyjne, bardzo zoptymalizowane podejście do tworzenia aplikacji z pomocą Reacta. Od routingu przez API do renderowania zdjęć, ufamy Next.jsowi i wierzymy, że prowadzi on nas do dobrych decyzji.\n\n## Dlaczego tRPC/Prisma/Tailwind/itp.?\n\nStaramy się utrzymać projekty w tak prosty sposób, jak tylko się da. Okazuje się jednak, że korzystamy z tych narzędzi w każdym \"projekcie-aplikacji\" jaki tylko budujemy. `create-t3-app` robi znakomitą robotę pozwalając ci zaadoptować te części, których potrzebujesz.\n\n### tRPC\n\ntRPC spełnia obietnice GraphQLa o bezproblemowej integracji klienta z serwerem bez niepotrzebnego boilerplate'a. Jest to przemyślane wykorzystanie TypeScripta które zaopatrzy Cię w niespotykane doświadczenie przy programowaniu.\n\n### Prisma\n\nPrisma dla SQLa to jak TypeScript dla JSa. Pozwala na DX jaki wcześniej nie istniał. Generując typy ze schematu zdefiniowanego przez użytkownika i kompatybilnego z [wieloma bazami danych](https://www.prisma.io/docs/concepts/database-connectors), Prisma gwarantuje typesafety na każdym kroku od bazy danych do twojej aplikacji.\n\nPrisma oddaje ci w ręce cały [zestaw narzędzi](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) ułatwiając codzienne integracje z bazą danych. Prisma Client odpowiedzialny za wykonywanie zapytań do bazy danych jest tak łatwy w użyciu, że nawet nie zorientujesz się, kiedy będziesz z niego korzystać. Prisma Studio natomiast to przystępny interfejs graficzny dla twojej bazy danych, który pozwala ci odczytywać z niej dane i manipulować nimi bez potrzeby pisania kodu.\n\n### Tailwind CSS\n\nTailwind sprawia wrażenie \"CSSa w trybie zen\".\n\nZaopatrując Cię w narzędzia do budowania, takie jak świetne domyślne kolory, spacingi oraz inne prymitywy, Tailwind w znaczny sposób ułatwia stworzenie dobrze wyglądającej aplikacji. W przeciwieństwie do bibliotek komponentów, nie sprawia niepotrzebnych problemów, kiedy chcesz stworzyć coś unikalnego i pięknego.\n\nDodatkowo, z podejściem \"inline\", Tailwind zachęca cię do stylizowania aplikacji bez martwienia się o nazywanie klas, organizowanie struktury plików czy rozwiązywanie innych problemów niekoniecznie mających coś wspólnego z tym, co chcesz właśnie stworzyć.\n\n### NextAuth.js\n\nKiedy chcesz dodać system kont do swojej aplikacji Next.js, NextAuth.js to znakomite rozwiązanie. Pozwala ono wdrożyć złożone systemy bezpieczeństwa nie zmuszając Cię przy tym do pisania ich własnoręcznie. NextAuth.js zawiera rozległą listę providerów, które zapewnią Ci szybki sposób na dodanie OAutha. Paczka ta posiada również wiele adapterów dla baz danych i ORMów.\n"
  },
  {
    "path": "www/src/pages/pt/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Deploy com Docker\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nVocê pode colocar essa stack em contêineres e fazer deploy dela como um único contêiner usando o Docker ou como parte de um grupo de contêineres usando o docker-compose. Veja [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) para um repositório de exemplo baseado neste documento.\n\n## Configuração do Projeto Docker\n\nPor favor, note que o Next.js requer um processo diferente para variáveis de ambiente em _build time_ (disponível no frontend, prefixado por `NEXT_PUBLIC`) e _runtime_, somente do lado do servidor. Nesta demonstração estamos usando duas variáveis. Preste atenção em suas posições no `Dockerfile`, argumentos de linha de comando e `docker-compose.yml`:\n\n- `DATABASE_URL` (usado pelo servidor)\n- `NEXT_PUBLIC_CLIENTVAR` (usado pelo cliente)\n\n### 1. Configuração do Next\n\nEm seu arquivo [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), configure a opção `output` como `standalone` para [reduzir o tamanho de imagens](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Criar arquivo dockerignore\n\n<details>\n    <summary>\n      Clique aqui e inclua esse conteúdo no arquivo <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Criação do arquivo Dockerfile\n\n> Como não estamos puxando as variáveis de ambiente do servidor para nosso contêiner, a [validação do esquema do ambiente](/en/usage/env-variables) falhará. Para evitar isso, temos que adicionar a flag `SKIP_ENV_VALIDATION=1` ao comando de compilação para que os schemas env não sejam validados no momento da compilação.\n\n<details>\n    <summary>\n      Clique aqui e inclua esse conteúdos no <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDÊNCIAS\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Instalação do Prisma Client - remova se não estiver usando o Prisma\n\nCOPY prisma ./\n\n# Instalação de dependências com base no package manager padrão\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile não encontrado.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Observações_**\n>\n> - _A emulação de `--platform=linux/amd64` pode não ser necessária após a mudança para o Node 18._\n> - _Consulte [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) para entender por que `libc6-compat` pode ser necessário._\n> - _Usando imagens baseadas em Alpine 3.17 [pode causar problemas no Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Realizando a configuração: `engineType = \"binary\"` corrige esse problema no Alpine 3.17, [mas apresenta um custo de performance adicional](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js coleta [dados anônimos de telemetria sobre uso geral](https://nextjs.org/telemetry). Remova o primeiro comentário de `ENV NEXT_TELEMETRY_DISABLED 1` para desabilitar a telemetria durante o build. Remova o segundo comentário para desabilitar a telemetria durante o tempo de execução._\n\n</div>\n</details>\n\n## Execute build e run da imagem localmente\n\nExecute `build` e `run` desta imagem localmente com os seguintes comandos:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nAbra [localhost:3000](http://localhost:3000/) para ver sua aplicação rodando.\n\n## Docker Compose\n\nVocê também pode usar o Docker Compose para criar a imagem e executar o contêiner.\n\n<details>\n    <summary>\n      Siga as etapas 1 a 4 acima, clique aqui e inclua o conteúdo no arquivo <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nExecute isso usando o comando `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nAbra [localhost:3000](http://localhost:3000/) para ver sua aplicação rodando.\n\n</div>\n</details>\n\n## Deploy na Railway\n\nVocê pode usar [deploys automáticos de Dockerfile](https://docs.railway.app/deploy/dockerfiles) em uma PaaS como a [Railway](https://railway.app) para fazer deploy das suas aplicações. Se você tiver o [CLI da Railway instalado](https://docs.railway.app/develop/cli#install), poderá fazer deploy da sua aplicação com os seguintes comandos:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nVá para \"Variables\" e inclua seu `DATABASE_URL`. Em seguida, vá para \"Settings\" e selecione \"Generate Domain\". Para ver um exemplo em execução no Railway, visite [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Recursos Úteis\n\n| Recurso                                         | Link                                                                 |\n| ----------------------------------------------- | -------------------------------------------------------------------- |\n| Referência do Dockerfile                        | https://docs.docker.com/engine/reference/builder/                    |\n| Referência da versão 3 do arquivo Compose       | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Referência da CLI do Docker                     | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Referência da CLI do Docker Compose             | https://docs.docker.com/compose/reference/                           |\n| Deploy do Next.js com imagem do Docker          | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js no Docker                               | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Exemplo de Next.js com Docker                   | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Criar imagem do Docker de um aplicativo Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/pt/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Deployment\",\n  layout: \"docs\",\n  description: \"Aprenda como fazer deploy para produção na sua aplicação T3.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/pt/deployment/netlify.mdx",
    "content": "---\ntitle: Netlify\ndescription: Fazendo deploy para a Netlify\nlayout: ../../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nNetlify é um provedor de deploy alternativo semelhante à Vercel. Veja [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) para um exemplo de repositório baseado nesta documentação.\n\n## Por que hospedar na Netlify\n\nA sabedoria popular diz que a Vercel possui um suporte melhor para Next.js já que foi ela que desenvolveu o Next.js. Eles possuem interesse em garantir que a plataforma esteja ajustada para um desempenho ideal e uma boa DX com Next.js. Isso é verdade para a maioria dos casos de uso, não fazendo sentido desviar-se do caminho padrão.\n\nHá também um sentimento comum de que diversos recursos do Next.js são suportados apenas na Vercel. Embora isso seja verdade para os novos recursos do Next.js que são testados e suportados na Vercel deste o seu lançamento, também é verdade que outros provedores como a Netlify buscam [implementar e liberar rapidamente versões de suporte](https://www.netlify.com/blog/deploy-nextjs-13/) para [recursos estáveis do Next.js](https://docs.netlify.com/integrations/frameworks/next-js/overview/)\n\nExistem diversos prós e contras dentre todos provedores de deploy, já que nenhum host pode consegue ter o melhor suporte para todos os casos de uso existente. Por exemplo, a Netlify criou o seu próprio [Next.js runtime customizado](https://github.com/netlify/next-runtime) para as Netlify Edge Functions (que rodam no Deno Deploy) e [mantém um único middleware para acessar e modificar respostas HTTP](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n<Callout type=\"info\">\n  Para verificar o status de recursos não estáveis do Next 13 veja [Using the\n  Next 13 `app` directory on\n  Netlify](https://github.com/netlify/next-runtime/discussions/1724).\n</Callout>\n\n## Configuração do Projeto\n\nHá diversas maneiras de configurar suas instruções de build, incluindo diretamente através da Netlify CLI ou pelo Netlify Dashboard. Embora não seja obrigatório, é recomendável criar e incluir um arquivo [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Isso garante que as versões fork ou clonadas do projeto sejam mais fáceis de implementar.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Usando o Netlify Dashboard\n\n1. Dê o push de seu código para um repositório do GitHub e inscreva-se na [Netlify](https://app.netlify.com/signup). Depois de ter criado uma conta, clique em **Add new site** e então **Import an existing project**.\n\n![Novo projeto na Netlify](/images/netlify-01-new-project.webp)\n\n2. Conecte o seu provedor Git.\n\n![Importar repositório](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Selecione o repositório de seu projeto.\n\n![Selecione o repositório de seu projeto](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. A Netlify detectará se você possui um arquivo `netlify.toml` e então vai automaticamente configurar seu comando de build e diretório de publicação.\n\n![Configurações de build do Nextjs](/images/netlify-04-configure-build-settings.webp)\n\n5. Clique em **Show advanced** e então **New variable** para adicionar suas variáveis de ambiente.\n\n![Adicionar variáveis de ambiente](/images/netlify-05-env-vars.webp)\n\n6. Clique em **Deploy site**, aguarde até o processo de build terminar, e então veja seu novo site.\n\n## Usando a Netlify CLI\n\nPara fazer o deploy a partir da linha de comando, primeiramente você fazer o push de seu projeto para um repositório do GitHub e [instalar a Netlify CLI](https://docs.netlify.com/cli/get-started/). Você pode instalar a `netlify-cli` como uma dependência de seu projeto ou instalar globalmente em sua máquina usando o seguinte comando:\n\n```bash\nnpm i -g netlify-cli\n```\n\nPara testar o seu projeto localmente, rode o comando [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) e abra [`localhost:8888`](http://localhost:8888/) para ver sua aplicação Netlify rodando localmente:\n\n```bash\nntl dev\n```\n\nRode o comando [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) para configurar seu projeto:\n\n```bash\nntl init\n```\n\nImporte as variáveis de ambiente de seu projeto que estão em seu arquivo `.env` com [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nFaça o deploy de seu projeto com [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Você precisará passar a flag `--build` para rodar o comando de build antes do deploy e a flag `--prod` para fazer o deploy do seu site em sua URL principal:\n\n```bash\nntl deploy --prod --build\n```\n\nPara ver um exemplo rodando na Netlify, visite [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/pt/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Fazendo deploy para a Vercel\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nRecomendamos fazer o deploy de sua aplicação na [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Isso facilita muito o deploy de sua aplicação Next.js.\n\n## Configuração do projeto\n\nA Vercel provavelmente configurará seu comando de build e publicará o diretório automaticamente. No entanto, você também pode especificar essas informações junto com outras configurações criando um arquivo chamado [`vercel.json`](https://vercel.com/docs/project-configuration) e incluindo os seguintes comandos:\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Usando o painel de controle da Vercel\n\n1. Depois de enviar seu código para um repositório GitHub, faça login na [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) com o GitHub e clique em **Add New Project**.\n\n![Novo projeto no Vercel](/images/vercel-new-project.webp)\n\n2. Importe o repositório GitHub com seu projeto.\n\n![Importar repositório](/images/vercel-import-project.webp)\n\n3. Adicione suas variáveis de ambiente.\n\n![Adicionar variáveis de ambiente](/images/vercel-env-vars.webp)\n\n4. Clique em **Deploy**. Agora, sempre que você enviar uma alteração ao seu repositório, a Vercel reimplementará automaticamente seu aplicativo!\n\n## Usando a CLI da Vercel\n\nPara fazer deploy a partir da linha de comando, você deve primeiro [instalar a CLI da Vercel globalmente](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nExecute o comando [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) para implantar seu projeto.\n\n```bash\nvercel\n```\n\nInclua `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` para variáveis de ambiente como a string de conexão do banco de dados. Use `--yes` se quiser pular as perguntas de implantação e dar a resposta padrão para cada uma.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nApós o primeiro deploy, esse comando o fará em um branch de preview. Você precisará incluir `--prod` para enviar alterações diretamente para a produção.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/pt/faq.mdx",
    "content": "---\ntitle: FAQ\ndescription: Perguntas frequentes sobre o Create T3 App\nlayout: ../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nAqui estão algumas perguntas frequentes sobre o Create T3 App.\n\n## O que vem a seguir? Como eu faço uma aplicação com isso?\n\nNós tentamos manter esse projeto o mais simples o possível, assim você pode começar só com o básico que configuramos pra você, e adicionar mais tarde o que se tornar necessário.\n\nCaso você não esteja familiarizado com as diferentes tecnologias usadas neste projeto, por favor se dirija à documentação respectiva. Se você ainda estiver perdido, sinta-se convidade a entrar na nossa comunidade no [Discord](https://t3.gg/discord) e pedir ajuda.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## Como faço para manter minha aplicação atualizada?\n\nCreate T3 App não é um framework, é uma ferramenta com o básico necessário para iniciar o desenvolvimento de uma aplicação. Isso significa que depois de inicializar uma aplicação, ele é seu. Não há nenhum comando de terminal ou algo do tipo para mantê-lo atualizado. Se desejas manter-se atualizado com qualquer atualização que façamos ao template, você pode [ativar as notificações de versões](https://docs.github.com/pt/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications) de nosso repositório. Sabendo de tudo isso, não é realmente necessário implementar toda e qualquer alteração de nosso template, em sua aplicação.\n\n## Onde aprender sobre a stack?\n\nPor mais que os recursos listados abaixo são alguns dos melhores que existem para a T3 Stack, a comunidade (e o [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) recomendam que você comece apenas usando a stack e aprendendo enquanto desenvolve e constrói com ela.\n\nSe você está cogitando usar o Create T3 App, há altas chances que você já esteja usando algumas partes da stack. Então por que não se jogar de cabeça e aprender outras partes enquanto constrói algo?\n\nAgora, nós percebemos que essa parte não funciona para todos. Então, se você sente que testou as recomendações e ainda assim gostaria de alguns recursos extras, ou só não está confiante em fazer por conta própria e/ou se sente sobrecarregado com a stack, confira esses incríveis tutoriais (infelizmente, só em inglês até o momento) sobre o Create T3 App:\n\n### Artigos\n\n- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Vídeos\n\n- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(recomendado)**\n- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Por que tem arquivos `.js` no projeto?\n\nConforme o axioma [Axioma T3 #3](/pt/introduction#segurança-de-tipo-não-é-opcional) nós consideramos _typesafety_ como um cidadão de primeira classe. Infelizmente, nem todos os frameworks e plugins suportam TypeScript, o que significa que alguns arquivos tiveram que ser arquivos `.js`.\n\nNós buscamos enfatizar que esses arquivos são JavaScript por uma razão, explicitamente declarando cada tipo de arquivo (`cjs` ou `mjs`) dependendo do que é suportado pela biblioteca que o usa. Também, todos os arquivos `js` nesse projeto ainda assim são checados em relação à tipo, usando a opção checkJs no compilador (tsconfig).\n\n## Estou tendo dificuldades em adicionar o i18n ao meu projeto. Existe alguma referência que eu possa usar?\n\nNós decidimos não incluir o i18n por padrão no `create-t3-app` por conta de ser um tópico muito opinado e haverem muitas maneiras de implementá-lo.\n\nDe qualquer forma, se você tiver dificuldades de implementá-lo e quiser ver um projeto de referência, nós temos um [repositório exemplo](https://github.com/juliusmarminge/t3-i18n) que mostra como você pode adicionar o i18n a um T3 app usando [next-i18next](https://github.com/i18next/next-i18next).\n\n## Por que nós estamos usando `/pages` e não `/app` do Next.js 13?\n\nConforme o [Axioma T3 #2](/pt/introduction#agir-com-responsabilidade), nós amamos _tecnologia de ponta_, porém valorizamos a estabilidade, nosso roteador inteiro é díficil de mover, [não é um bom lugar para utilizar _bleeding edges_](https://youtu.be/mnwUbtieOuI?t=1662). Enquanto `/app` é [instável e experimental](https://youtu.be/rnsC-12PVlM?t=818), não está pronto para produção; a API está em beta e é esperado que possua _breaking changes_.\n\n<Callout type=\"info\">\n  Para obter uma lista de recursos suportados, planejados e trabalhados no\n  diretório `/app`, visite a [Documentação beta do\n  Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n</Callout>\n"
  },
  {
    "path": "www/src/pages/pt/folder-structure-pages.mdx",
    "content": "---\ntitle: Estrutura de Pastas (Pages)\ndescription: Estrutura de pastas de um novo T3 App inicializado\nlayout: ../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nPor favor, selecione seus pacotes para ver a estrutura de pastas de um aplicativo recém-estruturado com essas seleções. Mais abaixo, você encontrará uma descrição de cada pacote.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nA pasta `prisma` contém o arquivo `schema.prisma` que é usado para configurar a conexão com o banco de dados e o schema do banco de dados. Ela também é onde são salvos os arquivos de migração e/ou scripts de seed, se usados. Veja [Uso do Prisma](/en/usage/prisma) para mais informações.\n\n</div>\n<div>\n\n### `public`\n\nA pasta `public` contém recursos estáticos que são servidos pelo servidor web. O `favicon.ico` é um exemplo de um recurso estático.\n\n</div>\n<div>\n\n### `src/env`\n\nUsado para a validação de variáveis ambiente e definição de tipos - veja [Variáveis de Ambiente](usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nA pasta `pages` contém todas as páginas da aplicação Next.js. O arquivo `index.tsx` na raiz da pasta `/pages` é a página inicial da aplicação. O arquivo `_app.tsx` é usado para envolver a aplicação com providers. Veja a [Documentação do Next.js](https://nextjs.org/docs/basic-features/pages) para mais informações.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nA pasta `api` contém todas as rotas API da aplicação Next.js. O arquivo `examples.ts` contém um exemplo de rota que usa o recurso de [Rotas API do Next.js](https://nextjs.org/docs/api-routes/introduction) junto com o prisma. O arquivo `restricted.ts` contém um exemplo de rota que usa o recurso de [Rotas API do Next.js](https://nextjs.org/docs/api-routes/introduction) e é protegido pelo [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nO arquivo `[...nextauth].ts` é a rota de autenticação com slug do NextAuth.js. Ele é usado para lidar com as requisições de autenticação. Veja [Uso do NextAuth.js](usage/next-auth) para mais informações sobre o NextAuth.js, e a [Documentação de Rotas Dinâmicas do Next.js](https://nextjs.org/docs/routing/dynamic-routes) para informações sobre rotas com parâmetros/slugs.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nO arquivo `[trpc].ts` é o ponto de entrada do tRPC. Ele é usado para lidar com as requisições do tRPC. Veja [Uso do tRPC](usage/trpc#-pagesapitrpctrpcts) para mais informações sobre esse arquivo, e [Documentação de Rotas Dinâmicas do Next.js](https://nextjs.org/docs/routing/dynamic-routes) para informações sobre rotas com parâmetros/slugs.\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nA pasta `server` é usada para de maneira clara separar código do servidor e código do cliente.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nContém utilitários para autenticação, como recuperar a sessão do usuário no lado do servidor. Veja [uso do NextAuth.js](usage/next-auth#usage-with-trpc) para mais informações.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nO arquivo db.ts é usado para instanciar o cliente Prisma no escopo global. Veja [uso do Prisma](usage/prisma#prisma-client) e [melhores práticas para usar o Prisma com o Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) para mais informações.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nA pasta api contém o código do lado do servidor do tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nA pasta routers contém todos as sub-rotas do tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nO arquivo `example.ts` é um exemplo de roteador tRPC que utiliza o utilitário `publicProcedure` para demonstrar como criar uma rota tRPC pública.\n\nDependendo dos pacotes escolhidos, este roteador contém mais ou menos rotas para melhor demonstrar o uso de acordo com suas necessidades.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/trpc/trpc.ts`\n\nO arquivo `trpc.ts` é o arquivo de configuração principal para seu back-end tRPC. Aqui nós:\n\n1. Definimos o contexto usado nas requests tRPC. Veja [uso do tRPC](usage/trpc#-serverapitrpcts) para mais informações.\n2. Exportamos os auxiliares de procedures. Veja [uso do tRPC](usage/trpc#-serverapitrpcts) para mais informações.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nO arquivo `root.ts` é usado para mesclar as rotas tRPC e exportá-las como um único roteador, bem como a definição de tipo da rota. Veja [uso do tRPC](usage/trpc#-serverapirootts) para mais informações.\n\n</div>\n<div>\n\n### `src/styles`\n\nA pasta `styles` contém os estilos globais da aplicação.\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/types`\n\nA pasta `types` é usada para guardar tipos ou definições de tipos reutilizáveis.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/types/next-auth.d.ts`\n\nO arquivo `next-auth.d.ts` é usado para estender o tipo padrão de sessão do NextAuth para incluir o ID de usuário. Veja [Uso do NextAuth.js](usage/next-auth#inclusão-do-userid-na-sessão) para mais informações.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nA pasta `utils` é usada para guardar funções utilitárias comuns reutilizáveis.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nO arquivo `api.ts` é o ponto de entrada front-end para o tRPC. Veja [uso do tRPC](usage/trpc#-utilsapits) para mais informações.\n\n</div>\n<div>\n\n### `.env`\n\nO arquivo `.env` é usado para armazenas as variáveis ambiente. Veja [Variáveis de Ambiente](usage/env-variables) para mais informações. Esse arquivo **não** deve ser commitado para o histórico do git.\n\n</div>\n<div>\n\n### `.env.example`\n\nO arquivo `.env.example` mostra um exemplo de de variáveis ambiente baseado nas bibliotecas escolhidas. Esse arquivo deve ser commitado para o histórico do git.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nO arquivo `.eslintrc.cjs` é usado para configurar o ESLint. Veja [Documentação do ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) para mais informações.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nO arquivo `next-env.d.ts` garante que os tipos do Next.js sejam lidos pelo compilador do TypeScript. **Você não deve remover ou editar, uma vez que pode mudar a qualquer momento.** Veja [Documentação do Next.js ](https://nextjs.org/docs/basic-features/typescript#existing-projects) para mais informações.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nO arquivo `next.config.mjs` é usado para configura o Next.js. Veja [Documentação do Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) para mais informações. Nota: a extensão .mjs é usada para permitir importações de módulos ESM.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nO arquivo `postcss.config.js` é usado para o uso do Tailwind PostCSS. Veja [Documentação do Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) para mais informações.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nO arquivo `prettier.config.mjs` é usado para configura o Prettier e incluir o prettier-plugin-tailwindcss para a formatação das classes CSS. Veja o post no [Blog do Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) para mais informações.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nO arquivo `tsconfig.json` é usado para configurar o TypeScript. Algumas configurações diferentes do padrão, como `strict mode`, foram habilitadas para garantir o melhor uso do TypeScript no create-t3-app e suas bibliotecas. Veja [Documentação do Typescript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) ou [Uso do TypeScript](usage/typescript) para mais informações.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/pt/installation.mdx",
    "content": "---\ntitle: Instalação\ndescription: Instruções de Instalação do Create T3 App\nlayout: ../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nPara estruturar uma aplicação usando `create-t3-app`, rode qualquer um dos comandos seguintes e responda as perguntas:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nApós sua aplicação ter sido estruturada, verifique os [Primeiros Passos](/pt/usage/first-steps) para começar a usar sua nova aplicação.\n\n## Uso avançado\n\n| Opção/Flag        | Descrição                                                                         |\n| ----------------- | --------------------------------------------------------------------------------- |\n| `[dir]`           | Inclua um argumento de diretório com um nome para o projeto                       |\n| `--noGit`         | Diga explicitamente à CLI para não inicializar um novo repositório git no projeto |\n| `-y`, `--default` | Ignore a CLI e inicialize um novo aplicativo t3 com todas as opções selecionadas  |\n| `--noInstall`     | Gera um projeto sem instalar as dependências                                      |\n\n## Uso experimental\n\nPara o nosso CI (Integração Contínua), nós temos algumas flags experimentais que te permitem inicializar qualquer aplicação sem responder nenhuma pergunta. Se esse caso de uso se aplicar a você, você pode usar essas flags. Note que essas flags são experimentais e podem mudar no futuro sem seguir nenhum versionamento.\n\n| Flag         | Descrição                              |\n| ------------ | -------------------------------------- |\n| `--CI`       | Informa a CLI que você está no modo CI |\n| `--trpc`     | Inclui o tRPC no projeto               |\n| `--prisma`   | Inclui o Prisma no projeto             |\n| `--nextAuth` | Inclui o NextAuth.js no projeto        |\n| `--tailwind` | Inclui o Tailwind CSS no projeto       |\n\n<Callout type=\"warning\">\n  Se você não providenciar a flag `CI`, o resto dessas flags não possui efeito.\n</Callout>\n\nVocê não precisa explicitamente excluir os pacotes que não deseja. De qualquer forma, se você preferir ser explícito, você pode passar a flag `false`, ex: `--nextAuth false`.\n\n### Exemplo\n\nO comando a seguir irá inicializar um T3 App com tRPC e Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/pt/introduction.md",
    "content": "---\ntitle: Introdução\ndescription: Introdução à T3 Stack\nlayout: ../../layouts/docs.astro\nlang: pt\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## A T3 Stack\n\nA _\"T3 Stack\"_ é uma stack de desenvolvimento web feita por [Theo](https://twitter.com/t3dotgg) focada na simplicidade, modularidade e ser full-stack mantendo a segurança de tipos (typesafe).\n\nAs peças principais são o [**Next.js**](https://nextjs.org/) e [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) é quase sempre incluso. Se você está fazendo algo que inclua back-end, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), e [**NextAuth.js**](https://next-auth.js.org/) são ótimas adições também.\n\nTalvez você tenha percebido que tem... várias peças. Mas isso é por design. Adicione, retire e troque as peças conforme necessário - essa stack é modular desde o núcleo :)\n\n## Então... o que é o create-t3-app? Um modelo?\n\nBasicamente. O `create-t3-app` é uma CLI (Command Line Interface) construída pelos experientes desenvolvedores da T3 Stack para agilizar a configuração inicial de um aplicativo T3 modular. Isso significa que cada uma das peças é opcional, e o \"modelo\" é gerado baseado nas suas necessidades específicas.\n\nDepois de incontáveis projetos e muitos anos com essas tecnologias, nós tempos muitas opiniões e percepções. Nós fizemos o nosso melhor para introduzi-las nessa CLI.\n\nIsto **NÃO** é um modelo completo. Nós **esperamos** que você traga suas próprias bibliotecas que resolvam as necessidades da **SUA** aplicação. Enquanto nós não queremos prescrever soluções para problemas específicos como gerenciamento de estado e deploy, nós [possuímos algumas recomendações listadas aqui](/pt/other-recs).\n\n## Axiomas T3\n\nSejamos francos - este é um _projeto opinado_. Nós compartilhamos um punhado de crenças fundamentais a respeito de desenvolvimento e as tratamos como base para nossas decisões.\n\n### Resolver Problemas\n\nÉ fácil cair nessa armadilhas de \"adicionar tudo\" - e nós explicitamente não queremos fazer isso. Tudo adicionado ao `create-t3-app` deve resolver um problema específico que existe dentro das principais tecnologias inclusas. Isso significa que nós não iremos adicionar coisas como bibliotecas de gerenciamento de estado (`zustand`, `redux`) mas iremos adicionar coisas como NextAuth.js e integrar o Prisma e tRPC para você.\n\n### Agir com Responsabilidade\n\nNós amamos tecnologia de ponta. A quantidade de velocidade e honestamente, diversão que vem com essas coisas novas é realmente muito legal. Nós pensamos que é importante agir com responsabilidade, usando tecnologias mais arriscadas nas partes menos arriscadas. Isso significa que não iríamos ⛔️ apostar em uma nova tecnologia de banco de dados arriscada (SQL é bom!). Porém felizmente ✅ apostar no tRPC uma vez que são só funções triviais de se mover.\n\n## Tipos seguros e bem definidos não são opcionais\n\nO objetivo declarado do `create-t3-app` é providenciar a maneira mais rápida de se começar uma aplicação web full-stack e **typesafe**. Nós levamos segurança de tipo muito a sério nessas partes, já que melhora nossa produtividade e nos ajuda a entregar menos bugs. Qualquer decisão que comprometa a natureza de segurança de tipo do `create-t3-app` é uma decisão que deve ser feita em um projeto diferente.\n"
  },
  {
    "path": "www/src/pages/pt/other-recs.md",
    "content": "---\ntitle: Outras Recomendações\ndescription: Bibliotecas e Serviços que nós recomendamos para vários projetos.\nlayout: ../../layouts/docs.astro\nlang: pt\n---\n\nNós reconhecemos que as bibliotecas inclusas no `create-t3-app` não resolvem todos os problemas. Enquanto nós te encorajamos a começar o seu projeto com as coisas que providenciamos, em algum momento você terá que adicionar novos pacotes. Apenas você pode saber o que o seu projeto precisa, mas aqui estão algumas coisas que nos encontramos recomendando com frequência.\n\nEstas são recomendações de contribuidores individuais do Create T3 App e não devem ser vistas como propriedades \"oficiais\" pela equipe Create T3 App ou T3-OSS. _**Faça sua própria pesquisa, especialmente antes de se comprometer com serviços pagos**_.\n\n## Gerenciamento de Estado\n\n_**Nota do editor**_: Bibliotecas de gerenciamento de estado podem ser boas, mas normalmente não são necessárias. Os hooks do React Query + tRPC devem ser capazes de tomar conta do seu estado do lado do servidor. Para o lado do cliente, comece com o `useState` do React, e procure por alguma dessas opções quando precisar de mais.\n\n### Zustand\n\n**Para nunca mais usar Redux**\n\nO \"moderno e simples Redux\", que você não sabia que precisava. Sempre podemos confiar em [Poimandres](https://github.com/pmndrs). Você pode construir tudo, desde aplicativos de videochamada até jogos e servidores com essa pequena biblioteca.\n\n- [Página inicial do Zustand](https://zustand-demo.pmnd.rs/)\n- [GitHub do Zustand](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Para nunca mais usar Context**\n\nPara uma abordagem mais atômica, o Jotai é difícil de ser batido. Também da [Poimandres](https://github.com/pmndrs), Jotai te permite definir singletons que parecem um useState global. Uma boa opção para manipulações de estado que não necessariamente precisam de uma máquina de estado.\n\n- [Página inicial do Jotai](https://jotai.org/)\n- [GitHub do Jotai](https://github.com/pmndrs/jotai)\n\n## Biblioteca de Componentes\n\nA maior parte das aplicações necessitam de vários componentes - botões de toggle, menus dropdown, modais, e assim por diante. Essas bibliotecas providenciam components bons, acessíveis e que você pode customizar como achar melhor.\n\n### Bibliotecas de Componentes não estilizados\n\nTambém conhecidas como bibliotecas headless, elas providenciam componentes não estilizados, acessíveis e bons que você pode customizar como achar melhor. Aqui estão algumas recomendações\n\n- [Radix UI](https://www.radix-ui.com/) oferece um conjunto poderoso de primitivos convenientes e acessíveis que você pode estilizar com CSS puro ou Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) feito pela equipe do Tailwind CSS também fornece componentes acessíveis e sem estilo que se integram perfeitamente ao Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) fornece primitivos de UI acessíveis para seu design system. Seu componente Date Picker é animal.\n\n### Bibliotecas de Componentes estilizados\n\n**Para quando você quer apenas que seu aplicativo seja OK**\n\nÀs vezes, você está construindo um projeto em que deseja apenas que a interface do usuário pareça decente fora da caixa. Para painéis de administração e outros projetos semelhantes, qualquer uma dessas bibliotecas de componentes fará o trabalho.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**Para criar bibliotecas de UI**\n\nCrie declarativamente uma biblioteca de UI com diferentes variantes de cor, tamanho etc. Quando seu projeto atinge uma escala em que você deseja um conjunto padronizado de componentes de interface do usuário com várias variantes usando Tailwind CSS, o CVA é uma ótima ferramenta.\n\n- [GitHub do Class Variance Authority](https://github.com/joe-bell/cva)\n\n## Animações\n\nPara quando você precisar de animações em seu aplicativo, aqui estão nossas recomendações.\n\n### AutoAnimate\n\n**Para animações com uma única linha de código**\n\nA maioria das bibliotecas de animação tenta satisfazer todos os casos de uso possíveis e, como resultado, torna-se desajeitada. O AutoAnimate é uma ferramenta de configuração zero que oferece uma melhoria significativa no UX sem nenhum esforço adicional do desenvolvedor.\n\n- [Página inicial do AutoAnimate](https://auto-animate.formkit.com/)\n- [GitHub do AutoAnimate](https://github.com/formkit/auto-animate)\n- [Snippet de um componente com AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Para animações complexas com código declarativo**\n\nO Framer Motion fornece uma sintaxe simples e declarativa e permite que você escreva menos código para criar tudo, desde animações complexas até gestos.\n\n- [Página inicial do Framer Motion](https://framer.com/motion)\n- [Documentation do Framer Motion](https://www.framer.com/docs/)\n\n## Deploy, Infraestrutura, Bancos de Dados e CI\n\n### Vercel\n\n**Para hospedar a sua aplicação**\n\nA Vercel tomou conta das implantações da web e transformou-as em uma integração do GitHub definida uma vez e esquecida. Nós escalamos para centenas de milhares de usuários sem problemas. Com tecnologia AWS, apenas uma interface muito melhor :)\n\n- [Página inicial da Vercel](https://vercel.com/)\n- [Guia de Deploy Create T3 App na Vercel](/pt/deployment/vercel)\n\n### PlanetScale\n\n**Para bancos de dados sem preocupações**\n\nPlanetScale é a melhor \"plataforma de banco de dados serverless\" que nós já usamos até então. Insana escalabilidade, boa experiência de desenvolvimento, e preço incomparável. Se você está usando SQL (e esperançosamente Prisma), isso é difícil de bater.\n\n- [Página inicial do PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Para hospedar sua infra**\n\nÉ a \"Heroku moderna\". A maneira mais fácil de colocar um servidor real em funcionamento. Se Vercel e PlanetScale não são suficientes, Railway provavelmente é. Aponte para um repositório do GitHub e pronto.\n\n- [Página inicial da Railway](https://railway.app/)\n\n### Upstash\n\n**Para Redis serverless**\n\nNós amamos Prisma e PlanetScale, mas alguns projetos precisam de uma solução mais performática. O Upstash permite que você obtenha o desempenho de memória do Redis em seu projeto sem servidor, sem precisar gerenciar a infraestrutura e escalar você mesmo.\n\n- [Página inicial do Upstash](https://upstash.com/)\n\n### Pusher\n\n**Para WebSockets serverless**\n\nSe WebSockets for o foco principal do seu projeto, considere um back-end mais tradicional, como [Fastify](https://www.fastify.io/) (que [também funciona com tRPC!](https://trpc.io/docs/v10/fastify)). Mas para adicionar rapidamente WebSockets a um aplicativo T3, o Pusher é uma excelente escolha.\n\n- [Página inicial do Pusher](https://pusher.com/)\n\n### Soketi\n\nO Soketi é uma alternativa auto-hospedável, simples e rápida ao Pusher. É totalmente compatível com o Pusher SDK, que você pode usar para se conectar ao servidor. Soketi serverless também está em beta.\n\n- [Página inicial do Soketi](https://soketi.app)\n- [GitHub do Soketi](https://github.com/soketi/soketi)\n\n## Analytics\n\nOs dados do usuário são muito valiosos quando você está criando um aplicativo. Aqui estão alguns provedores de análise que recomendamos.\n\n### Plausible\n\nPrecisa de análise? Plausível é uma das maneiras mais rápidas de obtê-los. Super mínimo. Ele ainda tem um [plugin simples para Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Página inicial do Plausible](https://plausible.io/)\n\n### Umami\n\nUmami é uma alternativa de código aberto, auto-hospedável, simples, rápida e focada em privacidade para o Google Analytics. Você pode implantá-lo facilmente em Vercel, Railway, etc. com PlanetScale como seu banco de dados.\n\n- [Página inicial do Umami](https://umami.is/)\n- [GitHub do Umami](https://github.com/umami-software/umami)\n\n## Outros\n\n### Next Bundle Analyzer\n\nÀs vezes, pode ser difícil determinar o que será incluído na saída de compilação do seu aplicativo. O Next Bundle Analyzer é uma maneira fácil de visualizar e analisar os pacotes JavaScript gerados.\n\n- [@next/bundle-analyzer no npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/pt/t3-collection.mdx",
    "content": "---\ntitle: Coleção T3\ndescription: Projetos bacanas open source e empresas usando a T3 stack\nlayout: ../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\nFez um projeto usando a T3 stack e deseja comparilhar? Adicione ele na lista!\n\n## Aplicações Open Source desenvolvidas usando a T3 Stack\n\n<OpenSourceAppList descriptionIntl=\"Descrição\" />\n\n## Empresas usando a T3 Stack\n\nNós adoraríamos saber de empresas usando a T3 Stack para seus apps. A sua empresa está usando a T3 Stacks e gostaria de compartilhar? Adicione à lista!\n\n<CompanyList descriptionIntl=\"Empresa\" />\n\n<Callout type=\"tip\">\n  Tem um projeto legal usando a T3 stack? Faça uma [pull\n  request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)\n  e adicione-o aqui!\n</Callout>\n"
  },
  {
    "path": "www/src/pages/pt/usage/env-variables.mdx",
    "content": "---\ntitle: Variáveis de Ambiente\ndescription: Iniciando com Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: pt\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nO Create T3 App usa sua mais nova biblioteca [@t3-oss/env-nextjs](https://env.t3.gg) e [zod](https://zod.dev) para validar variáveis de ambiente durante o tempo de execução (runtime) _e_ buildtime fornecendo uma lógica simples no arquivo `src/env.js`:\n\n## env.js\n\n_Muito longo, não li; Se você quiser adicionar uma nova variável de ambiente, você deve adicioná-la ao seu `.env` ao definir no validador em `src/env.js`._\n\nEste arquivo é dividido em duas partes - o esquema e a desestruturação do objeto, bem como a lógica de validação. A lógica de validação não deve ser tocada.\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env traz um novo conceito através do `createEnv`, o qual é responsável por criar o esquema e irá incluir a lógica de validação para variáveis de ambiente no cliente e servidor.\n\n<Callout type=\"info\">\n  Para mais informações sobre como o `createEnv` funciona internamente, confira\n  a documentação de [T3 Env](https://env.t3.gg/docs/introduction)\n</Callout>\n\n## Usando Variáveis de Ambiente\n\nQuando você quiser usar suas variáveis de ambiente, você pode importá-las de `env.js` e usá-las como faria normalmente. Se você importar isso no cliente e tentar acessar uma variável de ambiente do lado do servidor, receberá um erro em tempo de execução (runtime).\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` é totalmente tipado e fornece preenchimento automático\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ Isso lançará um erro em tempo de execução\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ Isso está correto\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nComo o arquivo `.env` padrão não está comprometido com o controle de versão, também incluímos um arquivo `.env.example`, no qual você pode, opcionalmente, manter uma cópia de seu arquivo `.env` com quaisquer segredos removidos. Isso não é necessário, mas recomendamos manter o exemplo atualizado para tornar mais fácil para os contribuidores começarem a usar seu ambiente.\n\nAlguns frameworks e outras ferramentas, como o Next.js, sugerem que você armazene variáveis em um arquivo `.env.local` e faça commit de arquivos `.env` em seu projeto. Isso não é recomendado, pois poderia facilitar o acidente de incluir variáveis ambiente secretas em seu histórico do git. Em vez disso, recomendamos que você armazene essas variáveis no arquivo `.env`, mantenha o arquivo `.env` em seu `.gitignore` e faça commit somente de arquivos `.env.example` em seu projeto.\n\n## Adicionando Variáveis Ambiente\n\nPara garantir que sua compilação nunca seja concluída sem as variáveis de ambiente de que o projeto precisa, você precisará adicionar novas variáveis de ambiente em **dois** locais:\n\n📄 `.env`: Insira sua variável de ambiente como faria normalmente em um arquivo `.env`, ou seja, `CHAVE=VALOR`. Além disso, certifique-se de desestruturar elas na opção `runtimeEnv`, por exemplo, `CHAVE: process.env.CHAVE`.\n\n📄 `env.js`: Adicione a lógica de validação apropriada para as variáveis de ambiente definindo um esquema Zod, por exemplo `NOME_DA_VARIAVEL: z.string()`\n\nOpcionalmente, você também pode manter `.env.example` atualizado:\n\n📄 `.env.example`: Insira sua variável de ambiente, mas certifique-se de não incluir o valor se for secreto, ou seja, `CHAVE=VALOR` ou `CHAVE=`\n\n### Exemplo\n\n_Quero adicionar meu token da API do Twitter como uma variável de ambiente do lado do servidor_\n\n1. Adicione a variável de ambiente a `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Adicione a variável de ambiente a `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n});\n```\n\n3. opcional: adicione a variável de ambiente a `.env.example`, mas não inclua o token\n\n```\nexport const env = createEnv({\n  // ...\n  runtimeEnv: {\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n"
  },
  {
    "path": "www/src/pages/pt/usage/first-steps.md",
    "content": "---\ntitle: Primeiros passos\ndescription: Começando com seu novo T3 App\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nVocê acabou de criar um novo aplicativo T3 e está pronto para começar. Aqui está o mínimo para que seu aplicativo funcione.\n\n## Banco de dados\n\nSe o seu aplicativo incluir o Prisma, certifique-se de executar `npx prisma db push` no diretório raiz do seu aplicativo. Este comando sincronizará o schema do Prisma com seu banco de dados e gerará as tipagens do TypeScript para o Prisma Client com base em seu schema. Observe que você precisa reiniciar o servidor TypeScript depois de fazer isso para que ele possa detectar os novos tipos gerados.\n\n## Autenticação\n\nSe seu aplicativo incluir NextAuth.js, vamos começar com o `DiscordProvider`. Este é um dos provedores mais simples que o NextAuth.js oferece, mas ainda requer um pouco de configuração inicial de sua parte.\n\nClaro, se você preferir usar um provedor de autenticação diferente, também pode usar um dos [muitos provedores](https://next-auth.js.org/providers/) que o NextAuth.js oferece.\n\n1. Você precisará de uma conta no Discord, então crie uma se ainda não tiver.\n2. Navegue até https://discord.com/developers/applications e clique em \"Novo aplicativo\" no canto superior direito. Dê um nome ao seu aplicativo e concorde com os Termos de Serviço.\n3. Depois de criar seu aplicativo, navegue até \"Configurações → OAuth2 → Geral\".\n4. Copie o \"ID do cliente\" e adicione-o ao seu `.env` como `AUTH_DISCORD_ID`.\n5. Clique em \"Redefinir Segredo\", copie o novo segredo e adicione-o ao seu `.env` como `AUTH_DISCORD_SECRET`.\n6. Clique em \"Adicionar redirecionamento\" e digite `http://localhost:3000/api/auth/callback/discord`.\n   - Para implantação de produção, siga as etapas anteriores para criar outro aplicativo Discord, mas desta vez substitua `http://localhost:3000` pela URL na qual você está implantando.\n7. Salve as alterações.\n\nAgora você deve conseguir fazer login.\n\n## Próximos passos\n\n- Se sua aplicação incluir tRPC, confira `src/pages/index.tsx` e `src/server/trpc/router/post.ts` para ver como funcionam as consultas tRPC.\n- Dê uma olhada na documentação `create-t3-app`, bem como nos documentos dos pacotes que sua aplicação inclui.\n- Junte-se ao nosso [Discord](https://t3.gg/discord) e dê-nos uma estrela no [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/pt/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Uso\",\n  layout: \"docs\",\n  description: \"Aprenda a usar as diferentes tecnologias da T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/pt/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: Uso do NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nQuando você deseja um sistema de autenticação em sua aplicação Next.js, o NextAuth.js é uma excelente solução para trazer a complexidade da segurança sem o incômodo de ter que construí-lo sozinho. Ele vem com uma extensa lista de provedores para adicionar rapidamente a autenticação OAuth e fornece adaptadores para muitos bancos de dados e ORMs.\n\n## Context Provider\n\nNo ponto de entrada do seu aplicativo, você verá que ele está envolvida pelo [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nEste provedor de contexto permite que seu aplicativo acesse os dados da sessão de qualquer lugar em seu aplicativo, sem ter que passá-los como props:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Lida com o estado não autenticado, por exemplo renderizar um componente SignIn\n    return <SignIn />;\n  }\n\n  return <p>Bem-vindo {session.user.name}!</p>;\n};\n```\n\n## Recuperando a sessão do lado do servidor.\n\nÀs vezes, você poderá querer solicitar a sessão no servidor. Para fazer isso, faça uma requisição usando o utilitário `getServerAuthSession` que `create-t3-app` fornece e passe-a para o cliente usando `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTA: `session` não terá um estado de carregamento, pois já foi pré-carregado no servidor\n\n  ...\n}\n```\n\n## Inclusão do `user.id` na Sessão\n\n`create-t3-app` está configurado para utilizar o [retorno de chamada de sessão (sesion callback)](https://next-auth.js.org/configuration/callbacks#session-callback) na configuração NextAuth.js para incluir o ID do usuário dentro do objeto `session`.\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nIsso é acoplado a um arquivo de declaração de tipo para garantir que o `user.id` tenha seu tipo quando acessado no objeto `session`. Leia mais sobre [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) nos documentos de NextAuth.js.\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nO mesmo padrão pode ser usado para adicionar quaisquer outros dados ao objeto `session`, como um campo `role`, mas **não deve ser mal utilizado para armazenar dados confidenciais** no cliente.\n\n## Uso com tRPC\n\nAo usar NextAuth.js com tRPC, você pode criar procedimentos protegidos e reutilizáveis usando [middleware](https://trpc.io/docs/v10/middlewares). Isso permite criar procedimentos que só podem ser acessados por usuários autenticados. `create-t3-app` configura tudo isso para você, permitindo que você acesse facilmente o objeto de sessão dentro de procedimentos autenticados.\n\nIsso é feito em um processo de duas etapas:\n\n1. Pegar a sessão dos headers da request usando a função [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). A vantagem de usar `getServerSession` em vez do `getSession` regular é que é uma função que é executada somente do lado do servidor e não faz chamadas de busca desnecessárias. O `create-t3-app` cria uma função auxiliar que abstrai essa API peculiar.\n\n```ts:server/common/get-server-auth-session.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await getServerSession(ctx.req, ctx.res, nextAuthOptions);\n};\n```\n\nUsando esta função auxiliar, podemos pegar a sessão e passá-la para o contexto tRPC:\n\n```ts:server/trpc/context.ts\nimport { getServerAuthSession } from \"../common/get-server-auth-session\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Criar um middleware tRPC que verifique se o usuário está autenticado. Em seguida, usamos o middleware em um `protectedProcedure`. Qualquer chamador para esses procedimentos deve ser autenticado, caso contrário, será lançado um erro que pode ser tratado adequadamente pelo cliente.\n\n```ts:server/trpc/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // inferer `session` som ikke-nullbar\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n}));\n```\n\nO objeto de sessão é uma representação leve e mínima do usuário e contém apenas alguns campos. Ao usar `protectedProcedures`, você tem acesso ao id do usuário que pode ser usado para buscar mais dados do banco de dados.\n\n```ts:server/trpc/router/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Uso com Prisma\n\nFazer o NextAuth.js funcionar com o Prisma requer muita [configuração inicial](https://authjs.dev/reference/adapter/prisma/). O `create-t3-app` lida com tudo isso para você e, se você selecionar Prisma e NextAuth.js, obterá um sistema de autenticação totalmente funcional com todos os modelos necessários pré-configurados. Enviamos seu aplicativo montado com um provedor do Discord OAuth pré-configurado, que escolhemos porque é um dos mais fáceis de começar - basta fornecer seus tokens no `.env` e pronto. No entanto, você pode adicionar facilmente mais provedores seguindo a [documentação do NextAuth.js](https://next-auth.js.org/providers/). Observe que certos provedores exigem que campos extras sejam adicionados a determinados modelos. Recomendamos que você leia a documentação do provedor que deseja usar para certificar-se de que possui todos os campos obrigatórios.\n\n### Adicionando novos campos aos seus modelos\n\nAo adicionar novos campos a qualquer um dos modelos `User`, `Account`, `Session` ou `VerificationToken` (provavelmente você só precisaria modificar o modelo `User`), você precisa ter em mente que o [Adaptador Prisma](https://next-auth.js.org/adapters/prisma) cria campos automaticamente nesses modelos quando novos usuários se inscrevem e fazem login. Portanto, ao adicionar novos campos a esses modelos, você deve fornecer padrão valores para eles, pois o adaptador não está ciente desses campos.\n\nSe, por exemplo, você quiser adicionar um `role` (cargo) ao modelo `User`, você precisará fornecer um valor padrão para o campo `role`. Isso é feito adicionando um valor `@default` ao campo `role` no modelo `User`:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Uso com o middleware Next.js\n\nUso de NextAuth.js com middleware Next.js [requer o uso da estratégia de sessão JWT](https://next-auth.js.org/configuration/nextjs#caveats) para autenticação. Isso ocorre porque o middleware só consegue acessar o cookie da sessão se for um JWT. Por padrão, `create-t3-app` é configurado para usar a estratégia de banco de dados **padrão**, em combinação com o Prisma como o adaptador de banco de dados.\n\n## Configurando o DiscordProvider padrão\n\n1. Vá para [a seção Aplicativos no Portal do desenvolvedor do Discord](https://discord.com/developers/applications) e clique em \"Novo aplicativo\"\n2. No menu de configurações, vá para \"OAuth2 => Geral\"\n\n- Copie o Client ID e cole-o em `AUTH_DISCORD_ID` em `.env`.\n- Em Client Secret, clique em \"Reset Secret\" e copie essa string para `AUTH_DISCORD_SECRET` em `.env`. Tenha cuidado, pois você não poderá ver esse segredo novamente e redefini-lo fará com que o existente expire.\n- Clique em \"Add Redirect\" e cole em `<app url>/api/auth/callback/discord` (exemplo para desenvolvimento local: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Salve suas alterações\n- É possível, mas não recomendado, usar o mesmo aplicativo Discord tanto para desenvolvimento quanto para produção. Você também pode considerar [mockar o Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) durante o desenvolvimento.\n\n## Recursos Úteis\n\n| Recurso                          | Link                                    |\n| -------------------------------- | --------------------------------------- |\n| Documentação do NextAuth.js      | https://next-auth.js.org/               |\n| GitHub do NextAuth.js            | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - com NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/pt/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Uso do Next.js\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nNext.js é um framework back-end para suas aplicações React.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nVeja a [Fala do Theo na Next.js Conf](https://www.youtube.com/watch?v=W4UhNo3HAMw) para entender melhor o que é Next.js e como ele funciona.</p>\n\n## Por que devo usá-lo?\n\nNós amamos React. Ele tornou o desenvolvimento de UI acessível de maneiras que nunca imaginamos antes. Também pode levar os desenvolvedores a alguns caminhos difíceis. O Next.js oferece uma abordagem altamente otimizada e levemente opinada para a criação de aplicações usando o React. Do roteamento às definições de API e à renderização de imagens, confiamos no Next.js para conduzir os desenvolvedores a boas decisões.\n\nJuntando o Next.js com a [Vercel](https://vercel.com/) torna o desenvolvimento e o deploy de aplicações web mais fáceis do que nunca. Sua interface gratuita extremamente generosa e super intuitiva fornece uma solução de apontar e clicar para implantar seu site (Nós ❤️ a Vercel)\n\n## Get Static/Server Props\n\nUm recurso chave do Next.js são seus recursos de busca de dados. É altamente recomendável ler a [documentação oficial](https://nextjs.org/docs/basic-features/data-fetching) para entender como usar cada método e como eles diferem. `getServerSideProps` geralmente é desencorajado, a menos que haja uma boa razão para isso, devido ao fato de que é uma chamada de bloqueio e deixará seu site lento. [Regeneração estática incremental (ISR)](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) é uma ótima alternativa para `getServerSideProps` quando os dados são dinâmicos e podem ser buscados de forma incremental.\n\n## Recursos Úteis\n\n| Recurso                            | Link                               |\n| ---------------------------------- | ---------------------------------- |\n| Documetação do Next.js             | https://nextjs.org/docs            |\n| GitHub do Next.js                  | https://github.com/vercel/next.js  |\n| Blog do Next.js                    | https://nextjs.org/blog            |\n| Discord do Next.js                 | https://nextjs.org/discord         |\n| Twitter do Next.js                 | https://twitter.com/nextjs         |\n| Canal do Youtube da Vercel/Next.js | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/pt/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Uso do Prisma\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nPrisma é um ORM para TypeScript, que permite que você defina seu schema e modelos de banco de dados em um arquivo `schema.prisma` e, em seguida, gere um cliente type-safe que pode ser usado para interagir com seu banco de dados a partir de seu back-end.\n\n## Prisma Client\n\nLocalizado em `/server/db/client.ts`, o Prisma Client é instanciado como uma variável global (conforme recomendado como [melhor prática](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) pela equipe da Prisma) e exportado para ser usado em suas rotas de API. Incluímos o Prisma Client em [Context](/en/usage/trpc#-serverapitrpcts) por padrão e recomendamos usá-lo em vez de importá-lo separadamente em cada arquivo.\n\n## Schema\n\nVocê encontrará o arquivo de esquema do Prisma em `/prisma/schema.prisma`. Este arquivo é onde você define seu esquema e modelos de banco de dados e é usado ao gerar o Prisma Client.\n\n### Com NextAuth.js\n\nQuando você seleciona NextAuth.js em combinação com Prisma, o arquivo de esquema é gerado e configurado para você com os valores recomendados para os modelos `User`, `Session`, `Account` e `VerificationToken`, de acordo com os modelos na [documentação do NextAuth.js](https://next-auth.js.org/adapters/prisma).\n\n## Banco de dados padrão\n\nO banco de dados padrão é um banco de dados SQLite, que é ótimo para desenvolvimento e criação rápida de uma prova de conceito, mas não é recomendado para produção. Você pode alterar o banco de dados a ser usado alterando o `provider` no bloco `datasource` para `postgresql` ou `mysql` e, em seguida, atualizando a string de conexão nas variáveis de ambiente para apontar para seu banco de dados.\n\n## Propagar seu banco de dados\n\n[Propagar seu banco de dados](https://www.prisma.io/docs/guides/database/seed-database) é uma ótima maneira de preencher rapidamente seu banco de dados com dados de teste para ajudá-lo a começar. Para configurar a propagação, você precisará criar um arquivo `seed.ts` no diretório `/prisma` e, em seguida, adicionar um script `seed` ao seu arquivo `package.json`. Você também precisará de algum compilador de TypeScript que possa executar o script de seed. Recomendamos [tsx](https://github.com/esbuild-kit/tsx), que é um compilador TypeScript de alto desempenho que usa esbuild e não requer nenhuma configuração ESM, mas `ts-node` ou outros compiladores funcionam também.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db/client\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nEm seguida, basta executar `pnpm db-seed` (ou `npm`/`yarn`) para propagar seu banco de dados.\n\n## Recursos Úteis\n\n| Recurso                              | Link                                                                                                                                              |\n| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Documentação do Prisma               | https://www.prisma.io/docs/                                                                                                                       |\n| GitHub do Prisma                     | https://github.com/prisma/prisma                                                                                                                  |\n| Adaptador de Prisma para NextAuth.js | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| Guia de Conexão com PlanetScale      | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/pt/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Uso do Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\n## O que é Tailwind CSS?\n\nTailwind CSS é um pequeno framework CSS focando em [classes utilitárias](https://tailwindcss.com/docs/utility-first) para criar designs personalizados, sem a troca de contexto que o CSS normal exige. É puramente uma estrutura CSS e não fornece nenhum componente ou lógica pré-criada, e fornece [um conjunto muito diferente de benefícios](https://www.youtube.com/watch?v=CQuTF-bkOgc) em comparação com um biblioteca de componentes como Material UI.\n\nIsso torna o CSS incrivelmente fácil e rápido de escrever, conforme mostrado no exemplo a seguir:\n\nCSS Antigo:\n\n1. Escreva CSS, geralmente em um arquivo separado\n\n```css\n.minha-classe {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Importe o CSS no seu componente\n\n```jsx\nimport \"./minha-classe.css\";\n```\n\n3. Adicione a classe no seu HTML\n\n```html\n<div class=\"minha-classe\">...</div>\n```\n\nEquivalente com Tailwind:\n\n1. Basta escrever classes em seu HTML\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nQuando usado em conjunto com Componentes React, é extremamente poderoso para construir UIs rapidamente.\n\nO Tailwind CSS possui um belo design system integrado, que vem pronto para uso com uma paleta de cores cuidadosamente escolhida, padrões de dimensionamento para estilos como largura/altura e preenchimento/margem para um design uniforme, bem como breakpoints para criar layouts responsivos. Este design system pode ser personalizado e estendido para criar a caixa de ferramentas exata de estilos que seu projeto precisa.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla mais conhecido como [mewtru](https://twitter.com/trunarla) deu uma palestra incrível sobre [construindo um design system usando Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Uso\n\nCertifique-se de ter plug-ins de editor para Tailwind instalados para melhorar sua experiência de escrita Tailwind.\n\n### Extensões e Plugins\n\n- [Extensão para o VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [Integration com JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Formatação\n\nAs classes Tailwind CSS podem facilmente ficar um pouco confusas, então um formatador para as classes é obrigatório. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) classifica as classes na [ordem recomendada](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) para que as classes correspondam ao pacote css gerado. Ao selecionar o Tailwind na CLI, instalaremos e configuraremos isso para você.\n\n### Aplicação de classe condicional\n\nAdicionar classes condicionalmente usando ternários pode ficar muito confuso e difícil de ler. Esses pacotes ajudam a organizar suas classes ao usar alguma lógica condicional.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Recursos Úteis\n\n| Recurso                       | Link                                                     |\n| ----------------------------- | -------------------------------------------------------- |\n| Documentação Tailwind         | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind Cheat Sheet          | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss           | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Comunidade do Tailwind        | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Servidor Discord do Tailwind  | https://tailwindcss.com/discord/                         |\n| Canal do Youtube TailwindLabs | https://www.youtube.com/tailwindlabs/                    |\n| Playground do Tailwind        | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/pt/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Uso do tRPC\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\nO tRPC nos permite escrever APIs seguras de ponta a ponta sem nenhuma geração de código ou sobrecarga de tempo de execução. Ele usa a grande inferência do TypeScript para inferir as definições de tipo do seu roteador de API e permite que você chame seus procedimentos de API de seu front-end com total segurança de tipo e preenchimento automático. Ao usar tRPC, seu front-end e back-end parecem mais próximos do que nunca, permitindo uma excelente experiência de desenvolvedor.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Criei o tRPC para permitir que as pessoas se movam mais rapidamente, removendo a necessidade de uma camada de API tradicional, enquanto ainda tenho a confiança de que nossos aplicativos não serão interrompidos à medida que iteramos rapidamente.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - criador do tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Como eu uso o tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\no contribuidor do tRPC [trashh_dev](https://twitter.com/trashh_dev) fez [uma fala esplêndida na Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) sobre o tRPC. É altamente recomendável que você assista, caso ainda não o tenha feito.\n\nCom tRPC, você escreve funções TypeScript em seu back-end e, em seguida, as chama de seu front-end. Um procedimento tRPC simples poderia ser assim:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nEste é um procedimento tRPC (equivalente a um manipulador de rota em um back-end tradicional) que primeiro valida a entrada usando Zod (que é a mesma biblioteca de validação que usamos para [variáveis de ambiente](./env-variables)) - neste caso , é garantir que a entrada seja uma string. Se a entrada não for uma string, ela enviará um erro informativo.\n\nApós a entrada, encadeamos uma função de resolução que pode ser uma [consulta](https://trpc.io/docs/v10/react-queries), [mutação](https://trpc.io/docs/v10/react-mutations) ou uma [assinatura](https://trpc.io/docs/v10/subscriptions). Em nosso exemplo, o resolvedor chama nosso banco de dados usando nosso cliente [prisma](./prisma) e retorna o usuário cujo `id` corresponde ao que passamos.\n\nVocê define seus procedimentos em `routers` que representam uma coleção de procedimentos relacionados com um namespace compartilhado. Você pode ter um roteador para `users`, um para `posts` e outro para `messages`. Esses roteadores podem ser mesclados em um único `appRouter` centralizado:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nObserve que precisamos apenas exportar as definições de tipo do nosso roteador, o que significa que nunca importaremos nenhum código de servidor em nosso cliente.\n\nAgora vamos chamar o procedimento em nosso frontend. tRPC fornece um wrapper para o `@tanstack/react-query` que permite que você utilize todo o poder dos hooks que eles fornecem, mas com o benefício adicional de ter suas chamadas de API digitadas e inferidas. Podemos chamar nossos procedimentos de nosso front-end assim:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nVocê notará imediatamente como o preenchimento automático e a segurança de tipo são bons. Assim que você escrever `api.`, seus roteadores aparecerão no preenchimento automático, e quando você selecionar um roteador, seus procedimentos também aparecerão. Você também receberá um erro de TypeScript se sua entrada não corresponder ao validador definido no back-end.\n\n## Inferindo erros\n\nPor padrão, `create-t3-app` configura um [formatador de erros](https://trpc.io/docs/error-formatting) que permite que você infira os erros do Zod se você receber erros de validação no back-end.\n\nExemplo de uso:\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` retornado com um erro no `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## Arquivos\n\nO tRPC requer bastante do template que o `create-t3-app` configura para você. Vamos ver os arquivos que são gerados:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nEste é o ponto de entrada para sua API que expõe o roteador tRPC. Normalmente, você não mexerá muito nesse arquivo, mas se precisar, por exemplo, habilitar o middleware CORS ou similar, é útil saber que o `createNextApiHandler` exportado é um [handler da API do Next.js](https://nextjs.org/docs/api-routes/introduction) que recebe uma [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) e [response](https://developer.mozilla.org/en-US/docs/Web/API/Response). Isso significa que você pode agrupar o `createNextApiHandler` em qualquer middleware que desejar. Veja abaixo um [trecho de exemplo](#ativando-o-cors) da adição de CORS.\n\n### 📄 `server/api/trpc.ts`\n\nEste arquivo é dividido em duas partes, criação de contexto e inicialização do tRPC:\n\n1. Definimos o contexto que é passado para seus procedimentos tRPC. O contexto são dados aos quais todos os seus procedimentos tRPC terão acesso, e é um ótimo lugar para colocar coisas como conexões com banco de dados, informações de autenticação, etc. Em create-t3-app, usamos duas funções, para habilitar o uso de um subconjunto do contexto quando não temos acesso ao objeto de solicitação.\n\n- `createInnerTRPCContext`: É aqui que você define o contexto que não depende da solicitação, por exemplo sua conexão com o banco de dados. Você pode usar esta função para [teste de integração](#exemplo-de-teste-de-integração) ou [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers) onde você não tem um objeto de solicitação/request.\n\n- `createTRPCContext`: É aqui que você define o contexto que depende da solicitação, por exemplo a sessão do usuário. Você solicita a sessão usando o objeto `opts.req` e, em seguida, passa a sessão para a função `createContextInner` para criar o contexto final.\n\n2. Inicializamos o tRPC e definimos [procedures](https://trpc.io/docs/v10/procedures) e [middlewares](https://trpc.io/docs/v10/middlewares) reutilizáveis. Por convenção, você não deve exportar o objeto inteiro t, mas sim criar procedures e middlewares reutilizáveis e exportá-los.\n\nVocê perceberá que usamos 'superjson' como [transformador de dados](https://trpc.io/docs/v10/data-transformers). Isso faz com que seus tipos de dados sejam preservados quando eles chegam ao cliente, então, por exemplo, se você enviar um objeto `Date`, o cliente retornará um `Date` e não uma string, que é o caso para a maioria das APIs.\n\n### 📄 `server/api/routers/*.ts`\n\nAqui é onde você define as rotas e procedimentos da sua API. Por convenção, você cria [rotas separados](https://trpc.io/docs/v10/router) para procedimentos relacionados.\n\n### 📄 `server/api/root.ts`\n\nAqui [mesclamos](https://trpc.io/docs/v10/merging-routers) todos as sub-rotas definidas em `routers/**` em um único roteador de aplicativo.\n\n### 📄 `utils/api.ts`\n\nEste é o ponto de entrada do front-end para tRPC. É aqui que você importará a **definição de tipo** do roteador e criará seu cliente tRPC junto com os hooks do react-query. Como habilitamos `superjson` como nosso transformador de dados no back-end, precisamos habilitá-lo também no front-end. Isso ocorre porque os dados serializados do back-end são \"desserializados\" no front-end.\n\nVocê definirá seus [links tRPC](https://trpc.io/docs/v10/links) aqui, que determinarão o fluxo de solicitação do cliente para o servidor. Usamos o \"padrão\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink) que permite [solicitar lotes](https://cloud.google.com/compute/docs/api/how-tos/batch), bem como um [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) que gera logs de solicitação úteis durante o desenvolvimento.\n\nPor fim, exportamos um [tipo auxiliar](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) que você pode usar para inferir seus tipos no frontend.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nContribuidor do Create T3 App [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) fez [um vídeo sobre fluxos de dados em tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Este vídeo é recomendado se você já usou o tRPC, mas ainda se sente um pouco incerto sobre como ele funciona.\n\n## Como faço para chamar minha API externamente?\n\nCom APIs regulares, você pode chamar seus endpoints usando qualquer cliente HTTP, como `curl`, `Postman`, `fetch`, `Insomnia` ou diretamente do seu navegador. Com tRPC, é um pouco diferente. Se você deseja chamar seus procedimentos sem o cliente tRPC, há duas maneiras recomendadas de fazer isso:\n\n### Expor um único procedimento externamente\n\nSe você deseja expor um único procedimento externamente, está procurando por [chamadas do lado do servidor](https://trpc.io/docs/v10/server-side-calls). Isso permitiria que você criasse um terminal de API Next.js normal, mas reutilizasse a parte do resolvedor de seu procedimento tRPC.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Expondo cada procedimento como um endpoint REST\n\nSe você deseja expor todos os procedimentos externamente, verifique o plug-in criado pela comunidade [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Ao fornecer alguns metadados extras para seus procedimentos, você pode gerar uma API REST compatível com OpenAPI a partir de seu roteador tRPC.\n\n### São apenas Requests HTTP\n\nO tRPC se comunica por meio de HTTP, portanto, também é possível chamar seus procedimentos tRPC usando solicitações HTTP \"regulares\". No entanto, a sintaxe pode ser complicada devido ao [protocolo RPC](https://trpc.io/docs/v10/rpc) que o tRPC usa. Se você estiver curioso, pode verificar como são as solicitações e respostas tRPC na guia de rede do seu navegador, mas sugerimos fazer isso apenas como um exercício educacional e aderir a uma das soluções descritas acima.\n\n## Comparação com um endpoint da API Next.js\n\nVamos comparar um endpoint da API Next.js com um procedimento tRPC. Digamos que queremos buscar um objeto de usuário de nosso banco de dados e retorná-lo ao frontend. Poderíamos escrever uma rota de API Next.js como esta:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nCompare isso com o exemplo tRPC acima e você verá algumas das vantagens do tRPC:\n\n- Em vez de especificar um URL para cada rota, o que pode ser irritante de depurar se você mover algo, todo o seu roteador é um objeto com preenchimento automático.\n- Você não precisa validar qual método HTTP foi usado.\n- Você não precisa validar se a consulta ou o corpo da solicitação contém os dados corretos no procedimento, pois o Zod cuida disso.\n- Em vez de criar uma resposta, você pode lançar erros e retornar um valor ou objeto como faria em qualquer outra função TypeScript.\n- Chamar o procedimento no frontend fornece preenchimento automático e segurança de tipo.\n\n## Snippets úteis\n\nAqui estão alguns snippets que podem ser úteis.\n\n### Ativando o CORS\n\nSe você precisar consumir sua API de um domínio diferente, por exemplo, em um monorepo que inclua um aplicativo React Native, talvez seja necessário habilitar o CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Ativar CORS\n  await cors(req, res);\n\n  // Criar e chamar o handler do tRPC\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Atualizações otimistas\n\nAs atualizações otimistas ocorrem quando atualizamos a interface do usuário antes que a chamada da API seja concluída. Isso dá ao usuário uma experiência melhor porque ele não precisa esperar que a chamada da API termine antes que a interface do usuário reflita o resultado de sua ação. No entanto, aplicativos que valorizam muito a exatidão dos dados devem evitar atualizações otimistas, pois não são uma representação \"verdadeira\" do estado de back-end. Você pode ler mais na [documentação do React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancele as requisições de saída (para que não substituam nossa atualização otimista)\n      await utils.post.list.cancel();\n\n      // Obtenha os dados do queryCache\n      const prevData = utils.post.list.getData();\n\n      // Atualizar os dados de forma otimista com nosso novo post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Retornar os dados anteriores para que possamos reverter se algo der errado\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // Se a mutation falhar, usar o valor de contexto de onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sincronizar com o servidor assim que a mutação for estabelecida\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Exemplo de teste de integração\n\nAqui está um exemplo de teste de integração que usa [Vitest](https://vitest.dev) para verificar se seu roteador tRPC está funcionando conforme o esperado, se o analisador de entrada infere o tipo correto e se os dados retornados correspondem à saída esperada.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\nSe seu procedimento estiver protegido, você pode passar um objeto `session` mockado quando criar o contexto:\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n\n  // ...\n});\n```\n\n## Recursos Úteis\n\n| Recurso                     | Link                                                    |\n| --------------------------- | ------------------------------------------------------- |\n| Documentação do tRPC        | https://www.trpc.io                                     |\n| Muitos exemplos de tRPC     | https://github.com/trpc/trpc/tree/next/examples         |\n| Documentação do React Query | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/pt/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Uso do TypeScript\nlayout: ../../../layouts/docs.astro\nlang: pt\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>\"Construa redes de segurança, não grades de proteção\"<span aria-hidden=\"true\">&quot;</span>\n      <small>(traduzido)</small>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 mr-4 rounded-full bg-neutral-500\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - Criador da T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nSeja você um desenvolvedor novo ou experiente, achamos que o TypeScript é obrigatório. Pode parecer intimidador no começo, mas, assim como muitas ferramentas, é algo que muitos nunca voltam atrás depois de começar a usá-lo.\n\nEle fornece feedback instantâneo enquanto você escreve seu código definindo os tipos de dados esperados e fornece autocomplete em seu editor de código ou grita com você com linhas onduladas vermelhas se você estiver tentando acessar uma propriedade que não existe ou tentando passe um valor do tipo errado, que de outra forma você teria que depurar mais adiante.\n\nÉ, talvez, a ferramenta que mais produtividade oferece aos desenvolvedores; fornecer documentação do código que você está escrevendo ou consumindo diretamente em seu editor e ter feedback instantâneo quando você inevitavelmente cometer erros é absolutamente inestimável.\n\n## Inferência de Tipos\n\nEmbora muitos novos desenvolvedores TypeScript se preocupem em _escrever_ TypeScript, muitos de seus benefícios na verdade não exigem que você altere seu código, em particular a inferência. Inferência significa que se algo for digitado, esse tipo o seguirá ao longo do fluxo do aplicativo sem precisar ser declarado novamente em outros lugares. Isso significa que, por exemplo, uma vez que você tenha definido os tipos de argumentos que uma função usa, o restante da função geralmente será typesafe sem exigir nenhum código adicional específico do TypeScript. Os desenvolvedores de bibliotecas trabalham muito para manter os tipos de suas bibliotecas, o que significa que nós, como desenvolvedores de aplicativos, podemos nos beneficiar da inferência e da documentação integrada em seu editor de código fornecida por esses tipos.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nConfira o vídeo de Theo sobre como [você pode estar usando o TypeScript errado](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Usos poderosos da inferência de tipos\n\n### Zod\n\nO [Zod](https://github.com/colinhacks/zod) é uma biblioteca de validação de esquema construída sobre TypeScript. Escreva um esquema que represente uma fonte única de verdade para seus dados, e o Zod garantirá que seus dados sejam válidos em todo o aplicativo, mesmo nos limites da rede e APIs externas.\n\n### Tanstack Query\n\nO [Tanstack Query](https://tanstack.com/query/v4/) fornece consultas (queries) e mutações (mutations) declarativas, sempre atualizadas e autogerenciadas que melhoram diretamente as experiências do desenvolvedor e do usuário.\n\n## Recursos Úteis\n\n| Recurso                                                    | Link                                                              |\n| ---------------------------------------------------------- | ----------------------------------------------------------------- |\n| Manual do TypeScript                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| Tutorial de TypeScript para iniciantes                     | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Desafios de Tipos                                          | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen do canal do YouTube TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/pt/why.md",
    "content": "---\ntitle: Por que CT3A?\ndescription: Porque você deve escolher o Create T3 App para o seu próximo projeto\nlayout: ../../layouts/docs.astro\nlang: pt\n---\n\nNós começamos o create-t3-app porque o [Theo](https://twitter.com/t3dotgg) se recusou a criar um template com suas tecnologias favoritas. Inspirado pelo create-next-app, [a CLI do Astro](https://astro.build) e um amor geral pela segurança de tipos, o time do create-t3-app trabalhou duro para construir o melhor ponto de início possível para novos projetos com a T3 Stack.\n\nSe você está interessado em usar o Next.js de uma maneira typesafe, este é o lugar para começar. Se você está curioso sobre alguma das escolhas de tecnologias que fizemos, siga com a leitura :)\n\n## Por que TypeScript?\n\nJavascript é difícil. Pra quê mais regras?\n\nNos firmemente acreditamos que a experiência que o Typescript proporciona irá te ajudar a ser um desenvolvedor melhor. Ele proporciona feedback instantâneo conforme você escreve seu código definindo os tipos esperados de data, e ou te fornece um autocomplete muito útil no seu editor ou grita por meio de linhas onduladas vermelhas se você está tentando acessar uma propriedade que não existe ou tentando passar um valor do tipo errado, o qual por outro lado você deveria debugar mais adiante. Se você é novo no desenvolvimento web ou um profissional experiente, o \"rigor\" do TypeScript vai te providenciar uma experiência menos frustrante, e mais consistente que o Javascript padrão.\n\nSegurança de tipo te faz mais rápido. Se você ainda não está convencido, você [deve estar usando o TypeScript errado...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Por que Next.js?\n\nNós amamos React. Ele tornou o desenvolvimento de interfaces mais acessível de maneira que nunca imaginávamos antes. Ele também pode levar os desenvolvedores para caminhos difíceis.\n\no Next.js oferece uma abordagem levemente opinada e altamente otimizada de criar aplicações usando React. Desde roteamento até definições de API até renderizações de imagens, nós confiamos que o Next.js levará os desenvolvedores tomarem boas decisões.\n\n## Por que tRPC/Prisma/Tailwind/etc?\n\nEnquanto nós acreditamos em manter as coisas o mais simples o possível, nós frequentemente encontramos essas tecnologias sendo usadas em qualquer \"projetinho\" que criamos. O `create-t3-app` faz um bom serviço deixando você adotar apenas as peças que precisa.\n\n### tRPC\n\nO tRPC cumpre a promessa do GraphQL de desenvolvimento de cliente contínuo em um servidor typesafe sem todo o boilerplate. É um abuso inteligente do TypeScript que fornece uma experiência de desenvolvimento incrível.\n\n### Prisma\n\nPrisma é para o SQL o que o Typescript é para o JS. Ele criou uma experiência de desenvolvimento que nunca existiu antes. Ao gerar tipos a partir de um esquema definido pelo usuário compatível com [vários bancos de dados](https://www.prisma.io/docs/concepts/database-connectors), o Prisma garante segurança de tipo de ponta-a-ponta do seu banco de dados até o seu aplicativo.\n\nO Prisma oferece todo um [conjunto de ferramentas](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) fazendo interações diárias com o seu banco de dados mais fácil. Notavelmente, o Prisma Client é responsável por fazer queryes e tornar SQL tão fácil que você mal vai notar que está usando, e o Prisma Studio é uma GUI (Interface Gráfica do Usuário) conveniente para seu banco de dados que te deixa ler e manipular seus dados rapidamente sem ter que escrever código.\n\n### Tailwind CSS\n\nTailwind é como o \"CSS no modo zen\".\n\nAo fornecer blocos de construção na forma de boas cores padrão, espaçamento e outros elementos primitivos, o Tailwind facilita a criação de um aplicativo de boa aparência. E, ao contrário das bibliotecas de componentes, isso não o impede quando você deseja levar seu aplicativo para o próximo nível e criar algo bonito e único.\n\nAlém disso, com sua abordagem inline, o Tailwind incentiva você a estilizar sem se preocupar em nomear classes, organizar arquivos ou qualquer outro problema não diretamente relacionado ao problema que você está tentando resolver.\n\n### NextAuth.js\n\nQuando você deseja um sistema de autenticação em seu aplicativo NextJS, o NextAuth.js é uma excelente solução para trazer a complexidade da segurança sem o incômodo de ter que construí-lo sozinho. Ele vem com uma extensa lista de provedores para adicionar rapidamente a autenticação OAuth e fornece adaptadores para muitos bancos de dados e ORMs.\n"
  },
  {
    "path": "www/src/pages/ru/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Развертывание в Docker\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nВы можете контейнеризировать этот стек и развернуть его как один контейнер с помощью Docker или как часть группы контейнеров с помощью docker-compose. Смотрите [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) для примера репозитория на основе этой документации.\n\n## Конфигурация проекта Docker\n\nПожалуйста обратите внимание, что Next.js нуждается в разных процессах для сборки (доступны во фронтенде, с префиксом `NEXT_PUBLIC`) и переменных окружения, доступных только на сервере. В этом примере мы используем две переменные, обратите внимание на их позиции в `Dockerfile`, аргументы командной строки и `docker-compose.yml`:\n\n- `DATABASE_URL` (используется сервером)\n- `NEXT_PUBLIC_CLIENTVAR` (используется клиентом)\n\n### 1. Конфигурация Next\n\nВ вашем [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), добавьте конфигурацию `output` со значением `standalone` для [уменьшения размера образа с помощью автоматического использования трассировок вывода](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Создайте dockerignore file\n\n<details>\n    <summary>\n      Нажмите здесь и вставьте содержимое в <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Создайте Dockerfile\n\n> Из-за того, что мы не извлекаем переменные окружения сервера в наш контейнер, [проверка схемы окружения](/ru/usage/env-variables) не пройдет. Чтобы этого избежать, мы должны добавить флаг `SKIP_ENV_VALIDATION=1` к команде сборки, чтобы схемы окружения не проверялись во время сборки.\n\n<details>\n    <summary>\n      Нажмите здесь и вставьте содержимое в <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Заметки_**\n>\n> - _Эмуляция `--platform=linux/amd64` может не быть необходимой после перехода на Node 18._\n> - _Посмотрите [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) чтобы понять, почему `libc6-compat` может быть необходим._\n> - _Использование образов, основанных на Alpine 3.17 [может привести к проблемам с Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Установка `engineType = \"binary\"` решает проблему с Alpine 3.17, [но имеет связанные с этим затраты производительности](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js собирает [анонимные данные о телеметрии общего использования](https://nextjs.org/telemetry). Раскомментируйте первый экземпляр `ENV NEXT_TELEMETRY_DISABLED 1`, чтобы отключить телеметрию во время сборки. Раскомментируйте второй экземпляр, чтобы отключить телеметрию во время выполнения._\n\n</div>\n</details>\n\n## Соберите и запустите образ локально\n\nСоберите и запустите этот образ локально с помощью следующих команд:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nОткройте [localhost:3000](http://localhost:3000/) чтобы увидеть запущенное приложение.\n\n## Docker Compose\n\nВы также можете использовать Docker Compose для сборки образа и запуска контейнера.\n\n<details>\n    <summary>\n      Проследуйте шагам 1-4 выше, нажмите здесь и добавьте содержимое в <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nЗапустите с помощью команды `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nОткройте [localhost:3000](http://localhost:3000/) чтобы увидеть запущенное приложение.\n\n</div>\n</details>\n\n## Развертывание на Railway\n\nВы можете использовать такой PaaS как автоматическое [развертывание Dockerfile](https://docs.railway.app/deploy/dockerfiles) от [Railway's](https://railway.app) для развертывания вашего приложения. Если у вас [установлен Railway CLI](https://docs.railway.app/develop/cli#install), вы можете развернуть свое приложение с помощью следующих команд:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nПерейдите к \"Variables\" и включите ваш `DATABASE_URL`. Затем перейдите к \"Settings\" и выберите \"Generate Domain.\" Чтобы увидеть работающий пример на Railway, перейдите к [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Полезные ресурсы\n\n| Ресурс                                    | Ссылка                                                               |\n| ----------------------------------------- | -------------------------------------------------------------------- |\n| Пример для Dockerfile                     | https://docs.docker.com/engine/reference/builder/                    |\n| Пример для файла Compose 3 версии         | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Пример Docker CLI                         | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Пример Docker Compose CLI                 | https://docs.docker.com/compose/reference/                           |\n| Развертывание Next.js с Docker Image      | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js в Docker'е                        | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Пример Next.js с Docker                   | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Создание Docker образа Next.js приложения | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/ru/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Развертывание\",\n  layout: \"docs\",\n  description: \"Научитесь развертывать ваше приложение T3 в продакшен.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/ru/deployment/netlify.md",
    "content": "---\ntitle: Netlify\ndescription: Развертывание в Netlify\nlayout: ../../../layouts/docs.astro\n---\n\nNetlify это альтернативый провайдер развертывания, похожий на Vercel. Вот [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) пример репозитория на основе этой документации.\n\n## Зачем развертывать на Netlify\n\nПринято считать, что Vercel имеет лучшую поддержку Next.js потому что Vercel разрабатывает Next.js. Они заинтересованы в том, чтобы платформа была настроена для оптимальной производительности и DX с Next.js. В большинстве случаев это будет правдой и в отклонении от стандартного пути не будет смысла.\n\nТакже существует общее мнение о том, что многие функции Next.js поддерживаются только на Vercel. Хотя это правда, что новые функции Next.js будут тестироваться и поддерживаться на Vercel в момент выпуска по умолчанию, также следует учитывать, что другие провайдеры, такие как Netlify, [быстро реализуют и выпускают поддержку](https://www.netlify.com/blog/deploy-nextjs-13/) для [стабильных функций Next.js](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nУ всех провайдеров развертывания есть преимущества и недостатки, поскольку ни один хост не может иметь лучшую поддержку для всех случаев использования. Например, Netlify разработал свой собственный [пользовательский Next.js runtime](https://github.com/netlify/next-runtime) для Netlify Edge Functions (которые работают на Deno Deploy) и [поддерживают уникальные промежуточные программы для доступа и изменения HTTP-ответов](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n> _Обратите внимание: Для того, чтобы отслеживать статус нестабильных функций Next 13, см. [Использование каталога `app` Next 13 на Netlify](https://github.com/netlify/next-runtime/discussions/1724)._\n\n## Конфигурация проекта\n\nСуществует несколько способов настройки инструкций сборки, включая прямое использование Netlify CLI или Netlify Dashboard. Хотя это не обязательно, рекомендуется создать и включить файл [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Это гарантирует, что форкнутые и клонированные версии проекта будут легче повторно развернуть.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Использование Netlify Dashboard\n\n1. Запушьте свой код в репозиторий GitHub и зарегистрируйтесь на [Netlify](https://app.netlify.com/signup). После того, как вы создали аккаунт, нажмите **Add new site** и затем **Import an existing project**.\n\n![Новый проект в Netlify](/images/netlify-01-new-project.webp)\n\n2. Подключите свой Git-провайдер.\n\n![Импортируйте репозиторий](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Выберите репозиторий вашего проекта.\n\n![Выберите репозиторий вашего проекта](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify обнаружит, если у вас есть файл `netlify.toml` и автоматически настроит команду сборки и каталог публикации.\n\n![Настройки сборки Nextjs](/images/netlify-04-configure-build-settings.webp)\n\n5. Нажмите **Show advanced** и затем **New variable**, чтобы добавить свои переменные среды.\n\n![Добавьте переменные среды](/images/netlify-05-env-vars.webp)\n\n6. Нажмите **Deploy site**, подождите, пока сборка завершится, и просмотрите свой новый сайт.\n\n## Использование Netlify CLI\n\nДля того, чтобы развернуть проект из командной строки, вы должны сначала запушить свой проект в репозиторий GitHub и [установить Netlify CLI](https://docs.netlify.com/cli/get-started/). Вы можете установить `netlify-cli` как зависимость проекта или установить его глобально на вашем компьютере с помощью следующей команды:\n\n```bash\nnpm i -g netlify-cli\n```\n\nДля того, чтобы протестировать свой проект локально, запустите команду [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) и откройте [`localhost:8888`](http://localhost:8888/) для просмотра вашего локально запущенного приложения Netlify:\n\n```bash\nntl dev\n```\n\nЗапустите команду [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment), чтобы настроить ваш проект:\n\n```bash\nntl init\n```\n\nИмпортируйте переменные среды вашего проекта из вашего файла `.env` с помощью [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nРазверните ваш проект с помошью [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Вам нужно будет передать флаг `--build`, чтобы запустить команду сборки перед развертыванием, и флаг `--prod`, чтобы развернуть на основном URL вашего сайта:\n\n```bash\nntl deploy --prod --build\n```\n\nДля просмотра примера на Netlify, перейдите на [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/ru/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Развертывание на Vercel\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nМы рекомендуем развертывать ваше приложение на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Он позволяет очень легко развертывать Next.js приложения.\n\n## Конфигурация проекта\n\nСкорее всего Vercel настроит вашу команду сборки и каталог публикации автоматически. Однако вы также можете уточнить эту информацию вместе с другими конфигурациями, создав файл [`vercel.json`](https://vercel.com/docs/project-configuration) и включив в него следующие команды. **В большинстве проектов это делать необязательно.**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Использование Vercel Dashboard\n\n1. После отправки вашего кода в репозиторий GitHub зарегистрируйтесь на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) с GitHub и нажмите **Add New Project**.\n\n![Новый проект на Vercel](/images/vercel-new-project.webp)\n\n2. Импортируйте репозиторий GitHub с вашим проектом.\n\n![Импортируйте репозитоpий](/images/vercel-import-project.webp)\n\n3. Добавьте ваши переменные среды.\n\n![Добавьте ваши переменные среды](/images/vercel-env-vars.webp)\n\n4. Нажмите **Deploy**. Теперь каждый раз, когда вы отправляете изменение в ваш репозиторий, Vercel автоматически переразвернет ваше приложение!\n\n## Использование Vercel CLI\n\nДля того, чтобы развернуть приложение из командной строки, вам сначала нужно [установить Vercel CLI глобально](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nЗапустите команду [`vercel`](https://vercel.com/docs/cli/deploying-from-cli), чтобы развернуть ваш проект.\n\n```bash\nvercel\n```\n\nДобавьте `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` для переменных среды, таких как строка подключения к базе данных. Используйте `--yes`, если хотите пропустить вопросы развертывания и дать ответ по умолчанию для каждого.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nПосле первого развертывания эта команда развернет изменения в ветку предварительного просмотра. Вам нужно будет включить `--prod`, чтобы отправить изменения напрямую на сайт в продакшене для будущих развертываний.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/ru/faq.md",
    "content": "---\ntitle: FAQ\ndescription: Часто задаваемые вопросы про Create T3 App\nlayout: ../../layouts/docs.astro\nlang: ru\n---\n\nЭто некоторые часто задаваемые вопросы о `create-t3-app`.\n\n## Что дальше? Как я могу создать приложение?\n\nМы стараемся сделать этот проект как можно проще, поэтому вы можете начать с того, что мы настроили для вас, а затем добавлять дополнительные вещи позже, когда они станут необходимыми.\n\nЕсли вы не знакомы с различными технологиями, используемыми в этом проекте, обратитесь к соответствующей документации. Если что то все еще не понятно, присоединяйтесь к нашему [Discord](https://t3.gg/discord) и попросите помощи.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## Какие учебные ресурсы сейчас доступны?\n\nНе смотря на то, что перечисленные ниже ресурсы являются одиними из лучших для T3 Stack, сообщество (и [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) рекомендует просто начать использовать стек и учиться в процессе разработки с его помощью.\n\nЕсли вы рассматриваете `create-t3-app`, скорее всего, вы уже использовали некоторые части стека. Так почему бы не погрузиться в проект с головой и узнать остальные технологии в процессе разработки?\n\nМы понимаем, что этот путь не подходит для каждого. Поэтому, если вы чувствуете, что рекомендации не достаточно, и вам все еще нужны ресурсы, или вы просто не уверены в своих силах и/или чувствуете себя перегруженным этим стеком, ознакомьтесь с этими потрясающими учебными материалами по `create-t3-app`:\n\n### Статьи\n\n- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)\n- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Видео\n\n- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Почему в проекте есть файлы `.js`?\n\nСогласно [T3-Аксиоме #3](/ru/introduction#typesafety-isnt-optional), мы считаем типобезопасность объектом первого класса. К сожалению, не все фреймворки и плагины поддерживают TypeScript, поэтому некоторые файлы конфигурации должны быть файлами `.js`.\n\nМы пытаемся подчеркнуть, что эти файлы являются файлами JavaScript не без причины, явно объявляя тип каждого файла (`cjs` или `mjs`), в зависимости от того, что поддерживается библиотекой, которой он используется. Кроме того, все файлы `js` в этом проекте все еще проверяются на типы с помощью комментария `@ts-check` вверху.\n\n## У меня не получается добавить i18n в мое приложение. Есть ли какие-либо рекомендации?\n\nМы решили не включать i18n по умолчанию в `create-t3-app`, потому что это очень субъективная тема, и есть много способов ее реализации.\n\nВ тоже время, если вы столкнулись с проблемами при реализации и хотите увидеть проект-образец, у нас есть [ссылка на репозиторий](https://github.com/juliusmarminge/t3-i18n) который показывает как вы можете добавить i18n в T3 App с помощью [next-i18next](https://github.com/i18next/next-i18next).\n\n## Почему мы используем `/pages` а не `/app` из Next.js 13?\n\nСогласно [T3-Аксиоме #2](/ru/introduction#bleed-responsibly), мы любим новинки, но ценим стабильность, вам будет сложно перенести весь маршрутизатор, [не лучшеее место для экспериментов](https://youtu.be/mnwUbtieOuI?t=1662). Хотя `/app` [представляет собой взгляд в будущее](https://youtu.be/rnsC-12PVlM?t=818), он еще не готов к использованию в продакшене; API находится в бета-версии и ожидается, что он будет иметь обратно несовместимые изменения.\n\nСписок поддерживаемых, запланированных и находящихся в разработке функций в каталоге `/app` можно найти в [бета-документации Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n"
  },
  {
    "path": "www/src/pages/ru/folder-structure-pages.mdx",
    "content": "---\ntitle: Файловая структура (Pages)\ndescription: Файловая структура нового T3 приложения\nlayout: ../../layouts/docs.astro\nlang: ru\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nПожалуйста выберите пакеты, чтобы увидеть файловую структуру нового приложения с выбранными пакетами. Ниже вы найдете описание каждого элемента.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nПапка `prisma` содержит файл `schema.prisma`, который используется для настройки соединения с базой данных и схемы базы данных. Также это место для хранения файлов миграции и/или сценариев заполнения, если они используются. Смотрите [Использование Prisma](/ru/usage/prisma) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `public`\n\nПапка `public` содержит статические файлы, которые обслуживаются веб-сервером. Файл `favicon.ico` - это пример статического файла.\n\n</div>\n<div>\n\n### `src/env`\n\nИспользуется для проверки переменных окружения и определения типов - смотрите [Переменные окружения](/ru/usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nПапка `pages` содержит все страницы приложения Next.js. Файл `index.tsx` в корневой папке `/pages` является домашней страницей приложения. Файл `_app.tsx` используется для оборачивания приложения провайдерами. Смотрите [документацию Next.js](https://nextjs.org/docs/basic-features/pages) для получения дополнительной информации.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nПапка `api` содержит все маршруты API приложения Next.js. Файл `examples.ts` (с Prisma) содержит пример маршрута, который использует функцию [Next.js API route](https://nextjs.org/docs/api-routes/introduction) вместе с Prisma. Файл `restricted.ts` (с Next-Auth) содержит пример маршрута, который использует функцию [Next.js API route](https://nextjs.org/docs/api-routes/introduction) и защищен с помошью [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nФайл `[...nextauth].ts` - это слаг-маршрут NextAuth.js для аутентификации. Он используется для обработки запросов аутентификации. Смотрите [Использование NextAuth.js](/ru/usage/next-auth) для получения дополнительной информации о NextAuth.js и [документацию Next.js о динамических маршрутах](https://nextjs.org/docs/routing/dynamic-routes) для получения информации о маршрутах catch-all/slug.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nФайл `[trpc].ts` - это точка входа tRPC API. Он используется для обработки запросов tRPC. Смотрите [Использование tRPC](/ru/usage/trpc#-pagesapitrpctrpcts) для получения дополнительной информации об этом файле и [документацию Next.js о динамических маршрутах](https://nextjs.org/docs/routing/dynamic-routes) для получения информации о маршрутах catch-all/slug.\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nПапка `server` используется для четкого разделения серверного кода от клиентского кода.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nСодержит утилиты для аутентификации, такие как получение сеанса пользователя на стороне сервера. Смотрите [Использование NextAuth.js](/ru/usage/next-auth#usage-with-trpc) для получения дополнительной информации.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nФайл `db.ts` используется для создания клиента Prisma на глобальном уровне. Смотрите [Использование Prisma](/ru/usage/prisma#prisma-client) и [лучшие практики по использованию Prisma с Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) для получения дополнительной информации.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nПапка `api` содержит серверный код tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nПапка `routers` содержит все ваши под-маршрутизаторы tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nФайл `example.ts` - это пример маршрутизатора tRPC, использующий вспомогательную функцию `publicProcedure` для демонстрации того, как создать публичный маршрут tRPC.\n\nОсновываясь на выбранных вами пакетах, этот маршрутизатор содержит больше или меньше маршрутов для лучшего демонстрирования использования ваших потребностей.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nФайл `trpc.ts` - это основной файл конфигурации для вашего tRPC-бэкэнда. В нем мы:\n\n1. Определяем контекст используемый в запросах tRPC. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapitrpcts) для получения дополнительной информации.\n2. Экспортируем вспомогательные функции процедур. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapitrpcts) для получения дополнительной информации.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nФайл `root.ts` используется для слияния маршрутизаторов tRPC и экспорта их как единого маршрутизатора, а также определения типа маршрутизатора. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapirootts) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `src/styles`\n\nПапка `styles` содержит глобальные стили приложения.\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/types`\n\nПапка `types` используется для хранения повторно используемых типов или объявлений типов.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/types/next-auth.d.ts`\n\nФайл `next-auth.d.ts` используется для расширения типа сеанса по умолчанию NextAuth на включение идентификатора пользователя. Смотрите [Использование NextAuth.js](/ru/usage/next-auth#включение-userid-в-сеанс) для получения дополнительной информации.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nПапка `utils` используется для хранения повторно используемых функций утилит.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nФайл `api.ts` является точкой входа для tRPC на стороне клиента. Смотрите [Использование tRPC](/ru/usage/trpc#-utilsapits) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `.env`\n\nФайл `.env` используется для хранения переменных среды. Смотрите [Переменные среды](/ru/usage/env-variables) для получения дополнительной информации. Этот файл **не** должен быть добавлен в историю git.\n\n</div>\n<div>\n\n### `.env.example`\n\nФайл `.env.example` показывает пример переменных среды на основе выбранных библиотек. Этот файл должен быть добавлен в историю git.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nФайл `.eslintrc.cjs` используется для настройки ESLint. Смотрите [документацию ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nФайл `next-env.d.ts` гарантирует, что типы Next.js будут обнаружены компилятором TypeScript. **Вы не должны удалять его или редактировать, поскольку он может измениться в любое время.** Смотрите [документацию Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nФайл `next.config.mjs` используется для настройки Next.js. Смотрите [Документацию Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) для получения дополнительной информации. Примечание: Расширение .mjs используется для разрешения импортов ESM.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nФайл `postcss.config.js` используется для использования Tailwind PostCSS. Смотрите [документацию Taiwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) для получения дополнительной информации.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nФайл `prettier.config.mjs` используется для настройки Prettier для включения prettier-plugin-tailwindcss для форматирования классов Tailwind CSS. Смотрите [пост блога Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) для получения дополнительной информации.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nФайл `tsconfig.json` используется для настройки TypeScript. Некоторые значения по умолчанию, такие как `strict mode`, были включены для обеспечения лучшего использования TypeScript для create-t3-app и его библиотек. Смотрите [документацию TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) или [Использование TypeScript](usage/typescript) для получения дополнительной информации.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/ru/installation.mdx",
    "content": "---\ntitle: Установка\ndescription: Инструкции по установке Create T3 App\nlayout: ../../layouts/docs.astro\nlang: ru\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nДля создания приложения с помощью `create-t3-app`, запустите одну из следующих трёх команд и ответьте на вопросы командной строки:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nПосле того, как приложение будет создано, ознакомьтесь с [первыми шагами](/ru/usage/first-steps), чтобы начать работу над вашим новым приложением.\n\n## Дополнительные параметры\n\n| Опции/Флаги       | Описание                                                                     |\n| ----------------- | ---------------------------------------------------------------------------- |\n| `[dir]`           | Добавьте аргумент каталога с именем проекта                                  |\n| `--noGit`         | Явно сообщите CLI не инициализировать новый git репозиторий в проекте        |\n| `-y`, `--default` | Обойти CLI и создать новое t3-приложение с помощью всех выбранных параметров |\n| `--noInstall`     | Сгенерировать проект без установки зависимостей                              |\n\n## Экспериментальное использование\n\nДля нашего CI мы имеем некоторые экспериментальные флаги, которые позволяют создавать любое приложение без каких-либо запросов. Если это применимо к вашему случаю, вы можете использовать эти флаги. Обратите внимание, что эти флаги являются экспериментальными и могут измениться в будущем без следования версированию semver.\n\n| Опции/Флаги  | Описание                                    |\n| ------------ | ------------------------------------------- |\n| `--CI`       | Сообщите CLI, что вы находитесь в режиме CI |\n| `--trpc`     | Добавить tRPC в проект                      |\n| `--prisma`   | Добавить Prisma в проект                    |\n| `--nextAuth` | Добавить NextAuth в проект                  |\n| `--tailwind` | Добавить Tailwind CSS в проект              |\n\n<Callout type=\"warning\">\n  если вы не указываете флаг `CI`, то остальные флаги не имеют эффекта.\n</Callout>\n\nВам не нужно явно отказываться от пакетов, которые вам не нужны. Однако, если вы предпочитаете быть явным, вы можете передать `false`, например `--nextAuth false`.\n\n### Например\n\nСледующий пример создаст приложение T3 с tRPC и Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/ru/introduction.md",
    "content": "---\ntitle: Введение\ndescription: Введение в T3 стек\nlayout: ../../layouts/docs.astro\nlang: ru\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\n_«T3 Stack»_ - это стек веб-разработки, созданный [Theo](https://twitter.com/t3dotgg), с упором на простоту, модульность и full-stack типизацию.\n\nОсновные части - [**Next.js**](https://nextjs.org/) и [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) почти всегда включен. Если вы делаете что-то напоминающее бэкенд, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), и [**NextAuth.js**](https://next-auth.js.org/) - отличные дополнения.\n\nВы могли заметить, что существует… много частей. Это сделано намеренно. Меняйте части в зависимости от ваших потребностей - этот стек является модульным по своей сути :)\n\n## И... что такое create-t3-app? Шаблон?\n\nВозможно? `create-t3-app` это CLI, созданный опытными разработчиками T3 стека, чтобы упростить настройку модульного приложения T3 стека. Это означает, что каждая часть является необязательной, и «шаблон» генерируется на основе ваших конкретных потребностей.\n\nПосле множества проектов и многих лет с этой технологией у нас есть множество мнений и знаний. Мы постарались зафиксировать их в этом CLI.\n\nЭто **НЕ** всеобъемлющий шаблон. Мы **ожидаем**, что вы будете использовать свои собственные библиотеки, которые решают потребности **ВАШЕГО** приложения. Хотя мы не хотим назначать решения для более конкретных проблем, таких как управление состоянием и развертывание, мы [имеем некоторые рекомендации, перечисленные здесь](/ru/other-recs).\n\n## Аксиомы T3\n\nБудем честными - это _субъективный проект_. Мы поделились несколькими основными убеждениями вокруг создания и рассматриваем их как основу для наших решений.\n\n### Решайте проблемы\n\nЛегко попасть в ловушку \"добавления всего\" - мы явно не хотим этого делать. Все, что добавляется в `create-t3-app`, должно решать конкретную проблему, которая существует в основных технологиях, включенных в него. Это означает, что мы не добавим библиотеки менеджмента состояния (`zustand`, `redux`), но мы добавим NextAuth.js и интегрируем Prisma и tRPC для вас.\n\n### Ответственность к новинкам\n\nМы любим технологические новинки. Получаемые скорость и, честно говоря, веселье от новых фиговин, действительно круто. Мы считаем важным использовать их ответственно, используя более рискованные технологии в менее рискованных частях. Это означает, что мы не будем ⛔️ делать ставку на рискованную новую технологию базы данных (SQL - это здорово!). Но мы с удовольствием ✅ сделаем ставку на tRPC, поскольку это просто функции, которые легко перенести.\n\n### Типобезопасность не является опциональной\n\nУказаная цель `create-t3-app` - это предоставить самый быстрый способ начать новое полнофункциональное, **типобезопасное** веб-приложение. Мы серьезно относимся к типобезопасности в этих частях, поскольку она повышает нашу продуктивность и помогает нам отправлять меньше ошибок. Любое решение, которое снижает типобезопасность `create-t3-app`, должно быть принято в другом проекте.\n"
  },
  {
    "path": "www/src/pages/ru/other-recs.md",
    "content": "---\ntitle: Дополнительные рекомендации\ndescription: Библиотеки и сервисы, которые мы рекомендуем для многих проектов\nlayout: ../../layouts/docs.astro\nlang: ru\n---\n\nМы понимаем, что библиотеки, включенные в `create-t3-app`, не решают каждую проблему. Хотя мы рекомендуем начать свой проект с того, что мы предоставляем, придет время, когда вам нужно будет установить другие пакеты. Только вы можете знать, в чем нуждается ваш проект, но вот некоторые решения, которые мы часто рекомендуем.\n\nЭто рекомендации отдельных участников create-t3-app и не должны рассматриваться как \"официальные\" одобрения команды create-t3-app или T3-OSS. _**Пожалуйста, проведите собственное исследование, особенно перед тем, как привязываться к платным услугам**_.\n\n## Управление состоянием\n\n_**Примечание редактора**_: Библиотеки управления состоянием могут быть отличными, но часто не требуются. Хуки React Query tRPC должны справиться с вашим серверным состоянием. Для клиентского состояния начните с `useState` React, и обратитесь к одному из этих вариантов, когда вам нужно больше.\n\n### Zustand\n\n**Для того, чтобы больше никогда не писать Redux**\n\n\"Современный простой Redux\", который вы не знали, что вам нужен. [Poimandres](https://github.com/pmndrs) всегда можно доверять. Вы можете создавать все, от видеозвонков до игр и серверов с этой маленькой библиотекой.\n\n- [Zustand Homepage](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Для того, чтобы больше никогда не писать Context**\n\nВ атомарном подходе Jotai трудно превзойти. Также от [Poimandres](https://github.com/pmndrs), Jotai позволяет определять синглтоны, которые кажутся глобальными useState. Отличный вариант для состояний, которые не требуют машины состояний прямо сейчас.\n\n- [Jotai Homepage](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## Библиотеки компонентов\n\nБольшинство приложений нуждаются в некотором наборе компонентов: переключатели, выпадающие меню, модальные окна и т.д. Эти библиотеки предоставляют отличные, доступные компоненты, которые вы можете использовать и настраивать по своему усмотрению.\n\n### Библиотеки компонентов без стилей\n\nТакже известны как headless библиотеки, они предоставляют отличные, нестилизованные и доступные компоненты, которые вы можете настроить по своему усмотрению. Вот несколько рекомендаций.\n\n- [Radix UI](https://www.radix-ui.com/) предоставляет вам мощный набор удобных и доступных примитивов, которые вы можете стилизовать с помощью обычного CSS или Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) от команды Tailwind CSS также предоставляет нестилизованные, доступные компоненты, которые интегрируются безупречно с Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) предоставляет доступные примитивы UI для вашей системы дизайна. Их компонент выбора даты - это высший уровень.\n\n### Библиотеки компонентов со стилями\n\n**Когда вам просто нужно, чтобы ваше приложение выглядело неплохо**\n\nИногда вы создаете проект, где вам просто нужно, чтобы пользовательский интерфейс выглядел нормально из коробки. Для административных панелей управления и других подобных проектов любая из этих библиотек компонентов справится с этой задачей.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**Для создания библиотек пользовательского интерфейса**\n\nДекларативно создавайте библиотеку пользовательского интерфейса с различными цветовыми, размерными и т.д. вариантами. Когда ваш проект достигает масштаба, где вам нужен стандартизированный набор компонентов пользовательского интерфейса с несколькими вариантами с использованием Tailwind CSS, CVA - отличный инструмент.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Анимации\n\nНаши рекомендации для создания анимаций в вашем приложении.\n\n### AutoAnimate\n\n**Для анимаций с одной строкой кода**\n\nБольшенство библиотек анимации пытаются удовлетворить каждый возможный случай использования и в результате становятся громоздкими. AutoAnimate - это инструмент без конфигурации, который даст вам значительное улучшение UX без дополнительных усилий разработчика.\n\n- [Главная страница AutoAnimate](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [Компонент для AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Для сложных анимаций с декларативным кодом**\n\nFramer Motion предоставляет простой, декларативный синтаксис и позволяет вам писать меньше кода для создания всего: от сложных анимаций и даже до жестов.\n\n- [Framer Motion Homepage](https://framer.com/motion)\n- [Framer Motion Documentation](https://www.framer.com/docs/)\n\n## Развертывание, инфраструктура, базы данных и CI\n\n### Vercel\n\n**Для хостинга (размещения) вашего приложения**\n\nVercel убрал мучения из процесса развертывания веб-приложений и сделал его простой \"установил-и-забыл\" интеграцией GitHub. Мы масштабировались до сотен тысяч пользователей без проблем. Работает на базе AWS, но имеет простой и удобный интерфейс :)\n\n- [Главная страница Vercel](https://vercel.com/)\n- [Гайд по развертыванию T3 приложения на Vercel](/ru/deployment/vercel)\n\n### PlanetScale\n\n**Для баз данных без беспокойства**\n\nPlanetScale - лучшая serverless платформа для баз данных, которую мы использовали до сих пор. Невероятная масштабируемость, отличный DX и фантастическая цена. Если вы используете SQL (и, надеюсь, Prisma), это трудно превзойти.\n\n- [Главная страница PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Для размещения вашей инфраструктуры**\n\n\"Современный Heroku\". Самый простой способ запустить реальный сервер. Если вам не хватает функционала Vercel и PlanetScale, то Railway, вероятно, вам подойдет. Укажите его на репозиторий GitHub и готово.\n\n- [Главная страница Railway](https://railway.app/)\n\n### Upstash\n\n**Для безсерверного Redis**\n\nМы любим Prisma и PlanetScale, но некоторые проекты требуют более производительного решения. Upstash позволяет вам получить in-memory производительность Redis в вашем безсерверном проекте, не заботясь о самостоятельном управлении инфраструктурой и масштабированием.\n\n- [Главная страница Upstash](https://upstash.com/)\n\n### Pusher\n\n**Для безсерверных WebSocket**\n\nЕсли WebSocket является основным фокусом вашего проекта, вы можете рассмотреть более традиционный бэкенд, такой как [Fastify](https://www.fastify.io/) (который [также работает с tRPC!](https://trpc.io/docs/v10/fastify)). Но для быстрого добавления WebSocket в T3 App, Pusher - отличный выбор.\n\n- [Главная страница Pusher](https://pusher.com/)\n\n### Soketi\n\nSoketi - это само-развертываемая, простая и быстрая альтернатива Pusher. Он полностью совместим с Pusher SDK, который вы можете использовать для подключения к серверу. Soketi serverless также находится в бета-версии.\n\n- [Главная страница Soketi](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Аналитика\n\nПользовательские данные очень ценны, когда вы создаете приложение. Вот несколько рекомендуемых провайдеров аналитики.\n\n### Plausible\n\nНужна аналитика? Plausible - один из самых быстрых способов ее получить. Супер минималистичный. У него даже есть [простой плагин для Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Главная страница Plausible](https://plausible.io/)\n\n### Umami\n\nUmami - это само-развертываемая, простая, быстрая и конфиденциальная альтернатива Google Analytics. Вы можете легко развернуть его на Vercel, Railway и т.д. с PlanetScale в качестве базы данных.\n\n- [Главная страница Umami](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n\n## Другое\n\n### Next Bundle Analyzer\n\nБывает сложно определить, что будет включено в сборку выходных данных для вашего приложения. Next Bundle Analyzer - это простой способ визуализировать и анализировать JavaScript-бандлы, которые генерируются.\n\n- [@next/bundle-analyzer на npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/ru/t3-collection.mdx",
    "content": "---\ntitle: T3 коллекция\ndescription: Крутые open source проекты и компании использующие T3 стек\nlayout: ../../layouts/docs.astro\nlang: ru\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\nСделали проект использующий T3 стек и хотите поделиться им? Добавьте его в список!\n\n## Open Source приложения сделанные с использованием T3 стека\n\n<OpenSourceAppList descriptionIntl=\"Описание\" repoIntl=\"Ссылка\" linkIntl=\"Ссылка\"/>\n\n## Компании использующие T3 стек\n\nНам бы очень хотелось узнать о компаниях использующих T3 стек для своих приложений. Ваша компания использует T3 стек и вы хотите поделиться этим? Добавьте её в список!\n\n<CompanyList linkIntl=\"Ссылка\"/>\n\n<Callout type=\"tip\">\nКрутой проект использующий T3 стек? Сделайте [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) и добавьте его в список!\n</Callout>\n"
  },
  {
    "path": "www/src/pages/ru/usage/env-variables.mdx",
    "content": "---\ntitle: Переменные среды\ndescription: Начало работы с Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: ru\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App использует собственный пакет [@t3-oss/env-nextjs](https://env.t3.gg) вместе с [Zod](https://github.com/colinhacks/zod) для валидации переменных среды во время выполнения _и_ во время сборки, предоставляя простую логику в файле `src/env.js`:\n\n## env.js\n\n_TLDR; Если вы хотите добавить новую переменную среды, вам следует добавить валидатор в `src/env.js`, а затем пару ключ-значение в `.env`._\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env использует `createEnv`, который отвечает за создание схемы и будет включать главную логику валидации для клиентских и серверных переменных среды.\n\n<Callout type=\"info\">\n  Для получения дополнительной информации о том, как `createEnv` работает\n  изнутри, посмотрите документацию [T3 Env](https://env.t3.gg/docs/introduction)\n  (EN)\n</Callout>\n\n## Использование переменных среды\n\nКогда вы хотите использовать переменные среды, вы можете импортировать их из `env.js` и использовать их как вы обычно использовали бы. Если вы импортируете этот файл на стороне клиента и попробуете получить серверную переменную, вы получите ошибку выполнения:\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` полностью типобезопасно и предоставляет автокомплит\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ Это даст ошибку\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ Тут все ОК\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nИз-за того, что файл `.env` по умолчанию не добавляется в систему контроля версий, мы также добавили файл `.env.example`, в котором вы можете по желанию сохранить копию вашего файла `.env` с удаленными секретами. Это необязательно, но мы рекомендуем держать пример в актуальном состоянии, чтобы сделать процесс настройки среды для новых участников проекта как можно проще.\n\nНекоторые фреймворки и инструменты сборки, такие как Next.js, предлагают хранить секреты в файле `.env.local` и коммитить файлы `.env` в ваш проект. Это не рекомендуется, поскольку это может облегчить случайный коммит секретов в ваш проект. Вместо этого мы рекомендуем хранить секреты в `.env`, держать ваш файл `.env` в `.gitignore` и коммитить только файлы `.env.example` в ваш проект.\n\n## Добавление переменных среды\n\nДля того, чтобы убедиться, что ваша сборка никогда не завершится без переменных среды, которые проект требует, вам нужно добавить новые переменные среды в **двух** местах:\n\n📄 `.env`: Введите переменную среды, как обычно делаете в файле `.env`, т.е. `KEY=VALUE`\n\n📄 `env.js`: Добавьте соответствующую логику валидации для переменных среды, определив для каждой из них Zod схему внутри `createEnv`, например `KEY: z.string()`. Кроме этого, убедитесь в том, что вы деструкткрировали их в опции `runtimeEnv`, например `KEY: process.env.KEY`.\n\n<Callout type=\"info\">\n  Зачем нужно деструктурировать переменные среды внутри `runtimeEnv`? Это\n  связано с тем, как Next.js собирает переменные среды в некоторых рантаймах.\n  Деструктурируя их вручную, мы гарантируем, что эти переменные не будут убраны\n  из финальной сборки.\n</Callout>\n\nОпционально, вы также можете обновлять файл `.env.example`:\n\n📄 `.env.example`: Введите вашу переменную среды, но убедитесь, что не включаете значение, если оно является секретным, т.е. `KEY=VALUE` или `KEY=`\n\n### Пример\n\n_Я хочу добавить мой Twitter API токен в качестве переменной среды на стороне сервера_\n\n1. Добавьте переменную среды в `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Добавьте переменную среды в `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n  runtimeEnv: {\n    // ...\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n\n3. _Опционально:_ Добавьте переменную среды в `.env.example`, но не включайте токен в `runtimeEnv`\n\n```\nTWITTER_API_TOKEN=\n```\n"
  },
  {
    "path": "www/src/pages/ru/usage/first-steps.md",
    "content": "---\ntitle: Первые шаги\ndescription: Начало работы с вашим новым T3 App\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nВы только что создали новое приложение T3 и готовы к работе. Вот минимальный набор для запуска вашего приложения.\n\n## База данных\n\nЕсли ваше приложение включает Prisma, убедитесь, что вы запустили `npx prisma db push` из корневого каталога вашего приложения. Эта команда синхронизирует схему Prisma с вашей базой данных и генерирует типы TypeScript для Prisma Client на основе вашей схемы. Обратите внимание, что вам нужно перезапустить сервер TypeScript после этого, чтобы он мог обнаружить сгенерированные типы.\n\n## Аутентификация\n\nЕсли ваше приложение включает NextAuth.js, мы начинаем с `DiscordProvider`. Это один из самых простых провайдеров, предлагаемый NextAuth.js, однако он все еще требует некоторой начальной настройки с вашей стороны.\n\nКонечно, если вы предпочитаете использовать другой провайдер аутентификации, вы также можете использовать один из [многих провайдеров](https://next-auth.js.org/providers/), которые предлагает NextAuth.js.\n\n1. Вам нужен аккаунт Discord, поэтому зарегистрируйтесь, если еще не зарегистрировались.\n2. Перейдите на https://discord.com/developers/applications и нажмите «New Application» в правом верхнем углу. Дайте вашему приложению имя и согласитесь с Условиями использования.\n3. Когда вы создадите приложение, перейдите к «Settings → OAuth2 → General».\n4. Скопируйте «Client ID» и добавьте его в ваш `.env` как `AUTH_DISCORD_ID`.\n5. Нажмите «Reset Secret», скопируйте новый секрет и добавьте его в ваш `.env` как `AUTH_DISCORD_SECRET`.\n6. Нажмите «Add Redirect» и введите `http://localhost:3000/api/auth/callback/discord`.\n   - Для развертывания в продакшене следуйте предыдущим шагам для создания другого приложения Discord, но на этот раз замените `http://localhost:3000` на URL, на который вы развертываете.\n7. Сохраните изменения.\n\nТеперь у вас должна быть возможность войти в систему.\n\n## Следующие шаги\n\n- Если ваше приложение включает tRPC, ознакомьтесь с `src/pages/index.tsx` и `src/server/trpc/router/post.ts`, чтобы узнать, как работают запросы tRPC.\n- Посмотрите на документацию `create-t3-app`, а также на документацию пакетов, которые включает ваше приложение.\n- Присоединяйтесь к нашему [Discord](https://t3.gg/discord) и поставьте звезду на [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/ru/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Использование\",\n  layout: \"docs\",\n  description: \"Научитесь использовать различные технологии из T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/ru/usage/next-auth.md",
    "content": "---\ntitle: NextAuth.js\ndescription: Использование NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nКогда вы хотите иметь систему аутентификации в вашем приложении Next.js, NextAuth.js - отличное решение, чтобы не заморачиваться с реализацией сложной безопасности самостоятельно. Он имеет обширный список провайдеров для быстрого добавления аутентификации OAuth и предоставляет адаптеры для многих баз данных и ORM.\n\n## Провайдер контекста\n\nВ точке входа вашего приложения вы увидите, что ваше приложение обернуто в [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nЭтот провайдер контекста позволяет вашему приложению получить доступ к данным сессии из любого места вашего приложения, не передавая их как пропсы:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // Handle unauthenticated state, e.g. render a SignIn component\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Получение сессии на сервере\n\nИногда вам может понадобиться запросить сессию на сервере. Чтобы сделать это, предварительно получите сессию с помощью функции-помощника `getServerAuthSession`, которую предоставляет `create-t3-app`, и передайте ее на клиент с помощью `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTE: `session` wont have a loading state since it's already prefetched on the server\n\n  ...\n}\n```\n\n## Включение `user.id` в сессию\n\n`create-t3-app` настроен для использования [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) в конфигурации NextAuth.js для включения ID пользователя в объект `session`.\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nЭто связано с файлом объявления типов, чтобы убедиться, что `user.id` типизирован при доступе к объекту `session`. Подробнее о [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) в документации NextAuth.js.\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nТакой же шаблон может быть использован для добавления любых других данных в объект `session`, например, поля `role`, но **не следует злоупотреблять для хранения конфиденциальных данных** на клиенте.\n\n## Использование с tRPC\n\nПри использовании NextAuth.js с tRPC вы можете создавать повторно используемые, защищенные процедуры с помощью [middleware](https://trpc.io/docs/v10/middlewares). Это позволяет вам создавать процедуры, которые могут быть доступны только аутентифицированным пользователям. `create-t3-app` настраивает все это для вас, позволяя вам легко получать доступ к объекту сессии в аутентифицированных процедурах.\n\nЭто делается в два шага:\n\n1. Возьмите сессию из заголовков запроса с помощью функции [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Преимущество использования `getServerSession` вместо обычного `getSession` заключается в том, что это server-side функция и она не вызывает ненужных вызовов fetch. `create-t3-app` создает вспомогательную функцию, которая абстрагирует этот особый API.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nИспользуя эту вспомогательную функцию, мы можем получить сессию и передать ее в контекст tRPC:\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Создайте tRPC middleware, которое проверяет, аутентифицирован ли пользователь. Затем мы используем middleware в `protectedProcedure`. Любой вызывающий эти процедуры должен быть аутентифицирован, иначе будет сгенерирована ошибка, которую можно правильно обработать на стороне клиента.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nОбект сессии - это легкое, минимальное представление пользователя и содержит только несколько полей. При использовании `protectedProcedures` у вас есть доступ к идентификатору пользователя, который можно использовать для получения большего количества данных из базы данных.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Использование с Prisma\n\nЧтобы заставить NextAuth.js и Prisma работать вместе, необходимо большое количество [начальной настройки](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` выполняет все это для вас, и если вы выберете одновременно и Prisma, и NextAuth.js, вы получите полностью работающую систему аутентификации со всеми предварительно настроенными, необходимыми моделями. Мы предоставляем вашему сгенерированому приложению предварительно настроеный провайдер Discord OAuth, который мы выбрали потому, с ним легче всего начать - просто укажите свои токены в `.env` и вы готовы к работе. Однако вы можете легко добавить больше провайдеров, следуя [докуменетации NextAuth.js](https://next-auth.js.org/providers/). Обратите внимание, что некоторые провайдеры требуют дополнительных полей для добавления в определенные модели. Мы рекомендуем вам прочитать документацию для провайдера, который вы хотите использовать, чтобы убедиться, что у вас есть все необходимые поля.\n\n### Добавление новых полей в ваши модели\n\nКогда вы добавляете новые поля в любую из моделей `User`, `Account`, `Session` или `VerificationToken` (в большинстве случаев вам потребуется только изменить модель `User`), вам нужно иметь в виду, что [адаптер Prisma](https://next-auth.js.org/adapters/prisma) автоматически создает поля в этих моделях при регистрации новых пользователей и входе в систему. Поэтому, добавляя новые поля в эти модели, вы должны предоставить значения по умолчанию для них, поскольку адаптер не знает о них.\n\nЕсли например, вы хотите добавить `role` в модель `User`, вам нужно будет предоставить значение по умолчанию для поля `role`. Это делается путем добавления значения `@default` к полю `role` в модели `User`:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Использование с Next.js middleware\n\nИспользование NextAuth.js с Next.js middleware [требует использования стратегии сеанса JWT](https://next-auth.js.org/configuration/nextjs#caveats) для аутентификации. Это связано с тем, что middleware может получить доступ к сессионной cookie только в том случае, если это JWT. По умолчанию, `create-t3-app` настроен на использование **default** стратегии базы данных, в сочетании с Prisma в качестве адаптера базы данных.\n\n## Настраиваем DiscordProvider по умолчанию\n\n1. Перейдите в [раздел Applications в Discord Developer Portal](https://discord.com/developers/applications), и нажмите на \"New Application\"\n2. В меню настроек перейдите к \"OAuth2 => General\"\n\n- Скопируйте Client ID и вставьте его в `AUTH_DISCORD_ID` в `.env`.\n- Возле Client Secret нажмите \"Reset Secret\" и скопируйте эту строку в `AUTH_DISCORD_SECRET` в `.env`. Будьте осторожны, поскольку вы больше не сможете увидеть этот секрет, и сброс его приведет к тому, что существующий истечет.\n- Нажмите \"Add Redirect\" и вставьте `<app url>/api/auth/callback/discord` (пример для локальной разработки: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Сохраните изменения\n- Возможно, но не рекомендуется, использовать одно и то же приложение Discord для разработки и продакшена. Вы также можете рассмотреть [Mocking the Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) во время разработки.\n\n## Полезные ресурсы\n\n| Ресурс                            | Ссылка                                  |\n| --------------------------------- | --------------------------------------- |\n| Документация NextAuth.js          | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/ru/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Использование Next.js\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nNext.js это бэкенд фреймворк для ваших React приложений.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nПосмотрите [выступление Theo на Next.js Conf](https://www.youtube.com/watch?v=W4UhNo3HAMw) чтобы получить более подробное понимание того, что такое Next.js и как он работает.\n\n## Почему я должен это использовать?\n\nМы любим React. Он сделал разработку UI доступной в том смысле, в котором мы раньше этого не могли себе представить. Он также может провести разработчиков по некоторым тернистым тропам. Next.js предлагает слегка субъективный, но очень оптимизированный подход к созданию приложений с использованием React. От маршрутизации до определений API до рендеринга изображений, мы доверяем Next.js, чтобы вести разработчиков к правильным решениям.\n\nСовмещая Next.js с [Vercel](https://vercel.com/), вы можете разрабатывать и разворачивать веб-приложения легче, чем когда-либо. Их чрезвычайно щедрый бесплатный тариф и супер интуитивный интерфейс предоставляют решение в один клик для развертывания вашего сайта (Мы ❤️ Vercel)\n\n## Get Static/Server Props\n\nКлючевые особенности Next.js - это возможности получения данных. Мы настоятельно рекомендуем прочитать [официальную документацию](https://nextjs.org/docs/basic-features/data-fetching), чтобы понять, как использовать каждый метод и чем они отличаются. `getServerSideProps` обычно не рекомендуется, если нет веской причины, из-за того, что это блокирующий вызов и он замедлит ваш сайт. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) - это отличная альтернатива `getServerSideProps`, когда данные динамичны и могут быть получены постепенно.\n\n## Полезные ресурсы\n\n| Ресурс                          | Ссылка                             |\n| ------------------------------- | ---------------------------------- |\n| Документация Next.js            | https://nextjs.org/docs            |\n| Next.js GitHub                  | https://github.com/vercel/next.js  |\n| Блог Next.js                    | https://nextjs.org/blog            |\n| Next.js Discord                 | https://nextjs.org/discord         |\n| Next.js Twitter                 | https://twitter.com/nextjs         |\n| Канал Vercel/Next.js на YouTube | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/ru/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Использование Prisma\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\nPrisma это ORM для TypeScript, который позволяет определять схему и модели базы данных в файле `schema.prisma`, а затем генерировать клиент, который обеспечивает типобезопасность и может использоваться для взаимодействия с базой данных из вашего бэкенда.\n\n## Prisma Client\n\nРасположенный в `/server/db/client.ts`, Prisma Client инициализируется как глобальная переменная (как рекомендовано [лучшими практиками](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) команды Prisma) и экспортируется для использования в ваших API маршрутах. Мы включаем Prisma Client в [Context](/ru/usage/trpc#-serverapitrpcts) по умолчанию и рекомендуем использовать его вместо отдельного импорта в каждом файле.\n\n## Схема\n\nВы найдете файл схемы Prisma в `/prisma/schema.prisma`. Этот файл используется для определения схемы и моделей базы данных, а также для генерации Prisma Client.\n\n### С NextAuth.js\n\nКогда вы выбираете NextAuth.js в сочетании с Prisma, файл схемы генерируется и настраевается для вас с рекомендуемыми значениями для моделей `User`, `Session`, `Account` и `VerificationToken`, согласно [документации NextAuth.js](https://next-auth.js.org/adapters/prisma).\n\n## База данных по умолчанию\n\nБаза данных по умолчанию - это база данных SQLite, которая отлично подходит для разработки и быстрого создания proof-of-concept, но не рекомендуется для использования в продакшене. Вы можете изменить базу данных, используя `provider` в блоке `datasource` на `postgresql` или `mysql`, а затем обновить строку подключения в переменных окружения, чтобы указать на вашу базу данных.\n\n## Заполнение (seeding) базы данных\n\n[Заполнение (seeding) вашей базы данных](https://www.prisma.io/docs/guides/database/seed-database) - это отличный способ быстро заполнить вашу базу данных тестовыми данными, чтобы помочь вам начать. Чтобы настроить заполнение, вам нужно создать файл `seed.ts` в каталоге `/prisma` и затем добавить скрипт `seed` в файл `package.json`. Вам также понадобится некоторый TypeScript-раннер, который может выполнить скрипт заполнения. Мы рекомендуем [tsx](https://github.com/esbuild-kit/tsx), который является очень эффективным TypeScript-раннером, который использует esbuild и не требует какой-либо конфигурации ESM, но `ts-node` или другие раннеры также будут работать.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nЗатем, просто запустите `pnpm db-seed` (или `npm`/`yarn`), чтобы заполнить вашу базу данных.\n\n## Полезные ресурсы\n\n| Ресурс                          | Ссылка                                                                                                                                            |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Документация Prisma             | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub                   | https://github.com/prisma/prisma                                                                                                                  |\n| NextAuth.JS Адаптер для Prisma  | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| Гайд по подключению PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/ru/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Использование Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\n## Что такое Tailwind CSS?\n\nTailwind CSS - это небольшой, [utility first](https://tailwindcss.com/docs/utility-first) CSS фреймворк для создания собственного дизайна, без переключения контекста, которое требуется для обычного CSS. Это чисто CSS фреймворк и не предоставляет никаких предварительно собранных компонентов или логики, и предоставляет [принципиально иной набор преимуществ](https://www.youtube.com/watch?v=CQuTF-bkOgc) по сравнению с библиотекой компонентов, такой как Material UI.\n\nОн делает CSS невероятно легким и быстрым для написания, как показано в следующем примере:\n\nСтарый CSS:\n\n1. Напишите CSS, часто в отдельном файле\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Импортируйте CSS в ваш компонент\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Добавьте класс в ваш HTML\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nЭквивалент в Tailwind:\n\n1. Просто напишите классы в вашем HTML\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nИспользуя вместе с React компонентами, он является чрезвычайно мощным для быстрого создания UI.\n\nTailwind CSS содержит встроенную красивую систему дизайна, которая поставляется из коробки с тщательно выбранной цветовой палитрой, размерами для стилей, таких как ширина/высота и отступы для единого дизайна, а также точками прерывания для создания адаптивных макетов. Эта система дизайна может быть настроена и расширена для создания точного набора стилей, которые необходимы вашему проекту.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla лучше известна как [mewtru](https://twitter.com/trunarla) дала потрясающую лекцию о [создании системы дизайна с использованием Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Использование\n\nУбедитесь, что у вас установлены плагины редактора для Tailwind, чтобы улучшить ваш опыт написания Tailwind.\n\n### Расширения и плагины\n\n- [Расширение для VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Форматирование\n\nКлассы Tailwind Css могут легко стать немного беспорядочными, поэтому форматтер для классов является необходимым. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) сортирует классы в [рекомендуемом порядке](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted), чтобы классы соответствовали собранному css-пакету. При выборе Tailwind в CLI мы установим и настроим это для вас.\n\n### Добавление классов в зависимости от условий\n\nДобавление классов в зависимости от условий с использованием тернарных операторов может стать очень беспорядочным и трудночитаемым. Эти пакеты помогают организовать ваши классы при использовании некоторой логики с условиями.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Полезные ресурсы\n\n| Ресурс                        | Ссылка                                                   |\n| ----------------------------- | -------------------------------------------------------- |\n| Документация Tailwind         | https://tailwindcss.com/docs/editor-setup/               |\n| Шпаргалка по Tailwind         | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss           | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community            | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Сервер Tailwind в Discord     | https://tailwindcss.com/discord/                         |\n| Канал TailwindLabs на Youtube | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground           | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/ru/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Использование tRPC\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\ntRPC позволяет нам писать типобезопасные API от конца до конца (end-to-end) без какой-либо генерации кода или накладных расходов на выполнение. Он использует отличную инференцию TypeScript для вывода типов маршрутизатора вашего API и позволяет вызывать процедуры API из вашего фронтенда с полной типобезопасностью и автодополнением. Используя tRPC, ваш фронтенд и бэкенд чувствуют себя ближе друг к другу, чем когда-либо, обеспечивая исключительный опыт разработчика.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>I built tRPC to allow people to move faster by removing the need of a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creator of tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Файлы\n\ntRPC требует много шаблонного кода, который `create-t3-app` настраивает для вас. Давайте рассмотрим файлы, которые генерируются:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nЭтот файл является точкой входа для вашего API и экспортирует ваш tRPC роутер. Обычно, вам не придется трогать этот файл, но если вам нужно, например, включить CORS middleware или что то подобное, полезно знать, что экспортируемый `createNextApiHandler` - это [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) который принимает [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) и [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) объект. Это означает, что вы можете обернуть `createNextApiHandler` в любой middleware, который вам нужен. См. ниже для [примера](#enabling-cors) добавления CORS.\n\n### 📄 `server/api/trpc.ts`\n\nЭтот файл разделен на две части: создание контекста и инициализация tRPC.\n\n1. Мы определяем контекст, который передается вашим tRPC процедурам. Контекст - это данные, к которым у вас есть доступ во всех ваших tRPC процедурах, и это отличное место, чтобы поместить вещи, такие как соединения с базой данных, информация об аутентификации и т.д. В create-t3-app мы используем две функции, чтобы включить использование подмножества контекста, когда у нас нет доступа к объекту запроса.\n\n- `createInnerTRPCContext`: Это то место, где вы определяете контекст, который не зависит от запроса, например, ваше соединение с базой данных. Вы можете использовать эту функцию для [интеграционного тестирования](#sample-integration-test) или [ssg-помощников](https://trpc.io/docs/v10/ssg-helpers), где у вас нет объекта запроса.\n\n- `createTRPCContext`: Здесь вы определяете контекст, который зависит от запроса: например, сессия пользователя. Вы запрашиваете сессию с помощью объекта `opts.req`, а затем передаете сессию в функцию `createInnerTRPCContext` для создания окончательного контекста.\n\n2. Мы инициализируем tRPC и определяем повторно используемые [процедуры](https://trpc.io/docs/v10/procedures) и [посредники](https://trpc.io/docs/v10/middlewares). По соглашению, вы не должны экспортировать весь объект `t`, а вместо этого создавать повторно используемые процедуры и посредники и экспортировать их.\n\nВы заметите что мы используем `superjson` как [преобразователь данных](https://trpc.io/docs/v10/data-transformers). Это позволяет сохранять типы данных, когда они достигают клиента, поэтому если вы, например, отправляете объект `Date`, клиент вернет `Date`, а не строку, что является случаем для большинства API.\n\n### 📄 `server/api/routers/*.ts`\n\nЭто то место, где вы определяете маршруты и процедуры вашего API. Вы [создаете отдельные маршрутизаторы](https://trpc.io/docs/v10/router) для связанных процедур.\n\n### 📄 `server/api/root.ts`\n\nЗдесь мы [объединяем](https://trpc.io/docs/v10/merging-routers) все под-маршрутизаторы, определенные в `routers/**` в единый маршрутизатор приложения.\n\n### 📄 `utils/api.ts`\n\nЭто точка входа для tRPC на фронтенде. Здесь вы импортируете **определение типов** маршрутизатора и создаете клиент tRPC вместе с хуками react-query. Поскольку мы включили `superjson` в качестве преобразователя данных на бэкенде, нам также нужно включить его на фронтенде. Это связано с тем, что сериализованные данные с бэкенда десериализуются на фронтенде.\n\nЗдесь вы определите свои [ссылки](https://trpc.io/docs/v10/links) tRPC, которые определяют поток запросов от клиента к серверу. Мы используем \"default\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink), который позволяет [группировать запросы](https://cloud.google.com/compute/docs/api/how-tos/batch), а также [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink), который выводит полезные журналы запросов во время разработки.\n\nВ конце концов, мы экспортируем [вспомогательный тип](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type), который вы можете использовать для вывода типов на фронтенде.\n\n## Как я могу использовать tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC контрибьютор [trashh_dev](https://twitter.com/trashh_dev) [выступил на Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) с рассказом о tRPC. Мы настоятельно рекомендуем вам посмотреть его, если вы еще не сделали это.\n\nС tRPC вы пишете функции TypeScript на бэкенде, а затем вызываете их из фронтенда. Простая процедура tRPC может выглядеть так:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nЭто процедура tRPC (эквивалент обработчика маршрута в традиционном бэкенде), которая сначала проверяет входные данные с помощью Zod (который является той же библиотекой проверки, которую мы используем для [переменных окружения](./env-variables)) - в этом случае мы убеждаемся, что входные данные являются строкой. Если входные данные не являются строкой, он отправит информативную ошибку.\n\nПосле входных данных мы применяем resolver функцию, которая может быть либо [запросом](https://trpc.io/docs/v10/react-queries), [мутацией](https://trpc.io/docs/v10/react-mutations) или [подпиской](https://trpc.io/docs/v10/subscriptions). В нашем примере resolver вызывает нашу базу данных с помощью клиента [prisma](./prisma) и возвращает пользователя, у которого `id` совпадает с тем, который мы передали.\n\nВы определяете свои процедуры в `роутерах` которые представляют собой коллекцию связанных процедур с общим пространством имен. У вас может быть один роутер для `пользователей`, один для `постов` и еще один для `сообщений`. Эти роутеры затем можно объединить в единый централизованный `appRouter`:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nОбратите внимание на то, что нам нужно экспортировать только типы наших роутеров, что означает, что мы никогда не импортируем серверный код на клиенте.\n\nТеперь давайте вызовим процедуру на нашем фронтенде. tRPC предоставляет обертку для `@tanstack/react-query`, которая позволяет вам использовать все возможности хуков (hooks), которые он предоставляет, но с дополнительным преимуществом того, что ваши вызовы API типизированы и инферированы (inferred). Мы можем вызывать наши процедуры с нашего фронтенда следующим образом:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nВы сразу заметите, насколько хороши автодополнение и типобезопасность. Как только вы начнете писать `trpc.`, ваши роутеры появятся в автодополнении, и когда вы выберете роутер, его процедуры также появятся. Вы также получите ошибку TypeScript, если ваш ввод не соответствует валидатору, который вы определили на бэкенде.\n\n## Как я могу вызывать свой API извне?\n\nВ обычных API, вы можете вызвать ваши конечные точки (endpoints) используя любой HTTP клиент, как `curl`, `Postman`, `fetch` или прямо из вашего браузера. С tRPC, это немного иначе. Если вы хотите вызывать ваши процедуры без клиента tRPC, есть два рекомендуемых способа сделать это:\n\n### Раскройте одну процедуру внешне\n\nЕсли вы хотите раскрыть вашу процедуру внешне, вы ищете [server side calls](https://trpc.io/docs/v10/server-side-calls). Это позволит вам создать обычную конечную точку (endpoint) API Next.js, но переиспользовать часть резолвера вашей tRPC процедуры.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Раскройте каждую процедуру внешне\n\nЕсли вы хотите раскрыть каждую процедуру внешне, ознакомьтесь с плагином сообщества [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Предоставляя дополнительные метаданные вашим процедурам, вы можете сгенерировать соответствующее REST API из вашего tRPC роутера.\n\n### Это всего лишь HTTP запросы\n\ntRPC взаимодействует через HTTP, поэтому также возможно вызывать ваши процедуры tRPC используя \"обычные\" HTTP запросы. Однако синтаксис может быть неприятным из-за [RPC протокола](https://trpc.io/docs/v10/rpc), который использует tRPC. Если вам интересно, вы можете проверить, что tRPC запросы и ответы выглядят в вашей вкладке сети браузера, но мы рекомендуем делать это только в качестве образовательного упражнения и придерживаться одного из решений, описанных выше.\n\n## Сравнение с конечной точкой (enpoint) Next.js API\n\nДавайте сравним конечную точку (endpoint) Next.js API с процедурой tRPC. Допустим, мы хотим получить объект пользователя из нашей базы данных и вернуть его на фронтенд. Мы могли бы написать конечную точку (endpoint) Next.js API следующим образом:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nСравните это с примером tRPC выше и вы увидите некоторые преймущества tRPC:\n\n- Вместо того, чтобы указывать URL для каждого маршрута, который может стать неудобным для отладки, если вы что-то переместите, ваш весь маршрутизатор - это объект с автозаполнением.\n- Вам не нужно проверять, какой HTTP метод был использован.\n- Вам не нужно проверять, что запрос или тело запроса содержат правильные данные в процедуре, потому что Zod позаботится об этом.\n- Вместо создания ответа, вы можете выбрасывать ошибки и возвращать значение или объект, как в любой другой функции TypeScript.\n- Вызывая процедуру на фронтенде, вы не получаете никакого автозаполнения или проверки типов.\n\n## Полезные сниппеты\n\nЗдесь приведены некоторые сниппеты, которые могут пригодиться.\n\n### Включение CORS\n\nЕсли вам нужно использовать ваш API с другого домена, например в монорепозитории, который включает в себя приложение React Native, вам может потребоваться включить CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Оптимистические обновления\n\nОптимистическое обновление - это когда мы обновляем пользовательский интерфейс до того, как API-запрос завершится. Это предоставляет пользователю лучший опыт, потому что он не должен ждать завершения API-запроса, прежде чем пользовательский интерфейс отобразит результат его действия. Однако приложения, которые ценят корректность данных, должны избегать оптимистические обновления, поскольку они не являются «истинным» представлением состояния бэкенда. Вы можете прочитать больше в [документации React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Простой Интеграционный Тест\n\nЗдесь преведен простой интеграционный тест, который использует [Vitest](https://vitest.dev), чтобы проверить, что ваш маршрутизатор tRPC работает должным образом, парсер входных данных выводит правильный тип и возвращаемые данные соответствуют ожидаемому результату.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n## Полезные ресурсы\n\n| Ресурс                                | Ссылка                                                  |\n| ------------------------------------- | ------------------------------------------------------- |\n| Документация по tRPC                  | https://www.trpc.io                                     |\n| Несколько примеров использования tRPC | https://github.com/trpc/trpc/tree/next/examples         |\n| Документация React Query              | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/ru/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Использование TypeScript\nlayout: ../../../layouts/docs.astro\nlang: ru\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creator of the T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nНесмотря на то новичок вы или же опытный разработчик, мы считаем, что TypeScript - это маст-хэв. Поначалу он может выглядеть угнетающе, но, как и многие другие инструменты, многие разработчики не возвращаются назад после того как начали его использовать.\n\nОн предоставляет обратную связь в режиме реального времени при написании кода, определяя ожидаемые типы данных, и предоставляет полезные подсказки в редакторе кода либо кричит красными волнистыми линиями, если вы пытаетесь получить доступ к свойству, которого не существует, или пытаетесь передать значение неправильного типа, которое в противном случае пришлось бы отлаживать дальше по линии.\n\nЭто инструмент, который, возможно, обеспечивает наибольшую производительность разработчикам; он предоставляет документацию для кода, который вы пишете или используете непосредственно в вашем редакторе и имеет мгновенную обратную связь, когда вы неизбежно делаете ошибки, что абсолютно бесценно.\n\n## Выведение типов (Type Inference)\n\nПока многие новые разработчики на TypeScript обеспокоены _написанием_ TypeScript, многие из его преимуществ на самом деле не требуют от вас изменения вашего кода вообще, в частности вывод типов. Вывод типов означает, что если что-то типизировано, этот тип будет следовать за ним в течение потока приложения без необходимости повторного объявления в других местах. Это означает, что, например, после того, как вы определили типы аргументов, которые принимает функция, остальная часть функции обычно будет безопасной в отношении типов без необходимости ввода какого-либо дополнительного кода, специфичного для TypeScript. Разработчики библиотек тратят огромное количество времени на поддержание типов для своих библиотек, что означает, что мы, как разработчики приложений, можем получить выгоду от вывода типов и встроенной документации в вашем редакторе кода, которые эти типы предоставляют.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nПосмотрите видео Theo о том, что [вы, возможно, используете TypeScript неправильно](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Мощные применения вывода типов\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) - это библиотека проверки схем, построенная поверх TypeScript. Напишите схему, которая представляет собой единственный источник истины для ваших данных, и Zod гарантирует, что ваши данные будут действительными во всем приложении, даже вне границ сети и внешних API.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) предоставляет вам декларативные, всегда актуальные автоматически управляемые запросы и мутации, которые напрямую улучшают как Developer, так и User Experience.\n\n## Полезные ресурсы\n\n| Ресурс                                                          | Ссылка                                                            |\n| --------------------------------------------------------------- | ----------------------------------------------------------------- |\n| Руководство по TypeScript                                       | https://www.typescriptlang.org/docs/handbook/                     |\n| Гайд по TypeScript для новичков                                 | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                                 | https://github.com/type-challenges/type-challenges                |\n| Канал Родни Маллена из мира TypeScript (Matt Pocock) на YouTube | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/ru/why.md",
    "content": "---\ntitle: Почему CT3A?\ndescription: Почему вам следует выбрать Create T3 App для вашего следующего проекта\nlayout: ../../layouts/docs.astro\nlang: ru\n---\n\nМы начали создавать create-t3-app, потому что [Theo](https://twitter.com/t3dotgg) отказался делать шаблон своих любимых технологий. Вдохновленный create-next-app, [CLI Astro](https://astro.build) и общей любовью к типобезопасности, команда create-t3-app трудилась, чтобы создать лучшую возможную отправную точку для новых проектов T3 Stack.\n\nЕсли вы заинтересованы в использовании Next.js в типобезопасном режиме, это то с чего нужно начать. Если вы интересуетесь любыми из конкретных технологических решений, которые мы приняли, читайте дальше :)\n\n## Почему TypeScript?\n\nJavaScript сложен. Зачем добавлять еще больше правил?\n\nМы всецело уверены, что опыт TypeScript позволяет вам быть лучшим разработчиком. Он предоставляет обратную связь во время написания кода, определяя ожидаемые типы данных, и либо предоставляет полезное автозаполнение в вашем редакторе, либо кричит вам красными волнистыми линиями, если вы пытаетесь получить доступ к свойству, которого не существует, или пытаетесь передать значение неправильного типа, что в противном случае пришлось бы отлаживать дальше по линии. Независимо от того, новичок вы в веб-разработке или опытный профессионал, «строгость» TypeScript обеспечивает менее раздражающий, более последовательный опыт, чем ванильный JS.\n\nТипобезопасность делает вас быстрее. Если вы еще не убеждены, вы [можете использовать TypeScript неправильно ...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Почему Next.js?\n\nМы любим React. Он сделал разработку UI доступной в том виде, в котором мы никогда не могли себе представить. Он также может привести разработчиков по некоторым тернистым путям.\n\nNext.js предлагает мение субъективный, но более оптимизированный подход к созданию приложений с использованием React. От маршрутизации до определения API до рендеринга изображений мы доверяем Next.js, чтобы вести разработчиков к правильным решениям.\n\n## Почему tRPC/Prisma/Tailwind/и т.д.?\n\nХотя мы верим, что все должно быть просто, мы находим, что эти части используются в каждом проекте, похожем на приложение. `create-t3-app` выполняет отличную работу, позволяя вам выбрать те части, которые вам нужны.\n\n### tRPC\n\ntRPC предоставляет все преимущества GraphQL, такие как бесшовная разработка клиента против типобезопасного сервера без всех шаблонов. Это умное злоупотребление TypeScript, которое обеспечивает невероятный опыт разработки.\n\n### Prisma\n\nPrisma для SQL то, что TypeScript для JS. Она создала опыт разработчика, которого раньше не было. Создавая типы из пользовательской схемы, совместимой с [несколькими базами данных](https://www.prisma.io/docs/concepts/database-connectors), Prisma гарантирует типобезопасность от начала до конца от вашей базы данных до вашего приложения.\n\nPrisma предоставляет целый [набор инструментов](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows), облегчающих ежедневное взаимодействие с вашей базой данных. В частности, Prisma Client отвечает за запросы и делает SQL настолько простым, что вы едва заметите, что его используете, а Prisma Studio - это удобный GUI для вашей базы данных, который позволяет быстро читать и манипулировать данными без необходимости писать код.\n\n### Tailwind CSS\n\nTailwind ощущается как \"CSS в режиме дзен\".\n\nБлагодаря предоставлению строительных блоков в виде хороших цветов по умолчанию, отступов и других примитивов Tailwind позволяет легко создавать приложение с хорошим внешним видом. И в отличие от библиотек компонентов, он не ограничивает вас, когда вы хотите вывести свое приложение на следующий уровень и создать что-то красивое и уникальное.\n\nК тому же, благодаря инлайновому подходу, Tailwind побуждает вас стилизовать без беспокойства о названии классов, организации файлов или любой другой проблеме, не связаной с решением задачи.\n\n### NextAuth.js\n\nКогда вы хотите добавить систему аутентификации в ваше приложение NextJS, NextAuth.js - отличное решение, чтобы не заморачиваться с реализацией сложной системы безопасности. Она имеет обширный список провайдеров для быстрого добавления аутентификации через OAuth и предоставляет адаптеры для многих баз данных и ORM.\n"
  },
  {
    "path": "www/src/pages/themeTest.astro",
    "content": "---\nimport HeadCommon from \"../components/headCommon.astro\";\nimport ThemeToggleButton from \"../components/navigation/themeToggleButton.astro\";\n\nimport \"../styles/global.css\";\nimport \"../styles/accessibility.css\";\n---\n\n<head>\n  <HeadCommon />\n</head>\n<main class=\"h-screen bg-default p-4\">\n  <div class=\"grid grid-cols-1 gap-2 sm:gap-4\">\n    <div>\n      <h1 class=\"py-4 text-4xl font-bold\">Colors</h1>\n      <ThemeToggleButton />\n      <div class=\"mt-8 grid grid-cols-2 gap-4 font-semibold\">\n        <div class=\"bg-neutral p-4\">Neutral</div>\n        <div class=\"bg-primary p-4\">Primary</div>\n        <div class=\"bg-secondary p-4\">Secondary</div>\n        <div class=\"bg-accent p-4\">Accent</div>\n        <div class=\"bg-warning p-4\">Warning</div>\n        <div class=\"bg-error p-4\">Error</div>\n        <div class=\"bg-success p-4\">Success</div>\n        <div class=\"bg-info p-4\">Info</div>\n      </div>\n    </div>\n    <div>\n      <h1 class=\"py-4 text-4xl font-bold\">Typography</h1>\n      <p class=\"text-9xl\">Text 9xl</p>\n      <p class=\"text-8xl\">Text 8xl</p>\n      <p class=\"text-7xl\">Text 7xl</p>\n      <p class=\"text-6xl\">Text 6xl</p>\n      <p class=\"text-5xl\">Text 5xl</p>\n      <p class=\"text-4xl\">Text 4xl</p>\n      <p class=\"text-3xl\">Text 3xl</p>\n      <p class=\"text-2xl\">Text 2xl</p>\n      <p class=\"text-xl\">Text xl</p>\n      <p class=\"text-lg\">Text lg</p>\n      <p>Text base</p>\n      <p class=\"text-sm\">Text sm</p>\n      <p class=\"text-xs\">Text xs</p>\n      <p><b>bold</b></p>\n      <p><code>code</code></p>\n      <p><em>emphasized</em></p>\n      <p class=\"underline\">underline</p>\n      <p class=\"overline\">overline</p>\n      <p class=\"line-through\">line-through</p>\n      <p class=\"no-underline\">no-underline</p>\n    </div>\n  </div>\n</main>\n"
  },
  {
    "path": "www/src/pages/uk/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: Деплоймент в Docker\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\nВи можете контейнеризувати цей стек і розгорнути його як один контейнер за допомогою Docker або як частину групи контейнерів за допомогою docker-compose. Дивіться [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) для прикладу репозиторію на основі цієї документації.\n\n## Конфігурація проекту Docker\n\nБудь ласка, зверніть увагу, що Next.js потребує різних процесів для білда (доступні у фронтенді, з префіксом `NEXT_PUBLIC`) та змінних середовища, доступних тільки на сервері. У цьому прикладі ми використовуємо дві змінні, зверніть увагу на їх позиції в `Dockerfile`, аргументи командного рядка та `docker-compose.yml`:\n\n- `DATABASE_URL` (використовується сервером)\n- `NEXT_PUBLIC_CLIENTVAR` (використовується клієнтом)\n\n### 1. Конфігурація Next\n\nУ вашому [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), додайте конфігурацію ` output` зі значенням `standalone` для [зменшення розміру образу за допомогою автоматичного використання трасувань виводу](https://nextjs.org/docs/advanced-features/output-file-tracing):\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. Створіть dockerignore file\n\n<details>\n    <summary>\n      Натисніть тут і вставте вміст у <code>.dockerignore</code>:\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. Створіть Dockerfile\n\n> Через те, що ми не виймаємо змінні середовища сервера в наш контейнер, [перевірка схеми середовища](/uk/usage/env-variables) не пройде. Щоб цього уникнути, ми повинні додати прапор `SKIP_ENV_VALIDATION=1` до команди білда, щоб схеми оточення не перевірялися під час білда.\n\n<details>\n    <summary>\n      Натисніть тут і вставте вміст у <code>Dockerfile</code>:\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl1.1-compat\nWORKDIR /app\n\n# Install Prisma Client - remove if not using Prisma\n\nCOPY prisma ./\n\n# Install dependencies based on the preferred package manager\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_Нотатки_**\n>\n> - _Емуляція `--platform=linux/amd64` може не бути необхідною після переходу на Node 18._\n> - _Подивіться [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) щоб зрозуміти, чому `libc6-compat` може бути необхідним._\n> - _Використання образів, заснованих на Alpine 3.17 [може призвести до проблем з Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Встановлення `engineType = \"binary\"` вирішує проблему з Alpine 3.17, [але має пов'язані з цим витрати продуктивності](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._\n> - _Next.js збирає [анонімні дані про телеметрію загального використання](https://nextjs.org/telemetry). Розкоментуйте перший екземпляр `ENV NEXT_TELEMETRY_DISABLED 1`, щоб вимкнути телеметрію під час білда. Розкоментуйте другий екземпляр, щоб вимкнути телеметрію під час виконання._\n\n</div>\n</details>\n\n## Зберіть та запустіть образ локально\n\nЗберіть і запустіть цей образ локально за допомогою наступних команд:\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\nВідкрийте [localhost:3000](http://localhost:3000/) щоб побачити запущений додаток.\n\n## Docker Compose\n\nВи також можете використовувати Docker Compose для збирання образу та запуску контейнера.\n\n<details>\n    <summary>\n      Пройдіть кроки 1-4 вище, натисніть тут і додайте вміст в <code>docker-compose.yml</code>:\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\nЗапустіть за допомогою команди `docker compose up`:\n\n```bash\ndocker compose up\n```\n\nВідкрийте [localhost:3000](http://localhost:3000/) щоб побачити запущений додаток.\n\n</div>\n</details>\n\n## Деплоймент на Railway\n\nВи можете використовувати PaaS як автоматичний [деплоймент Dockerfile](https://docs.railway.app/deploy/dockerfiles) від [Railway's](https://railway.app) для деплою вашої програми. Якщо у вас [встановлений Railway CLI](https://docs.railway.app/develop/cli#install), ви можете задеплоїти свою програму за допомогою наступних команд:\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\nПерейдіть до \"Variables\" і увімкніть ваш `DATABASE_URL`. Потім перейдіть до \"Settings\" і виберіть \"Generate Domain.\" Щоб побачити працюючий приклад на Railway, перейдіть до [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).\n\n## Корисні ресурси\n\n| Ресурс                                   | Посилання                                                            |\n| ---------------------------------------- | -------------------------------------------------------------------- |\n| Приклад для Dockerfile                   | https://docs.docker.com/engine/reference/builder/                    |\n| Приклад для файлу Compose 3 версії       | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Приклад Docker CLI                       | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Приклад Docker Compose CLI               | https://docs.docker.com/compose/reference/                           |\n| Розгортання Next.js із Docker Image      | https://nextjs.org/docs/deployment#docker-image                      |\n| Next.js в Docker'е                       | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Приклад Next.js з Docker                 | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| Створення Docker образу Next.js програми | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/uk/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Деплоймент\",\n  layout: \"docs\",\n  description: \"Навчіться деплоїти вашу програму T3 в продакшен.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/uk/deployment/netlify.md",
    "content": "---\ntitle: Netlify\ndescription: Деплоймент в Netlify\nlayout: ../../../layouts/docs.astro\n---\n\nNetlify - це альтернативний провайдер деплою, схожий на Vercel. Ось [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) приклад репозиторію на основі цієї документації.\n\n## Навіщо деплоїти на Netlify\n\nВважають, що Vercel має кращу підтримку Next.js тому що Vercel розробляє Next.js. Вони зацікавлені в тому, щоб платформа була налаштована для оптимальної продуктивності та DX з Next.js. Найчастіше це так і у відхиленні від стандартного шляху не буде сенсу.\n\nТакож існує спільна думка про те, що багато функцій Next.js підтримуються тільки на Vercel. Хоча це правда, що нові функції Next.js будуть тестуватись і підтримуватись на Vercel в момент випуску за замовчуванням, також слід враховувати, що інші провайдери, такі як Netlify, [швидко реалізують та випускають підтримку](https://www.netlify.com/blog/deploy-nextjs-13/) для [стабільних функцій Next.js](https://docs.netlify.com/integrations/frameworks/next-js/overview/).\n\nВсі провайдери деплойменту мають переваги і недоліки, оскільки жоден хост не може мати кращу підтримку для всіх випадків використання. Наприклад, Netlify розробив свій власний [користувальницький Next.js runtime](https://github.com/netlify/next-runtime) для Netlify Edge Functions (які працюють на Deno Deploy) та [підтримують унікальні проміжні програми для доступу та зміни HTTP-відповідей](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).\n\n> _Зверніть увагу: Щоб відстежувати статус нестабільних функцій Next 13, див. [Використання каталогу `app` Next 13 на Netlify](https://github.com/netlify/next-runtime/discussions/1724)._\n\n## Конфігурація проекту\n\nІснує кілька способів налаштування інструкцій білда, включаючи пряме використання Netlify CLI або Netlify Dashboard. Хоча це не обов'язково, рекомендується створити та включити файл [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Це гарантує, що форкнуті та клоновані версії проекту будуть легше повторно задеплоєні.\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## Використання Netlify Dashboard\n\n1. Запуште свій код до репозиторію GitHub і зареєструйтесь на [Netlify](https://app.netlify.com/signup). Після того, як ви створили обліковий запис, натисніть **Add new site** і потім **Import an existing project**.\n\n![Новий проект у Netlify](/images/netlify-01-new-project.webp)\n\n2. Підключіть свій провайдер Git.\n\n![Імпортуйте репозиторій](/images/netlify-02-connect-to-git-provider.webp)\n\n3. Виберіть репозиторій вашого проекту.\n\n![Виберіть репозиторій вашого проекту](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify виявить, якщо у вас є файл `netlify.toml` і автоматично налаштує команду білда та директорію публікацій.\n\n![Налаштування збірки Nextjs](/images/netlify-04-configure-build-settings.webp)\n\n5. Натисніть **Show advanced**, а потім **New variable**, щоб додати свої змінні середовища.\n\n![Додати змінні середовища](/images/netlify-05-env-vars.webp)\n\n6. Натисніть **Deploy site**, зачекайте, поки білд завершиться, і перегляньте свій новий сайт.\n\n## Використання Netlify CLI\n\nДля того, щоб задеплоїти проект із командного рядка, ви повинні спочатку запушити свій проект до репозиторію GitHub і [встановити Netlify CLI](https://docs.netlify.com/cli/get-started/). Ви можете встановити `netlify-cli` як залежність проекту або встановити його глобально на вашому комп'ютері за допомогою наступної команди:\n\n```bash\nnpm i -g netlify-cli\n```\n\nДля того, щоб протестувати свій проект локально, запустіть команду [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) та відкрийте [`localhost :8888`](http://localhost:8888/) для перегляду вашої локально запущеної програми Netlify:\n\n```bash\nntl dev\n```\n\nЗапустіть команду [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment), щоб налаштувати ваш проект:\n\n```bash\nntl init\n```\n\nІмпортуйте змінні середовища вашого проекту з вашого файлу `.env` за допомогою [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):\n\n```bash\nntl env:import .env\n```\n\nЗадеплойте ваш проект за допомогою [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Вам потрібно буде передати прапор `--build`, щоб запустити команду білда перед деплойментом, та прапор `--prod`, щоб задеплоїти на основному URL вашого сайту:\n\n```bash\nntl deploy --prod --build\n```\n\nЩоб переглянути приклад на Netlify, перейдіть на [ct3a.netlify.app](https://ct3a.netlify.app/).\n"
  },
  {
    "path": "www/src/pages/uk/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: Деплоймент на Vercel\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\nМи рекомендуємо деплоїти вашу програму на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Він дозволяє дуже легко деплоїти Next.js програми.\n\n## Конфігурація проекту\n\nШвидше за все Vercel налаштує вашу команду збірки та каталог публікації автоматично. Однак ви також можете уточнити цю інформацію разом з іншими конфігураціями, створивши файл [vercel.json](https://vercel.com/docs/project-configuration) і включивши в нього наступні команди. **У більшості проектів це робити необов'язково.**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## Використання Vercel Dashboard\n\n1. Після відправки вашого коду до репозиторію GitHub зареєструйтесь на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) з GitHub і натисніть **Add New Project**.\n\n![Новий проект на Vercel](/images/vercel-new-project.webp)\n\n2. Імпортуйте репозиторій GitHub із вашим проектом.\n\n![Імпортуйте репозиторій](/images/vercel-import-project.webp)\n\n3. Додайте ваші змінні середовища.\n\n![Додайте ваші змінні середовища](/images/vercel-env-vars.webp)\n\n4. Натисніть **Deploy**. Тепер щоразу, коли ви відправляєте зміни до вашого репозиторію, Vercel автоматично передеплоїть вашу програму!\n\n## Використання Vercel CLI\n\nДля того, щоб задеплоїти програму з командного рядка, вам спочатку потрібно [встановити Vercel CLI глобально](https://vercel.com/docs/cli#installing-vercel-cli).\n\n```bash\nnpm i -g vercel\n```\n\nЗапустіть команду [`vercel`](https://vercel.com/docs/cli/deploying-from-cli), щоб задеплоїти ваш проект.\n\n```bash\nvercel\n```\n\nДодайте `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` для змінних середовища, таких як рядок підключення до бази даних. Використовуйте `--yes`, якщо хочете пропустити питання деплою та дати відповідь за умовчанням для кожного.\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\nПісля першого деплою ця команда задеплоїть зміни у гілку попереднього перегляду. Вам потрібно буде включити `-prod`, щоб відправити зміни безпосередньо на сайт у продакшені для майбутніх деплоїв.\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/uk/examples.mdx",
    "content": "---\ntitle: Приклади\ndescription: Приклади різних існуючих додатків\nlayout: ../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\nimport Form from \"../../components/docs/exampleOptionForm.astro\";\n\nВи можете випробувати різні комбінації технологій, які пропонує create-t3-app.\n\n<Callout type=\"info\">\n  Ви не можете вибрати `prisma` та `drizzle` одночасно.\n</Callout>\n\n<Form />\n\n<Callout type=\"warning\">\n  Деякі функції можуть не працювати, якщо ви не створите файл env\n</Callout>\n"
  },
  {
    "path": "www/src/pages/uk/faq.mdx",
    "content": "---\ntitle: FAQ\ndescription: Найпоширеніші запитання про Create T3 App\nlayout: ../../layouts/docs.astro\nlang: uk\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nЦе деякі часті запитання про `create-t3-app`.\n\n## Що далі? Як я можу створити додаток?\n\nМи намагаємося зробити цей проект якомога простішим, тому ви можете почати з того, що ми налаштували для вас, а потім додавати додаткові вам речі, коли вони стануть вам необхідними.\n\nЯкщо ви не знайомі з різними технологіями, що використовуються в цьому проєкті, зверніться до відповідної документації. Якщо щось усе ще не зрозуміло, приєднуйтесь до нашого [Discord](https://t3.gg/discord) і попросіть допомоги.\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n\n## Як мені тримати свій додаток оновленим?\n\nДодаток Create T3 – це інструмент для будування, а не фреймворк. Це означає, що як тільки ви ініціалізуєте програму, вона стане вашою. Немає жодного інструменту CLI після інсталяції, який би допомагав вам залишатися в курсі подій. Якщо ви хочете відстежувати будь-які вдосконалення, які ми вносимо в шаблон, ви можете [увімкнути сповіщення про випуски](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) у нашому репозиторії. Зважаючи це, насправді не обов'язково вносити кожну зміну, яку ми вносимо в шаблон у вашій програмі.\n\n## Які навчальні ресурси зараз доступні?\n\nНе дивлячись на те, що перераховані нижче ресурси є одними з найкращих для T3 Stack, спільнота (і [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) рекомендує просто почати використовувати стек і вчитися в процесі розробки з його допомогою.\n\nЯкщо ви розглядаєте Create T3 App, швидше за все, ви вже використовували деякі частини стека. То чому б не зануритися в проєкт з головою і не вивчити решту технологій у процесі розробки?\n\nМи розуміємо, що цей шлях не підходить для кожного. Тому, якщо ви відчуваєте, що ви спробували рекомендований шлях і цього недостатньо, і вам все ще потрібні ресурси, або ви просто не впевнені у своїх силах та/або почуваєтесь перевантаженим цим стеком, ознайомтеся з цими приголомшливими навчальними матеріалами щодо Create T3 App:\n\n### Статті\n\nДеякі з них можуть бути застарілими.\n\n- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### Відео\n\n- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(рекомендовано)**\n- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## Чому в проєкті є файли `.js`?\n\nЗгідно з [T3-Аксіомою #3](/uk/introduction#%D1%82%D0%B8%D0%BF%D0%BE%D0%B1%D0%B5%D0%B7%D0%BF%D0%B5%D0%BA%D0%B0-%D0%BD%D0%B5-%D1%94-%D0%BE%D0%BF%D1%86%D1%96%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%8E), ми вважаємо типобезпеку об'єктом першого класу. На жаль, не всі фреймворки та плагіни підтримують TypeScript, тому деякі файли конфігурації мають бути файлами `.js`.\n\nМи намагаємося підкреслити, що ці файли є файлами JavaScript не без причини, явно оголошуючи тип кожного файлу (`cjs` або `mjs`), залежно від того, що підтримується бібліотекою, якою він використовується. Крім того, всі файли `js` у цьому проєкті все ще перевіряються на типи за допомогою коментаря `@ts-check` вгорі.\n\n## У мене не виходить додати i18n до мого додатка. Чи є якісь рекомендації?\n\nМи вирішили не включати i18n за замовчуванням у `create-t3-app`, тому що це дуже суб'єктивна тема, і є багато способів її реалізації.\n\nУ той же час, якщо ви зіткнулися з проблемами під час реалізації та хочете побачити проєкт-зразок, у нас є [посилання на репозиторій](https://github.com/juliusmarminge/t3-i18n), яке показує, як ви можете додати i18n в T3 App за допомогою [next-i18next](https://github.com/i18next/next-i18next).\n\n## Чому ми використовуємо `/pages` а не `/app` з Next.js 13?\n\nЗгідно з [T3-Аксіомою #2](/uk/introduction#%D0%BE%D0%BD%D0%BE%D0%B2%D0%BB%D1%8E%D0%B9%D1%82%D0%B5%D1%81%D1%8C-%D0%B7-%D0%B2%D1%96%D0%B4%D0%BF%D0%BE%D0%B2%D1%96%D0%B4%D0%B0%D0%BB%D1%8C%D0%BD%D1%96%D1%81%D1%82%D1%8E), ми любимо новинки, але цінуємо стабільність, вам буде складно перенести весь маршрутизатор, [не найкраще місце для експериментів](https://youtu.be/mnwUbtieOuI?t=1662). Хоча `/app` [являє собою погляд у майбутнє](https://youtu.be/rnsC-12PVlM?t=818), він ще не готовий до використання в продакшені; API перебуває в бета-версії, і очікується, що він матиме зворотно несумісні зміни.\n\n<Callout type=\"info\">\n  Список підтримуваних, запланованих і тих, що перебувають у розробці, функцій у\n  каталозі `/app` можна знайти в [бета-документації\n  Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n</Callout>\n"
  },
  {
    "path": "www/src/pages/uk/folder-structure-pages.mdx",
    "content": "---\ntitle: Файлова структура (Pages)\ndescription: Файлова структура нового T3 додатка\nlayout: ../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\nБудь ласка, виберіть пакети, щоб побачити файлову структуру нового додатка з обраними пакетами. Нижче ви знайдете опис кожного елемента.\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\nПапка `prisma` містить файл `schema.prisma`, який використовується для налаштування з'єднання з базою даних і схеми бази даних. Також це місце для зберігання файлів міграції та/або сценаріїв заповнення, якщо вони використовуються. Дивіться [Використання Prisma](/uk/usage/prisma) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `public`\n\nПапка `public` містить статичні файли, які обслуговуються веб-сервером. Файл `favicon.ico` - це приклад статичного файлу.\n\n</div>\n<div>\n\n### `src/env`\n\nВикористовується для перевірки змінних оточення і визначення типів - дивіться [Змінні оточення](/uk/usage/env-variables).\n\n</div>\n<div>\n\n### `src/pages`\n\nПапка `pages` містить усі сторінки додатка Next.js. Файл `index.tsx` у кореневій папці `/pages` є домашньою сторінкою додатка. Файл `_app.tsx` використовується для обертання додатка провайдерами. Дивіться [документацію Next.js](https://nextjs.org/docs/basic-features/pages) для отримання додаткової інформації.\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\nПапка `api` містить усі маршрути API додатка Next.js. Файл `examples.ts` (з Prisma) містить приклад маршруту, який використовує функцію [Next.js API route](https://nextjs.org/docs/api-routes/introduction) разом із Prisma. Файл `restricted.ts` (з Next-Auth) містить приклад маршруту, який використовує функцію [Next.js API route](https://nextjs.org/docs/api-routes/introduction) і захищений за допомогою [NextAuth.js](https://next-auth.js.org/).\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\nФайл `[...nextauth].ts` - це slug-маршрут NextAuth.js для аутентифікації. Він використовується для обробки запитів аутентифікації. Дивіться [Використання NextAuth.js](/uk/usage/next-auth) для отримання додаткової інформації про NextAuth.js і [документацію Next.js про динамічні маршрути](https://nextjs.org/docs/routing/dynamic-routes) для отримання інформації про маршрути catch-all/slug.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\nФайл `[trpc].ts` - це точка входу tRPC API. Він використовується для обробки запитів tRPC. Дивіться [Використання tRPC](/uk/usage/trpc#-pagesapitrpctrpcts) для отримання додаткової інформації про цей файл і [документацію Next.js про динамічні маршрути](https://nextjs.org/docs/routing/dynamic-routes) для отримання інформації про маршрути catch-all/slug.\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\nПапка `server` використовується для чіткого поділу серверного коду від клієнтського коду.\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\nМістить утиліти для автентифікації, такі як отримання сесії користувача на стороні сервера. Дивіться [Використання NextAuth.js](/uk/usage/next-auth#usage-with-trpc) для отримання додаткової інформації.\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\nФайл `db.ts` використовується для створення клієнта Prisma на глобальному рівні. Дивіться [Використання Prisma](/uk/usage/prisma#prisma-client) і [кращі практики по використанню Prisma з Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) для отримання додаткової інформації.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\nПапка `api` містить серверний код tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\nПапка `routers` містить усі ваші під-маршрутизатори tRPC.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\nФайл `example.ts` - це приклад маршрутизатора tRPC, який використовує допоміжну функцію `publicProcedure` для демонстрації того, як створити публічний маршрут tRPC.\n\nБазуючись на обраних вами пакетах, цей маршрутизатор містить більше або менше маршрутів для кращого демонстрування використання ваших потреб.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\nФайл `trpc.ts` - це основний файл конфігурації для вашого tRPC-бекенду. У ньому ми:\n\n1. Визначаємо контекст, який використовується в запитах tRPC. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapitrpcts) для отримання додаткової інформації.\n2. Експортуємо допоміжні функції процедур. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapitrpcts) для отримання додаткової інформації.\n\n</div>\n\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nФайл `root.ts` використовується для мерджу маршрутизаторів tRPC і експорту їх як єдиного маршрутизатора, а також визначення типу маршрутизатора. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapirootts) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `src/styles`\n\nПапка `styles` містить глобальні стилі додатка.\n\n</div>\n<div data-components=\"nextauth\">\n\n### `src/types`\n\nПапка `types` використовується для зберігання повторно використовуваних типів або оголошень типів.\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/types/next-auth.d.ts`\n\nФайл `next-auth.d.ts` використовується для розширення типу сесії за замовчуванням NextAuth на включення ідентифікатора користувача. Дивіться [Використання NextAuth.js](/uk/usage/next-auth#включення-userid-в-сеанс) для отримання додаткової інформації.\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\nПапка `utils` використовується для зберігання повторно використовуваних функцій утиліт.\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\nФайл `api.ts` є точкою входу для tRPC на стороні клієнта. Дивіться [Використання tRPC](/uk/usage/trpc#-utilsapits) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `.env`\n\nФайл `.env` використовується для зберігання змінних середовища. Дивіться [Змінні середовища](/uk/usage/env-variables) для отримання додаткової інформації. Цей файл **не** повинен бути доданий в історію git.\n\n</div>\n<div>\n\n### `.env.example`\n\nФайл `.env.example` показує приклад змінних середовища на основі обраних бібліотек. Цей файл має бути доданий в історію git.\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\nФайл `.eslintrc.cjs` використовується для налаштування ESLint. Дивіться [документацію ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\nФайл `next-env.d.ts` гарантує, що типи Next.js будуть виявлені компілятором TypeScript. **Ви не повинні видаляти його або редагувати, оскільки він може змінитися в будь-який час.** Дивіться [документацію Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `next.config.mjs`\n\nФайл `next.config.mjs` використовується для налаштування Next.js. Дивіться [Документацію Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) для отримання додаткової інформації. Примітка: Розширення .mjs використовується для дозволу імпорту ESM.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\nФайл `postcss.config.js` використовується для використання Tailwind PostCSS. Дивіться [документацію Taiwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) для отримання додаткової інформації.\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\nФайл `prettier.config.mjs` використовується для налаштування Prettier для ввімкнення prettier-plugin-tailwindcss для форматування класів Tailwind CSS. Дивіться [пост блогу Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) для отримання додаткової інформації.\n\n</div>\n<div>\n\n### `tsconfig.json`\n\nФайл `tsconfig.json` використовується для налаштування TypeScript. Деякі значення за замовчуванням, такі як `strict mode`, були увімкнені для забезпечення кращого використання TypeScript для create-t3-app та його бібліотек. Дивіться [документацію TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) або [Використання TypeScript](usage/typescript) для отримання додаткової інформації.\n\n</div>\n<div>\n### `drizzle.config.ts`\n\nФайл `drizzle.config.ts` використовується для налаштування drizzle kit. Дивіться [документацію](https://orm.drizzle.team/kit-docs/config-reference) для отримання додаткової інформації.\n\n</div>\n"
  },
  {
    "path": "www/src/pages/uk/installation.mdx",
    "content": "---\ntitle: Встановлення\ndescription: Інструкції зі встановлення Create T3 App\nlayout: ../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\nДля створення додатка за допомогою `create-t3-app`, запустіть одну з наступних трьох команд і дайте відповідь на запитання командного рядка:\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\nПісля того, як додаток буде створено, ознайомтеся з [першими кроками](/uk/usage/first-steps), щоб почати роботу над вашим новим додатком.\n\n## Додаткові параметри\n\n| Опції/Флаги       | Опис                                                               |\n| ----------------- | ------------------------------------------------------------------ |\n| `[dir]`           | Додання аргументу з директорії з ім'ям проекту                     |\n| `--noGit`         | Повідомлення CLI не ініціалізувати новий git репозиторій у проекті |\n| `-y`, `--default` | Створення нового t3-додатку з дефолтними параметрами               |\n| `--noInstall`     | Генерація проекту без встановлення залежностей                     |\n\n## Експериментальне використання\n\nДля нашого CI ми маємо деякі експериментальні прапори, які дають змогу створювати будь-який додаток без будь-яких запитів. Якщо це стосується вашого випадку, ви можете використовувати ці прапори. Зверніть увагу, що ці прапори є експериментальними і можуть змінитися в майбутньому без зміни версії.\n\n| Опції/Флаги  | Опис                                            |\n| ------------ | ----------------------------------------------- |\n| `--CI`       | Повідомлення CLI, що ви перебуваєте в режимі CI |\n| `--trpc`     | Додавання tRPC у проєкт                         |\n| `--prisma`   | Додавання Prisma у проєкт                       |\n| `--nextAuth` | Додавання NextAuth у проєкт                     |\n| `--tailwind` | Додавання Tailwind CSS у проєкт                 |\n\n<Callout type=\"warning\">\n  Якщо ви не вказуєте прапор `CI`, то інші прапори не мають ефекту.\n</Callout>\n\nВам не потрібно явно відмовлятися від пакетів, які вам не потрібні. Однак, якщо ви віддаєте перевагу бути точним, ви можете передати `false`, наприклад `--nextAuth false`.\n\n### Приклад\n\nНаступний приклад створить додаток T3 з tRPC і Tailwind CSS.\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/uk/introduction.md",
    "content": "---\ntitle: Вступ\ndescription: Вступ в T3 стек\nlayout: ../../layouts/docs.astro\nlang: uk\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\n_\"T3 Stack\"_ - це стек веб-розробки, створений [Theo](https://twitter.com/t3dotgg), з упором на простоту, модульність і full-stack типобезпека.\n\nОсновні частини - [**Next.js**](https://nextjs.org/) і [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) майже завжди включені. Якщо ви робите щось, що нагадує бекенд, [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), і [**NextAuth.js**](https://next-auth.js.org/) - чудові доповнення.\n\nВи могли помітити, що тут... багато частин. Це зроблено наміренно. Змінюйте частини залежно від ваших потреб - цей стек є модульним за своєю суттю :)\n\n## І... що таке create-t3-app? Шаблон?\n\nЩось типу? `create-t3-app` - це CLI, створений досвідченими розробниками T3 стека, щоб спростити налаштування модульного додатка T3 стека. Це означає, що кожна частина є необов'язковою, і \"шаблон\" генерується на основі ваших конкретних потреб.\n\nПісля безлічі проєктів і багатьох років із цією технологією у нас є безліч думок та інсайтів. Ми постаралися зафіксувати їх у цьому CLI.\n\nЦе **НЕ** всеосяжний шаблон. Ми **очікуємо**, що ви будете використовувати свої власні бібліотеки, які вирішують потреби **ВАШОГО** додатка. Хоча ми не хочемо призначати рішення для більш конкретних проблем, таких як управління станом і деплоймент, ми [маємо деякі рекомендації, перераховані тут](/uk/other-recs).\n\n## Аксіоми T3\n\nБудемо чесними - це _суб'єктивний проєкт_. Ми поділилися кількома основними переконаннями навколо створення і розглядаємо їх як основу для наших рішень.\n\n### Вирішуйте проблеми\n\nЛегко потрапити в пастку \"додавання всього\" - ми явно не хочемо цього робити. Усе, що додається в `create-t3-app`, повинно вирішувати конкретну проблему, яка існує в основних технологіях, включених до нього. Це означає, що ми не додамо бібліотеки менеджменту стану (`zustand`, `redux`), але ми додамо NextAuth.js та інтегруємо Prisma і tRPC для вас.\n\n### Оновлюйтесь з відповідальністю\n\nМи любимо технологічні новинки. Швидкість і, будемо чесними, приколів від нових фіговін, дійсно круті. Ми вважаємо важливим використовувати їх відповідально, використовуючи більш ризиковані технології в менш ризикованих частинах. Це означає, що ми не будемо ⛔️ робити ставку на ризиковану нову технологію бази даних (SQL - це здорово!). Але ми із задоволенням ✅ зробимо ставку на tRPC, оскільки це просто функції, які легко замінити.\n\n### Типобезпека не є опціональною\n\nЗазначена мета Create T3 App - це надати найшвидший спосіб розпочати новий повнофункціональний, **типобезпечний** веб-додаток. Ми серйозно ставимося до типобезпеки в цих частинах, оскільки вона підвищує нашу продуктивність і допомагає нам створювати менше багів. Будь-яке рішення, яке знижує типобезпеку Create T3 App, це рішення, яке повинно бути прийнято в іншому проекті.\n"
  },
  {
    "path": "www/src/pages/uk/other-recs.md",
    "content": "---\ntitle: Додаткові рекомендації\ndescription: Бібліотеки та сервіси, які ми рекомендуємо для багатьох проектів\nlayout: ../../layouts/docs.astro\nlang: uk\n---\n\nМи розуміємо, що бібліотеки, включені до `create-t3-app`, не вирішують кожну проблему. Хоча ми рекомендуємо розпочати свій проект з того, що ми надаємо, настане час, коли вам потрібно буде встановити інші пакети. Тільки ви можете знати, чого потребує ваш проект, але ось деякі рішення, які ми часто рекомендуємо.\n\nЦе рекомендації окремих учасників Create T3 App і не повинні розглядатись як \"офіційні\" рекомендації команди Create T3 App або T3-OSS. _**Будь ласка, проведіть власне дослідження, особливо перед тим, як прив'язуватись до платних сервісів**_.\n\n## Управління станом\n\n_**Примітка редактора**_: Бібліотеки керування станом можуть бути відмінними, але часто не потрібні. tRPC's хуки React Query повинні впоратися із вашим серверним станом. Для клієнтського стану почніть з `useState` React, і зверніться до одного з цих варіантів, коли вам буде потрібно більше.\n\n### Zustand\n\n**Для того, щоб більше ніколи не використовувати Redux**\n\n\"Сучасний простий Redux\", який ви не знали, що вам потрібен. [Poimandres](https://github.com/pmndrs) завжди можна довіряти. Ви можете створювати все, від відеодзвінків до ігор та серверів із цією маленькою бібліотекою.\n\n- [Головна Zustand](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**Для того, щоб більше ніколи не використовувати Context**\n\nJotai важко перевершити в підході Atomic. Також від [Poimandres](https://github.com/pmndrs), Jotai дозволяє визначати сінгелтони, які здаються глобальними useState. Відмінний варіант для станів, які не вимагають стейт машини прямо зараз.\n\n- [Головна Jotai](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## Бібліотеки компонентів\n\nБільшість додатків потребують однакову низку компонентів: перемикачі, меню, модальні вікна і т.д. Ці бібліотеки надають відмінні, доступні компоненти, які ви можете використовувати та налаштовувати на свій розсуд.\n\n### Бібліотеки компонентів без стилів\n\nТакож відомі як headless бібліотеки, вони надають відмінні, нестилізовані та доступні компоненти, які ви можете налаштувати на свій розсуд. Ось кілька рекомендацій.\n\n- [Radix UI](https://www.radix-ui.com/) надає потужний набір зручних і доступних примітивів, які ви можете стилізувати за допомогою звичайного CSS або Tailwind CSS.\n\n- [Headless UI](https://headlessui.com/) від команди Tailwind CSS також надає нестилізовані, доступні компоненти, які бездоганно інтегруються з Tailwind CSS.\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) надає доступні примітивні налаштування UI для вашої системи дизайну. Їхній компонент вибору дати - це найвищий рівень.\n\n### Бібліотеки компонентів зі стилями\n\n**Коли вам просто потрібно, щоб ваш додаток виглядав непогано**\n\nІноді ви створюєте проект, де вам просто потрібно, щоб інтерфейс користувача виглядав від початку. Для адміністративних панелей управління та інших подібних проектів будь-яка з цих бібліотек компонентів упорається з цим завданням.\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**Для створення бібліотек інтерфейсу користувача**\n\nДекларативно створюйте бібліотеку інтерфейсу користувача з різними кольоровими, розмірними і т.д. варіантами. Коли ваш проект досягає масштабу, де вам потрібен стандартизований набір компонентів інтерфейсу користувача з кількома варіантами з використанням Tailwind CSS, CVA - відмінний інструмент.\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## Анімації\n\nНаші рекомендації для створення анімацій у вашому додатку.\n\n### AutoAnimate\n\n**Для анімацій з одним рядком коду**\n\nБільшість бібліотек анімації намагаються задовольнити кожен можливий випадок використання і стають громіздкими. AutoAnimate – це інструмент без конфігурації, який дасть вам значне покращення UX без додаткових зусиль розробника.\n\n- [Головна AutoAnimate](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [Компонент для AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**Для складних анімацій із декларативним кодом**\n\nFramer Motion надає простий, декларативний синтаксис і дозволяє писати менше коду для створення всього: від складних анімацій і навіть до жестів.\n\n- [Головна Framer Motion](https://framer.com/motion)\n- [Документація Framer Motion](https://www.framer.com/docs/)\n\n## Деплоймент, інфраструктура, бази даних і CI\n\n### Vercel\n\n**Для хостинга вашого додатка**\n\nVercel позбавив нас болю при деплойменті веб-додатків, зробивши його простою інтеграцією з GitHub, яку можна встановити і забути. Ми без проблем масштабувалися до сотень тисяч користувачів. Він працює на AWS, але має набагато кращий інтерфейс :)\n\n- [Головна Vercel](https://vercel.com/)\n- [Гайд із деплою T3 додатка на Vercel](/uk/deployment/vercel)\n\n### PlanetScale\n\n**Для баз даних без занепокоєння**\n\nPlanetScale - найкраща serverless платформа для баз даних, яку ми використовували. Неймовірна масштабованість, чудовий DX і фантастична ціна. Якщо ви використовуєте SQL (і, сподіваюся, Prisma), це важко перевершити.\n\n- [Головна PlanetScale](https://planetscale.com/)\n\n### Railway\n\n**Для розміщення вашої інфраструктури**\n\n\"Сучасний Heroku\". Найпростіший спосіб запустити реальний сервер. Якщо вам не вистачає функціоналу Vercel і PlanetScale, то Railway, ймовірно, вам підійде. Вкажіть його на репозиторій GitHub і готово.\n\n- [Головна Railway](https://railway.app/)\n\n### Upstash\n\n**Для serverless Redis**\n\nМи любимо Prisma і PlanetScale, але деякі проєкти вимагають більш продуктивного рішення. Upstash дає вам змогу отримати in-memory продуктивність Redis у вашому безсерверному проєкті, не переймаючись самостійним управлінням інфраструктурою та масштабуванням.\n\n- [Головна Upstash](https://upstash.com/)\n\n### Pusher\n\n**Для безсерверних WebSocket-ів**\n\nЯкщо WebSocket є основним фокусом вашого проекту, ви можете розглянути більш традиційний бекенд, такий як [Fastify](https://www.fastify.io/) (який [також працює з tRPC!](https://trpc.io/docs/v10/fastify)). Але для швидкого додавання WebSocket у T3 App, Pusher - чудовий вибір.\n\n- [Головна Pusher](https://pusher.com/)\n\n### Soketi\n\nSoketi - це самодостатня, проста і швидка альтернатива Pusher. Він повністю сумісний з Pusher SDK, який ви можете використовувати для підключення до сервера. Soketi serverless також перебуває в бета-версії.\n\n- [Головна Soketi](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## Аналітика\n\nКористувацькі дані дуже цінні, коли ви створюєте додаток. Ось кілька рекомендованих провайдерів аналітики.\n\n### Plausible\n\nПотрібна аналітика? Plausible - один із найшвидших способів її отримати. Супер мінімалістичний. У нього навіть є [простий плагін для Next.js](https://plausible.io/docs/proxy/guides/nextjs).\n\n- [Головна Plausible](https://plausible.io/)\n\n### Umami\n\nUmami - це самодостатня, проста, швидка і конфіденційна альтернатива Google Analytics. Ви можете легко задеплоїти його на Vercel, Railway і т.д. з PlanetScale як базою даних.\n\n- [Головна Umami](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n- [Umami Cloud](https://cloud.umami.is/)\n\n## Інше\n\n### Next Bundle Analyzer\n\nБуває складно визначити, що буде включено до збірки вихідних даних для вашого додатка. Next Bundle Analyzer - це простий спосіб візуалізувати й аналізувати JavaScript-бандли, які генеруються.\n\n- [@next/bundle-analyzer на npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/uk/t3-collection.mdx",
    "content": "---\ntitle: T3 колекція\ndescription: Круті open source проекти та компанії, що використовують T3 стек\nlayout: ../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\n\nЗробили проект, що використовує T3 стек і хочете поділитися ним? Додайте його до списку!\n\n## Open Source програми зроблені з використанням T3 стека\n\n<OpenSourceAppList\n  descriptionIntl=\"Опис\"\n  repoIntl=\"Посилання\"\n  linkIntl=\"Посилання\"\n/>\n\n## Компанії використовують T3 стек\n\nНам би дуже хотілося дізнатися про компанії, які використовують T3 стек для своїх додатків. Ваша компанія використовує стек T3 і ви хочете поділитися цим? Додайте її до списку!\n\n<CompanyList companyIntl=\"Опис\" linkIntl=\"Посилання\" />\n\n<Callout type=\"tip\">\n  Є крутий проект, що використовує T3 стек? Зробіть [pull\n  request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)\n  та додайте його до списку!\n</Callout>\n"
  },
  {
    "path": "www/src/pages/uk/usage/drizzle.mdx",
    "content": "---\ntitle: Drizzle\ndescription: Використання Drizzle\nlayout: ../../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\n<Callout type=\"info\">\n  Опція `drizzle` є новим додатком и жодні документи ще не були написані. Ми\n  будемо раді вашим внескам!\n</Callout>\n"
  },
  {
    "path": "www/src/pages/uk/usage/env-variables.mdx",
    "content": "---\ntitle: Змінні середовища\ndescription: Початок роботи з Create T3 App\nlayout: ../../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App використовує власний пакет [@t3-oss/env-nextjs](https://env.t3.gg) разом із [Zod](https://github.com/colinhacks/zod) для валідації змінних середовища під час виконання _та_ під час збирання, надаючи просту логіку у файлі `src/env.js`:\n\n## env.js\n\n_TLDR; Якщо ви хочете додати нову змінну середовища, вам слід додати валідатор до `src/env.js`, а потім пару ключ-значення в `.env`._\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env використовує `createEnv`, який відповідає за створення схеми і буде включати головну логіку валідації для клієнтських і серверних змінних середовища.\n\n<Callout type=\"info\">\n  Для отримання додаткової інформації про те, як `createEnv` працює зсередини,\n  подивіться документацію [T3 Env](https://env.t3.gg/docs/introduction) (EN)\n</Callout>\n\n## Використання змінних середовища\n\nКоли ви хочете використовувати змінні середовища, ви можете імпортувати їх із `env.js` і використовувати їх так, як ви зазвичай використовували б. Якщо ви імпортуєте цей файл на стороні клієнта і спробуєте отримати серверну змінну, ви отримаєте помилку виконання:\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` is fully typesafe and provides autocompletion\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ This will throw a runtime error\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ This is fine\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\nЧерез те, що файл `.env` за замовчуванням не додається до системи контролю версій, ми також додали файл `.env.example`, в якому ви можете за бажанням зберегти копію вашого файлу `.env` з видаленими secrets. Це необов'язково, але ми рекомендуємо тримати приклад в актуальному стані, щоб зробити процес налаштування середовища для нових учасників проекту якомога простішим.\n\nДеякі фреймворки та інструменти збірки, такі як Next.js, пропонують зберігати secrets у файлі `.env.local` і коммітити файли `.env` у ваш проект. Це не рекомендується, оскільки це може полегшити випадковий комміт secrets у ваш проект. Натомість ми рекомендуємо зберігати secrets в `.env`, тримати ваш файл `.env` в `.gitignore` і коммітити лише файли `.env.example` у ваш проект.\n\n## Додавання змінних середовища\n\nДля того, щоб переконатися, що ваша збірка ніколи не завершиться без змінних середовища, які проєкт вимагає, вам потрібно додати нові змінні середовища в **двох** місцях:\n\n📄 `.env`: Введіть змінну середовища, як зазвичай робите у файлі `.env`, тобто `KEY=VALUE`\n\n📄 `env.js`: Додайте відповідну логіку валідації для змінних середовища, визначивши для кожної з них Zod схему всередині `createEnv`, наприклад `KEY: z.string()`. Крім цього, переконайтеся в тому, що ви деструктурували їх в опції `runtimeEnv`, наприклад `KEY: process.env.KEY`.\n\n<Callout type=\"info\">\n  Навіщо потрібно деструктурувати змінні середовища всередині `runtimeEnv`? Це\n  пов'язано з тим, як Next.js збирає змінні середовища в деяких рантаймах.\n  Деструктуруючи їх вручну, ми гарантуємо, що ці змінні не будуть прибрані з\n  фінальної збірки.\n</Callout>\n\nОпціонально, ви також можете оновлювати файл `.env.example`:\n\n📄 `.env.example`: Введіть вашу змінну середовища, але переконайтеся, що не включаєте значення, якщо воно є секретним, тобто `KEY=VALUE` або `KEY=`.\n\n### Приклад\n\n_Я хочу додати мій Twitter API токен як змінну середовища на стороні сервера_\n\n1. Додайте змінну середовища в `.env`:\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. Додайте змінну середовища в `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n  runtimeEnv: {\n    // ...\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n\n3. _Опціонально:_ Додайте змінну середовища в `.env.example`, але не включайте токен в `runtimeEnv`.\n\n```\nTWITTER_API_TOKEN=\n```\n\n## Type Coercion\n\nУсі змінні які ви додаєте до `.env` будуть импортовані як рядки, навіть якщо їх значення має представляти інший тип. Якщо ви хочете використовувати ваші змінні середовища як інший тип під час рантайму, ви можете використовувати `coerce` з Zod для конвертації рядків в тип, який ви хочете. Це викине помилку, якщо конвертація не вдасться.\n\nДодайте змінну до вашого `.env`:\n\n```\nSOME_NUMBER=123\nSOME_BOOLEAN=true\n```\n\nПотім, провалідуйте їх в `env.js`:\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    SOME_NUMBER: z.coerce.number(),\n    SOME_BOOLEAN: z.coerce.boolean(),\n  },\n  // ...\n  runtimeEnv: {\n    SOME_NUMBER: process.env.SOME_NUMBER,\n    SOME_BOOLEAN: process.env.SOME_BOOLEAN,\n  },\n});\n```\n"
  },
  {
    "path": "www/src/pages/uk/usage/first-steps.md",
    "content": "---\ntitle: Перші кроки\ndescription: Початок роботи з вашим новим T3 App\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\nВи щойно створили новий додаток T3 і готові до роботи. Ось мінімум для запуску вашої програми.\n\n## База даних\n\n### MySQL, PostgreSQL\n\nЯкщо ви обираєте MySQL або PostgreSQL як свою базу даних, ваше T3 додаток буде починатись з `start-database.sh` bash-скриптом, який може створити контейнер Docker з базою даних для локальної розробки. Якщо у вас вже є база даних, ви можете видалити цей файл і вказати свої облікові дані для бази даних в `.env`. На macOS ви також можете використовувати [DBngin](https://dbngin.com/), якщо ви не хочете використовувати Docker.\n\n### Prisma\n\nЯкщо ваш додаток включає Prisma, переконайтеся, що ви запустили `npx prisma db push` з кореневої директорії вашої програми. Ця команда синхронізує схему Prisma з вашою базою даних і генерує типи TypeScript для Prisma Client на основі вашої схеми. Зверніть увагу, що вам потрібно [перезапустити сервер TypeScript](https://tinytip.co/tips/vscode-restart-ts/) після цього, щоб він міг виявити згенеровані типи.\n\n### Drizzle\n\nЯкщо ваш додаток включає в себе Drizzle, перевірте `.env` файл для інструкцій щодо побудови вашої змінної середовища `DATABASE_URL`. Як тільки ваш файл середовища готовий, запустіть `pnpm db:push` (або еквівалент для інших менеджерів пакетів), щоб відправити вашу схему.\n\n## Аутентифікація\n\nЯкщо ваш додаток включає NextAuth.js, ми починаємо з `DiscordProvider`. Це один з найпростіших провайдерів, пропонований NextAuth.js, однак він все ще вимагає певного початкового налаштування з вашого боку.\n\nЗвичайно, якщо ви віддаєте перевагу використанню іншого провайдера автентифікації, ви також можете використати один із [багатьох провайдерів](https://next-auth.js.org/providers/), які пропонує NextAuth.js.\n\n1. Вам потрібен обліковий запис Discord, тому зареєструйтеся, якщо ще не зареєструвалися.\n2. Перейдіть на https://discord.com/developers/applications і натисніть \"New Application\" у правому верхньому куті. Дайте вашому додатку ім'я та погодьтеся з Умовами використання.\n3. Коли ви створите додаток, перейдіть до \"Settings → OAuth2 → General\".\n4. Скопіюйте \"Client ID\" і додайте його у ваш `.env` як `AUTH_DISCORD_ID`.\n5. Натисніть \"Reset Secret\", скопіюйте новий secret і додайте його у ваш `.env` як `AUTH_DISCORD_SECRET`.\n6. Натисніть \"Add Redirect\" і введіть `http://localhost:3000/api/auth/callback/discord`.\n   - Для деплойменту в продакшені дотримуйтесь попередніх кроків для створення іншого додатка Discord, але цього разу замініть `http://localhost:3000` на URL, на який ви деплоїте.\n7. Збережіть зміни.\n\nТепер у вас має бути можливість увійти в систему.\n\n## Сетап едітора\n\nНаступні розширення рекомендуються для оптимального досвіду розробки. Нижче наведені посилання на підтримку плагінів для редактора.\n\n- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)\n- [Prettier Extension](https://prettier.io/docs/en/editors.html)\n\n## Наступні кроки\n\n- Якщо ваш додаток включає tRPC, ознайомтеся з `src/pages/index.tsx` і `src/server/trpc/router/post.ts`, щоб дізнатися, як працюють запити tRPC.\n- Подивіться на документацію `create-t3-app`, а також на документацію пакетів, які включає ваш додаток.\n- Приєднуйтесь до нашого [Discord](https://t3.gg/discord) і поставте зірку на [GitHub](https://github.com/t3-oss/create-t3-app)! :)\n"
  },
  {
    "path": "www/src/pages/uk/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Використання\",\n  layout: \"docs\",\n  description: \"Навчіться використовувати різні технології з T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/uk/usage/next-auth.mdx",
    "content": "---\ntitle: NextAuth.js\ndescription: Використання NextAuth.js\nlayout: ../../../layouts/docs.astro\nlang: uk\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nКоли ви хочете мати систему автентифікації у вашому додатку Next.js, NextAuth.js - чудове рішення, щоб не морочитися з реалізацією складної безпеки самостійно. Він має великий список провайдерів для швидкого додавання аутентифікації OAuth і надає адаптери для багатьох баз даних і ORM.\n\n## Провайдер контексту\n\nУ точці входу вашого додатка ви побачите, що ваш додаток загорнутий у [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\nЦей провайдер контексту дає змогу вашому застосунку отримати доступ до даних сесії з будь-якого місця вашого застосунку, не передаючи їх як пропси:\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n     // Handle unauthenticated state, e.g. render a SignIn component\n     return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## Отримання сесії на сервері\n\nІноді вам може знадобитися запросити сесію на сервері. Щоб зробити це, попередньо отримайте сесію за допомогою функції-помічника `getServerAuthSession`, яку надає `create-t3-app`, і передайте її на клієнт за допомогою `getServerSideProps`:\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // NOTE: `session` wont have a loading state since it's already prefetched on the server\n\n  ...\n}\n```\n\n## Включення `user.id` у сесію\n\nCreate T3 App налаштований для використання [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) у конфігурації NextAuth.js для включення ID користувача в об'єкт`session`.\n\n```ts:pages/api/auth/[...nextauth].ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\nЦе пов'язано з файлом оголошення типів, щоб переконатися, що `user.id` типізовано під час доступу до об'єкта `session`. Детальніше про [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) у документації NextAuth.js.\n\n```ts:types/next-auth.d.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  інтерфейс Session {\n    user? {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\nТакий самий шаблон може бути використаний для додавання будь-яких інших даних в об'єкт `session`, наприклад, поля `role`, але **ним не слід зловживати для зберігання конфіденційних даних** на клієнті.\n\n## Використання з tRPC\n\nПри використанні NextAuth.js з tRPC ви можете повторно створити використовувані, захищені процедури за допомогою [middleware](https://trpc.io/docs/v10/middlewares). Це дозволяє вам створювати процедури, які можуть бути доступні тільки автентифікованим користувачам. `create-t3-app` налаштовує все це для вас, дозволяючи вам легко отримувати доступ до сесії об’єкта в аутентифікованих процедурах.\n\nЦе робиться в два кроки:\n\n1. Викликайте сесію із заголовків запиту за допомогою функції [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Перевага використання `getServerSession` замість звичайного `getSession` полягає в тому, що це серверна функція і вона не викликає непотрібних викликів fetch. `create-t3-app` створює допоміжну функцію, яка абстрагує це конкретне API щоб вам не треба було імпортувати обидва ваших NextAuth.js варіанти так як і `getServerSession` функцію кожного разу коли вам треба отримати доступ до сесії.\n\n```ts:server/auth.ts\nexport const getServerAuthSession = async (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return await getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\nВикористовуючи цю допоміжну функцію, ми можемо отримати сесію та передати її в контексті tRPC:\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. Створіть tRPC middleware, яке перевіряє, аутентифіковано чи користувач. Потім ми використовуємо middleware в `protectedProcedure`. Будь-який виклик процедур повинен бути автентифікований, інакше буде сгенерована помилка, яку можна правильно опрацювати на стороні клієнта.\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) =>  {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // infers the `session` as non-nullable\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n})\n```\n\nОб'єкт сесії - це легке, мінімальне представлення користувача і містить лише кілька полів. При використанні `protectedProcedures` у вас є доступ до ідентифікатора користувача, який можна використовувати для отримання більшої кількості даних з бази даних.\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## Використання з Prisma\n\nЩоб змусити NextAuth.js і Prisma працювати разом, необхідна велика кількість [початкових налаштувань](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` виконує все це для вас, і якщо ви виберете одночасно і Prisma, і NextAuth.js, ви отримаєте повністю працюючу систему аутентифікації з усіма попередньо вбудованими, необхідними моделями. Ми надаємо вашому сгенерованому додатку попередньо вбудований провайдер Discord OAuth, який ми вибрали тому, що з ним легше всього почати – просто введіть свої токени в `.env` і ви готові до роботи. Однак ви можете легко додати більше провайдерів, слідуючи [докуменації NextAuth.js](https://next-auth.js.org/providers/). Зверніть увагу, що деякі провайдери вимагають додаткових полів для додавання в певні моделі. Ми рекомендуємо вам прочитати документацію для провайдера, який ви хочете використовувати, щоб переконатися, що у вас є всі необхідні поля.\n\n### Додавання нових полів у ваші моделі\n\nКоли ви додаєте нові поля до будь-якої з моделей `User`, `Account`, `Session` або `VerificationToken` (у більшості випадків вам потрібно лише змінити модель `User`), вам потрібно мати на увазі, що [адаптер Prisma](https://next-auth.js.org/adapters/prisma) автоматично створює поля в цих моделях при реєстрації нових користувачів та вході до системи. Тому, додаючи нові поля до цих моделей, ви повинні надати значення за замовчуванням для них, оскільки адаптер не знає про них.\n\nЯкщо, наприклад, ви хочете додати `role` у модель `User`, вам потрібно буде надати значення за замовчуванням для поля `role`. Це робиться шляхом додавання значення `@default` до поля `role` у моделі `User`:\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## Використання з Next.js middleware\n\nВикористання NextAuth.js з Next.js middleware [вимагає використання стратегії сеансу JWT](https://next-auth.js.org/configuration/nextjs#caveats) для автентифікації. Це пов'язано з тим, що middleware може отримати доступ до сесійного cookie тільки в тому випадку, якщо це JWT. За замовчуванням, create-t3-app налаштований на використання **default** стратегії бази даних, у поєднанні з Prisma як адаптера бази даних.\n\n<Callout type=\"warning\">\n  Використання сесій баз даних - рекомендований підхід, й вам варто почитати про\n  JWT перед тим як переходити до стратегії JWT сесії, щоб уникнути будь-яких\n  проблем з безпекою.\n</Callout>\n\nПісля переходу до стратегії JWT сесії, переконайтеся, що ви оновили `session` колбек в `src/server/auth.ts`.\n\nОб'єкт `user` буде `undefined`. Замість цього, витягніть ID користувача з об'єкту `token`.\n\nНаприклад:\n\n```diff:server/auth.ts\n  export const authOptions: NextAuthOptions = {\n+   session: {\n+     strategy: \"jwt\",\n+   },\n    callbacks: {\n-     session: ({ session, user }) => ({\n+     session: ({ session, token }) => ({\n        ...session,\n        user: {\n          ...session.user,\n-         id: user.id,\n+         id: token.sub,\n        },\n      }),\n    },\n  }\n```\n\n## Налаштовуємо DiscordProvider за замовчуванням\n\n1. Перейдіть до розділу Applications у [Discord Developer Portal](https://discord.com/developers/applications) і натисніть \"New Application\"\n2. У меню налаштувань перейдіть до \"OAuth2 => General\"\n\n- Скопіюйте Client ID і вставте його в `AUTH_DISCORD_ID` у `.env`.\n- Біля Client Secret натисніть \"Reset Secret\" і скопіюйте цей рядок у `AUTH_DISCORD_SECRET` у `.env`. Будьте обережними, оскільки ви більше не зможете побачити цей secret, і скидання його призведе до того, що існуючий протермінується.\n- Натисніть \"Add Redirect\" і вставте `<app url>/api/auth/callback/discord` (приклад для локальної розробки: <code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>)\n- Збережіть зміни\n- Можливо, але не рекомендується, використовувати один і той же додаток Discord для розробки та продакшену. Ви також можете розглянути [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) під час розробки.\n\n## Корисні ресурси\n\n| Ресурс                            | Посилання                               |\n| --------------------------------- | --------------------------------------- |\n| Документація NextAuth.js          | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/uk/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Використання Next.js\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\nNext.js це бекенд фреймворк для ваших React додатків.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nПодивіться [виступ Theo на Next.js Conf](https://www.youtube.com/watch?v=W4UhNo3HAMw) щоб отримати більш детальне розуміння того, що таке Next.js і як він працює.\n\n## Чому я повинен це використовувати?\n\nМи любимо React. Він зробив розробку UI доступною у тому вигляді, в якому ми ніколи не могли собі уявити. Він також може вести розробників тернистими шляхами. Next.js пропонує злегка суб'єктивний, більш оптимізований підхід до створення додатків з використанням React. Від маршрутизації до визначення API до візуалізації зображень ми довіряємо Next.js, щоб вести розробників до правильних рішень.\n\nПоєднуючи Next.js з [Vercel](https://vercel.com/), ви можете розробляти та деплоїти веб-програми легше, ніж будь-коли. Їх надзвичайно щедрий безкоштовний тариф та супер інтуїтивний інтерфейс надають рішення в один клік для деплойменту вашого сайту (Ми ❤️ Vercel)\n\n## Get Static/Server Props\n\nКлючові особливості Next.js – це можливості отримання даних. Ми наполегливо рекомендуємо прочитати [офіційну документацію](https://nextjs.org/docs/basic-features/data-fetching), щоб зрозуміти, як використовувати кожен метод і чим вони відрізняються. `getServerSideProps` зазвичай не рекомендується, якщо немає вагомої причини, тому що це блокуючий виклик і він уповільнить ваш сайт. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) - це відмінна альтернатива `getServerSideProps`, коли дані динамічні та можуть бути отримані поступово.\n\nЯкщо ви все одно хочете використовувати цю функцію, перегляньте ці посилання: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) та [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers)\n\n## Корисні ресурси\n\n| Ресурс                    | Посилання                          |\n| ------------------------- | ---------------------------------- |\n| Next.js Документація      | https://nextjs.org/docs            |\n| Next.js GitHub            | https://github.com/vercel/next.js  |\n| Next.js Блог              | https://nextjs.org/blog            |\n| Next.js Discord           | https://nextjs.org/discord         |\n| Next.js Twitter           | https://twitter.com/nextjs         |\n| Vercel/Next.js на YouTube | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/uk/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Використання Prisma\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\nPrisma це ORM для TypeScript, який дозволяє визначати схему та моделі бази даних у файлі `schema.prisma`, а потім генерувати клієнт, який забезпечує типобезпеку та може використовуватись для взаємодії з базою даних з вашого бекенда.\n\n## Prisma Client\n\nРозташований в `/server/db/client.ts`, Prisma Client ініціалізується як глобальна змінна (як рекомендовано [кращими практиками](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) команди Prisma) та експортується для використання у ваших API маршрутах. Ми включаємо Prisma Client у [Context](/uk/usage/trpc#-serverapitrpcts) за замовчуванням і рекомендуємо використовувати його замість окремого імпорту у кожному файлі.\n\n## Схема\n\nВи знайдете файл схеми Prisma в `/prisma/schema.prisma`. Цей файл використовується для визначення схеми та моделей баз даних, а також для генерації Prisma Client.\n\n### З NextAuth.js\n\nКоли ви вибираєте NextAuth.js у поєднанні з Prisma, файл схеми генерується і налаштовується для вас з рекомендованими значеннями для моделей `User`, `Session`, `Account` та `VerificationToken`, згідно з [документацією NextAuth.js](https://next-auth.js.org/adapters/prisma).\n\n## База даних за замовчуванням\n\nБаза даних за замовчуванням - це база даних SQLite, яка відмінно підходить для розробки та швидкого створення proof-of-concept, але не рекомендується для використання у продакшені. Ви можете змінити базу даних, використовуючи 'provider' в блоці 'datasource' на 'postgresql' або 'mysql', а потім оновити рядок підключення до змінних середовища, щоб вказати на вашу базу даних.\n\n## Заповнення (seeding) бази даних\n\n[Заповнення (seeding) вашої бази даних](https://www.prisma.io/docs/guides/database/seed-database) - це чудовий спосіб швидко заповнити вашу базу даних тестовими даними, щоб допомогти вам розпочати. Щоб налаштувати заповнення, вам потрібно створити файл `seed.ts` у каталозі `/prisma` і потім додати скрипт `seed` у файл `package.json`. Вам також знадобиться певний TypeScript-раннер, який може виконати скрипт заповнення. Ми рекомендуємо [tsx](https://github.com/esbuild-kit/tsx), який є дуже ефективним TypeScript-раннером, який використовує esbuild і не вимагає будь-якої конфігурації ESM, але `ts-node` або інші раннери також працюватимуть.\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\nПотім, просто запустіть `pnpm db-seed` (або `npm`/`yarn`), щоб заповнити вашу базу даних.\n\n## Корисні ресурси\n\n| Ресурс                         | Посилання                                                                                                                                         |\n| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Документація Prisma            | https://www.prisma.io/                                                                                                                            |\n| Prisma GitHub                  | https://github.com/prisma/                                                                                                                        |\n| Prisma Migrate Playground      | https://playground.prisma.io/guides                                                                                                               |\n| NextAuth.JS Адаптер для Prisma | https://next-auth.js.org/adapters/                                                                                                                |\n| Гайд з підключення PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/uk/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Використання Tailwind CSS\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\n## Що таке Tailwind CSS?\n\nTailwind CSS - це невеликий [utility first](https://tailwindcss.com/docs/utility-first) CSS фреймворк для створення власного дизайну, без перемикання контексту, який потрібний для звичайного CSS. Це чисто CSS фреймворк і він не надає ніяких попередньо зібраних компонентів або логіки, і надає [принципово інший набір переваг](https://www.youtube.com/watch?v=CQuTF-bkOgc) у порівнянні з бібліотекою компонентів, такою як наприклад Material UI.\n\nВін робить CSS неймовірно легким і швидким для написання, як показано в наступному прикладі:\n\nСтарий CSS:\n\n1. Напишіть CSS, часто в окремому файлі\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. Імпортуйте CSS у ваш компонент\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. Додайте клас у ваш HTML\n\n```html\n<div class=\"my-class\">...</div>\n```\n\nЕквівалент у Tailwind:\n\n1. Просто напишіть класи у вашому HTML\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\nВикористовуючи разом із React компонентами, він є надзвичайно потужним для швидкого створення UI.\n\nTailwind CSS містить вбудовану красиву систему дизайну, яка поставляється від початку з ретельно вибраною палітрою кольорів, розмірами для стилів, таких як ширина/висота і відступи для єдиного дизайну, а також точками переривання для створення адаптивних макетів. Ця система дизайну може бути налаштована та розширена для створення точного набору стилів, які потрібні вашому проекту.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla краще відома як [mewtru](https://twitter.com/trunarla) дала приголомшливу лекцію про [створення системи дизайну з використанням Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).\n\n## Використання\n\nПереконайтеся, що у вас є плагіни редактора для Tailwind, щоб поліпшити ваш досвід написання Tailwind.\n\n### Розширення та плагіни\n\n- [Розширення для VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### Форматування\n\nКласи Tailwind CSS можуть легко стати трохи безладними, тому форматтер для класів є необхідним. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) сортує класи у [рекомендованому порядку](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted), щоб класи відповідали зібраному css-пакету. При виборі Tailwind у CLI ми встановимо та налаштуємо це для вас.\n\n### Додавання класів в залежності від умов\n\nДодавання класів в залежності від умов з використанням тернарних операторів може стати дуже безладним і важким для читання. Ці пакети допомагають організувати ваші класи, використовуючи деяку логіку з умовами.\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## Корисні ресурси\n\n| Ресурс                        | Посилання                                                |\n| ----------------------------- | -------------------------------------------------------- |\n| Документація Tailwind         | https://tailwindcss.com/docs/editor-setup/               |\n| Шпаргалка по Tailwind         | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss           | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind Community            | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Сервер Tailwind в Discord     | https://tailwindcss.com/discord/                         |\n| Канал TailwindLabs на Youtube | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground           | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/uk/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: Використання tRPC\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\ntRPC дозволяє нам писати типобезпечні API від кінця до кінця (end-to-end) без будь-якої генерації коду чи подовження рантайму. Він використовує чудовий висновок TypeScript для виведення визначень типів вашого API-маршрутизатора і дозволяє викликати ваші API-процедури з інтерфейсу з повною безпекою типів і автоматичним завершенням. Використовуючи tRPC, ваш фронтенд і бекенд почуваються ближче один до одного, ніж будь-коли, забезпечуючи винятковий досвід розробника.\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>I built tRPC to allow people to move faster by removing the need of a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate.<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - creator of tRPC</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## Як я можу використовувати tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC контриб'ютор [trashh_dev](https://twitter.com/trashh_dev) [виступив на Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) з розповіддю про tRPC. Ми рекомендуємо вам подивитися, якщо ви ще не зробили це.\n\nЗ tRPC ви пишете функції TypeScript на бекенді, а потім викликаєте їх із фронтенду. Проста процедура tRPC може виглядати так:\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\nЦе процедура tRPC (еквівалент route handler-а у традиційному бекенді), яка спочатку перевіряє вхідні дані за допомогою Zod (який є тією самою бібліотекою перевірки, яку ми використовуємо для [змінних середовища](./env-variables)) – у цьому випадку ми переконуємось , що вхідні дані є рядком. Якщо вхідні дані не є рядком, він надішле інформативну помилку.\n\nПісля вхідних даних ми застосовуємо функцію, яка може бути або [запитом](https://trpc.io/docs/v10/react-queries), [мутацією](https://trpc.io/docs/v10/react-mutations) або [підпискою](https://trpc.io/docs/v10/subscriptions). У нашому прикладі resolver викликає нашу базу даних за допомогою клієнта [prisma](./prisma) і повертає користувача, у якого `id` збігається з тим, що ми передали.\n\nВи визначаєте свої процедури в `routers` які є колекцією пов'язаних процедур із спільним ім'ям. У вас може бути один роутер для користувачів, один для постів і ще один для повідомлень. Ці роутери потім можна об'єднати в єдиний централізований `appRouter`:\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\nЗверніть увагу, що нам потрібно експортувати тільки типи наших роутерів, що означає, що ми ніколи не імпортуємо серверний код на клієнта.\n\nТепер давайте викличемо процедуру на нашому фронтенді. tRPC надає обгортку для `@tanstack/react-query`, яка дозволяє використовувати всі можливості хуків (hooks), які він надає, але з додатковою перевагою того, що ваші виклики API типізовані та інферовані (inferred). Ми можемо викликати наші процедури з фронтенду так:\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\nВи відразу помітите, наскільки хороші автодоповнення та типобезпека. Як тільки ви почнете писати `api.`, ваші роутери з'являться в автодоповненні, і коли ви оберете роутер, його процедури також з'являться. Ви також отримаєте помилку TypeScript, якщо ваше введення не відповідає валідатору, який ви визначили на бекенді.\n\n## Обробка помилок\n\nПо дефолту, `create-t3-app` створює [error formatter](https://trpc.io/docs/error-formatting) який дозволяє вам виводити ваші Zod помилки якщо ви отримуєте помилки валідації на бекенді.\n\nПриклад використання:\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` returned with an error on the `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## Файли\n\ntRPC вимагає багато шаблонного коду, який `create-t3-app` налаштовує для вас. Давайте розглянемо файли, що генеруються:\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\nЦей файл є точкою входу для вашого API та експортує ваш tRPC роутер. Зазвичай, вам не доведеться чіпати цей файл, але якщо вам потрібно, наприклад, включити CORS middleware або щось подібне, корисно знати, що експортований `createNextApiHandler` - це [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) який приймає [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) та [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) об'єкт. Це означає, що ви можете обернути `createNextApiHandler` у будь-який middleware, який вам потрібен. Дивись нижче для [прикладу](#enabling-cors) додавання CORS.\n\n### 📄 `server/api/trpc.ts`\n\nЦей файл поділено на дві частини: створення контексту та ініціалізація tRPC.\n\n1. Ми визначаємо контекст, який передається вашим tRPC процедурам. Контекст - це дані, до яких у вас є доступ у всіх ваших процедурах tRPC, і це відмінне місце, щоб помістити речі, такі як з'єднання з базою даних, інформація про аутентифікацію і т.д. У create-t3-app ми використовуємо дві функції, щоб увімкнути використання підмножини контексту, коли ми не маємо доступу до об'єкта запиту.\n\n- `createInnerTRPCContext`: Це те місце, де ви визначаєте контекст, який не залежить від запиту, наприклад, ваше з'єднання з базою даних. Ви можете використовувати цю функцію для [інтеграційного тестування](#sample-integration-test) або [ssg-помічників](https://trpc.io/docs/v10/ssg-helpers), де у вас немає об'єкта запиту.\n\n- `createTRPCContext`: Тут ви визначаєте контекст, який залежить від запиту: наприклад, сесія користувача. Ви запитуєте сесію за допомогою об'єкта `opts.req`, а потім передаєте сесію у функцію `createInnerTRPCContext` для створення остаточного контексту.\n\n2. Ми ініціалізуємо tRPC і визначаємо повторно використовані [процедури](https://trpc.io/docs/v10/procedures) та [посередники](https://trpc.io/docs/v10/middlewares). За угодою, ви не повинні експортувати весь об'єкт `t`, а натомість створювати повторно використовувані процедури та посередники та експортувати їх.\n\nВи помітите, що ми використовуємо `superjson` як [перетворювач даних](https://trpc.io/docs/v10/data-transformers). Це дозволяє зберігати типи даних, коли вони досягають клієнта, тому якщо ви, наприклад, відправляєте об'єкт `Date`, клієнт поверне `Date`, а не рядок, що є нагодою для більшості API.\n\n### 📄 `server/api/routers/*.ts`\n\nЦе те місце, де ви визначаєте маршрути та процедури вашого API. Ви [створюєте окремі маршрутизатори](https://trpc.io/docs/v10/router) для пов'язаних процедур.\n\n### 📄 `server/api/root.ts`\n\nТут ми [об'єднуємо](https://trpc.io/docs/v10/merging-routers) всі під-маршрутизатори, визначені в `routers/**` в єдиний додатковий маршрутизатор.\n\n### 📄 `utils/api.ts`\n\nЦе точка входу для tRPC на фронтенді. Тут ви імпортуєте **визначення типів** маршрутизатора та створюєте клієнт tRPC разом із хуками react-query. Оскільки ми включили `superjson` як перетворювач даних на бекенді, нам також потрібно включити його на фронтенді. Це тому що серіалізовані дані з бэкенда десеріалізуються на фронтенді.\n\nТут ви визначите свої tRPC [посилання](https://trpc.io/docs/v10/links), які визначають потік запитів від клієнта до сервера. Ми використовуємо \"default\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink), який дозволяє [групувати запити](https://cloud.google.com/compute/docs/api/how-tos/batch), а також [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink), що виводить корисні журнали запитів під час розробки.\n\nЗрештою, ми експортуємо [допоміжний тип](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type), який ви можете використовувати для виведення типів на фронтенді.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCreate T3 App контриб’ютор [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) зробив [відео про потоки даних у tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Це відео рекомендовано якщо ви використовували tRPC, але все ще відчуваєте, що трохи не розумієте як воно працює.\n\n## Як я можу викликати свій API ззовні?\n\nУ звичайних API, ви можете викликати ваші кінцеві точки (endpoints) використовуючи будь-який HTTP клієнт, як `curl`, `Postman`, `fetch` або прямо з вашого браузера. З tRPC, це працює трохи інакше. Якщо ви хочете викликати ваші процедури без клієнта tRPC, є два рекомендовані способи зробити це:\n\n### Розкрийте одну процедуру зовні\n\nЯкщо ви бажаєте розкрити вашу процедуру зовні, вам варто шукати [server side calls](https://trpc.io/docs/v10/server-side-calls). Це дозволить вам створити звичайну кінцеву точку (endpoint) API Next.js, але перевикористовувати частину резолвера вашої процедури tRPC.\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### Розкрийте кожну процедуру зовнішньо\n\nЯкщо ви хочете розкрити будь-яку процедуру ззовні, познайомтеся з плагіном спільноти [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Надаючи додаткові метаданні вашим процедурам, ви можете створити відповідний REST API з вашого маршрутизатора tRPC.\n\n### Це всього лише HTTP-запити\n\ntRPC взаємодіє через HTTP, тому також можна викликати ваші процедури tRPC за допомогою \"звичайних\" HTTP-запитів. Однак синтаксис може бути неприйнятним із-за [протоколу RPC](https://trpc.io/docs/v10/rpc), який використовує tRPC. Якщо вам цікаво, ви можете перевірити, як виглядають запити та відповіді tRPC у вашій network вкладці веб-браузера, але ми рекомендуємо робити це лише в якості навчальної вправи і притримуватися одного з рішень, описаних вище.\n\n## Порівняння з кінцевою точкою (enpoint) Next.js API\n\nДавайте порівняємо кінцеву точку Next.js API з процедурою tRPC. Припустимо, ми хочемо отримати об'єкт користувача з нашої бази даних і повернути його на фронтенд. Ми могли б написати кінцеву точку Next.js API таким чином:\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\nПорівняйте це з прикладом tRPC вище і ви побачите деякі переваги tRPC:\n\n- Замість того, щоб вказувати URL для кожного маршруту, який може стати незручним для дебагінгу, якщо ви перемістите щось, ваш весь маршрутизатор - це об'єкт з автозаповненням.\n- Вам не потрібно перевіряти, який метод HTTP був використаний.\n- Вам не потрібно перевіряти, що запит або тіло запиту містять правильні дані у процедурі, тому що Zod подбає про це.\n- Замість створення відповіді, ви можете викидати помилки та повертати значення або об'єкт, як у будь-якій іншій функції TypeScript.\n- Викликаючи процедуру на фронтенді, ви отримуєте автозаповнення та перевірку типів.\n\n## Корисні сніпети\n\nТут наведені деякі сніпети, які можуть стати в нагоді.\n\n### Включення CORS\n\nЯкщо вам потрібно використовувати ваш API з іншого домену, наприклад в монорепозиторії, який включає додаток React Native, вам може знадобитися включити CORS:\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Enable cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### Оптимістичні оновлення\n\nОптимістичне оновлення - це коли ми оновлюємо інтерфейс користувача до того, як API-запит завершиться. Це надає користувачеві кращий досвід, тому що він не повинен чекати завершення API-запиту, перш ніж інтерфейс користувача відобразить результат його дії. Однак програми, які цінують коректність даних, повинні уникати оптимістичних оновлень, оскільки вони не є «вірним» уявленням стану бекенда. Ви можете прочитати більше у [документації React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // Cancel outgoing fetches (so they don't overwrite our optimistic update)\n      await utils.post.list.cancel();\n\n      // Get the data from the queryCache\n      const prevData = utils.post.list.getData();\n\n      // Optimistically update the data with our new post\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // Return the previous data so we can revert if something goes wrong\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // If the mutation fails, use the context-value from onMutate\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // Sync with server once mutation has settled\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### Простий Інтеграційний Тест\n\nТут приведено простий інтеграційний тест, який використовує [Vitest](https://vitest.dev), щоб перевірити, що ваш маршрутизатор tRPC працює належним чином, парсер вхідних даних виводить правильний тип і дані, що повертаються, відповідають очікуваному результату.\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\nЯкшо ваша процедура захищена, ви можете передати замоканий об'єкт `session` при створенні контексту:\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n\n  // ...\n});\n```\n\n## Корисні ресурси\n\n| Ресурс                               | Посилання                                               |\n| ------------------------------------ | ------------------------------------------------------- |\n| Документація tRPC                    | https://www.trpc.io                                     |\n| Декілька прикладів використання tRPC | https://github.com/trpc/trpc/tree/next/examples         |\n| Документація React Query             | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/uk/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Використання TypeScript\nlayout: ../../../layouts/docs.astro\nlang: uk\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>Build safety nets, not guard rails<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - creator of the T3 Stack</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\nНезважаючи на те новачок ви або досвідчений розробник, ми вважаємо, що TypeScript - це маст-хев. Спочатку він може виглядати гнітюче, але, як і багато інших інструментів, багато розробників не повертаються назад після того, як почали його використовувати.\n\nВін надає зворотний зв'язок в режимі реального часу при написанні коду, визначаючи очікувані типи даних, і надає корисні підказки в редакторі коду або кричить червоними хвилястими лініями, якщо ви намагаєтеся отримати доступ до властивості, якої не існує, або намагаєтеся передати значення неправильного типу, яке в іншому випадку довелося б налагоджувати далі по лінії.\n\nЦе інструмент, який, мабуть, забезпечує найбільшу продуктивність розробникам; він надає документацію для коду, який ви пишете або використовуєте безпосередньо у вашому редакторі та має миттєвий зворотний зв'язок, коли ви неминуче робите помилки, що абсолютно безцінно.\n\n## Виведення типів (Type Inference)\n\nПоки багато нових розробників на TypeScript стурбовані написанням TypeScript, багато з його переваг насправді не вимагають від вас зміни вашого коду взагалі, зокрема виведення типів. Висновок типів означає, що якщо щось типізовано, цей тип слідуватиме за ним протягом потоку програми без необхідності повторного оголошення в інших місцях. Це означає, що, наприклад, після того, як ви визначили типи аргументів, які приймає функція, решта функції зазвичай буде безпечною щодо типів без необхідності введення будь-якого додаткового коду, специфічного для TypeScript. Розробники бібліотек витрачають величезну кількість часу на підтримку типів для своїх бібліотек, що означає, що ми, як розробники додатків, можемо отримати вигоду від виведення типів та вбудованої документації у вашому редакторі коду, який ці типи надають.\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nПерегляньте відео Theo про те, що [ви, можливо, використовуєте TypeScript неправильно](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## Потужні застосування виведення типів\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) - це бібліотека перевірки схем, побудована поверх TypeScript. Напишіть схему, яка є єдиним джерелом істини для ваших даних, і Zod гарантує, що ваші дані будуть дійсними у всьому додатку, навіть поза межами мережі та зовнішніх API.\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) надає вам декларативні, завжди актуальні автоматично керовані запити та мутації, які безпосередньо покращують як Developer, так і User Experience.\n\n## Корисні ресурси\n\n| Ресурс                                                           | Посилання                                                         |\n| ---------------------------------------------------------------- | ----------------------------------------------------------------- |\n| Посібник з TypeScript                                            | https://www.typescriptlang.org/docs/handbook/                     |\n| Гайд по TypeScript для новачків                                  | https://github.com/total-typescript/beginners-typescript-tutorial |\n| Type Challenges                                                  | https://github.com/type-challenges/type-challenges                |\n| Канал Родні Маллена зі світу TypeScript (Matt Pocock) на YouTube | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/uk/why.md",
    "content": "---\ntitle: Чому CT3A?\ndescription: Чому вам слід вибрати Create T3 App для наступного проекту?\nlayout: ../../layouts/docs.astro\nlang: uk\n---\n\nМи почали Create T3 App, тому що [Theo](https://twitter.com/t3dotgg) відмовився робити шаблон своїх улюблених технологій. Натхненний create-next-app, [Astro's CLI](https://astro.build) та загальною любов'ю до типобезпеки, команда Create T3 App працювала, щоб створити кращу можливу відправну точку для нових проектів T3 Stack.\n\nЯкщо ви зацікавлені у використанні Next.js у типобезпечному варіанті, це те, з чого потрібно почати. Якщо ви цікавитеся будь-якими з конкретних технологічних рішень, які ми зробили, читайте далі :)\n\n## Чому TypeScript?\n\nJavaScript складний. Навіщо додавати ще більше правил?\n\nМи цілком впевнені, що досвід TypeScript дозволяє вам бути кращим розробником. Він надає зворотний зв'язок під час написання коду, визначаючи очікувані типи даних, і, або допомгає корисним автозаповненням у вашому редакторі, або кричить на вас червоними хвилястими лініями, якщо ви намагаєтеся отримати доступ до властивості, якої не існує, або намагаєтеся передати значення неправильного типу, що в іншому випадку довелося б налагоджувати в подальшому. Незалежно від того, новачок ви у веб-розробці або досвідчений професіонал, \"суворість\" TypeScript забезпечує менш дратівливий, більш послідовний досвід, ніж ванільний JS.\n\nТипобезпека робить вас швидше. Якщо ви ще не переконані, ви [можете використовувати TypeScript неправильно...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## Чому Next.js?\n\nМи любимо React. Він зробив розробку UI доступною у тому вигляді, в якому ми ніколи не могли собі уявити. Він також може вести розробників тернистими шляхами.\n\nNext.js пропонує злегка суб'єктивний, більш оптимізований підхід до створення додатків з використанням React. Від маршрутизації до визначення API до візуалізації зображень ми довіряємо Next.js, щоб вести розробників до правильних рішень.\n\n## Чому tRPC/Prisma/Tailwind/и т.д.?\n\nХоча ми віримо, що все має бути якнайлегше, ми знаходимо, що ці частини використовуються в кожному проекті, складнішому ніж \"лендінг\" (напр. проєкти зі складнішими технологіями і логікою). `create-t3-app` виконує чудову роботу, дозволяючи вам вибрати ті частини, які вам потрібні.\n\n### tRPC\n\ntRPC надає всі переваги GraphQL, такі як гладка та безперервна розробка клієнта проти типобезпечного сервера без будь-якого бойлерплейту. Це розумний аб'юз TypeScript, яке забезпечує неймовірний досвід розробки.\n\n### Prisma\n\nPrisma для SQL це те й що TypeScript для JS. Вона створила досвід розробки, якого раніше не було. Створюючи типи з схеми користувача, сумісної з [кількома базами даних](https://www.prisma.io/docs/concepts/database-connectors), Prisma гарантує безпеку типів від початку до кінця від вашої бази даних до вашої програми.\n\nPrisma надає цілий [набір інструментів](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows), що полегшують щоденну взаємодію з вашою базою даних. Зокрема, Prisma Client відповідає за запити та робить SQL настільки простим, що ви ледве помітите, що його використовуєте, а Prisma Studio – це зручний GUI для вашої бази даних, який дозволяє швидко читати та маніпулювати даними без необхідності писати код.\n\n### Tailwind CSS\n\nTailwind відчувається як \"CSS у режимі дзен\".\n\nЗавдяки наданню будівельних блоків у вигляді гарних кольорів за замовчуванням, відступів та інших примітивних налаштувань Tailwind дозволяє легко створювати додаток із гарним зовнішнім виглядом. І на відміну від бібліотек компонентів, він не обмежує вас, коли ви хочете вивести свою програму на наступний рівень і створити щось красиве та унікальне.\n\nДо того ж, завдяки інлайновому підходу, Tailwind спонукає вас стилізувати без занепокоєння про назву класів, організацію файлів або будь-яку іншу проблему, не пов'язану з вирішенням завдання.\n\n### NextAuth.js\n\nКоли ви хочете додати систему аутентифікації у вашу програму NextJS, NextAuth.js - відмінне рішення, щоб не морочитися з реалізацією складної системи безпеки. Вона має великий список провайдерів для швидкого додавання аутентифікації через OAuth і надає адаптери для багатьох баз даних та ORM.\n"
  },
  {
    "path": "www/src/pages/zh-hans/deployment/docker.md",
    "content": "---\ntitle: Docker\ndescription: 使用 Docker 部署\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\n你可以将这个 stack 容器化，将它作为一个单独容器使用 Docker 来部署，或者作为一系列容器的部分，使用 docker-compose 来部署。参看基于本文档的示例仓库 [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker)。\n\n## Docker 项目配置\n\n请注意 Next.js 会针对编译时客户端的环境变量（在客户端，名称前缀含有 `NEXT_PUBLIC`） 和运行时环境的服务器端变量有不同的处理过程。在本次演示中我们将使用两个环境变量，请注意它们在 `Dockerfile` 文件中的位置、命令行参数以及文件 `docker-compose.yml`：\n\n- `DATABASE_URL` （被用于服务器端）\n- `NEXT_PUBLIC_CLIENTVAR` （被用于客户端）\n\n### 1. Next 的配置\n\n在你的 [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js) 文件里，添加构建输出选项 `standalone`，以[自动借助追踪输出文件来降低镜像文件的大小](https://nextjs.org/docs/advanced-features/output-file-tracing)：\n\n```diff\nexport default defineNextConfig({\n  reactStrictMode: true,\n  swcMinify: true,\n+ output: \"standalone\",\n});\n```\n\n### 2. 创建 dockerignore 文件\n\n<details>\n    <summary>\n      点击这里并将下方内容添加到 <code>.dockerignore</code> 里：\n    </summary>\n<div class=\"content\">\n\n```\n.env\nDockerfile\n.dockerignore\nnode_modules\nnpm-debug.log\nREADME.md\n.next\n.git\n```\n\n</div>\n\n</details>\n\n### 3. 创建 Dockerfile\n\n> 因为我们并没有将服务端环境变量导入到我们的容器里，因此 [环境变量的 schema 验证](/zh-hans/usage/env-variables) 肯定不会通过。为了防止这种情况发生，我们必须在构建命令中添加 `SKIP_ENV_VALIDATION=1` 标识，以便 env-schema 不会在编译时被验证。\n\n<details>\n    <summary>\n      点击这里并将下方内容添加到 <code>Dockerfile</code> 里：\n    </summary>\n<div class=\"content\">\n\n```docker\n##### DEPENDENCIES\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS deps\nRUN apk add --no-cache libc6-compat openssl\nWORKDIR /app\n\n# 安装 Prisma 客户端 - 如果不需要 Prisma，移除下一行\n\nCOPY prisma ./\n\n# 使用 PNPM 包管理工具安装依赖包\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\\* ./\n\nRUN \\\n if [ -f yarn.lock ]; then yarn --frozen-lockfile; \\\n elif [ -f package-lock.json ]; then npm ci; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### BUILDER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS builder\nARG DATABASE_URL\nARG NEXT_PUBLIC_CLIENTVAR\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN \\\n if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \\\n elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \\\n elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \\\n else echo \"Lockfile not found.\" && exit 1; \\\n fi\n\n##### RUNNER\n\nFROM --platform=linux/amd64 node:16-apline3.17 AS runner\nWORKDIR /app\n\nENV NODE_ENV production\n\n# ENV NEXT_TELEMETRY_DISABLED 1\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\nCOPY --from=builder /app/next.config.js ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/package.json ./package.json\n\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static\n\nUSER nextjs\nEXPOSE 3000\nENV PORT 3000\n\nCMD [\"node\", \"server.js\"]\n\n```\n\n> **_注意_**\n>\n> - _在迁移到 Node 18 后，可能就没有必要再使用 `--platform=linux/amd64` 了。_\n> - _参看 [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) 来了解为什么使用 `libc6-compat`_\n> - _Next.js 会收集 [关于使用情况的匿名观测数据](https://nextjs.org/telemetry)。取消注释第一个 `ENV NEXT_TELEMETRY_DISABLED 1`，以在构建过程中关闭该观测功能。取消注释第二个 `ENV NEXT_TELEMETRY_DISABLED 1` 以关闭在运行时的观测功能。_\n\n</div>\n</details>\n\n## 在本地构建和运行镜像\n\n通过下方命令在本地构建和运行该镜像：\n\n```bash\ndocker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .\ndocker run -p 3000:3000 -e DATABASE_URL=\"database_url_goes_here\" ct3a-docker\n```\n\n在浏览器中访问 [localhost:3000](http://localhost:3000/) 来查看运行的应用。\n\n## Docker Compose\n\n你也可以使用 Docker Compose 来创建镜像以运行容器。\n\n<details>\n    <summary>\n      遵循以上 1 - 4 的步骤，点击这里，将下方内容添加到 <code>docker-compose.yml</code> 里：\n    </summary>\n<div class=\"content\">\n\n```yaml\nversion: \"3.9\"\nservices:\n  app:\n    platform: \"linux/amd64\"\n    build:\n      context: .\n      dockerfile: Dockerfile\n      args:\n        NEXT_PUBLIC_CLIENTVAR: \"clientvar\"\n    working_dir: /app\n    ports:\n      - \"3000:3000\"\n    image: t3-app\n    environment:\n      - DATABASE_URL=database_url_goes_here\n```\n\n命令行运行 `docker compose up`：\n\n```bash\ndocker compose up\n```\n\n在浏览器中访问 [localhost:3000](http://localhost:3000/) 来查看运行的应用。\n\n</div>\n</details>\n\n## 部署到 Railway\n\n你可以使用 PaaS（平台即服务）工具，例如 [Railway's](https://railway.app)，自动完成 [Dockerfile 部署](https://docs.railway.app/deploy/dockerfiles) 来部署你的应用。如果你已经 [安装了 Railway CLI 命令行工具](https://docs.railway.app/develop/cli#install)，你可以使用下方命令来部署你的应用：\n\n```bash\nrailway login\nrailway init\nrailway link\nrailway up\nrailway open\n```\n\n前往 \"Variables\"，填入你的 `DATABASE_URL`。然后前往 \"Settings\" 里，选择 \"Generate Domain\"。访问 [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/) 来查看托管在 Railway 上的项目。\n\n## 有用的资源\n\n| 资源                                  | 链接                                                                 |\n| ------------------------------------- | -------------------------------------------------------------------- |\n| Dockerfile 参考手册                   | https://docs.docker.com/engine/reference/builder/                    |\n| Compose file 第三版参考手册           | https://docs.docker.com/compose/compose-file/compose-file-v3/        |\n| Docker CLI 命令行工具参考手册         | https://docs.docker.com/engine/reference/commandline/docker/         |\n| Docker Compose CLI 命令行工具参考手册 | https://docs.docker.com/compose/reference/                           |\n| 使用 Docker 镜像 部署 Next.js         | https://nextjs.org/docs/deployment#docker-image                      |\n| Docker 中的 Next.js                   | https://benmarte.com/blog/nextjs-in-docker/                          |\n| Next.js 搭配 Docker 示例              | https://github.com/vercel/next.js/tree/canary/examples/with-docker   |\n| 创建一个 Next.js 应用的 Docker 镜像   | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |\n"
  },
  {
    "path": "www/src/pages/zh-hans/deployment/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Deployment\",\n  layout: \"docs\",\n  description: \"Learn how to deploy your T3 app to production.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Deployment\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/zh-hans/deployment/netlify.mdx",
    "content": "---\ntitle: Netlify\ndescription: 部署到 Netlify\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nNetlify 是与 Vercel 类似的托管平台服务商。参看基于本文档的示例仓库 [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify)。\n\n## 为什么托管到 Netlify\n\n传统观点认为 Vercel 有着对 Next.js 绝佳的支持，因为他们开发了 Next.js。他们通过对平台的调校，确保搭配 Next.js 的最佳性能和开发体验，从而从中营利。对于大多数使用场景，使用 Vercel 部署 Next.js 无可厚非，偏离标准选择也没有多大意义。\n\n然而也有一种普遍的看法是，很多 Next.js 的功能特性都仅限于 Vercel。虽然说默认情况下，Next.js 的新特性在发布时确实都只会在 Vercel 平台上被测试，然后被其所支持，但对于 [稳定的 Next.js 特性](https://docs.netlify.com/integrations/frameworks/next-js/overview/)，像 Netlify 这样的其他部署平台也会 [迅速为之提供支持](https://www.netlify.com/blog/deploy-nextjs-13/)。\n\n所有的部署平台都有相对的优缺点，因为没有一家供应商能对所有的使用场景都提供最好的支持。举例来说，Netlify 为他们的边缘函数（它们运行在 Deno 环境）自行创建了一个 [定制的 Next.js 运行时](https://github.com/netlify/next-runtime)，[使用了独有的中间件来访问和修改 HTTP 响应](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify)。\n\n<Callout type=\"info\">\n  要追踪 Next 13 非稳定特性的最新状态，参看 [在 Netlify 上使用 Next.js 13 的 `app` 目录](https://github.com/netlify/next-runtime/discussions/1724)。\n</Callout>\n\n## 项目配置\n\n有很多方法来配置你应用的打包部署流程，包括直接通过 Netlify CLI 命令行工具或 Netlify 管理面板。虽然说并不强求，但我们还是建议创建一个 [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) 文件，并将它放在你的项目中。这么做能使被 fork 和 clone 的项目版本都可以更便利地被重复部署。\n\n```toml\n[build]\n  command = \"next build\"\n  publish = \".next\"\n```\n\n## 使用 Netlify 管理面板\n\n1. 将你的代码 push 到 GitHub 仓库，然后注册 [Netlify](https://app.netlify.com/signup)。当你创建完账号后，点击 **Add new site** 然后再点击 **Import an existing project**。\n\n![New project on Netlify](/images/netlify-01-new-project.webp)\n\n2. 连接 Git 服务商。\n\n![Import repository](/images/netlify-02-connect-to-git-provider.webp)\n\n3. 选择你项目的仓库地址。\n\n![Select your project's repository](/images/netlify-03-pick-a-repository-from-github.webp)\n\n4. Netlify 将会检测你的项目是否包含文件 `netlify.toml`，然后会自动为你配置好构建命令和打包目录。\n\n![Nextjs build settings](/images/netlify-04-configure-build-settings.webp)\n\n5. 点击 **Show advanced** 然后点击 **New variable** 来添加你的环境变量。\n\n![Add environment variables](/images/netlify-05-env-vars.webp)\n\n6. 点击 **Deploy site**，等待部署完成，然后就可以访问你的新网站了。\n\n## 使用 Netlify CLI 命令行工具\n\n要使用命令行工具来部署到 Netlify，你必须首先将你的项目部署到 GitHub，并 [安装 Netlify CLI 命令行工具](https://docs.netlify.com/cli/get-started/)。你既可以将 `netlify-cli` 作为项目依赖来安装，也可以通过下方命令全局安装：\n\n```bash\nnpm i -g netlify-cli\n```\n\n为了在本地测试你的项目，运行命令 [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) 然后访问 [`localhost:8888`](http://localhost:8888/) 来查看本地运行的 Netlify 应用：\n\n```bash\nntl dev\n```\n\n运行命令 [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) 来配置你的项目：\n\n```bash\nntl init\n```\n\n使用命令 [`ntl env:import`](https://cli.netlify.com/commands/env#envimport) 从 `.env` 文件中导入环境变量：\n\n```bash\nntl env:import .env\n```\n\n通过命令 [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys) 来部署你的项目。在部署之前你需要先传入 `--build` 标识来将你的项目打包，然后传入 `--prod` 标识来部署到生产环境：\n\n```bash\nntl deploy --prod --build\n```\n\n访问 [ct3a.netlify.app](https://ct3a.netlify.app/) 来查看运行在 Netlify 上的示例项目。\n"
  },
  {
    "path": "www/src/pages/zh-hans/deployment/vercel.md",
    "content": "---\ntitle: Vercel\ndescription: 部署到 Vercel\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\n我们推荐将你的应用部署到 [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss)。它大大简化了 Next.js 应用的部署流程。\n\n## 项目配置\n\nVercel 很大可能会自动帮你配置好部署命令，以及构建导出目录。然而，你也可以通过创建一个 [`vercel.json`](https://vercel.com/docs/project-configuration) 文件，并加入下列命令。**这对大部分项目来说不是必需的。**\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \"dist\",\n  \"devCommand\": \"npm run dev\",\n  \"installCommand\": \"npm install\"\n}\n```\n\n## 使用 Vercel 管理面板\n\n1. 当你将代码成功 push 到 GitHub 仓库后，使用 GitHub 注册 [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss)，然后点击**添加新项目**。\n\n![New project on Vercel](/images/vercel-new-project.webp)\n\n2. 从 GitHub 仓库导入你的项目。\n\n![Import repository](/images/vercel-import-project.webp)\n\n3. 添加环境变量。\n\n![Add environment variables](/images/vercel-env-vars.webp)\n\n4. 点击**部署**。现在只要当你将修改 push 到仓库后，Vercel 会自动为你重新部署应用。\n\n## 使用 Vercel CLI 命令行工具\n\n为了使用命令行工具来部署，你必须先 [全局安装 Vercel 的命令行工具](https://vercel.com/docs/cli#installing-vercel-cli)。\n\n```bash\nnpm i -g vercel\n```\n\n运行 [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) 命令来部署你的项目。\n\n```bash\nvercel\n```\n\n加入参数 `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` 来指定环境变量的值，例如数据库连接的地址。如果你想要跳过问答，使用默认的部署配置，加入标识 `--yes`。\n\n```bash\nvercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes\n```\n\n在第一次部署之后，这个命令会将项目部署到一个预览分支。你在之后的部署中需要加入 `--prod` 标识来直接将修改 push 到生产环境中。\n\n```bash\nvercel --prod\n```\n"
  },
  {
    "path": "www/src/pages/zh-hans/faq.mdx",
    "content": "---\ntitle: 常见疑问\ndescription: 关于 Create T3 App 的常见疑问\nlayout: ../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\n这里罗列了一些关于 Create T3 App 的常见疑问。\n\n## 下一步呢？我怎么通过它开发一个应用？\n\n我们努力保持这个项目尽可能的简单，这样你就可以通过我们设定的脚手架来开始制作应用，而且可以在之后有需要的时候添入额外的东西。\n\n如果你对项目中的不同技术不熟悉，请参看它们对应的文档。倘若看过文档后你依然有不明白的地方，请加入到我们的 [Discord](https://t3.gg/discord) 来寻求帮助。\n\n- [Next.js](https://nextjs.org/)\n- [NextAuth.js](https://next-auth.js.org)\n- [Prisma](https://prisma.io)\n- [Tailwind CSS](https://tailwindcss.com)\n- [tRPC](https://trpc.io)\n- [Drizzle](https://orm.drizzle.team/docs/overview)\n\n## 如何使我的应用保持更新？\nCreate T3 App 是一个脚手架工具，而不是一个框架。这意味着一旦你初始化了一个应用程序，它就是你的了。没有类似于 postinstall CLI 的工具来帮助你保持最新状态。如果你想跟踪我们对模板所做的任何改进，你可以在我们的存储库上[启用发布通知](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository)功能。\n话虽如此，但不一定需要将我们对模板所做的每一个更改都应用到你的应用程序中。\n\n## 现在有哪些关于 T3 Stack 的学习资源可供参考？\n\n尽管以下列出的资源已经是现有关于 T3 Stack 的最好教程了，但社区（和 [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)）依然推荐你直接开始使用它，与此同时你可以在通过它构建应用的过程中来学习。\n\n如果你考虑使用 Create T3 App，很大可能是因为你已经用到了其包含的某些库。所以何不先直接用起来，然后在构建应用的过程中去学习其他陌生的部分？\n\n好吧，现在我们意识到这种方法不一定适用于每个人。所以，倘若你已经尝试了上述方法，却依然想要一些教学资源，或者你对自己不太自信，抑或觉得这个脚手架包含太多东西，一时难以消化，那你可以尝试参考下方一些关于 Create T3 App 的非常棒的教程：\n\n### 文章\n\n其中的一些也许已经过时。\n\n- [初探 Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)\n- [将你的 T3 App 迁移到 Turborepo](https://www.jumr.dev/blog/t3-turbo)\n- [将 Stripe 集成到你的 T3 App 中](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)\n\n### 视频\n\n- [T3 Stack 教程 - 从 0 到上线，0 元成本 (Next.js, tRPC, TypeScript, Tailwind, Prisma 等)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(推荐)**\n- [Jack Herrington - 使用 T3 Stack 创建一个笔记应用](https://www.youtube.com/watch?v=J1gzN1SAhyM)\n- [使用 T3 Stack 创建推特克隆应用 - tRPC、Next.js、Prisma、Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)\n- [使用 T3 Stack 创建博客应用 - tRPC、TypeScript、Next.js、Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)\n- [使用 T3 Stack 来创建实时聊天应用 - TypeScript、Tailwind、tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)\n- [ T3 Stack - 我们是如何创建它的](https://www.youtube.com/watch?v=H-FXwnEjSsI)\n- [Create T3 App 的概览（Next、Typescript、Tailwind、tRPC、Next-Auth）](https://www.youtube.com/watch?v=VJH8dsPtbeU)\n\n## 项目中为什么会有 `.js` 格式的文件？\n\n正如在 [T3 - 原则第三条](/zh-hans/introduction#类型安全不是可选的) 里所讲到的，我们将类型安全放在首位。不幸的是，并非所有的框架和插件都支持 TypeScript，这也就意味着有一些配置文件必须是 `.js` 格式。\n\n我们想要强调的是，这些文件是 JavaScript 是有原因的，我们通过根据它们所使用的库的支持程度来显式声明每个文件的类型（`cjs` 或 `mjs`）。而且，项目中所有的 `js` 文件也会使用编译器（tsconfig）中的 checkJs 选项进行类型检查。\n\n## 我正努力为我的应用添加多语言功能。有我能够借鉴的吗？\n\n我们已经决定 `create-t3-app` 默认不支持多语言功能，因为这是一个非常 opinionated 的话题，有很多不同的方法来实现它。\n\n然而，如果你觉得实现它很困难，想参考一些项目的话，这里有一个 [参考仓库](https://github.com/juliusmarminge/t3-i18n)，展示了如何可以通过 [next-i18next](https://github.com/i18next/next-i18next) 为 T3 App 提供多语言支持。\n\n## 为什么我们还用 `/pages` 而不是 Next.js 13 新推出的 `/app`？\n\n正如在 [T3-原则第二条](/zh-hans/introduction#负责任地尝鲜) 里提到的，我们热爱新技术，但是也看重稳定性，项目的整个路由不是很容易迁移，而你却在此使用风险较高的新技术，[这不是一个明智的选择](https://youtu.be/mnwUbtieOuI?t=1662)。`/app` 目前只是 [对未来特性的一瞥而已](https://youtu.be/rnsC-12PVlM?t=818)，它还未做好准备被用于生产环境；这项 API 还处于 beta 阶段，可以预见接下来还会有破坏性的改变。\n\n<Callout type=\"info\">\n  对于 `/app` 目录中支持的、计划的和正在开发的功能列表，请访问 [beta Next.js docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).\n</Callout>\n"
  },
  {
    "path": "www/src/pages/zh-hans/folder-structure-pages.mdx",
    "content": "---\ntitle: 文件夹结构 (Pages)\ndescription: 新创建的 T3 App 的文件夹结构\nlayout: ../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Diagram from \"../../components/docs/folderStructureDiagramPages.astro\";\nimport Form from \"../../components/docs/folderStructureForm.astro\";\n\n请选择你要安装的依赖包来查看一个对应新建的 T3 App 的文件夹结构。继续往下阅读，你可以从每个文件夹的描述了解它们对应的用途。\n\n<Form />\n\n<Diagram />\n\n<div data-components=\"prisma\">\n\n### `prisma`\n\n文件夹 `prisma` 包含了 `schema.prisma` 文件，它被用于配置数据库连接和定义数据结构。数据库的迁移记录文件以及初始化种子脚本（如果你需要的话）也会被放在这个文件夹里。 参看 [Prisma 的用法](/zh-hans/usage/prisma) 来了解更多。\n\n</div>\n<div>\n\n### `public`\n\n文件夹 `public` 包含了一些将被托管在服务器上的静态资源。例如文件 `favicon.ico`。\n\n</div>\n<div>\n\n### `src/env`\n\n用于环境变量的验证和类型定义 - 参看 [环境变量](/zh-hans/usage/env-variables)。\n\n</div>\n<div>\n\n### `src/pages`\n\n文件夹 `pages` 包含了 Next.js 应用的所有页面。根目录下的文件 `index.tsx` 则是应用程序的首页。文件 `_app.tsx` 被用于使用 provider 来包裹整个应用程序。参看 [Next.js 文档](https://nextjs.org/docs/basic-features/pages) 来了解更多。\n\n</div>\n<div data-components=\"nextauth trpc\">\n\n#### `src/pages/api`\n\n文件夹 `api` 包含了 Next.js 应用的所有 API 路由。参看 [Next.js API 路由](https://nextjs.org/docs/api-routes/introduction) 来获取有关 API 路由的信息。\n\n</div>\n<div data-components=\"nextauth\">\n\n#### `src/pages/api/auth/[...nextauth].ts`\n\n文件 `[...nextauth].ts` 包含了 NextAuth.js 认证的动态 slug 路由。它被用于处理认证请求。参看 [NextAuth.js 用法](/zh-hans/usage/next-auth) 来了解更多关于 NextAuth.js 的用法，以及 [Next.js 动态路由文档](https://nextjs.org/docs/routing/dynamic-routes) 来了解更多关于 catch-all 和 slug 路由的信息。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/pages/api/trpc/[trpc].ts`\n\n文件 `[trpc].ts` 是 tRPC API 的入口。它被用于处理 tRPC 请求。参看 [tRPC 用法](/zh-hans/usage/trpc#-pagesapitrpctrpcts) 来了解更多关于这个文件的信息，以及 [Next.js 动态路由文档](https://nextjs.org/docs/routing/dynamic-routes) 来了解更多关于 catch-all 和 slug 路由的信息。\n\n</div>\n<div data-components=\"trpc prisma nextauth\">\n\n### `src/server`\n\n文件夹 `server` 被用于清晰划分服务端和客户端代码。\n\n</div>\n<div data-components=\"nextauth+trpc\">\n\n#### `src/server/auth.ts`\n\n服务器端认证逻辑的主入口。在这里，我们设置 NextAuth.js 的 [配置选项](/zh-hans/usage/next-auth)，执行 [模块扩展](/zh-hans/usage/next-auth#inclusion-of-userid-on-the-session)，并提供一些认证的 DX 工具，例如在服务器端检索用户的会话。参看 [NextAuth.js 用法](/zh-hans/usage/next-auth#搭配-trpc-的用法) 来了解更多。\n\n</div>\n<div data-components=\"prisma\">\n\n#### `src/server/db.ts`\n\n文件 `db.ts` 被用于初始化一个全局的 Prisma 客户端。 参看 [Prisma 用法](/zh-hans/usage/prisma#prisma-客户端) 和 [使用 Prisma 与 Next.js 的最佳实践](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) 来了解更多。\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/server/api`\n\n文件夹 `api` 包含了 tRPC 服务端的代码。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers`\n\n文件夹 `routers` 包含了你的所有 tRPC 子路由。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/routers/example.ts`\n\n文件 `example.ts` 包含了一段 tRPC 路由的示例代码，它利用 `publicProcedure` 来展示如何创建一个公开不受保护的 tRPC 路由。\n\n根据你选择的包，这个路由包含更多或更少的路由，以最好地展示符合你需求的用法。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/trpc.ts`\n\n文件 `trpc.ts` 是 tRPC 后端的主要配置文件。我们在这里进行以下操作：\n\n1. 定义在 tRPC 请求中使用的上下文。 参看 [tRPC 用法](usage/trpc#-serverapitrpcts) 来了解更多。\n2. 导出 procedure。 参看 [tRPC 用法](usage/trpc#-serverapitrpcts) 来了解更多。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/server/api/root.ts`\n\nroot.ts 文件用于合并 tRPC 子路由并将它们导出为一个单一的路由，同时也导出了路由的类型定义。详见 tRPC 用法。\n\n文件 `root.ts` 被用于合并 tRPC 子路由并将它们导出为一个单一的路由，同时也导出了路由的类型定义。参看 [tRPC 用法](usage/trpc#-serverapirootts) 来了解更多。\n\n</div>\n<div>\n\n### `src/styles`\n\n文件夹 `styles` 包含了应用的全局样式。\n\n</div>\n<div data-components=\"trpc\">\n\n### `src/utils`\n\n文件夹 `utils` 被用于存储经常复用的工具函数。\n\n</div>\n<div data-components=\"trpc\">\n\n#### `src/utils/api.ts`\n\n文件 `trpc.ts` 是 tRPC 的前端入口。参看 [tRPC 用法](/zh-hans/usage/trpc#-utilsapits) 来了解更多。\n\n</div>\n<div>\n\n### `.env`\n\n文件 `.env` 被用于保存环境变量。参看 [环境变量](/zh-hans/usage/env-variables) 来了解更多。该文件**不**应该被提交到 git 历史记录里。\n\n</div>\n<div>\n\n### `.env.example`\n\n文件 `.env.example` 根据所选库包展示了一个环境变量示例配置。这个文件需要被提交到 git 历史记录里。\n\n</div>\n<div>\n\n### `.eslintrc.cjs`\n\n文件 `.eslintrc.cjs` 被用于配置 ESLint。参看 [ESLint 文档](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) 来了解更多。\n\n</div>\n<div>\n\n### `next-env.d.ts`\n\n文件 `next-env.d.ts` 确保 TypeScript 编译器能够采用 Next.js 的类型。**你不应该移除或修改该文件，因为它可以随时发生变化。** 参看 [Next.js 文档](https://nextjs.org/docs/basic-features/typescript#existing-projects) 来了解更多。\n\n</div>\n<div>\n\n### `next.config.mjs`\n\n文件 `next.config.mjs` 被用于配置 Next.js。参看 [Next.js 文档](https://nextjs.org/docs/api-reference/next.config.js/introduction) 来了解更多。注意：.mjs 格式的文件被用于允许以 ESM 方式导入。\n\n</div>\n<div data-components=\"tailwind\">\n\n### `postcss.config.js`\n\n文件 `postcss.config.js` 被用于配置 Tailwind PostCSS 的用法。参看 [Tailwind PostCSS 文档](https://tailwindcss.com/docs/installation/using-postcss) 来了解更多。\n\n</div>\n<div data-components=\"tailwind\">\n\n### `prettier.config.mjs`\n\n文件 `prettier.config.mjs` 被用于配置 Prettier，以使用插件 prettier-plugin-tailwindcss 来格式化 Tailwind CSS 的类名。参看 [Tailwind CSS 博客](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) 来了解更多。\n\n</div>\n<div>\n\n### `tsconfig.json`\n\n文件 `tsconfig.json` 被用于配置 TypeScript。一些非默认项，例如 `strict mode` 已经被启用来保证使用 Create T3 App 和它所含库时能获得最佳的 TypeScript 开发体验。参看 [TypeScript 文档](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) 或 [TypeScript 用法](/zh-hans/usage/typescript) 来了解更多。\n\n</div>\n<div>\n\n### `drizzle.config.ts`\n\n文件 `drizzle.config.ts` 被文件用于配置 drizzle kit。更多信息请参看 [文档](https://orm.drizzle.team/kit-docs/config-reference)。\n\n</div>\n"
  },
  {
    "path": "www/src/pages/zh-hans/installation.mdx",
    "content": "---\ntitle: 安装\ndescription: 创建 T3 应用程序的安装说明\nlayout: ../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Callout from \"../../components/docs/callout.tsx\";\n\n要使用 `create-t3-app` 创建一个应用程序，请运行以下任意一个命令，并回答命令提示符的问题：\n\n### npm\n\n```bash\nnpm create t3-app@latest\n```\n\n### yarn\n\n```bash\nyarn create t3-app\n```\n\n### pnpm\n\n```bash\npnpm create t3-app@latest\n```\n\n### bun\n\n```bash\nbun create t3-app@latest\n```\n\n在你的应用程序被创建后，请查看 [第一步](/zh-hans/usage/first-steps) 以开始你的新应用。\n\n## 高级用法\n\n| 选项 / 标识       | 说明                                       |\n| ----------------- | ------------------------------------------ |\n| `[dir]`           | 添加一个带有项目名称的目录参数             |\n| `--noGit`         | 显式告诉 CLI 不在项目中初始化新的 git 仓库 |\n| `-y`, `--default` | 跳过 CLI 并选中所有选项来初始化新的 t3-app |\n| `--noInstall`     | 创建项目，但不自动安装依赖包               |\n\n## 实验性用法\n\n我们的 CI 有一些实验性的标识，允许你可以无需问答式地直接创建应用程序。如果这种用例适用于你，你可以使用这些标识。请注意，这些标识是实验性的，将来可能会在不遵循 semver 版本的情况下改变。\n\n| 标识         | 描述                      |\n| ------------ | ------------------------- |\n| `--CI`       | 让 CLI 知道你在 CI 模式中 |\n| `--trpc`     | 添加 tRPC 到项目          |\n| `--prisma`   | 添加 Prisma 到项目        |\n| `--nextAuth` | 添加 NextAuth.js 到项目   |\n| `--tailwind` | 添加 Tailwind CSS 到项目  |\n\n<Callout type=\"warning\">\n  如果你没有提供 `CI` 标识，那么其余的这些标识将无法生效。\n</Callout>\n\n你不需要明确地选择不要的依赖包。然而如果你想这样做，你可以在包名后加个 `false`，例如 `--nextAuth false`。\n\n### 示例\n\n下面的命令将使用 tRPC 和 Tailwind CSS 创建一个 T3 应用程序。\n\n```bash\npnpm dlx create-t3-app@latest --CI --trpc --tailwind\n```\n"
  },
  {
    "path": "www/src/pages/zh-hans/introduction.md",
    "content": "---\ntitle: 简介\ndescription: T3 Stack 简介\nlayout: ../../layouts/docs.astro\nlang: zh-hans\n---\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/YkOSUVzOAA4\" title=\"The best stack for your next project\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n## T3 Stack\n\n_\"T3 Stack\"_ 是由 [Theo](https://twitter.com/t3dotgg) 创建的一个 web 开发技术栈，专注于简单性、模块化和全栈类型安全。\n\n核心部分是 [**Next.js**](https://nextjs.org/) 和 [**TypeScript**](https://typescriptlang.org/)。[**Tailwind CSS**](https://tailwindcss.com/) 几乎总是被包含在内。如果你正在做任何类似后端的事情，[**tRPC**](https://trpc.io/)、[**Prisma**](https://prisma.io/) 和 [**NextAuth.js**](https://next-auth.js.org/) 都是很好的补充。\n\n你可能已经注意到它有很多组成部分，这是设计如此。按需调换——本技术栈的核心是模块化的 :)\n\n## 所以 ... create-t3-app 是什么？一个模板吗？\n\n算是吧？`create-t3-app` 是由经验丰富的 T3 Stack 开发者构建的 CLI 命令行工具，用于简化一个模块化的 T3 Stack 应用程序的配置过程。这意味着每个部分都是可选的，而“模板”则是根据你的具体需求生成的。\n\n经过无数项目和多年的技术积累，我们沉淀了很多的观点和见解。我们尽力将它们融入到了这个 CLI 中。\n\n这**不是**一个包罗万象的模板。我们**期望**你能带来自己的库，以解决**你自己的**应用程序需求。虽然我们不想为更具体的问题（如状态管理和项目部署）指定解决方案，但我们 [在这里列出了一些推荐选项](/zh-hans/other-recs)。\n\n## T3 原则\n\n坦白地说——这是一个非常 _opinionated 的项目_。我们在构建方面有不少共同的核心信念，并把它们作为我们做出决策的基础。\n\n### 解决问题\n\n很容易陷入“添加一切”的陷阱 —— 我们明确不想这样做。被添入到 `create-t3-app` 中的每个部分都应该解决存在于核心技术中的特定问题。这意味着我们不会添加诸如状态库（`zustand`、`redux`）之类的东西，但我们会添加像 NextAuth.js 之类的库，并为你集成 Prisma 和 tRPC。\n\n### 负责任地“尝鲜”\n\n我们热爱前沿技术。诚然，新技术带来的速度和乐趣真的很酷。我们认为，负责任地尝试新技术很重要，可以在风险较小的部分使用风险较大的技术。这意味着我们不会 ⛔️ 把赌注押在有风险的新数据库技术上（SQL 很棒！）。但我们很乐意 ✅ 押注于 tRPC，因为它只是一些很容易被移除的函数而已。\n\n### 类型安全不是可选的\n\nCreate T3 App 宣称的目标是提供最快捷的方式来创建一个新的全栈**类型安全**的 web 应用。我们在这方面十分认真对待类型安全，因为它确实提高了我们的生产力，并帮助我们减少了错误的产生。倘若你想在类型安全上做出妥协，你应该另外创建一个项目，而不是使用 Create T3 App。\n"
  },
  {
    "path": "www/src/pages/zh-hans/other-recs.md",
    "content": "---\ntitle: 其他推荐\ndescription: 我们推荐的一些库和服务\nlayout: ../../layouts/docs.astro\nlang: zh-hans\n---\n\n我们意识到 `create-t3-app` 所包含的库或工具并不能解决每一个问题。虽然我们鼓励你用我们提供的这些工具来创建项目，但有的时候你还是会需要用到其他库。只有你自己才能了解你的项目真正需要什么，不过这里有一份我们自己经常推荐的库或工具的清单，你大可参考一下。\n\n这些推荐来自于 Create T3 App 的个人贡献者们，不应该被视为 Create T3 App 团队或这个开源软件的“官方”认可。_**请自行搜索，尤其是在使用付费服务之前**_。\n\n## 状态管理\n\n_**编者注词**_: 状态管理库本身很棒，但经常没有必要使用。tRPC 集成的 React Query hooks 应该能够胜任处理服务端的状态。对于客户端的状态，先用 React 自带的 `useState`，倘若还有需求再从这些库里挑一个使用。\n\n### Zustand\n\n**没有必要再使用 Redux 了**\n\n你不知道你是否需要这个现代版的精简 Redux。但 [Poimandres](https://github.com/pmndrs) 这个团队永远值得你的信任。无论你想构建什么，从视频通话应用到游戏，乃至服务器端，你都可以通过这个轻量库来处理状态。\n\n- [Zustand 官网](https://zustand-demo.pmnd.rs/)\n- [Zustand GitHub](https://github.com/pmndrs/zustand)\n\n### Jotai\n\n**没有必要再使用 Context 了**\n\n没有比 Jotai 更能以原子化的方式处理状态的了。同样由 [Poimandres](https://github.com/pmndrs) 出品，Jotai 可以让你定义一些状态原子，它们像是全局的 useState。对于一些状态，用状态机来解决似乎“大材小用”，这时候用 Jotai 来处理是非常不错的选择。\n\n- [Jotai 官网](https://jotai.org/)\n- [Jotai GitHub](https://github.com/pmndrs/jotai)\n\n## 组件库\n\n大部分应用都需要不少组件 —— 开关按钮、下拉菜单、对话框等等。以下这些库都提供了非常不错的支持无障碍访问的组件，并且能够让你根据喜好自定义修改。\n\n### 无样式的组件库\n\n也常以无头组件库为人所知，它们提供了无样式、支持无障碍访问的组件，支持根据个人喜好自定义样式。这里罗列了一些推荐。\n\n- [Radix UI](https://www.radix-ui.com/) 给你提供了一系列方便的无障碍底层组件，能够让你搭配原生 CSS 或 Tailwind CSS 使用。\n\n- [Headless UI](https://headlessui.com/) 由 Tailwind CSS 官方团队出品，同样也提供了无样式、支持无障碍访问的组件，你可以无缝将它们与 Tailwind CSS 搭配使用。\n\n- [React Aria](https://react-spectrum.adobe.com/react-aria/) 来自于 Adobe，同样也提供了支持无障碍访问的底层组件，你可以拿来搭建设计系统。他们的日期选择组件绝对是数一数二的。\n\n### 包含样式的组件库\n\n**适用于当你想要你的应用看起来还不错时**\n\n有时候在创建应用时，你只想要你的应用 UI 一开始就看起来还不错，不想自行逐一设计每个组件。那对于管理面板或其他类似的项目，以下任何一个组件库都能帮你达到目标。\n\n- [Chakra UI](https://chakra-ui.com)\n- [Mantine](https://mantine.dev)\n- [@shadcn/ui](https://ui.shadcn.com/)\n\n### Class Variance Authority\n\n**适用于拿来构建 UI 库**\n\nCVA 能让你声明式地通过不同的颜色、尺寸等组成不同变体，从而构建一个 UI 库。当你的项目达到一定规模后，你可能想要通过使用 Tailwind CSS 来实现多个组件变体，进而来实现 UI 组件标准化，这时候就是 CVA 派上用场的时候了。\n\n- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)\n\n## 动画\n\n当你需要在应用中使用动画，这里是我们的推荐。\n\n### AutoAnimate\n\n**适用于用一行代码完成动画**\n\n大部分动画库都试着满足每种使用场景，这会导致它们变得很笨重。AutoAnimate 是一款零配置的工具，它能够显著地为你带来 UX 的提升，而不需要额外的代码。\n\n- [AutoAnimate 官网](https://auto-animate.formkit.com/)\n- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)\n- [AutoAnimate 组件代码片段](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)\n\n### Framer Motion\n\n**适用于用声明式代码来完成复杂动画**\n\nFramer Motion 提供了一种简单、声明式的语法，从复杂的动画，甚至到手势操作，它都能让你可以通过少量代码来实现。\n\n- [Framer Motion 官网](https://framer.com/motion)\n- [Framer Motion 文档](https://www.framer.com/docs/)\n\n## 部署、基础设施、数据库和持续集成\n\n### Vercel\n\n**适用于部署你的 App**\n\nVercel 帮你解决了 web 应用部署的痛点，可以让你轻松通过 GitHub 仓库部署你的应用。我们部署在 Vercel 的服务已经扩展达到数十万用户，目前还没有任何问题。Vercel 基于 AWS，不过有更好的交互界面 :)\n\n- [Vercel 官网](https://vercel.com/)\n- [Create T3 App Vercel 部署指引](/zh-hans/deployment/vercel)\n\n### PlanetScale\n\n**适用于免操心地使用数据库**\n\nPlanetScale 是我们目前用过的最好的“无服务数据库平台”。它有着令人惊叹的规模、出色的开发者体验，以及超值的价格。如果你正在使用 SQL（希望是 Prisma），PlanetScale 是你的不二之选。\n\n- [PlanetScale 官网](https://planetscale.com/)\n\n### Railway\n\n**适用于托管你的基建**\n\n“现代版的 Heroku”。最快速简单的方式来启用一个服务器。如果 Vercel 和 PlanetScale 都无法满足你的需求，Railway 很可能是唯一的选择了。将它对接到 GitHub 仓库就行了。\n\n- [Railway 官网](https://railway.app/)\n\n### Upstash\n\n**适用于需要无服务的 Redis**\n\n我们很喜欢 Prisma 和 PlanetScale，但是有一些项目要求更高的性能。Upstash 允许你的应用能获得 Redis 提供的内存高性能，而无需自己去管理和扩容服务器。\n\n- [Upstash 官网](https://upstash.com/)\n\n### Pusher\n\n**适用于需要无服务的 WebSockets**\n\n如果 WebSockets 是你项目的主要聚焦点，你可能需要考虑使用一个更传统的后端服务，例如 [Fastify](https://www.fastify.io/) （它同样也可以 [搭配 tRPC 使用！](https://trpc.io/docs/v10/fastify)）。但是要快速将 Webstockets 添加到 T3 项目中， Pusher 是一个很好的选择。\n\n- [Pusher 官网](https://pusher.com/)\n\n### Soketi\n\nSoketi 是一个支持自行部署的、简单快速的 Pusher 替代方案。它完全与 Pusher SDK 兼容。无服务的 Soketi 也正处于 beta 阶段。\n\n- [Soketi 官网](https://soketi.app)\n- [Soketi GitHub](https://github.com/soketi/soketi)\n\n## 数据统计分析\n\n当你创建一个应用的时候，用户统计数据是十分宝贵的。这里罗列了一些我们推荐的数据统计分析工具。\n\n### Plausible\n\n需要数据统计和分析？使用 Plausible 是最快的方法之一。它超级轻量，甚至还有一个针对 [Next.js 的简单插件](https://plausible.io/docs/proxy/guides/nextjs)。\n\n- [Plausible 官网](https://plausible.io/)\n\n### Umami\n\nUmami 是一个开源的、支持自行部署、简单快速、注重隐私的 Google Analytics 备选方案。你可以使用 PlanetScale 作为数据库，轻松地将其部署到 Vercel、Railway 等平台上，也可以使用其云版本。\n\n- [Umami 官网](https://umami.is/)\n- [Umami GitHub](https://github.com/umami-software/umami)\n- [Umami Cloud](https://cloud.umami.is/)\n\n## 其他\n\n### Next Bundle Analyzer\n\n有时候想要确定 App 中哪部分被纳入打包文件中是很困难的。Next Bundle Analyzer 这个工具可以为你可视化并分析自动生成的 JavaScript 打包文件。\n\n- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer)\n"
  },
  {
    "path": "www/src/pages/zh-hans/t3-collection.mdx",
    "content": "---\ntitle: T3 合集\ndescription: 那些使用 T3 stack 的有趣开源项目和公司\nlayout: ../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport OpenSourceAppList from \"../../components/docs/openSourceAppList.tsx\";\nimport CompanyList from \"../../components/docs/companyList.tsx\";\nimport Callout from \"../../components/docs/callout.tsx\";\n\n使用 T3 stack 创建了一个项目并想要分享？将它添加到这个列表里吧。\n\n## 使用 T3 Stack 的开源项目\n\n<OpenSourceAppList descriptionIntl=\"描述\" repoIntl=\"仓库\" linkIntl=\"链接\" />\n\n## 使用 T3 Stack 的公司\n\n我们很乐意知道哪些公司使用了 T3 stack 来构建他们的应用。你所在的公司正在使用 T3 stack 并且想要分享它？快加入到下方的列表中吧！\n\n<CompanyList companyIntl=\"公司\" linkIntl=\"链接\" />\n\n<Callout type=\"tip\">用 T3 stack 构建了很酷的项目？开一个 [PR](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) 将它加进来吧！</Callout>\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/drizzle.mdx",
    "content": "---\ntitle: Drizzle\ndescription: Drizzle 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nDrizzle 是一个无头的 TypeScript ORM，提供 [关系型](https://orm.drizzle.team/docs/rqb) 和 [类 SQL](https://orm.drizzle.team/docs/select) 的查询 API。它可以处理数据库迁移和模式，并提供类型安全的数据库客户端。同时，它还附带 [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview)，一组用于帮助查询数据库的工具。\n\n## Drizzle 客户端\n\nDrizzle 客户端位于 `src/server/db/index.ts` 文件中。在此文件中，您可以定义数据库连接 URL，并将数据库模式连接到数据库对象。\n\n```ts:src/server/db/index.ts\nimport { env } from \"~/env\";\nimport * as schema from \"./schema\";\nimport postgres from \"postgres\";\n\nconst conn = postgres(env.DATABASE_URL);\n\nexport const db = drizzle(conn, { schema });\n```\n\n我们建议将数据库客户端包含在 tRPC 的 Context 中：\n\n```ts:src/server/api/trpc.ts\nimport { db } from \"~/server/db\";\n\nexport const createTRPCContext = async (opts: { headers: Headers }) => {\n  const session = await auth();\n\n  return {\n    db,\n    session,\n    ...opts,\n  };\n};\n```\n\n## 模式（Schema）\n\nDrizzle 的模式文件位于 `src/server/db/schema.ts`。此文件是您定义数据库模式和模型的地方，并与 Drizzle 客户端连接。\n\n当您选择使用 NextAuth.js 配合 Prisma 时，模式文件会按照 [Auth.js 文档](https://authjs.dev/getting-started/adapters/drizzle) 中的推荐值，为 `User`、`Session`、`Account` 和 `VerificationToken` 模型自动生成并设置。\n\n## Drizzle Kit\n\nDrizzle Kit 是一组命令行工具，旨在帮助您管理数据库。当您选择 Drizzle 作为 ORM 时，T3 Stack 会自动包含 Drizzle Kit。\n\n```json:package.json\n\"scripts\": {\n    ...\n    \"db:generate\": \"drizzle-kit generate\",\n    \"db:migrate\": \"drizzle-kit migrate\",\n    \"db:push\": \"drizzle-kit push\",\n    \"db:studio\": \"drizzle-kit studio\",\n    ...\n  },\n```\n\n### 脚本说明\n\n`db:generate`  \n从数据库模式生成 TypeScript 类型和模型，确保类型安全并轻松与 Drizzle ORM 集成。\n\n`db:migrate`  \n将待处理的迁移应用到数据库中，保持模式与项目中的更改和更新同步。\n\n`db:push`  \n将本地模式更改直接推送到数据库，而无需显式的迁移文件。这在开发中快速同步时非常有用。\n\n`db:studio`  \n打开一个可视化界面，用于管理和检查数据库表、数据和关系。\n\n## 实用资源\n\n| 资源                   | 链接                                                |\n| ---------------------- | --------------------------------------------------- |\n| Drizzle 文档           | https://orm.drizzle.team/docs/overview              |\n| Drizzle GitHub         | https://github.com/drizzle-team/drizzle-orm         |\n| Auth.JS Drizzle 适配器 | https://authjs.dev/getting-started/adapters/drizzle |\n| Drizzle Kit 迁移指南   | https://orm.drizzle.team/docs/kit-overview          |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/env-variables.mdx",
    "content": "---\ntitle: 环境变量\ndescription: 开始使用 create-t3-app\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\nCreate T3 App 使用自己的包 [@t3-oss/env-nextjs](https://env.t3.gg) 和 [zod](https://zod.dev) ，通过在 `src/env.js` 中提供一个简单的逻辑，在运行时和构建时验证环境变量。\n\n## env.js\n\n_简而言之，如果你想要添加一个新的环境变量，你需要在 src/env.js 中添加一个验证器，然后在 .env 文件中添加键值对。_\n\n```ts:env.js\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    NODE_ENV: z.enum([\"development\", \"test\", \"production\"]),\n  },\n  client: {\n    // NEXT_PUBLIC_CLIENTVAR: z.string(),\n  },\n  runtimeEnv: {\n    NODE_ENV: process.env.NODE_ENV,\n  },\n});\n```\n\nT3 Env 使用 `createEnv` 函数来创建 schema，以验证客户端和服务端的环境变量。\n\n<Callout type=\"info\">\n  如果你想了解更多 `createEnv` 函数的内部工作原理，可以参看 [T3\n  Env](https://env.t3.gg/docs/introduction) 的文档。\n</Callout>\n\n## 使用环境变量\n\n当你想使用你的环境变量时，你可以从创建的 `env.js` 中导入，并像平常一样使用它们。如果你在客户端导入并尝试访问服务端环境变量，你将得到一个运行时错误。\n\n```ts:pages/api/hello.ts\nimport { env } from \"../../env.js\";\n\n// `env` 是完全类型安全的，并提供自动完成功能\nconst dbUrl = env.DATABASE_URL;\n```\n\n```ts:pages/index.tsx\nimport { env } from \"../env.js\";\n\n// ❌ 这将抛出一个运行时错误\nconst dbUrl = env.DATABASE_URL;\n\n// ✅ 这是正确的\nconst wsKey = env.NEXT_PUBLIC_WS_KEY;\n```\n\n## .env.example\n\n由于默认的 `.env` 文件不会被提交到版本控制中，因此我们还提供了一个 `.env.example` 文件，你可以在其中选择性地保留你的 `.env` 文件的副本，并删除其中的任何机密信息。这不是必需的，但我们建议保持示例文件的更新，以便让贡献者更轻松地开始配置他们的环境。\n\n有些框架和构建工具（例如 Next.js）建议你将机密信息存储在 `.env.local` 文件中，并将 `.env` 文件提交到你的项目中。我们不建议这样做，因为这样很容易意外地将机密信息提交到你的项目中。相反，我们建议你将机密信息存储在 `.env` 文件中，将 `.env` 文件添加到 `.gitignore` 中，只将 `.env.example` 文件提交到你的项目中。\n\n## 添加环境变量\n\n为了确保项目所需的环境变量不会丢失，您需要在两个位置添加新的环境变量。\n\n📄 `.env`：像在 `.env` 文件中一样输入您的环境变量，例如：`KEY=VALUE`\n\n📄 `env.js`：为每个环境变量添加适当的验证逻辑，在 `createEnv` 中定义一个Zod模式，例如：`KEY: z.string()`。此外，确保在 `runtimeEnv` 选项中对它们进行解构，例如：KEY: `process.env.KEY`\n\n<Callout type=\"info\">\n  为什么需要在 `runtimeEnv` 中对环境变量进行解构？ 这是由于 Next.js\n  在某些运行时中绑定环境变量的方式所致。 通过手动解构，可以确保变量永远不会从\n  bundle 中剔除。\n</Callout>\n\n你也可以选择更新 `.env.example`\n\n📄 `.env.example`：输入你的环境变量，但确保不要在 `runtimeEnv` 选项中包含机密信息, 例如： `KEY=VALUE` 或 `KEY=`\n\n### 示例\n\n1. 在 `.env` 中添加环境变量：\n\n```\nTWITTER_API_TOKEN=1234567890\n```\n\n2. 在 `env.js` 中添加环境变量：\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    TWITTER_API_TOKEN: z.string(),\n  },\n  // ...\n  runtimeEnv: {\n    // ...\n    TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,\n  },\n});\n```\n\n3. _可选：_ 将环境变量添加到 `.env.example`，并确保不在 `runtimeEnv` 选项中包含机密信息。\n\n```bash\nTWITTER_API_TOKEN=\n```\n\n## 类型强制\n\n所有添加到 `.env` 中的变量都将以字符串的形式导入，即使它们的值表示不同的类型。如果你想在运行时使用不同类型的环境变量，可以使用 Zod 的 `coerce` 将字符串转换为你想要的类型。如果转换失败，它将抛出错误。\n\n将变量添加到你的 `.env`：\n\n```\nSOME_NUMBER=123\nSOME_BOOLEAN=true\n```\n\n然后，在 `env.js` 中验证它们：\n\n```ts\nimport { createEnv } from \"@t3-oss/env-nextjs\";\nimport { z } from \"zod\";\n\nexport const env = createEnv({\n  server: {\n    SOME_NUMBER: z.coerce.number(),\n    SOME_BOOLEAN: z.coerce.boolean(),\n  },\n  // ...\n  runtimeEnv: {\n    SOME_NUMBER: process.env.SOME_NUMBER,\n    SOME_BOOLEAN: process.env.SOME_BOOLEAN,\n  },\n});\n```\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/first-steps.md",
    "content": "---\ntitle: 第一步\ndescription: 从你的全新 T3 App 开始吧\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\n你刚刚创建了一个全新的 T3 App，并准备好继续。下面是一些最简化的必要准备，来让你的 App 运行起来。\n\n## 数据库\n\n如果你的 App 包括了 Prisma，务必记得从项目根目录运行命令 `npx prisma db push`。 这行命令将同步 Prisma schema 和你的数据库，并且会根据 schema 为 Prisma 客户端生成对应的类型声明。注意你在完成这一步之后，需要 [重启 TypeScript 服务器](https://tinytip.co/tips/vscode-restart-ts/)，以便它能够检测到那些生成的类型。\n\n### Drizzle\n\n如果你的 App 包含了 Drizzle，请查看 `.env` 文件，了解如何构建你的 `DATABASE_URL` 环境变量。当 env 文件准备就绪后，运行 `pnpm db:push`（或其他软件包管理器的类似方法）来推送你的 schema。\n\n## 认证\n\n如果你的 App 包含了 NextAuth.js，那我们可以先从 `DiscordProvider` 开始。这是 NextAuth.js 提供的最简单的第三方服务之一，但是它仍然需要你做一些初始化的操作。\n\n当然，如果你倾向于使用另一个第三方认证服务，你可以在 NextAuth.js 支持的 [服务列表](https://next-auth.js.org/providers/) 中找到你想要的服务。\n\n1. 你将需要一个 Discord 账号，所以如果你没有，请先注册一个。\n2. 前往 <https://discord.com/developers/applications> 然后在右上角点击 \"New Application\"。给你的应用创建一个名称，并同意相关的服务条款。\n3. 当你的应用被创建后，前往 \"Settings → OAuth2 → General\"。\n4. 复制 \"Client ID\" 然后作为 `AUTH_DISCORD_ID` 添加到 `.env`。\n5. 点击 \"Reset Secret\"，复制新的密钥，然后作为 `AUTH_DISCORD_SECRET` 添加到 `.env`。\n6. 点击 \"Add Redirect\"，然后输入 `http://localhost:3000/api/auth/callback/discord`。\n   - 对于生产环境的部署，按照之前的步骤来创建另一个 Discord 应用，但是这一次将链接 `http://localhost:3000` 替换为实际生产环境的链接。\n7. 保存你的更改。\n\n你现在应该可以登入到你的应用中了。\n\n## 编辑器设置\n\n为了获得最佳的开发者体验，建议安装以下扩展。下面的链接提供了针对特定编辑器的插件支持。\n\n- [Prisma 扩展](https://www.prisma.io/docs/guides/development-environment/editor-setup)\n- [Tailwind CSS IntelliSense 扩展](https://tailwindcss.com/docs/editor-setup)\n- [Prettier 扩展](https://prettier.io/docs/en/editors.html)\n\n## 下一步\n\n- 如果你的应用包含了 tRPC，参看 `src/pages/index.tsx` 和 `src/server/api/routers/post.ts` 来了解 tRPC 查询是如何工作的。\n- 浏览 Create T3 App 的文档，以及你应用中所用到包的文档。\n- 加入到我们的 [Discord](https://t3.gg/discord) 中，并记得在 [GitHub](https://github.com/t3-oss/create-t3-app) 上给我们的项目点颗星！ :)\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/index.astro",
    "content": "---\nimport IndexPage from \"../../../components/docs/indexPage.astro\";\nimport { SIDEBAR, type Frontmatter } from \"../../../config\";\nimport { getLanguageFromURL } from \"../../../languages\";\nimport Layout from \"../../../layouts/docs.astro\";\n\nconst frontmatter: Frontmatter = {\n  title: \"Usage\",\n  layout: \"docs\",\n  description: \"Learn how to use the different technology from the T3 Stack.\",\n};\n\nconst lang = getLanguageFromURL(Astro.url.pathname);\nconst sidebarEntries = SIDEBAR[lang][\"Usage\"]!;\nconst files = await Astro.glob(\"./*.{md,mdx,astro}\");\n---\n\n<Layout frontmatter={frontmatter} headings={[]}>\n  <IndexPage\n    frontmatter={frontmatter}\n    sidebarEntries={sidebarEntries}\n    files={files}\n  />\n</Layout>\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/next-auth.mdx",
    "content": "---\ntitle: NextAuth.js\ndescription: NextAuth.js 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\nisMdx: true\n---\n\nimport Callout from \"../../../components/docs/callout.tsx\";\n\n当你想在你的 Next.js 应用中集成认证系统时，NextAuth.js 是一个很好的解决方案，它为我们引入了足够复杂的安全措施，而无需我们自己去构建。它广泛支持不同的服务，能够快速将 OAuth 认证集成进来，并为许多数据库和 ORM 提供了适配器。\n\n## Context Provider\n\n在你应用的入口处，你会看到整个应用被 [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider) 包裹：\n\n```tsx:pages/_app.tsx\n<SessionProvider session={session}>\n  <Component {...pageProps} />\n</SessionProvider>\n```\n\n这个上下文 provider 能使你在应用的任何地方访问到 session 数据，而不需要一层一层地将它作为参数传递：\n\n```tsx:pages/users/[id].tsx\nimport { useSession } from \"next-auth/react\";\n\nconst User = () => {\n  const { data: session } = useSession();\n\n  if (!session) {\n    // 处理未认证的情况，例如渲染一个登入组件\n    return <SignIn />;\n  }\n\n  return <p>Welcome {session.user.name}!</p>;\n};\n```\n\n## 在服务端检索 session\n\n有时你可能想在服务端请求 session。 为此, 可以使用 `create-t3-app` 提供的`getServerAuthSession` 辅助函数来预获取 session，然后使用 `getServerSideProps` 将其传递给客户端：\n\n```tsx:pages/users/[id].tsx\nimport { getServerAuthSession } from \"../server/auth\";\nimport { type GetServerSideProps } from \"next\";\n\nexport const getServerSideProps: GetServerSideProps = async (ctx) => {\n  const session = await getServerAuthSession(ctx);\n  return {\n    props: { session },\n  };\n};\n\nconst User = () => {\n  const { data: session } = useSession();\n  // 注意: `session` 不会有加载状态，因为它已经在服务器上预获取了。\n\n  ...\n}\n```\n\n## 在 session 中添加 `user.id`\n\n默认设置下， Create T3 App 利用了 NextAuth.js 配置里的 [session 回调函数](https://next-auth.js.org/configuration/callbacks#session-callback) 来帮你将用户的 ID 添加到 `session` 对象里。\n\n```ts:server/auth.ts\ncallbacks: {\n    session({ session, user }) {\n      if (session.user) {\n        session.user.id = user.id;\n      }\n      return session;\n    },\n  },\n```\n\n这耦合了类型声明文件，来保证从 `session` 对象里获取 `user.id` 时，它是类型安全的。 参看 NextAuth.js 的文档，阅读更多关于 [`模块扩充`](https://next-auth.js.org/getting-started/typescript#module-augmentation)。\n\n```ts:server/auth.ts\nimport { DefaultSession } from \"next-auth\";\n\ndeclare module \"next-auth\" {\n  interface Session {\n    user?: {\n      id: string;\n    } & DefaultSession[\"user\"];\n  }\n}\n```\n\n你也可以用同样的方法将其他数据，例如 `role` 字段加入到 `session` 对象里，**但不应该被滥用于在客户端存储敏感数据**。\n\n## 搭配 tRPC 的用法\n\n当你搭配 NextAuth.js 和 tRPC 一同使用时，你可以通过 [中间件](https://trpc.io/docs/v10/middlewares) 来创建可复用的、受保护的 procedure 路由函数。只有登入后的用户才能访问这些受保护的路由。`create-t3-app` 已经为你铺好了路，使你能够在认证路由里轻松访问到 session 里的数据。\n\n这个过程可以被分为两步完成：\n\n1. 先通过函数 [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession) 从请求头里获得 session。使用 `getServerSession` 而不是普通的 `getSession` 函数的优势是，它是一个服务端的函数，不会触发无必要的数据请求调用。 `create-t3-app` 创建了一个帮助函数，将这个特殊的 API 抽象了出来，这样你就不需要每次访问会话时都导入你的 NextAuth.js 选项以及 `getServerSession` 函数。\n\n```ts:server/auth.ts\nexport const getServerAuthSession = (ctx: {\n  req: GetServerSidePropsContext[\"req\"];\n  res: GetServerSidePropsContext[\"res\"];\n}) => {\n  return getServerSession(ctx.req, ctx.res, authOptions);\n};\n```\n\n通过使用这个帮助函数，我们可以获取 session，并将它传给 tRPC 的上下文：\n\n```ts:server/api/trpc.ts\nimport { getServerAuthSession } from \"../auth\";\n\nexport const createContext = async (opts: CreateNextContextOptions) => {\n  const { req, res } = opts;\n  const session = await getServerAuthSession({ req, res });\n  return await createContextInner({\n    session,\n  });\n};\n```\n\n2. 创建一个 tRPC 中间件，来检测用户是否已通过认证。然后我们可以在一个 `protectedProcedure` 里调用该中间件。任何对该路由的调用都会被要求认证，否则会抛出一个错误，由客户端妥善处理。\n\n```ts:server/api/trpc.ts\nexport const protectedProcedure = t.procedure.use(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: \"UNAUTHORIZED\" });\n  }\n  return next({\n    ctx: {\n      // inferer `session` som ikke-nullbar\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n}));\n```\n\n这个 session 对象是对用户数据的一个轻量、最小化表示，仅包含了少量字段。当使用 `protectedProcedures` 时，你可以借助访问用户 ID 来从数据库里读取该用户的更多数据。\n\n```ts:server/api/routers/user.ts\nconst userRouter = router({\n  me: protectedProcedure.query(async ({ ctx }) => {\n    const user = await prisma.user.findUnique({\n      where: {\n        id: ctx.session.user.id,\n      },\n    });\n    return user;\n  }),\n});\n```\n\n## 搭配 Prisma 使用\n\n要将 NextAuth.js 搭配 Prisma 一起使用需要非常多的 [初始化步骤](https://authjs.dev/reference/adapter/prisma/)。`create-t3-app` 可以帮你完成这些工作，如果你在用 CLI 创建应用时同时选择了 Prisma 和 NextAuth.js，那你的应用已经集成了一个完全正常运行的认证系统，所有的数据库模型都已经预先配置好了。我们为你的应用预先配置了 Discord OAuth 认证服务，因为它是最方便实现的服务之一 —— 只需要在 `.env` 文件里提供令牌即可。然而，你也可以根据 [NextAuth.js 文档](https://next-auth.js.org/providers/) 来轻松添加更多其他第三方认证服务。要注意的是有部分特定的第三方服务需要你在数据模型上添加额外的字段。我们推荐你去阅读你想要添加的第三方验证服务的文档，以便确保你已经提供所有要求的字段了。\n\n### 给你的模型添加新的字段\n\n当你给 `User`、`Account`、`Session` 或 `VerificationToken` 中任何一个模型添加字段时（大部分情况你只需要修改 `User` 模型），你要注意的是 [Prisma 适配器](https://next-auth.js.org/adapters/prisma) 会在用户注册和登入时自动给这些模型添加额外的字段，因此你必须给这些字段提供初始值，因为这个适配器并不能知道这些字段是否已经存在。\n\n如果你想要，例如给 `User` 模型添加一个 `role` 字段，你需要为它提供一个默认初始值。你可以通过给 `User` 模型的 `role` 字段添加一个 `@default` 属性来完成：\n\n```diff:prisma/schema.prisma\n+ enum Role {\n+   USER\n+   ADMIN\n+ }\n\n  model User {\n    ...\n+   role Role @default(USER)\n  }\n```\n\n## 搭配 Next.js 中间件使用\n\n将 NextAuth.js 搭配 Next.js 中间件一同使用[需要采用 JWT session 策略](https://next-auth.js.org/configuration/nextjs#caveats) 来进行认证。这是因为只有当会话 cookie 为 JWT 时，中间件才能够获取到它。默认情况下，Create T3 App 会用 Prisma 作为数据库适配器，并采取**默认**的数据库策略。\n\n<Callout type=\"warning\">\n  使用数据库会话是推荐的方法，如果要切换到 JWT 会话策略，请先了解\n  JWT，以避免出现任何安全问题。\n</Callout>\n\n在切换到 JWT 会话策略后，请确保更新 `src/server/auth.ts` 中的 `session` 回调函数。\n`user` 对象将为 `undefined`。相反，应从 `token` 对象中检索用户的 ID。\n例如：\n\n```diff:server/auth.ts\n  export const authOptions: NextAuthOptions = {\n+   session: {\n+     strategy: \"jwt\",\n+   },\n    callbacks: {\n-     session({ session, user }) {\n+     session({ session, token }) {\n-       if (session.user) {\n+       if (session.user && token.sub) {\n-         session.user.id = user.id;\n+         session.user.id = token.sub;\n        }\n        return session;\n      }\n    },\n  };\n```\n\n## 配置默认的 DiscordProvider\n\n1. 前往 [Discord 开发者页面的应用部分](https://discord.com/developers/applications)，然后点击 \"New Application\"\n2. 在设置菜单中，依次前往 \"OAuth2 => General\"\n\n- 复制 Client ID，然后粘贴到 `.env` 文件中的 `AUTH_DISCORD_ID`。\n- 在 Client Secret 下方，点击 \"Reset Secret\"，然后复制该字符串到 `env` 中的 `AUTH_DISCORD_SECRET`。务必要细心，因为你无法再次查看该密钥了，而将它重置会让现存的密钥失效。\n- 点击 \"Add Redirect\"，然后将你应用的网址替换 `<app url>/api/auth/callback/discord` 里的 `<app url>`（例如，一个开发阶段的完整链接像这样：<code class=\"break-all\">http://localhost:3000/api/auth/callback/discord</code>）\n- 保存你的更改\n- 在开发和生产环境使用同一个 Discord 应用是可行的，但不鼓励这么做。你应该也考虑在开发阶段 [模拟认证服务](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts)。\n\n## 有用的资源\n\n| 资源                              | 链接                                    |\n| --------------------------------- | --------------------------------------- |\n| NextAuth.js 文档                  | https://next-auth.js.org/               |\n| NextAuth.js GitHub                | https://github.com/nextauthjs/next-auth |\n| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth  |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/next-js.md",
    "content": "---\ntitle: Next.js\ndescription: Next.js 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\nNext.js 是你 React 应用的后端框架。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/W4UhNo3HAMw\" title=\"Next.js is a backend framework\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n不妨观看 [Theo 在 Next.js Conf 上的演讲](https://www.youtube.com/watch?v=W4UhNo3HAMw) 来更好地理解 Next.js 究竟是什么以及它是如何运作的。</p>\n\n## 为什么我应该使用它？\n\n我们热爱 React。它以一种我们从未想过的方式将 UI 开发变得如此简单。但是它同样也给开发者们带来了一些困难。而 Next.js 就为我们提供了一种轻量 opinionated，却高度优化的方式来使用 React 创建应用。从路由到 API 定义，再到图片渲染，我们相信 Next.js 会帮助开发者做出正确的决定。\n\n而将 Next.js 搭配 [Vercel](https://vercel.com/) 一同使用使得 web 应用的开发体验前所未有的棒。他们慷慨的免费套餐以及非常直观的用户界面让我们可以通过点击几下的方式就可以部署网站（我们 ❤️ Vercel）。\n\n## Get Static / Server Props\n\nNext.js 的一项关键特性就是它支持的几种获取数据的方法。我们强烈推荐先通读 [官方文档](https://nextjs.org/docs/basic-features/data-fetching) 来理解如何使用每一种方法，以及它们之间的区别。一般情况下不推荐使用 `getServerSideProps`，除非有好的理由，因为它是一个阻塞 UI 的方法，会减慢你的网站运行速度。当数据是动态且需要被增量获取时，[Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) 便是 `getServerSideProps` 的一个非常好的备选方案。\n\n如果你仍需要使用这个特性，可以查看这些链接：[Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) 和 [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers)。\n\n## 有用的资源\n\n| 资源                        | 链接                               |\n| --------------------------- | ---------------------------------- |\n| Next.js 文档                | https://nextjs.org/docs            |\n| Next.js GitHub              | https://github.com/vercel/next.js  |\n| Next.js 博客                | https://nextjs.org/blog            |\n| Next.js Discord             | https://nextjs.org/discord         |\n| Next.js 推特                | https://twitter.com/nextjs         |\n| Vercel/Next.js YouTube 频道 | https://www.youtube.com/c/VercelHQ |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/prisma.md",
    "content": "---\ntitle: Prisma\ndescription: Prisma 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\nPrisma 是一个 TypeScript 的 ORM (Object-relational mapping) 工具，它允许你在文件 `schema.prisma` 中为你的数据库定义数据结构和模型，然后借此生成一个类型安全的客户端，从而在后端和你的数据库进行交互。\n\n## Prisma 客户端\n\nPrisma 客户端位于文件 `/server/db.ts`， 以全局变量被初始化（这被推荐为 [最佳实践](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem)），然后被导出用于你的各个 API 路由函数中。我们默认将 Prisma 客户端放置在 [上下文](/zh-hans/usage/trpc#-serverapitrpcts)，鼓励通过访问上下文来使用它，这样就无需在每个文件里导入了。\n\n## Schema\n\n你可以在 `/prisma/schema.prisma` 找到 Prisma 的 schema。在这个文件中你可以定义数据库的数据结构和模型，同时它也会被用于生成 Prisma 客户端。\n\n### 搭配 NextAuth.js\n\n当你选择 NextAuth.js 搭配 Prisma 使用时，根据 [NextAuth.js 文档](https://next-auth.js.org/adapters/prisma)，schema 文件会被自动生成，其中默认包含了 `User`、`Session`、`Account` 和 `VerificationToken` 模型，并已经自动添加了推荐的字段。\n\n## 默认数据库\n\n默认数据库是一个 SQLite 数据库，这对开发阶段来说很棒，因为它能够快速启动概念验证，但不推荐用于生产环境。你可以将 `datasource` 中的 `provider` 修改为 `postgresql` 或 `mysql`，然后在环境变量里修改一下对应数据库的连接地址，来更换数据库。\n\n## 给数据库填充初始数据\n\n[给数据库填充初始数据](https://www.prisma.io/docs/guides/database/seed-database) 是一种很好的方法，它能快速给你的数据库填充测试数据以帮助你开始。为了设置填充，你将需要在目录 `/prisma` 下创建一个 `seed.ts` 脚本文件，然后在 `package.json` 文件中添加 `seed` 命令。你也会需要一个 TypeScript 执行环境来运行该数据填充脚本。我们推荐 [tsx](https://github.com/esbuild-kit/tsx)，它采用 esbuild，是一个性能很好的 TypeScript 执行环境，无需额外的 ESM 配置，不过也可以使用 `ts-node` 或其他执行环境。\n\n```jsonc:package.json\n{\n  \"scripts\": {\n    \"db-seed\": \"NODE_ENV=development prisma db seed\"\n  },\n  \"prisma\": {\n    \"seed\": \"tsx prisma/seed.ts\"\n  }\n}\n```\n\n```ts:prisma/seed.ts\nimport { db } from \"../src/server/db\";\n\nasync function main() {\n  const id = \"cl9ebqhxk00003b600tymydho\";\n  await db.example.upsert({\n    where: {\n      id,\n    },\n    create: {\n      id,\n    },\n    update: {},\n  });\n}\n\nmain()\n  .then(async () => {\n    await db.$disconnect();\n  })\n  .catch(async (e) => {\n    console.error(e);\n    await db.$disconnect();\n    process.exit(1);\n  });\n```\n\n然后，运行命令 `pnpm db-seed`（或 `npm` / `yarn`）来给数据库填充初始数据。\n\n## 有用的资源\n\n| 资源                      | 链接                                                                                                                                              |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Prisma 文档               | https://www.prisma.io/docs/                                                                                                                       |\n| Prisma GitHub             | https://github.com/prisma/prisma                                                                                                                  |\n| Prisma Migrate 演练场     | https://playground.prisma.io/guides                                                                                                               |\n| NextAuth.JS Prisma 适配器 | https://next-auth.js.org/adapters/prisma                                                                                                          |\n| PlanetScale 连接指引      | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/tailwind.md",
    "content": "---\ntitle: Tailwind CSS\ndescription: Tailwind CSS 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\n## 什么是 Tailwind CSS？\n\nTailwind CSS 是一个[功能优先](https://tailwindcss.com/docs/utility-first) 的微型 CSS 框架，它可被用于创建自定义设计，而无需常规 CSS 要求的上下文切换。Tailwind CSS 纯粹是一个 CSS 框架，并不提供预设的组件或逻辑，相比如 Material UI 的组件库，它带来了非常 [不同的好处](https://www.youtube.com/watch?v=CQuTF-bkOgc)。\n\n它使得写 CSS 变得格外简单快速，如下面的例子所示：\n\n以往的 CSS：\n\n1. 通常在单独的文件里写 CSS\n\n```css\n.my-class {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  background-color: #fff;\n  border: 1px solid #e2e8f0;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n```\n\n2. 在组件里导入 CSS 文件\n\n```jsx\nimport \"./my-class.css\";\n```\n\n3. 将类名添加到 HTML 元素\n\n```html\n<div class=\"my-class\">...</div>\n```\n\n在 Tailwind CSS 中，这等同于：\n\n1. 直接在 HTML 元素里写类名\n\n```html\n<div\n  class=\"flex flex-col items-center justify-center rounded border border-gray-200 bg-white p-4\"\n>\n  ...\n</div>\n```\n\n当搭配 React 组件一同使用时，它强大的功能能够帮助我们快速搭建 UI。\n\nTailwind CSS 有一套内置的精美设计系统，它包含了精心挑选的色彩方案、为统一设计的尺寸模式（例如宽度 / 高度和填充 / 边距），以及为创建响应式布局所需的断点功能，这一切都开箱即用。这套设计系统可以完全按照你项目的需求来进行自定义配置和扩展。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/T-Zv73yZ_QI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nTru Narla 也即 [mewtru](https://twitter.com/trunarla) 之前发表过关于 [使用 Tailwind CSS 构建设计系统](https://www.youtube.com/watch?v=T-Zv73yZ_QI) 的精彩演讲。\n\n## 用法\n\n务必为你的代码编辑器添加对应的 Tailwind 插件，以提升开发体验。\n\n### 扩展与插件\n\n- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)\n- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)\n- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)\n\n### 格式化\n\nTailwind CSS 的类名很容易变得混乱，所以一个类名格式化工具非常有必要。[Tailwind CSS Prettier 插件](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) 会按照 [推荐的顺序](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) 给不同的类排序，这样代码里的类名顺序就和最终打包文件中的类名顺序保持一致。当你用命令行工具创建 T3 应用时选择了 Tailwind，我们会默认帮你安装并配置好该插件。\n\n### 条件性地添加类\n\n使用三元操作符来条件性地添加类会变得混乱，且难以阅读。以下两个包可以在需要条件性逻辑时帮你组织好类名。\n\n- [clsx](https://github.com/lukeed/clsx)\n- [classnames](https://github.com/JedWatson/classnames)\n\n## 有用的资源\n\n| 资源                      | 链接                                                     |\n| ------------------------- | -------------------------------------------------------- |\n| Tailwind 文档             | https://tailwindcss.com/docs/editor-setup/               |\n| Tailwind 备忘录           | https://nerdcave.com/tailwind-cheat-sheet/               |\n| awesome-tailwindcss       | https://github.com/aniftyco/awesome-tailwindcss/         |\n| Tailwind 社区             | https://github.com/tailwindlabs/tailwindcss/discussions/ |\n| Tailwind Discord 服务器   | https://tailwindcss.com/discord/                         |\n| TailwindLabs Youtube 频道 | https://www.youtube.com/tailwindlabs/                    |\n| Tailwind Playground       | https://play.tailwindcss.com/                            |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/trpc.md",
    "content": "---\ntitle: tRPC\ndescription: tRPC 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\ntRPC 能够让我们在无需代码自动生成器的帮助或在运行时额外检测的情况下，写出端对端类型安全的 API。它利用了 TypeScript 的强大推断功能来推断出你 API 路由的类型定义，并让你在前端能够调用 API 时充分享受完全类型安全和全自动补全的特性。当使用 tRPC 时，你应用的前端和后端部分会感觉比以前更加紧密，这带来了非常棒的开发体验。\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>我创建 tRPC 的目的是为了通过移除传统的 API 层来帮助人们更快地构建应用，但与此同时依然保证 App 在快速迭代的构建过程中不会出现大问题。<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @alexdotjs\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"https://avatars.githubusercontent.com/u/459267?v=4\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Alex - tRPC 的创建者</span>\n      <a\n        href=\"https://twitter.com/alexdotjs\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @alexdotjs\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n## 我怎么使用 tRPC?\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/2LYM8gf184U\" title=\"Making typesafe APIs easy with tRPC\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\ntRPC 贡献者 [trashh_dev](https://twitter.com/trashh_dev) 在 [Next.js Conf 上关于 tRPC 做了一个非常棒的演讲](https://www.youtube.com/watch?v=2LYM8gf184U)。若还没有看过的话，我们强烈建议你观看一下。\n\n通过 tRPC，你可以在后端编写 TypeScript 函数，然后从你的前端直接调用。一个简单的 tRPC 路由函数 procedure 可能长这样：\n\n```ts:server/api/routers/user.ts\nconst userRouter = createTRPCRouter({\n  getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {\n    return ctx.prisma.user.findFirst({\n      where: {\n        id: input,\n      },\n    });\n  }),\n});\n```\n\n这是一个 tRPC procedure（等同于传统后端中的路由函数），它将先通过 Zod（我们将同样用它来验证 [环境变量](/zh-hans/usage/env-variables)）来验证输入 —— 在上述的例子里，它将确保输入是合法的字符串。如果输入不是字符串，它会返回一个直观的错误信息。\n\n在输入之后，我们链式地添加了一个 resolver 函数，它可以被用于 [查询](https://trpc.io/docs/v10/react-queries)、[修改](https://trpc.io/docs/v10/react-mutations) 或 [订阅](https://trpc.io/docs/v10/subscriptions)。在我们的例子中，这个 resolver 函数通过 [Prisma](/zh-hans/usage/prisma) 客户端读取了数据库，然后返回一条 `id` 匹配传入参数的用户数据。\n\n你在 `routers` 中定义许多 procedure 路由函数，它表示这些相关路由函数的公共命名空间。你可以有不同的路由，例如 `users`、`posts` 以及 `messages`。然后将这些路由统一集中合并到 `appRouter` 里：\n\n```ts:server/api/root.ts\nconst appRouter = createTRPCRouter({\n  users: userRouter,\n  posts: postRouter,\n  messages: messageRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n```\n\n需要注意的是我们只需要将合并后的路由的类型定义导出，这意味着我们将不会在客户端导入任何服务端的代码。\n\n现在让我们在前端调用路由函数。tRPC 为 `@tanstack/react-query` 做了一层封装，这既可以让你充分利用它所提供的各种 hooks 功能，又能在调用 API 时享受类型安全和类型推断带来的好处。我们可以这样调用后端的路由函数：\n\n```tsx:pages/users/[id].tsx\nimport { useRouter } from \"next/router\";\nimport { api } from \"../../utils/api\";\n\nconst UserPage = () => {\n  const { query } = useRouter();\n  const userQuery = api.users.getById.useQuery(query.id);\n  return (\n    <div>\n      <h1>{userQuery.data?.name}</h1>\n    </div>\n  );\n};\n```\n\n你会立即感受到类型安全和自动补全带来的好处。只要当你输入 `api.` 时，你所定义的路由都会显示在自动补全的菜单里，然后当你选择了一个路由，它所包含的路由函数也会显示出来。如果你的输入不符合你在后端定义的验证器的要求，TypeScript 也会将错误显示出来。\n\n## 推断错误\n\n默认情况下，`create-t3-app` 设置了一个 [error formatter](https://trpc.io/docs/error-formatting)，让你在后端出现验证错误时可以推断出你的 Zod 错误。\n\n使用示例：\n\n```tsx\nfunction MyComponent() {\n  const { mutate, error } = api.post.create.useMutation();\n\n  return (\n    <form onSubmit={(e) => {\n      e.preventDefault();\n      const formData = new FormData(e.currentTarget);\n      mutate({ title: formData.get('title') });\n    }}>\n      <input name=\"title\" />\n      {error?.data?.zodError?.fieldErrors.title && (\n        {/** `mutate` returned with an error on the `title` */}\n        <span className=\"mb-8 text-red-500\">\n          {error.data.zodError.fieldErrors.title}\n        </span>\n      )}\n\n      ...\n    </form>\n  );\n}\n```\n\n## 文件\n\ntRPC 需要不少样板代码，不过 `create-t3-app` 已经帮你完成。让我们看一下这些被自动创建的文件：\n\n### 📄 `pages/api/trpc/[trpc].ts`\n\n这里是你项目 API 的入口，它暴露了 tRPC 的路由。正常情况下，你不会去修改这个文件，但如果需要的话，例如开启 CORS 中间件或其他类似的情况，知道下面的信息是很有用的：被导出的 `createNextApiHandler` 是一个 [Next.js API 的 handler](https://nextjs.org/docs/api-routes/introduction)，它分别接受一个 [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) 和一个 [response](https://developer.mozilla.org/en-US/docs/Web/API/Response?retiredLocale=sv-SE) 对象作为参数。这意味着 `createNextApiHandler` 可以被任何你想要的中间件包裹。查看下方添加 CORS 的 [示例代码](#enabling-cors)。\n\n### 📄 `server/api/trpc.ts`\n\n这个文件分为两部分，上下文创建和 tRPC 初始化。\n\n1. 我们定义传递给你的 tRPC 路由函数的上下文。上下文就是一个数据对象，你定义的所有 tRPC 路由函数都会访问它来获取数据，它被用来存放了一些例如数据库的连接、认证信息等数据。在 create-t3-app 里，当我们不需要获取整个请求对象时，我们分别使用两个函数来取得上下文的部分数据。\n\n- `createInnerTRPCContext`: 这里你可以定义不依赖请求的上下文，例如数据库的连接。你可以使用这个函数来做 [集成测试](#sample-integration-test) 或 [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers)，这些场景下你都没有一个请求对象。\n\n- `createTRPCContext`: 你可以在这里定义依赖于请求的上下文，例如用户的 session。你通过使用 `opts.req` 来获取 session，然后将它传给 `createInnerTRPCContext` 函数来创建最后完整的上下文。\n\n2. 我们初始化 tRPC，并定义可复用的 [procedure](https://trpc.io/docs/v10/procedures) 路由函数和 [中间件](https://trpc.io/docs/v10/middlewares)。按照惯例，你不应该将整个 `t` 对象导出，而是通过转换创建复用的路由和中间件，并导出它们。\n\n你会注意到我们使用了 `superjson` 作为 [数据解析工具](https://trpc.io/docs/v10/data-transformers)。在数据被发送到客户端时，它会帮你保留数据类型。例如你发送了一个 `Date` 类型的对象，客户端会返回一个相同类型的 `Date`，而不是像其他大多数 API 一样返回一个字符串。\n\n### 📄 `server/api/routers/*.ts`\n\n你可以在这里定义 API 的路由及其函数。按照惯例，你在这里为相关的路由函数 procedure [创建分离的路由](https://trpc.io/docs/v10/router)\n\n### `server/api/root.ts`\n\n在这里我们把所有在 `routers/**` 中定义的子路由 [合并](https://trpc.io/docs/v10/merging-routers) 到一个单一的应用路由里。\n\n### 📄 `utils/api.ts`\n\n这里是 tRPC 的前端入口。你可以在这里导入路由的**类型定义**，创建你的 tRPC 客户端以及 react-query hooks。因为我们已经在后端将 `superjson` 设置为数据序列化工具，我们同样需要在前端开启它。这是因为从后端传入的序列化在前端还未被反序列化。\n\n你将在这里定义 tRPC [links](https://trpc.io/docs/v10/links)，它们被用于决定从客户端到服务器的请求流。我们采用 \"default\" [`httpBatchLink`](https://trpc.io/docs/v10/links/httpBatchLink)，它会帮我们开启 [批量请求](https://cloud.google.com/compute/docs/api/how-tos/batch) 的功能，以及采用 [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink)，它则帮我们在开发阶段打印出有用的请求日志信息。\n\n最后，我们导出一个 [helper 类型](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type)，你可以通过它在前端来推断类型。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/x4mu-jOiA0Q\" title=\"How tRPC really works\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\nCreate T3 App 的贡献者 [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) 制作了 [一个关于 tRPC 数据流的视频](https://www.youtube.com/watch?v=x4mu-jOiA0Q)。如果你已经使用过 tRPC 但仍感到有些不清楚它的工作原理，我们建议你观看这个视频。\n\n## 如何从外部调用我的 API？\n\n对于常规的 API 来说，你可以使用诸如 `curl`、`Postman`、`fetch` 这样的 HTTP 客户端或直接在浏览器里访问你的 API 端点。但对于 tRPC，调用方法有点不同。如果你不想使用 tRPC 客户端来访问路由函数，这边有两种推荐方式来实现：\n\n### 向外暴露单个路由函数\n\n如果你想向外暴露单个路由函数，你可以查阅 [服务端调用](https://trpc.io/docs/v10/server-side-calls)。这允许你使用常规的 Next.js API 端点，但同时让你可以复用 tRPC 路由函数的 resolver 部分。\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\nimport { appRouter, createCaller } from \"../../../server/api/root\";\nimport { createTRPCContext } from \"../../../server/api/trpc\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // Create context and caller\n  const ctx = await createTRPCContext({ req, res });\n  const caller = createCaller(ctx);\n  try {\n    const { id } = req.query;\n    const user = await caller.user.getById(id);\n    res.status(200).json(user);\n  } catch (cause) {\n    if (cause instanceof TRPCError) {\n      // An error from tRPC occurred\n      const httpCode = getHTTPStatusCodeFromError(cause);\n      return res.status(httpCode).json(cause);\n    }\n    // Another error occurred\n    console.error(cause);\n    res.status(500).json({ message: \"Internal server error\" });\n  }\n};\n\nexport default userByIdHandler;\n```\n\n### 将每个路由函数作为 REST API 端点暴露出来\n\n如果你想要将每一个 procedure 对外暴露出来，不妨使用这个社区维护的插件 [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master)。通过给你的路由函数提供一些额外的元数据，你可以用 tRPC 路由来生成兼容 OpenAPI 规范的 REST API。\n\n### 它只是 HTTP 请求\n\ntRPC 通过 HTTP 协议来传输数据，因此使用“常规”的 HTTP 请求来调用你的 tRPC 路由是没有问题的。然而，由于 tRPC 使用的 [RPC 通讯协议](https://trpc.io/docs/v10/rpc) 不同，写起来的语法会十分繁琐。如果你好奇的话，不妨在你的浏览器开发工具下的网络标签里查看一下 tRPC 的请求和响应长什么样，但是我们建议使用常规 HTTP 请求只是出于教学意义，你还是应该坚持使用上述提到的方式之一来调用 tRPC。\n\n## 与 Next.js API 对比\n\n让我们将 Next.js API 和 tRPC 路由做个对比吧。假设我们想要从数据库获取用户的数据，然后在前端显示出来。我们可能会写一段如下方所示的 Next.js API 代码：\n\n```ts:pages/api/users/[id].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\n\nimport { prisma } from \"../../../server/db\";\n\nconst userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {\n  if (req.method !== \"GET\") {\n    return res.status(405).end();\n  }\n\n  const { id } = req.query;\n\n  if (!id || typeof id !== \"string\") {\n    return res.status(400).json({ error: \"Invalid id\" });\n  }\n\n  const examples = await prisma.example.findFirst({\n    where: {\n      id,\n    },\n  });\n\n  res.status(200).json(examples);\n};\n\nexport default userByIdHandler;\n```\n\n```ts:pages/users/[id].tsx\nimport { useState, useEffect } from \"react\";\nimport { useRouter } from \"next/router\";\n\nconst UserPage = () => {\n  const router = useRouter();\n  const { id } = router.query;\n\n  const [user, setUser] = useState(null);\n  useEffect(() => {\n    fetch(`/api/user/${id}`)\n      .then((res) => res.json())\n      .then((data) => setUser(data));\n  }, [id]);\n};\n```\n\n将这段代码和上面的 tRPC 示例做比较，你可以清楚地看到 tRPC 的优势所在：\n\n- 你无需为每一个路由定义一个 URL，倘若这样做，只要你修改了一些代码就会让调试变得很困难，而现在你的整个路由就只是一个支持自动补全的对象而已。\n- 你无需验证使用了哪个 HTTP 方法（比如 POST 还是 GET）。\n- 你无需验证请求查询参数或请求体，因为 Zod 已经替你完成了。\n- 你无需创建一个响应，而是可以像在任何 TypeScript 函数中一样，直接抛出错误、返回值或对象即可。\n- 在前端直接调用 procedure 函数为你带来了自动补全和类型安全的好处。\n\n## 有用的代码片段\n\n这里有一些可能比较有用的代码片段。\n\n### 开启 CORS（跨源资源共享）\n\n如果你需要从不同的域来访问你的 API，例如在一个包含 React Native 应用的 monorepo 的项目里，你可能需要开启 CORS：\n\n```ts:pages/api/trpc/[trpc].ts\nimport { type NextApiRequest, type NextApiResponse } from \"next\";\n\nimport { createNextApiHandler } from \"@trpc/server/adapters/next\";\nimport { appRouter } from \"~/server/api/root\";\nimport { createTRPCContext } from \"~/server/api/trpc\";\nimport cors from \"nextjs-cors\";\n\nconst handler = async (req: NextApiRequest, res: NextApiResponse) => {\n  // 开启 cors\n  await cors(req, res);\n\n  // Create and call the tRPC handler\n  return createNextApiHandler({\n    router: appRouter,\n    createContext: createTRPCContext,\n  })(req, res);\n};\n\nexport default handler;\n```\n\n### 乐观更新\n\n乐观更新是指在 API 调用完成之前更新 UI，达到前端界面快速响应用户交互的效果。这给用户带来了更好的体验，因为他们不需要等待 API 调用完成，然后 UI 来反映操作结果。然而，那些特别着重数据准确性的应用应该避免使用乐观更新，因为它们并不是后端数据状态的真实表达。你可以在 [React Query 文档](https://tanstack.com/query/v4/docs/guides/optimistic-updates) 阅读更多相关内容。\n\n```tsx\nconst MyComponent = () => {\n  const listPostQuery = api.post.list.useQuery();\n\n  const utils = api.useContext();\n  const postCreate = api.post.create.useMutation({\n    async onMutate(newPost) {\n      // 取消发送中的 fetch 请求（所以它们不会覆盖掉我们的乐观更新）\n      await utils.post.list.cancel();\n\n      // 从 queryCache 中获取数据\n      const prevData = utils.post.list.getData();\n\n      // 用我们的新文章来做乐观更新\n      utils.post.list.setData(undefined, (old) => [...old, newPost]);\n\n      // 返回之前的数据，这样做可以让我们在错误发生时回滚\n      return { prevData };\n    },\n    onError(err, newPost, ctx) {\n      // 当修改失败后，使用来自 onMutate 中的值\n      utils.post.list.setData(undefined, ctx.prevData);\n    },\n    onSettled() {\n      // 当修改完成后，与服务端同步\n      utils.post.list.invalidate();\n    },\n  });\n};\n```\n\n### 集成测试示例\n\n这个集成测试示例使用了 [Vitest](https://vitest.dev) 来检测 tRPC 路由如预期正常工作，输入解析函数会自行推断出正确的类型，然后返回的数据与预期的结果相匹配。\n\n```ts\nimport { type inferProcedureInput } from \"@trpc/server\";\nimport { expect, test } from \"vitest\";\n\nimport { appRouter, type AppRouter } from \"~/server/api/root\";\nimport { createInnerTRPCContext } from \"~/server/api/trpc\";\n\ntest(\"example router\", async () => {\n  const ctx = await createInnerTRPCContext({ session: null });\n  const caller = appRouter.createCaller(ctx);\n\n  type Input = inferProcedureInput<AppRouter[\"example\"][\"hello\"]>;\n  const input: Input = {\n    text: \"test\",\n  };\n\n  const example = await caller.example.hello(input);\n\n  expect(example).toMatchObject({ greeting: \"Hello test\" });\n});\n```\n\n如果你的 procedure 是受保护的，你可以传入一个模拟的 `session` 对象来创建上下文：\n\n```ts\ntest(\"protected example router\", async () => {\n  const ctx = await createInnerTRPCContext({\n    session: {\n      user: { id: \"123\", name: \"John Doe\" },\n      expires: \"1\",\n    },\n  });\n  const caller = appRouter.createCaller(ctx);\n\n  // ...\n});\n```\n\n## 有用的资源\n\n| 资源             | 链接                                                    |\n| ---------------- | ------------------------------------------------------- |\n| tRPC 文档        | https://www.trpc.io                                     |\n| 大量的 tRPC 示例 | https://github.com/trpc/trpc/tree/next/examples         |\n| React Query 文档 | https://tanstack.com/query/v4/docs/adapters/react-query |\n"
  },
  {
    "path": "www/src/pages/zh-hans/usage/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: TypeScript 的用法\nlayout: ../../../layouts/docs.astro\nlang: zh-hans\n---\n\n<blockquote className=\"w-full relative border-l-4 italic bg-t3-purple-200 dark:text-t3-purple-50 text-zinc-900 dark:bg-t3-purple-300/20 p-2 rounded-md text-sm my-3 border-neutral-500 quote\">\n  <div className=\"relative w-fit flex items-center justify-center p-1\">\n    <p className=\"mb-4 text-lg\">\n      <span aria-hidden=\"true\">&quot;</span>搭建安全的防护网，而不是护栏。<span aria-hidden=\"true\">&quot;</span>\n    </p>\n  </div>\n  <cite className=\"flex items-center justify-end pr-4 pb-2\">\n    <img\n      alt=\"Avatar of @t3dotgg\"\n      className=\"w-12 rounded-full bg-neutral-500 [margin-inline-end:16px]\"\n      src=\"/images/theo_300x300.webp\"\n    />\n    <div className=\"flex flex-col items-start not-italic\">\n      <span className=\" text-sm font-semibold\">Theo - T3 Stack 的创建者</span>\n      <a\n        href=\"https://twitter.com/t3dotgg\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n        className=\"text-sm\"\n      >\n        @t3dotgg\n      </a>\n    </div>\n  </cite>\n</blockquote>\n\n无论你是菜鸟还是老手，我们认为 TypeScript 是一个必选项。初看起来这像是恐吓，但就像很多其他工具一样，你用过 TypeScript 之后就很难再回头了。\n\n在你写代码时，它通过预设的数据类型来提供实时反馈；而如果你在代码中尝试访问不存在的属性或尝试传递错误类型的值时，它要么会在编辑器中提供有用的自动补全功能，要么会用红色的波浪线来提醒你错误代码，让你不得不进行进一步调试。\n\n它很可能是一款给程序员带来最高生产力的工具；给你写的或引用的代码添加文档说明，并在你不可避免犯错的情况下提供即时反馈，这绝对是无价的。\n\n## 类型推断\n\n当许多 TypeScript 开发者担心需要额外 _编写_ TypeScript 代码，但实际上你不需要修改任何代码就获得了很多它带来的好处，特别是类型推断。类型推断意味着，如果某个数据被加了类型，无论你在应用的任何地方使用这个数据，都能得到它所携带的类型，而无需额外在使用它的地方重新声明它的类型。这也就意味着，比方说一旦你定义了一个函数的参数类型，函数的剩余部分一般会被保证类型安全，无需再写更多 TypeScript 的代码。开源库项目的开发者们投入了大量工作来为他们的库维护类型定义，这意味着我们作为应用程序的开发者在编写代码过程中，借助编辑器可以从这些库的类型推断和内置文档中获益。\n\n<div class=\"embed\">\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RmGHnYUqQ4k\" title=\"You might be using Typescript wrong\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n</div>\n\n点击观看 Theo 的视频，了解为什么说 [你可能用错了 TypeScript](https://www.youtube.com/watch?v=RmGHnYUqQ4k).\n\n## 类型推断的强大用途\n\n### Zod\n\n[Zod](https://github.com/colinhacks/zod) 是一个基于 TypeScript 的 schema 验证库。写一个 schema，它代表了你项目中数据的唯一真实来源，而 Zod 则会保证应用中所有的数据都是有效合法的，甚至是来自跨网络和外部 API 的数据。\n\n### Tanstack Query\n\n[Tanstack Query](https://tanstack.com/query/v4/) 提供了声明式的、永远最新的、自动管理的数据查询和修改方法，这直接改进了开发体验和用户体验。\n\n## 有用的资源\n\n| 资源                                                   | 链接                                                              |\n| ------------------------------------------------------ | ----------------------------------------------------------------- |\n| TypeScript 手册                                        | https://www.typescriptlang.org/docs/handbook/                     |\n| TypeScript 入门教程                                    | https://github.com/total-typescript/beginners-typescript-tutorial |\n| 类型挑战                                               | https://github.com/type-challenges/type-challenges                |\n| Rodney Mullen of TypeScript (Matt Pocock) Youtube 频道 | https://www.youtube.com/c/MattPocockUk/videos                     |\n"
  },
  {
    "path": "www/src/pages/zh-hans/why.md",
    "content": "---\ntitle: 为什么选择 CT3A？\ndescription: 为什么你应该选择 Create T3 App 来创建你的下一个项目\nlayout: ../../layouts/docs.astro\nlang: zh-hans\n---\n\n我们创建 Create T3 App 的初衷，是因为 [Theo](https://twitter.com/t3dotgg) 拒绝将他最喜欢的几种技术做成模板。受到 create-next-app、[Astro 的 CLI 命令行工具](https://astro.build) 和对类型安全普遍热爱的启发，Create T3 App 团队努力地为创建新的 T3 Stack 项目建立了最好的起点。\n\n如果你对以类型安全的方式使用 Next.js 感兴趣，这就是开始的地方。如果你对我们的具体技术选择感到好奇，请继续阅读 :)\n\n## 为什么使用 TypeScript？\n\nJavaScript 已经很难了。为什么还要增加更多规则？\n\n我们坚信 TypeScript 提供的经验会帮助你成为更好的开发者。在你写代码时，它通过预设的数据类型来提供实时反馈；而如果你在代码中尝试访问不存在的属性或尝试传递错误类型的值时，它要么会在编辑器中提供有用的自动补全功能，要么会用红色的波浪线来提醒你错误代码，让你不得不进行进一步调试。无论你是 web 开发的新手还是老手，TypeScript 的“严格性”可以让它比原生 JavaScript 为你带来更少的挫败感，却带来更一致的开发体验。\n\n类型安全可以让你更快地写代码。如果你不承认这一点，你可能 [用错了 TypeScript。。。](https://www.youtube.com/watch?v=RmGHnYUqQ4k)\n\n## 为什么使用 Next.js？\n\n我们热爱 React。它使 UI 开发以我们从未想象过的方式进行。但它也会将开发者引向一些艰难的道路。\n\nNext.js 为使用 React 创建应用程序提供了一种轻度 opinionated、高度优化的方法。从路由到 API 定义，再到图片渲染，我们都相信 Next.js 能引导开发者做出正确的决定。\n\n## 为什么使用 tRPC / Prisma / Tailwind 等？\n\n虽然我们相信要尽可能保持简单，但我们发现我们创建的每一个类似“应用程序”的项目中都会用到这些技术。`create-t3-app` 很好地让你能够采用你需要的部分。\n\n### tRPC\n\ntRPC 实现了 GraphQL 的承诺，即针对类型安全服务端的无缝客户端开发，且不需要任何样板代码。这是对 TypeScript 的巧妙滥用，它提供了令人难以置信的开发体验。\n\n### Prisma\n\nPrisma 之于 SQL 就像 TypeScript 之于 JS。它创造了前所未有的开发者体验。通过从与 [几种数据库](https://www.prisma.io/docs/concepts/database-connectors) 兼容的自定义 schema 中生成类型，Prisma 保证了从数据库到应用程序的端到端类型安全。\n\nPrisma 提供了 [一整套工具](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows)，使与数据库的日常交互更加容易。值得注意的是，用 Prisma 客户端来负责数据库查询，使得 SQL 变得十分简单，以至于你几乎不会注意到你在使用它，而 Prisma Studio 是一个方便的数据库 GUI，可以让你快速读取和操作数据，而无需编写代码。\n\n### Tailwind CSS\n\nTailwind 给人的感觉就像“禅式的 CSS”。\n\nTailwind 通过良好的默认颜色、间距和其他原语的形式为我们提供了构建块，使得创建漂亮美观的应用程序变得十分容易。而当你想将应用程序提升到一个新的水平并创造美丽而独特的 UI 时，不同于组件库，它并不会在这方面阻碍你。\n\n此外，由于其类似于内联的方法，Tailwind 鼓励你进行样式设计，而不必担心命名 class、组织文件或任何其他与你试图解决的问题没有直接联系的问题。\n\n### NextAuth.js\n\n当你想在 NextJS 应用程序中添加身份验证系统时，NextAuth.js 是一个很好的解决方案，可以引入足够复杂的安全措施，而无需自己构建它。它广泛支持不同的第三方服务，可以快速添加 OAuth 认证，并为许多数据库和 ORM 提供适配器。\n"
  },
  {
    "path": "www/src/styles/accessibility.css",
    "content": "@media prefers-reduced-motion {\n  * {\n    animation: none !important;\n    transition: none !important;\n    scroll-behavior: auto !important;\n  }\n}\n\n*:not(.focus-none) {\n  @apply outline-2 outline-offset-2 !outline-t3-purple-400 transition-[outline-offset] focus-visible:outline;\n}\n\n*:not(:active):focus-visible {\n  @apply outline-offset-4;\n}\n\na:has(> img) {\n  @apply inline-block;\n}\n"
  },
  {
    "path": "www/src/styles/algolia/button.css",
    "content": "/*! @docsearch/css Button 3.2.1 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */\n.DocSearch-Button {\n  align-items: center;\n  background: var(--docsearch-searchbox-background);\n  border: 0;\n  border-radius: 40px;\n  color: var(--docsearch-muted-color);\n  cursor: pointer;\n  display: flex;\n  font-weight: 500;\n  height: 36px;\n  justify-content: space-between;\n  margin: 0 0 0 16px;\n  padding: 0 8px;\n  user-select: none;\n}\n.DocSearch-Button:active,\n.DocSearch-Button:focus,\n.DocSearch-Button:hover {\n  background: var(--docsearch-searchbox-focus-background);\n  box-shadow: var(--docsearch-searchbox-shadow);\n  color: var(--docsearch-text-color);\n  outline: none;\n}\n.DocSearch-Button-Container {\n  align-items: center;\n  display: flex;\n}\n.DocSearch-Search-Icon {\n  stroke-width: 1.6;\n}\n.DocSearch-Button .DocSearch-Search-Icon {\n  color: var(--docsearch-text-color);\n}\n.DocSearch-Button-Placeholder {\n  font-size: 1rem;\n  padding: 0 12px 0 6px;\n}\n.DocSearch-Button-Keys {\n  display: flex;\n  min-width: calc(40px + 0.8em);\n}\n.DocSearch-Button-Key {\n  align-items: center;\n  background: var(--docsearch-key-gradient);\n  border-radius: 3px;\n  box-shadow: var(--docsearch-key-shadow);\n  color: var(--docsearch-muted-color);\n  display: flex;\n  height: 18px;\n  justify-content: center;\n  margin-right: 0.4em;\n  position: relative;\n  padding: 0 0 2px;\n  border: 0;\n  top: -1px;\n  width: 20px;\n}\n@media (max-width: 768px) {\n  .DocSearch-Button-Keys,\n  .DocSearch-Button-Placeholder {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "www/src/styles/algolia/modal.css",
    "content": "/*! @docsearch/css Modal 3.2.1 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */\n.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:focus{outline:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:\"» \"}.DocSearch-Prefill{appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}"
  },
  {
    "path": "www/src/styles/algolia/style.css",
    "content": "/*! @docsearch/css 3.2.1 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */\nhtml {\n  --docsearch-primary-color: rgb(var(--color-primary));\n  --docsearch-text-color: rgb(var(--color-foreground));\n  --docsearch-spacing: 12px;\n  --docsearch-icon-stroke-width: 1.4;\n  --docsearch-highlight-color: var(--docsearch-primary-color);\n  --docsearch-muted-color: #969faf;\n  --docsearch-container-background: rgba(22, 24, 30, 0.1);\n  --docsearch-logo-color: #e8ddff;\n  --docsearch-modal-border: rgb(63, 65, 95, 0.25);\n  --docsearch-modal-width: 560px;\n  --docsearch-modal-height: 600px;\n  --docsearch-modal-background: rgb(var(--color-background));\n  --docsearch-modal-shadow: 0px 4px 15px 6px rgba(0, 0, 0, 0.1);\n  --docsearch-searchbox-height: 45px;\n  --docsearch-searchbox-background: rgba(0, 0, 0, 0);\n  --docsearch-searchbox-focus-background: rgba(0, 0, 0, 0);\n  --docsearch-searchbox-shadow: none;\n  --docsearch-hit-height: 56px;\n  --docsearch-hit-color: rgb(var(--color-foreground));\n  --docsearch-hit-active-color: rgb(232 221 255);\n  --docsearch-hit-background: rgba(0, 0, 0, 0);\n  --docsearch-hit-shadow: none;\n  --docsearch-key-background: rgb(220, 216, 248);\n  --docsearch-key-color: rgb(152, 145, 187);\n  --docsearch-key-border: rgb(152, 145, 187);\n  --docsearch-footer-height: 44px;\n  --docsearch-footer-background: rgba(0, 0, 0, 0);\n  --docsearch-footer-shadow: none, 0 -3px 6px 0 rgba(69, 98, 155, 0.12);\n}\nhtml.dark {\n  --docsearch-key-background: rgb(41, 29, 100);\n  --docsearch-key-border: rgb(14, 6, 50);\n  --docsearch-modal-border: rgba(95, 98, 146, 0.25);\n}\n.DocSearch-Button {\n  align-items: center;\n  background: var(--docsearch-searchbox-background);\n  border: 0;\n  border-radius: 40px;\n  color: var(--docsearch-muted-color);\n  cursor: pointer;\n  display: flex;\n  font-weight: 500;\n  height: 36px;\n  justify-content: space-between;\n  margin: 0 0 0 16px;\n  padding: 0 8px;\n  user-select: none;\n}\n.DocSearch-Button:active,\n.DocSearch-Button:focus,\n.DocSearch-Button:hover {\n  background: var(--docsearch-searchbox-focus-background);\n  box-shadow: var(--docsearch-searchbox-shadow);\n  color: var(--docsearch-text-color);\n  outline: none;\n}\n.DocSearch-Button-Container {\n  align-items: center;\n  display: flex;\n}\n.DocSearch-Search-Icon {\n  stroke-width: 1.6;\n  margin-inline-end: 15px;\n}\n.DocSearch-Button .DocSearch-Search-Icon {\n  color: var(--docsearch-text-color);\n}\n.DocSearch-Button-Placeholder {\n  font-size: 1rem;\n  padding: 0 12px 0 6px;\n}\n.DocSearch-Button-Keys {\n  display: flex;\n  min-width: calc(40px + 0.8em);\n}\n@media (max-width: 768px) {\n  .DocSearch-Button-Keys,\n  .DocSearch-Button-Placeholder {\n    display: none;\n  }\n}\n.DocSearch-Container,\n.DocSearch-Container * {\n  box-sizing: border-box;\n}\n.DocSearch-Container *:hover {\n  text-decoration: none !important;\n}\n.DocSearch-Container {\n  background-color: var(--docsearch-container-background);\n  backdrop-filter: blur(5px);\n  height: 100vh;\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100vw;\n  z-index: 200;\n  display: flex;\n  justify-content: center;\n}\n.DocSearch-Container a {\n  text-decoration: none;\n}\n.DocSearch-Link {\n  appearance: none;\n  background: none;\n  border: 0;\n  color: var(--docsearch-highlight-color);\n  cursor: pointer;\n  font: inherit;\n  margin: 0;\n  padding: 0;\n}\n.DocSearch-Modal {\n  background: var(--docsearch-modal-background);\n  border-radius: 6px;\n  box-shadow: var(--docsearch-modal-shadow);\n  flex-direction: column;\n  margin-top: 60px;\n  width: var(--docsearch-modal-width);\n  height: fit-content;\n  position: relative;\n  border: 1px solid var(--docsearch-modal-border);\n  cursor: default;\n}\n.DocSearch-SearchBar {\n  display: flex;\n  padding: var(--docsearch-spacing) var(--docsearch-spacing) 0;\n}\n.DocSearch-Form {\n  align-items: center;\n  background: var(--docsearch-searchbox-focus-background);\n  border-radius: 4px;\n  box-shadow: var(--docsearch-searchbox-shadow);\n  display: flex;\n  height: var(--docsearch-searchbox-height);\n  margin: 0;\n  padding: 0 var(--docsearch-spacing);\n  position: relative;\n  width: 100%;\n}\n.DocSearch-Input {\n  appearance: none;\n  background: transparent;\n  border: 0;\n  color: var(--docsearch-text-color);\n  flex: 1;\n  font: inherit;\n  font-size: 1.2em;\n  height: 100%;\n  outline: none;\n  padding-inline-start: 8px;\n  width: 80%;\n}\n.DocSearch-Input::placeholder {\n  color: var(--docsearch-muted-color);\n  opacity: 1;\n}\n.DocSearch-Input::-webkit-search-cancel-button,\n.DocSearch-Input::-webkit-search-decoration,\n.DocSearch-Input::-webkit-search-results-button,\n.DocSearch-Input::-webkit-search-results-decoration {\n  display: none;\n}\n.DocSearch-LoadingIndicator,\n.DocSearch-MagnifierLabel,\n.DocSearch-Reset {\n  margin: 0;\n  padding: 0;\n}\n.DocSearch-Reset {\n  margin-inline-start: 12px;\n}\n.DocSearch-MagnifierLabel,\n.DocSearch-Reset {\n  align-items: center;\n  color: var(--docsearch-highlight-color);\n  display: flex;\n  justify-content: center;\n}\n.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,\n.DocSearch-LoadingIndicator {\n  display: none;\n}\n.DocSearch-Container--Stalled .DocSearch-LoadingIndicator {\n  align-items: center;\n  color: var(--docsearch-highlight-color);\n  display: flex;\n  justify-content: center;\n}\n@media screen and (prefers-reduced-motion: reduce) {\n  .DocSearch-Reset {\n    animation: none;\n    appearance: none;\n    background: none;\n    border: 0;\n    border-radius: 50%;\n    color: var(--docsearch-icon-color);\n    cursor: pointer;\n    right: 0;\n    stroke-width: var(--docsearch-icon-stroke-width);\n  }\n}\n.DocSearch-Reset {\n  animation: fade-in 0.1s ease-in forwards;\n  appearance: none;\n  background: none;\n  border: 0;\n  border-radius: 50%;\n  color: var(--docsearch-icon-color);\n  cursor: pointer;\n  padding: 2px;\n  right: 0;\n  stroke-width: var(--docsearch-icon-stroke-width);\n}\n.DocSearch-Reset[hidden] {\n  display: none;\n}\n.DocSearch-Reset:focus {\n  outline: none;\n}\n.DocSearch-Reset:hover {\n  color: var(--docsearch-highlight-color);\n}\n.DocSearch-LoadingIndicator svg,\n.DocSearch-MagnifierLabel svg {\n  height: 24px;\n  width: 24px;\n}\n.DocSearch-Cancel {\n  display: none;\n}\n.DocSearch-Dropdown {\n  margin-top: 10px;\n  max-height: calc(\n    var(--docsearch-modal-height) - var(--docsearch-searchbox-height) -\n      var(--docsearch-spacing) - var(--docsearch-footer-height)\n  );\n  min-height: var(--docsearch-spacing);\n  overflow-y: auto;\n  overflow-y: overlay;\n  padding: 0 var(--docsearch-spacing);\n  scrollbar-color: var(--docsearch-muted-color)\n    var(--docsearch-modal-background);\n  scrollbar-width: thin;\n}\n.DocSearch-Dropdown::-webkit-scrollbar {\n  width: 12px;\n}\n.DocSearch-Dropdown::-webkit-scrollbar-track {\n  background: transparent;\n}\n.DocSearch-Dropdown::-webkit-scrollbar-thumb {\n  background-color: var(--docsearch-muted-color);\n  border: 3px solid var(--docsearch-modal-background);\n  border-radius: 20px;\n}\n.DocSearch-Dropdown ul {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n}\n.DocSearch-Label {\n  font-size: 0.75em;\n  line-height: 1.6em;\n}\n.DocSearch-Help,\n.DocSearch-Label {\n  color: var(--docsearch-muted-color);\n}\n.DocSearch-Help {\n  font-size: 0.9em;\n  margin: 0;\n  user-select: none;\n}\n.DocSearch-Title {\n  font-size: 1.2em;\n}\n.DocSearch-Logo a {\n  display: flex;\n}\n[dir='rtl'] .DocSearch-Logo a {\n  flex-direction: row-reverse;\n}\n.DocSearch-Logo svg {\n  color: var(--docsearch-logo-color);\n  margin-inline-start: 8px;\n}\n[dir='rtl'] .DocSearch-Logo svg {\n  margin-inline-end: 8px;\n}\n.DocSearch-Hits:last-of-type {\n  margin-bottom: 24px;\n}\n.DocSearch-Hits mark {\n  background: none;\n  color: var(--docsearch-highlight-color);\n}\n.DocSearch-HitsFooter {\n  color: var(--docsearch-muted-color);\n  display: flex;\n  font-size: 0.85em;\n  justify-content: center;\n  margin-bottom: var(--docsearch-spacing);\n  padding: var(--docsearch-spacing);\n}\n.DocSearch-HitsFooter a {\n  border-bottom: 1px solid;\n  color: inherit;\n}\n.DocSearch-Hit {\n  border-radius: 4px;\n  display: flex;\n  padding-bottom: 4px;\n  position: relative;\n}\n@media screen and (prefers-reduced-motion: reduce) {\n  .DocSearch-Hit--deleting {\n    transition: none;\n  }\n}\n.DocSearch-Hit--deleting {\n  opacity: 0;\n  transition: all 0.25s linear;\n}\n@media screen and (prefers-reduced-motion: reduce) {\n  .DocSearch-Hit--favoriting {\n    transition: none;\n  }\n}\n.DocSearch-Hit--favoriting {\n  transform: scale(0);\n  transform-origin: top center;\n  transition: all 0.25s linear;\n  transition-delay: 0.25s;\n}\n.DocSearch-Hit a {\n  background: var(--docsearch-hit-background);\n  border-radius: 4px;\n  box-shadow: var(--docsearch-hit-shadow);\n  display: block;\n  padding-left: var(--docsearch-spacing);\n  width: 100%;\n}\n.DocSearch-Hit-source {\n  background: var(--docsearch-modal-background);\n  color: rgb(var(--color-foreground));\n  font-size: 1em;\n  font-weight: 500;\n  line-height: 32px;\n  margin: 0 -4px;\n  padding: 8px 4px 8px;\n  position: sticky;\n  top: 0;\n  z-index: 10;\n}\n.DocSearch-Hit-Tree {\n  color: var(--docsearch-muted-color);\n  height: var(--docsearch-hit-height);\n  opacity: 0.5;\n  stroke-width: var(--docsearch-icon-stroke-width);\n  width: 24px;\n}\n.DocSearch-Hit[aria-selected=\"true\"] a {\n  background-color: var(--docsearch-highlight-color);\n}\n.DocSearch-Hit[aria-selected=\"true\"] mark {\n  text-decoration: underline;\n}\n.DocSearch-Hit-Container {\n  align-items: center;\n  color: var(--docsearch-hit-color);\n  display: flex;\n  flex-direction: row;\n  height: var(--docsearch-hit-height);\n  padding: 0 var(--docsearch-spacing) 0 0;\n}\n.DocSearch-Hit-icon {\n  height: 20px;\n  width: 20px;\n}\n.DocSearch-Hit-action,\n.DocSearch-Hit-icon {\n  color: var(--docsearch-muted-color);\n  stroke-width: var(--docsearch-icon-stroke-width);\n}\n.DocSearch-Hit-action {\n  align-items: center;\n  display: flex;\n  height: 22px;\n  width: 22px;\n}\n.DocSearch-Hit-action svg {\n  display: block;\n  height: 18px;\n  width: 18px;\n}\n.DocSearch-Hit-action + .DocSearch-Hit-action {\n  margin-left: 6px;\n}\n.DocSearch-Hit-action-button {\n  appearance: none;\n  background: none;\n  border: 0;\n  border-radius: 50%;\n  color: inherit;\n  cursor: pointer;\n  padding: 2px;\n}\nsvg.DocSearch-Hit-Select-Icon {\n  display: none;\n}\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-Select-Icon {\n  display: block;\n}\n.DocSearch-Hit-action-button:focus,\n.DocSearch-Hit-action-button:hover {\n  background: rgba(0, 0, 0, 0.2);\n  transition: background-color 0.1s ease-in;\n}\n@media screen and (prefers-reduced-motion: reduce) {\n  .DocSearch-Hit-action-button:focus,\n  .DocSearch-Hit-action-button:hover {\n    transition: none;\n  }\n}\n.DocSearch-Hit-action-button:focus path,\n.DocSearch-Hit-action-button:hover path {\n  fill: rgb(var(--color-foreground));\n}\n.DocSearch-Hit-content-wrapper {\n  display: flex;\n  flex: 1 1 auto;\n  flex-direction: column;\n  font-weight: 500;\n  justify-content: center;\n  line-height: 1.2em;\n  margin: 0 8px;\n  overflow-x: hidden;\n  position: relative;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  width: 80%;\n}\n.DocSearch-Hit-title {\n  font-size: 0.9em;\n}\n.DocSearch-Hit-path {\n  color: var(--docsearch-muted-color);\n  font-size: 0.75em;\n}\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-action,\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-icon,\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-path,\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-text,\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-title,\n.DocSearch-Hit[aria-selected=\"true\"] .DocSearch-Hit-Tree,\n.DocSearch-Hit[aria-selected=\"true\"] mark {\n  color: var(--docsearch-hit-active-color) !important;\n}\n@media screen and (prefers-reduced-motion: reduce) {\n  .DocSearch-Hit-action-button:focus,\n  .DocSearch-Hit-action-button:hover {\n    background: rgba(0, 0, 0, 0.2);\n    transition: none;\n  }\n}\n.DocSearch-ErrorScreen,\n.DocSearch-NoResults,\n.DocSearch-StartScreen {\n  font-size: 0.9em;\n  margin: 0 auto;\n  padding: 36px 0;\n  text-align: center;\n  width: 80%;\n}\n.DocSearch-Screen-Icon {\n  color: var(--docsearch-muted-color);\n  padding-bottom: 12px;\n}\n.DocSearch-NoResults-Prefill-List {\n  display: inline-block;\n  padding-bottom: 24px;\n  text-align: left;\n}\n.DocSearch-NoResults-Prefill-List ul {\n  display: inline-block;\n  padding: 8px 0 0;\n}\n.DocSearch-NoResults-Prefill-List li {\n  list-style-position: inside;\n  list-style-type: \"» \";\n}\n.DocSearch-Prefill {\n  appearance: none;\n  background: none;\n  border: 0;\n  border-radius: 1em;\n  color: var(--docsearch-highlight-color);\n  cursor: pointer;\n  display: inline-block;\n  font-size: 1em;\n  font-weight: 700;\n  padding: 0;\n}\n.DocSearch-Prefill:focus,\n.DocSearch-Prefill:hover {\n  outline: none;\n  text-decoration: underline;\n}\n.DocSearch-Footer {\n  align-items: center;\n  background: var(--docsearch-footer-background);\n  border-radius: 0 0 8px 8px;\n  box-shadow: var(--docsearch-footer-shadow);\n  display: flex;\n  flex-direction: row-reverse;\n  flex-shrink: 0;\n  height: var(--docsearch-footer-height);\n  justify-content: space-between;\n  padding: 0 var(--docsearch-spacing);\n  position: relative;\n  user-select: none;\n  width: 100%;\n  z-index: 300;\n}\n.DocSearch-Commands {\n  color: var(--docsearch-muted-color);\n  display: flex;\n  list-style: none;\n  margin: 0;\n  padding: 0;\n}\n.DocSearch-Commands li {\n  align-items: center;\n  display: flex;\n}\n.DocSearch-Commands li:not(:last-of-type) {\n  margin-inline-end: 0.8em;\n}\n.DocSearch-Commands-Key,\n.DocSearch-Button-Key {\n  align-items: center;\n  background-color: var(--docsearch-key-background);\n  border-radius: 2px;\n  display: flex;\n  height: 18px;\n  justify-content: center;\n  margin-inline-end: 0.4em;\n  padding: 0 0 1px;\n  color: var(--docsearch-key-color);\n  border: 1px solid var(--docsearch-key-border);\n  width: 20px;\n}\n@media (max-width: 768px) {\n  :root {\n    --docsearch-spacing: 10px;\n    --docsearch-footer-height: 40px;\n  }\n  .DocSearch-Dropdown {\n    height: 100%;\n  }\n  .DocSearch-Container {\n    height: 100vh;\n    height: -webkit-fill-available;\n    height: calc(var(--docsearch-vh, 1vh) * 100);\n  }\n  .DocSearch-Footer {\n    border-radius: 0;\n    bottom: 0;\n    position: absolute;\n  }\n  .DocSearch-Hit-content-wrapper {\n    display: flex;\n    position: relative;\n    width: 80%;\n  }\n  .DocSearch-Modal {\n    border-radius: 0;\n    box-shadow: none;\n    height: 100vh;\n    height: -webkit-fill-available;\n    height: calc(var(--docsearch-vh, 1vh) * 100);\n    margin: 0;\n    max-width: 100%;\n    width: 100%;\n  }\n  .DocSearch-Dropdown {\n    max-height: calc(\n      var(--docsearch-vh, 1vh) * 100 - var(--docsearch-searchbox-height) -\n        var(--docsearch-spacing) - var(--docsearch-footer-height)\n    );\n  }\n  .DocSearch-Cancel {\n    appearance: none;\n    background: none;\n    border: 0;\n    color: var(--docsearch-highlight-color);\n    cursor: pointer;\n    display: inline-block;\n    flex: none;\n    font: inherit;\n    font-size: 1em;\n    font-weight: 500;\n    margin-left: var(--docsearch-spacing);\n    outline: none;\n    overflow: hidden;\n    padding: 0;\n    user-select: none;\n    white-space: nowrap;\n  }\n  .DocSearch-Commands,\n  .DocSearch-Hit-Tree {\n    display: none;\n  }\n}\n@keyframes fade-in {\n  0% {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n"
  },
  {
    "path": "www/src/styles/global.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  /* Design System Theming */\n  html {\n    --color-default: 236 228 236;\n    --color-neutral: 29 40 58;\n    --color-primary: 112 64 255;\n    --color-secondary: 58 191 248;\n    --color-accent: 244 113 181;\n    --color-warning: 244 193 82;\n    --color-error: 251 111 132;\n    --color-success: 43 212 189;\n    --color-info: 12 166 233;\n    --color-foreground: 15 23 42;\n    --color-background: 236 228 236;\n\n    @apply bg-default text-slate-900;\n  }\n\n  html.dark {\n    --color-default: 15 23 41;\n    --color-neutral: 29 40 58;\n    --color-primary: 112 64 255;\n    --color-secondary: 58 191 248;\n    --color-accent: 244 113 181;\n    --color-warning: 244 193 82;\n    --color-error: 251 111 132;\n    --color-success: 43 212 189;\n    --color-info: 12 166 233;\n    --color-foreground: 232 221 255;\n    --color-background: 15 23 41;\n\n    @apply bg-default text-t3-purple-100;\n  }\n\n  html {\n    @apply scroll-smooth accent-primary scrollbar-thin scrollbar-track-transparent scrollbar-thumb-t3-purple-300 dark:scrollbar-track-transparent dark:scrollbar-thumb-t3-purple-300;\n  }\n\n  /* Typewriter */\n  .cursor::after {\n    display: block;\n    content: \"\";\n    position: absolute;\n    width: 4px;\n    height: 100%;\n    background-color: #fff;\n    animation: cursor 0.6s linear infinite alternate;\n    will-change: opacity;\n  }\n\n  @keyframes cursor {\n    0%,\n    40% {\n      opacity: 1;\n    }\n\n    60%,\n    100% {\n      opacity: 0;\n    }\n  }\n\n  /* Base stylings */\n  *:focus:not(:focus-visible) {\n    outline: none;\n  }\n\n  a:hover,\n  a:focus {\n    text-decoration: underline;\n  }\n\n  a:focus {\n    outline: 2px solid currentColor;\n    outline-offset: 0.25em;\n  }\n\n  button:focus {\n    outline: 2px solid currentColor;\n    outline-offset: 0.25em;\n  }\n\n  article > section :is(ul, ol) > * + * {\n    margin-top: 0.75rem;\n  }\n\n  article > section li > :is(p, pre, blockquote):not(:first-child) {\n    margin-top: 1rem;\n  }\n\n  article > section :is(ul, ol) {\n    padding-inline-start: 1em;\n  }\n\n  article > section nav :is(ul, ol) {\n    padding-inline-start: inherit;\n  }\n\n  td,\n  th {\n    padding: 6px;\n    text-align: inline-start;\n  }\n\n  .t3-scrollbar {\n    @apply scrollbar-thin scrollbar-track-slate-300 scrollbar-thumb-t3-purple-300 dark:scrollbar-track-t3-purple-200/10 dark:scrollbar-thumb-t3-purple-300;\n  }\n\n  .t3-scrollbar::-webkit-scrollbar-thumb {\n    @apply rounded-full;\n  }\n\n  .line-clamp-1 {\n    overflow: hidden;\n    display: -webkit-box;\n    -webkit-box-orient: vertical;\n    -webkit-line-clamp: 1;\n  }\n\n  h1[id],\n  h2[id],\n  h3[id],\n  h4[id],\n  h5[id],\n  #content {\n    @apply scroll-mt-36 lg:scroll-mt-24;\n  }\n\n  /* only at less than md */\n  @media (max-width: 767.5px) {\n    .mobile-sidebar-toggle {\n      overflow: hidden;\n      height: 100vh;\n    }\n\n    .mobile-sidebar-toggle #grid-left {\n      z-index: 20;\n      display: flex;\n      width: 100vw;\n      height: 100vh;\n    }\n  }\n\n  /* Markdown Styling */\n  .markdown {\n    @apply flex w-full flex-col items-start justify-start px-4 leading-relaxed text-slate-900 selection:bg-t3-purple-200 selection:text-t3-purple-500 dark:text-t3-purple-100 dark:selection:bg-t3-purple-100 dark:selection:text-slate-900;\n  }\n  .markdown h1 {\n    @apply mt-8 mb-4 text-3xl font-extrabold;\n  }\n  .markdown h2 {\n    @apply mt-8 mb-4 text-2xl font-semibold;\n  }\n  .markdown h3 {\n    @apply mt-4 mb-2 text-xl font-semibold;\n  }\n  .markdown h4 {\n    @apply mt-2 mb-1 text-base font-medium;\n  }\n  .markdown li {\n    @apply list-disc text-slate-900 dark:text-white;\n  }\n  .markdown ol > li {\n    @apply mb-2 list-decimal;\n  }\n  .markdown p {\n    @apply mb-4 dark:text-white;\n  }\n  .markdown a > p {\n    @apply mb-0 text-sm;\n  }\n  .markdown a:not(.heading-link--hidden---effects) {\n    @apply text-t3-purple-500 underline decoration-slate-500 \n          decoration-dotted underline-offset-2  \n          hover:text-t3-purple-700 dark:text-t3-purple-200 \n          dark:decoration-t3-purple-200 dark:hover:text-t3-purple-300;\n  }\n\n  :is([dir=\"rtl\"]) .markdown a[rel~=\"noreferrer\"] > span {\n    @apply inline-flex -scale-x-100;\n  }\n\n  .markdown code {\n    @apply break-words [direction:ltr] [unicode-bidi:embed] lg:break-normal;\n  }\n\n  .markdown .code-wrapper {\n    @apply inline rounded border border-t3-purple-200 bg-t3-purple-200/40 px-0.5 py-[0.5px] dark:border-t3-purple-400/30 dark:bg-t3-purple-400/20;\n  }\n\n  .markdown .remark-code-title {\n    @apply z-10 -mb-1 mt-3 w-full rounded-t-md border border-t3-purple-300/80 bg-[#191724] px-2 py-1 font-mono text-t3-purple-200;\n  }\n\n  .markdown pre {\n    @apply mx-auto mb-3 rounded border border-t3-purple-300/80 p-2 pl-3 font-mono shadow-xl sm:pt-2;\n  }\n\n  .markdown ol {\n    @apply w-full;\n  }\n\n  .markdown details {\n    @apply mt-2 w-full rounded-md border border-t3-purple-300/80 bg-[#191724] px-3 transition-all duration-300 ease-in-out;\n  }\n  .markdown details[open] {\n    @apply bg-t3-purple-200/10;\n  }\n  .markdown details pre {\n    @apply border-0 shadow-none;\n  }\n  .markdown details > summary {\n    @apply cursor-pointer text-[#A6ACCD];\n  }\n  .markdown summary {\n    @apply py-3;\n  }\n\n  .markdown p > img {\n    @apply mt-8 text-sm;\n  }\n  .markdown table > tbody > tr > td > a {\n    overflow-wrap: anywhere;\n  }\n  .markdown table {\n    @apply max-w-full table-fixed;\n  }\n  .markdown table > tbody > tr > td {\n    @apply align-top;\n  }\n  .markdown blockquote a {\n    @apply text-slate-900 dark:text-t3-purple-50;\n  }\n  .DocSearch-SearchBar {\n    @apply my-3 rounded-md bg-purple-400 p-2 text-sm;\n  }\n\n  #DocSearch-SearchBar {\n    @apply my-3 rounded-md bg-purple-400 p-2 text-sm;\n  }\n\n  .embed {\n    @apply relative mb-2 h-0 w-full pb-[56.25%];\n  }\n\n  .embed iframe {\n    @apply absolute top-0 left-0 h-full w-full;\n  }\n}\n"
  },
  {
    "path": "www/src/styles/swiper.css",
    "content": ":root {\n  --swiper-theme-color: rgb(var(--color-primary)) !important;\n  --swiper-pagination-bullet-inactive-color: #fff;\n  --swiper-pagination-bullet-inactive-opacity: 20%;\n}\n"
  },
  {
    "path": "www/src/utils/fetchGithub.ts",
    "content": "import { z } from \"zod\";\n\ninterface Options<T extends \"commits\" | \"repo\"> {\n  throwIfNotOk?: boolean;\n  throwIfNoAuth?: boolean;\n  fetchType: T;\n}\n\nexport const repoSchema = z.object({\n  stargazers_count: z.number(),\n});\n\nexport const commitsSchema = z.array(\n  z.object({\n    commit: z.object({\n      author: z.object({\n        date: z.string(),\n      }),\n    }),\n    author: z.object({\n      login: z.string(),\n      id: z.number(),\n    }),\n  }),\n);\n\nexport type Commit = z.infer<typeof commitsSchema>[number];\n\n/** Helper function to fetch the GitHub API with an auth token to avoid rate limiting. */\nexport const fetchGithub = async <T extends \"commits\" | \"repo\">(\n  url: string,\n  opts: Options<T>,\n): Promise<z.infer<\n  T extends \"repo\" ? typeof repoSchema : typeof commitsSchema\n> | null> => {\n  const { throwIfNotOk = true, throwIfNoAuth = true, fetchType } = opts;\n\n  const schema = fetchType === \"commits\" ? commitsSchema : repoSchema;\n\n  const token = import.meta.env.PUBLIC_GITHUB_TOKEN as string | undefined;\n\n  if (!token) {\n    const msg =\n      \"No Github token found. Please set PUBLIC_GITHUB_TOKEN in .env to avoid rate limiting.\";\n    if (throwIfNoAuth) {\n      throw new Error(msg);\n    }\n    console.warn(msg);\n\n    const response = await fetch(url);\n    const data = (await response.json()) as Promise<unknown>;\n\n    const parsed = schema.safeParse(data);\n    if (!parsed.success) {\n      console.warn(\n        \"Could not parse GitHub API response. This could be caused by rate limiting.\",\n      );\n\n      return null;\n    }\n\n    return parsed.data;\n  }\n\n  const auth = `Basic ${Buffer.from(token, \"binary\").toString(\"base64\")}`;\n\n  const res = await fetch(url, {\n    headers: {\n      Authorization: auth,\n      \"User-Agent\": \"@ct3a-www/1.0\",\n    },\n  });\n\n  const data = await res.json();\n\n  if (!res.ok) {\n    const msg = `Request to fetch ${url} failed. Reason: ${res.statusText}\n    Message: ${\n      data && typeof data === \"object\" && \"message\" in data\n        ? data.message\n        : \"unknown\"\n    }`;\n    if (throwIfNotOk) {\n      throw new Error(msg);\n    }\n    console.warn(msg);\n  }\n\n  const parsed = schema.safeParse(data);\n\n  if (!parsed.success) {\n    const msg = \"Could not parse GitHub API response.\";\n    if (throwIfNotOk) {\n      throw new Error(msg);\n    }\n    console.warn(msg);\n\n    return null;\n  }\n\n  return parsed.data;\n};\n"
  },
  {
    "path": "www/src/utils/ogFont.ts",
    "content": "/** https://github.com/juliusmarminge/jumr.dev/blob/main/app/og-image/get-fonts.ts */\n\nexport async function getFont<TWeights extends readonly number[]>({\n  family,\n  weights,\n  text,\n}: {\n  family: string;\n  weights: TWeights;\n  text?: string;\n}): Promise<Record<TWeights[number], ArrayBuffer>> {\n  const API = `https://fonts.googleapis.com/css2?family=${family}:wght@${weights.join(\n    \";\",\n  )}${text ? `&text=${encodeURIComponent(text)}` : \"\"}`;\n\n  const css = await (\n    await fetch(API, {\n      headers: {\n        // Make sure it returns TTF.\n        \"User-Agent\":\n          \"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1\",\n      },\n    })\n  ).text();\n\n  const fonts = css\n    .split(\"@font-face {\")\n    .splice(1)\n    .map((font) => {\n      const u = /src: url\\((.+)\\) format\\('(opentype|truetype)'\\)/.exec(font);\n      const w = /font-weight: (\\d+)/.exec(font);\n      return u?.[1] && w?.[1] ? { url: u[1], weight: parseInt(w[1]) } : null;\n    })\n    .filter(\n      (font): font is { url: string; weight: TWeights[number] } => !!font,\n    );\n\n  const promises = fonts.map(async (font) => {\n    const res = await fetch(font.url);\n    return [font.weight, await res.arrayBuffer()];\n  });\n\n  // Object.fromEntries is typed as returning any *sigh*\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n  return Object.fromEntries(await Promise.all(promises));\n}\n"
  },
  {
    "path": "www/src/utils/pagination.ts",
    "content": "import {\n  SIDEBAR,\n  type Sidebar,\n  type SidebarItem,\n  type SidebarItemLink,\n} from \"../config\";\n\nexport function paginate(lang: keyof Sidebar, path: SidebarItemLink) {\n  const routes = Object.values(SIDEBAR[lang]).flat() as SidebarItem[];\n  const index = routes.map((item) => item.link).indexOf(path);\n  if (index === -1) return { prev: undefined, next: undefined };\n  const prev = index > 0 ? routes[index - 1] : undefined;\n  const next = index < routes.length - 1 ? routes[index + 1] : undefined;\n  return { prev, next };\n}\n"
  },
  {
    "path": "www/src/utils/siteUrl.ts",
    "content": "export const SITE_URL = import.meta.env.VERCEL_URL\n  ? `https://${import.meta.env.VERCEL_URL}`\n  : \"http://localhost:3000\";\n"
  },
  {
    "path": "www/tailwind.config.ts",
    "content": "import scrollbar from \"tailwind-scrollbar\";\nimport { type Config } from \"tailwindcss\";\n\nexport default {\n  content: [\"./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}\"],\n  darkMode: \"selector\",\n  theme: {\n    extend: {\n      colors: {\n        default: \"rgb(var(--color-default) / <alpha-value>)\",\n        neutral: \"rgb(var(--color-neutral) / <alpha-value>)\",\n        primary: \"rgb(var(--color-primary) / <alpha-value>)\",\n        secondary: \"rgb(var(--color-secondary) / <alpha-value>)\",\n        accent: \"rgb(var(--color-accent) / <alpha-value>)\",\n        warning: \"rgb(var(--color-warning) / <alpha-value>)\",\n        error: \"rgb(var(--color-error) / <alpha-value>)\",\n        success: \"rgb(var(--color-success) / <alpha-value>)\",\n        info: \"rgb(var(--color-info) / <alpha-value>)\",\n\n        \"t3-purple-50\": \"#F3EEFF\",\n        \"t3-purple-100\": \"#e8ddff\",\n        \"t3-purple-200\": \"#c3b4fc\",\n        \"t3-purple-300\": \"#9e8bf9\",\n        \"t3-purple-400\": \"#7a62f6\",\n        \"t3-purple-500\": \"#5749f3\",\n        \"t3-purple-600\": \"#4a3eeb\",\n        \"t3-purple-700\": \"#3d34e3\",\n        \"t3-purple-800\": \"#3029db\",\n        \"t3-purple-900\": \"#231ed3\",\n        \"t3-purple-1000\": \"#1613cb\",\n      },\n      animation: {\n        draw: \"draw 2s linear normal\",\n      },\n    },\n    keyframes: {\n      draw: {\n        to: { strokeDashoffset: \"200\" },\n      },\n    },\n    fontFamily: {\n      sans: [\n        '\"InterVariable\"',\n        \"ui-sans-serif\",\n        \"system-ui\",\n        \"-apple-system\",\n        \"BlinkMacSystemFont\",\n        '\"Segoe UI\"',\n        \"Roboto\",\n        '\"Helvetica Neue\"',\n        \"Arial\",\n        '\"Noto Sans\"',\n        \"sans-serif\",\n        '\"Apple Color Emoji\"',\n        '\"Segoe UI Emoji\"',\n        '\"Segoe UI Symbol\"',\n        '\"Noto Color Emoji\"',\n      ],\n      serif: [\"ui-serif\", \"Georgia\"],\n      mono: [\n        '\"JetBrains Mono\"',\n        \"monospace\",\n        \"ui-monospace\",\n        \"Menlo\",\n        \"Monaco\",\n        '\"Cascadia Mono\"',\n        '\"Segoe UI Mono\"',\n        '\"Roboto Mono\"',\n        '\"Oxygen Mono\"',\n        '\"Ubuntu Monospace\"',\n        '\"Source Code Pro\"',\n        '\"Fira Mono\"',\n        '\"Droid Sans Mono\"',\n        '\"Courier New\"',\n      ],\n    },\n  },\n  plugins: [scrollbar({ nocompatible: true })],\n} satisfies Config;\n"
  },
  {
    "path": "www/tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strictest\",\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    // Skip type checking of external libraries.\n    \"skipLibCheck\": true\n  },\n  \"include\": [\n    \"src\",\n    \"astro.config.mjs\",\n    \".eslintrc.cjs\",\n    \"**/*.js\",\n    \"**/*.cjs\",\n    \"**/*.mjs\",\n    \"../reset.d.ts\",\n    \"./tailwind.config.ts\"\n  ]\n}\n"
  },
  {
    "path": "www/vercel.json",
    "content": "{\n  \"headers\": [\n    {\n      \"source\": \"/:all*(ttf|otf|woff|woff2)\",\n      \"headers\": [\n        {\n          \"key\": \"Cache-Control\",\n          \"value\": \"public, max-age=31536000, immutable\"\n        }\n      ]\n    }\n  ],\n  \"cleanUrls\": true,\n  \"redirects\": [\n    {\n      \"source\": \"/en\",\n      \"destination\": \"/\"\n    },\n    {\n      \"source\": \"/docs\",\n      \"destination\": \"/en/introduction\"\n    },\n    {\n      \"source\": \"/discord\",\n      \"destination\": \"https://discord.gg/xHdCpcPHRE\"\n    },\n    {\n      \"source\": \"/github\",\n      \"destination\": \"https://github.com/t3-oss/create-t3-app\"\n    },\n    {\n      \"source\": \"/showcase\",\n      \"destination\": \"/en/t3-collection\"\n    },\n    {\n      \"source\": \"/collection\",\n      \"destination\": \"/en/t3-collection\"\n    },\n    {\n      \"source\": \"/awesome\",\n      \"destination\": \"/en/t3-collection\"\n    }\n  ]\n}\n"
  }
]