The _"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:
- [Next.js](https://nextjs.org)
- [tRPC](https://trpc.io)
- [Tailwind CSS](https://tailwindcss.com)
- [TypeScript](https://typescriptlang.org)
- [Prisma](https://prisma.io)
- [Drizzle](https://orm.drizzle.team)
- [NextAuth.js](https://next-auth.js.org)
### So... what is `create-t3-app`? A template?
Kind 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.
After 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.
This 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).
T3 Axioms
We'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.
### 1. Solve Problems
It'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.
### 2. Bleed Responsibly
We 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.
### 3. Typesafety Isn't Optional
The 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.
Getting Started
To scaffold an app using `create-t3-app`, run any of the following four commands and answer the command prompt questions:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
For more advanced usage, check out the [CLI docs](https://create.t3.gg/en/installation).
Community
For help, discussion about best practices, or any other conversation that would benefit create-t3-app:
[Join the T3 Discord Server](https://t3.gg/discord)
Contributors
We 💖 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.
);
}
================================================
FILE: cli/template/extras/src/app/page/with-tw.tsx
================================================
import Link from "next/link";
export default function HomePage() {
return (
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how to
deploy it.
);
}
================================================
FILE: cli/template/extras/src/env/with-auth-db-planetscale.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
AUTH_SECRET:
process.env.NODE_ENV === "production"
? z.string()
: z.string().optional(),
AUTH_DISCORD_ID: z.string(),
AUTH_DISCORD_SECRET: z.string(),
DATABASE_URL: z
.string()
.url()
.refine(
(str) => !str.includes("YOUR_MYSQL_URL_HERE"),
"You forgot to change the default URL"
),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
AUTH_SECRET: process.env.AUTH_SECRET,
AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,
AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-auth-db.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
AUTH_SECRET:
process.env.NODE_ENV === "production"
? z.string()
: z.string().optional(),
AUTH_DISCORD_ID: z.string(),
AUTH_DISCORD_SECRET: z.string(),
DATABASE_URL: z.string().url(),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
AUTH_SECRET: process.env.AUTH_SECRET,
AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,
AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-auth.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
AUTH_SECRET:
process.env.NODE_ENV === "production"
? z.string()
: z.string().optional(),
AUTH_DISCORD_ID: z.string(),
AUTH_DISCORD_SECRET: z.string(),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
AUTH_SECRET: process.env.AUTH_SECRET,
AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID,
AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET,
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-better-auth-db-planetscale.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
BETTER_AUTH_SECRET:
process.env.NODE_ENV === "production"
? z.string()
: z.string().optional(),
BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),
BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),
DATABASE_URL: z
.string()
.url()
.refine(
(str) => !str.includes("YOUR_MYSQL_URL_HERE"),
"You forgot to change the default URL"
),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,
BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-better-auth-db.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
BETTER_AUTH_SECRET:
process.env.NODE_ENV === "production" ? z.string() : z.string().optional(),
BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),
BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),
DATABASE_URL: z.string().url(),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,
BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-better-auth.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
BETTER_AUTH_SECRET:
process.env.NODE_ENV === "production" ? z.string() : z.string().optional(),
BETTER_AUTH_GITHUB_CLIENT_ID: z.string(),
BETTER_AUTH_GITHUB_CLIENT_SECRET: z.string(),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
BETTER_AUTH_GITHUB_CLIENT_ID: process.env.BETTER_AUTH_GITHUB_CLIENT_ID,
BETTER_AUTH_GITHUB_CLIENT_SECRET: process.env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-db-planetscale.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
DATABASE_URL: z
.string()
.url()
.refine(
(str) => !str.includes("YOUR_MYSQL_URL_HERE"),
"You forgot to change the default URL"
),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/env/with-db.js
================================================
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
/**
* Specify your server-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars.
*/
server: {
DATABASE_URL: z.string().url(),
NODE_ENV: z
.enum(["development", "test", "production"])
.default("development"),
},
/**
* Specify your client-side environment variables schema here. This way you can ensure the app
* isn't built with invalid env vars. To expose them to the client, prefix them with
* `NEXT_PUBLIC_`.
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*/
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
* useful for Docker builds.
*/
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
/**
* Makes it so that empty strings are treated as undefined. `SOME_VAR: z.string()` and
* `SOME_VAR=''` will throw an error.
*/
emptyStringAsUndefined: true,
});
================================================
FILE: cli/template/extras/src/index.module.css
================================================
.main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background-image: linear-gradient(to bottom, #2e026d, #15162c);
}
.container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3rem;
padding: 4rem 1rem;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
.title {
font-size: 3rem;
line-height: 1;
font-weight: 800;
letter-spacing: -0.025em;
margin: 0;
color: white;
}
@media (min-width: 640px) {
.title {
font-size: 5rem;
}
}
.pinkSpan {
color: hsl(280 100% 70%);
}
.cardRow {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 1rem;
}
@media (min-width: 640px) {
.cardRow {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 768px) {
.cardRow {
gap: 2rem;
}
}
.card {
max-width: 20rem;
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
border-radius: 0.75rem;
color: white;
background-color: rgb(255 255 255 / 0.1);
}
.card:hover {
background-color: rgb(255 255 255 / 0.2);
transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
}
.cardTitle {
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
margin: 0;
}
.cardText {
font-size: 1.125rem;
line-height: 1.75rem;
}
.showcaseContainer {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.showcaseText {
color: white;
text-align: center;
font-size: 1.5rem;
line-height: 2rem;
}
.authContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
}
.loginButton {
border-radius: 9999px;
background-color: rgb(255 255 255 / 0.1);
padding: 0.75rem 2.5rem;
font-weight: 600;
color: white;
text-decoration-line: none;
transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
}
.loginButton:hover {
background-color: rgb(255 255 255 / 0.2);
}
.form {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.input {
width: 100%;
border-radius: 9999px;
padding: 0.5rem 1rem;
color: black;
}
.submitButton {
all: unset;
border-radius: 9999px;
background-color: rgb(255 255 255 / 0.1);
padding: 0.75rem 2.5rem;
font-weight: 600;
color: white;
text-align: center;
transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
}
.submitButton:hover {
background-color: rgb(255 255 255 / 0.2);
}
================================================
FILE: cli/template/extras/src/pages/_app/base.tsx
================================================
import { type AppType } from "next/dist/shared/lib/utils";
import { Geist } from "next/font/google";
import "~/styles/globals.css";
const geist = Geist({
subsets: ["latin"],
});
const MyApp: AppType = ({ Component, pageProps }) => {
return (
);
};
export default MyApp;
================================================
FILE: cli/template/extras/src/pages/_app/with-auth-trpc-tw.tsx
================================================
import { type Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import { type AppType } from "next/app";
import { Geist } from "next/font/google";
import { api } from "~/utils/api";
import "~/styles/globals.css";
const geist = Geist({
subsets: ["latin"],
});
const MyApp: AppType<{ session: Session | null }> = ({
Component,
pageProps: { session, ...pageProps },
}) => {
return (
);
};
export default api.withTRPC(MyApp);
================================================
FILE: cli/template/extras/src/pages/_app/with-auth-trpc.tsx
================================================
import { type Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import { type AppType } from "next/app";
import { Geist } from "next/font/google";
import { api } from "~/utils/api";
import "~/styles/globals.css";
const geist = Geist({
subsets: ["latin"],
});
const MyApp: AppType<{ session: Session | null }> = ({
Component,
pageProps: { session, ...pageProps },
}) => {
return (
{sessionData && Logged in as {sessionData.user?.name}}
{secretMessage && - {secretMessage}}
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-better-auth-trpc-tw.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { authClient } from "~/server/better-auth/client";
import { api } from "~/utils/api";
export default function Home() {
const hello = api.post.hello.useQuery({ text: "from tRPC" });
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
{sessionData && Logged in as {sessionData.user?.name}}
{secretMessage && - {secretMessage}}
{sessionData ? (
) : (
)}
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-better-auth-trpc.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { authClient } from "~/server/better-auth/client";
import { api } from "~/utils/api";
import styles from "./index.module.css";
export default function Home() {
const hello = api.post.hello.useQuery({ text: "from tRPC" });
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
{sessionData && Logged in as {sessionData.user?.name}}
{secretMessage && - {secretMessage}}
{sessionData ? (
) : (
)}
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-better-auth-tw.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { authClient } from "~/server/better-auth/client";
export default function Home() {
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
>
);
}
function AuthShowcase() {
const { data: sessionData, isPending } = authClient.useSession();
if (isPending) {
return
Loading...
;
}
return (
{sessionData && Logged in as {sessionData.user?.name}}
{sessionData ? (
) : (
)}
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-better-auth.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { authClient } from "~/server/better-auth/client";
import styles from "./index.module.css";
export default function Home() {
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
>
);
}
function AuthShowcase() {
const { data: sessionData, isPending } = authClient.useSession();
if (isPending) {
return
Loading...
;
}
return (
{sessionData && Logged in as {sessionData.user?.name}}
{sessionData ? (
) : (
)}
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-trpc-tw.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { api } from "~/utils/api";
export default function Home() {
const hello = api.post.hello.useQuery({ text: "from tRPC" });
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
>
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-trpc.tsx
================================================
import Head from "next/head";
import Link from "next/link";
import { api } from "~/utils/api";
import styles from "./index.module.css";
export default function Home() {
const hello = api.post.hello.useQuery({ text: "from tRPC" });
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
>
);
}
================================================
FILE: cli/template/extras/src/pages/index/with-tw.tsx
================================================
import Head from "next/head";
import Link from "next/link";
export default function Home() {
return (
<>
Create T3 App
Create T3 App
First Steps →
Just the basics - Everything you need to know to set up your
database and authentication.
Documentation →
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
>
);
}
================================================
FILE: cli/template/extras/src/server/api/root.ts
================================================
import { postRouter } from "~/server/api/routers/post";
import { createCallerFactory, createTRPCRouter } from "~/server/api/trpc";
/**
* This is the primary router for your server.
*
* All routers added in /api/routers should be manually added here.
*/
export const appRouter = createTRPCRouter({
post: postRouter,
});
// export type definition of API
export type AppRouter = typeof appRouter;
/**
* Create a server-side caller for the tRPC API.
* @example
* const trpc = createCaller(createContext);
* const res = await trpc.post.all();
* ^? Post[]
*/
export const createCaller = createCallerFactory(appRouter);
================================================
FILE: cli/template/extras/src/server/api/routers/post/base.ts
================================================
import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
// Mocked DB
interface Post {
id: number;
name: string;
}
const posts: Post[] = [
{
id: 1,
name: "Hello World",
},
];
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: publicProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ input }) => {
const post: Post = {
id: posts.length + 1,
name: input.name,
};
posts.push(post);
return post;
}),
getLatest: publicProcedure.query(() => {
return posts.at(-1) ?? null;
}),
});
================================================
FILE: cli/template/extras/src/server/api/routers/post/with-auth-drizzle.ts
================================================
import { z } from "zod";
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
import { posts } from "~/server/db/schema";
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: protectedProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
await ctx.db.insert(posts).values({
name: input.name,
createdById: ctx.session.user.id,
});
}),
getLatest: protectedProcedure.query(async ({ ctx }) => {
const post = await ctx.db.query.posts.findFirst({
orderBy: (posts, { desc }) => [desc(posts.createdAt)],
});
return post ?? null;
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
});
================================================
FILE: cli/template/extras/src/server/api/routers/post/with-auth-prisma.ts
================================================
import { z } from "zod";
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: protectedProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
return ctx.db.post.create({
data: {
name: input.name,
createdBy: { connect: { id: ctx.session.user.id } },
},
});
}),
getLatest: protectedProcedure.query(async ({ ctx }) => {
const post = await ctx.db.post.findFirst({
orderBy: { createdAt: "desc" },
where: { createdBy: { id: ctx.session.user.id } },
});
return post ?? null;
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
});
================================================
FILE: cli/template/extras/src/server/api/routers/post/with-auth.ts
================================================
import { z } from "zod";
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
let post = {
id: 1,
name: "Hello World",
};
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: protectedProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ input }) => {
post = { id: post.id + 1, name: input.name };
return post;
}),
getLatest: protectedProcedure.query(() => {
return post;
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
});
================================================
FILE: cli/template/extras/src/server/api/routers/post/with-drizzle.ts
================================================
import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { posts } from "~/server/db/schema";
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: publicProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
await ctx.db.insert(posts).values({
name: input.name,
});
}),
getLatest: publicProcedure.query(async ({ ctx }) => {
const post = await ctx.db.query.posts.findFirst({
orderBy: (posts, { desc }) => [desc(posts.createdAt)],
});
return post ?? null;
}),
});
================================================
FILE: cli/template/extras/src/server/api/routers/post/with-prisma.ts
================================================
import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
export const postRouter = createTRPCRouter({
hello: publicProcedure
.input(z.object({ text: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
create: publicProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
return ctx.db.post.create({
data: {
name: input.name,
},
});
}),
getLatest: publicProcedure.query(async ({ ctx }) => {
const post = await ctx.db.post.findFirst({
orderBy: { createdAt: "desc" },
});
return post ?? null;
}),
});
================================================
FILE: cli/template/extras/src/server/api/trpc-app/base.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
return {
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
================================================
FILE: cli/template/extras/src/server/api/trpc-app/with-auth-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/auth";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth();
return {
db,
session,
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-app/with-auth.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/auth";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth();
return {
session,
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-app/with-better-auth-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/better-auth";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth.api.getSession({
headers: opts.headers,
});
return {
db,
session,
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-app/with-better-auth.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/better-auth";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth.api.getSession({
headers: opts.headers,
});
return {
session,
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-app/with-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: { headers: Headers }) => {
return {
db,
...opts,
};
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/base.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import superjson from "superjson";
import { ZodError } from "zod";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
type CreateContextOptions = Record;
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = (_opts: CreateContextOptions) => {
return {};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = (_opts: CreateNextContextOptions) => {
return createInnerTRPCContext({});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/with-auth-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import { type Session } from "next-auth";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/auth";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
interface CreateContextOptions {
session: Session | null;
}
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = (opts: CreateContextOptions) => {
return {
session: opts.session,
db,
};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
// Get the session from the server using the getServerSession wrapper function
const session = await auth(req, res);
return createInnerTRPCContext({
session,
});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/with-auth.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import { type Session } from "next-auth";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/auth";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
interface CreateContextOptions {
session: Session | null;
}
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = ({ session }: CreateContextOptions) => {
return {
session,
};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async ({
req,
res,
}: CreateNextContextOptions) => {
// Get the session from the server using the getServerSession wrapper function
const session = await auth(req, res);
return createInnerTRPCContext({
session,
});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/with-better-auth-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/better-auth";
import { type Session } from "~/server/better-auth/config";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
interface CreateContextOptions {
session: Session | null;
}
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = (opts: CreateContextOptions) => {
return {
session: opts.session,
db,
};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async ({ req }: CreateNextContextOptions) => {
// Convert IncomingHttpHeaders to Headers object
const headers = new Headers();
for (const [key, value] of Object.entries(req.headers)) {
if (Array.isArray(value)) {
value.forEach((v) => headers.append(key, v));
} else if (value) {
headers.append(key, value);
}
}
const session = await auth.api.getSession({
headers,
});
return createInnerTRPCContext({
session,
});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/with-better-auth.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
// import { } from "next-auth";
import superjson from "superjson";
import { ZodError } from "zod";
import { auth } from "~/server/better-auth";
import { type Session } from "~/server/better-auth/config";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
interface CreateContextOptions {
session: Session | null;
}
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = ({ session }: CreateContextOptions) => {
return {
session,
};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async ({ req }: CreateNextContextOptions) => {
// Convert IncomingHttpHeaders to Headers object
const headers = new Headers();
for (const [key, value] of Object.entries(req.headers)) {
if (Array.isArray(value)) {
value.forEach((v) => headers.append(key, v));
} else if (value) {
headers.append(key, value);
}
}
const session = await auth.api.getSession({
headers,
});
return createInnerTRPCContext({
session,
});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the session is valid and guarantees `ctx.session.user` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure
.use(timingMiddleware)
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
================================================
FILE: cli/template/extras/src/server/api/trpc-pages/with-db.ts
================================================
/**
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
* 1. You want to modify request context (see Part 1).
* 2. You want to create a new middleware or type of procedure (see Part 3).
*
* TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
import superjson from "superjson";
import { ZodError } from "zod";
import { db } from "~/server/db";
/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/
type CreateContextOptions = Record;
/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
*/
const createInnerTRPCContext = (_opts: CreateContextOptions) => {
return {
db,
};
};
/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = (_opts: CreateNextContextOptions) => {
return createInnerTRPCContext({});
};
/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/
const t = initTRPC.context().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
/**
* Create a server-side caller.
*
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;
/**
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
*
* These are the pieces you use to build your tRPC API. You should import these a lot in the
* "/src/server/api/routers" directory.
*/
/**
* This is how you create new routers and sub-routers in your tRPC API.
*
* @see https://trpc.io/docs/router
*/
export const createTRPCRouter = t.router;
/**
* Middleware for timing procedure execution and adding an artificial delay in development.
*
* You can remove this if you don't like it, but it can help catch unwanted waterfalls by simulating
* network latency that would occur in production but not in local development.
*/
const timingMiddleware = t.middleware(async ({ next, path }) => {
const start = Date.now();
if (t._config.isDev) {
// artificial delay in dev
const waitMs = Math.floor(Math.random() * 400) + 100;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
const result = await next();
const end = Date.now();
console.log(`[TRPC] ${path} took ${end - start}ms to execute`);
return result;
});
/**
* Public (unauthenticated) procedure
*
* This is the base piece you use to build new queries and mutations on your tRPC API. It does not
* guarantee that a user querying is authorized, but you can still access user session data if they
* are logged in.
*/
export const publicProcedure = t.procedure.use(timingMiddleware);
================================================
FILE: cli/template/extras/src/server/auth/config/base.ts
================================================
import { type DefaultSession, type NextAuthConfig } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
* object and keep type safety.
*
* @see https://next-auth.js.org/getting-started/typescript#module-augmentation
*/
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
}
// interface User {
// // ...other properties
// // role: UserRole;
// }
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
* @see https://next-auth.js.org/configuration/options
*/
export const authConfig = {
providers: [
DiscordProvider,
/**
* ...add more providers here.
*
* Most other providers require a bit more work than the Discord provider. For example, the
* GitHub provider requires you to add the `refresh_token_expires_in` field to the Account
* model. Refer to the NextAuth.js docs for the provider you want to use. Example:
*
* @see https://next-auth.js.org/providers/github
*/
],
callbacks: {
session: ({ session, token }) => ({
...session,
user: {
...session.user,
id: token.sub,
},
}),
},
} satisfies NextAuthConfig;
================================================
FILE: cli/template/extras/src/server/auth/config/with-drizzle.ts
================================================
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { type DefaultSession, type NextAuthConfig } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";
import { db } from "~/server/db";
import {
accounts,
sessions,
users,
verificationTokens,
} from "~/server/db/schema";
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
* object and keep type safety.
*
* @see https://next-auth.js.org/getting-started/typescript#module-augmentation
*/
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
}
// interface User {
// // ...other properties
// // role: UserRole;
// }
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
* @see https://next-auth.js.org/configuration/options
*/
export const authConfig = {
providers: [
DiscordProvider,
/**
* ...add more providers here.
*
* Most other providers require a bit more work than the Discord provider. For example, the
* GitHub provider requires you to add the `refresh_token_expires_in` field to the Account
* model. Refer to the NextAuth.js docs for the provider you want to use. Example:
*
* @see https://next-auth.js.org/providers/github
*/
],
adapter: DrizzleAdapter(db, {
usersTable: users,
accountsTable: accounts,
sessionsTable: sessions,
verificationTokensTable: verificationTokens,
}),
callbacks: {
session: ({ session, user }) => ({
...session,
user: {
...session.user,
id: user.id,
},
}),
},
} satisfies NextAuthConfig;
================================================
FILE: cli/template/extras/src/server/auth/config/with-prisma.ts
================================================
import { PrismaAdapter } from "@auth/prisma-adapter";
import { type DefaultSession, type NextAuthConfig } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";
import { db } from "~/server/db";
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
* object and keep type safety.
*
* @see https://next-auth.js.org/getting-started/typescript#module-augmentation
*/
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
}
// interface User {
// // ...other properties
// // role: UserRole;
// }
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
* @see https://next-auth.js.org/configuration/options
*/
export const authConfig = {
providers: [
DiscordProvider,
/**
* ...add more providers here.
*
* Most other providers require a bit more work than the Discord provider. For example, the
* GitHub provider requires you to add the `refresh_token_expires_in` field to the Account
* model. Refer to the NextAuth.js docs for the provider you want to use. Example:
*
* @see https://next-auth.js.org/providers/github
*/
],
adapter: PrismaAdapter(db),
callbacks: {
session: ({ session, user }) => ({
...session,
user: {
...session.user,
id: user.id,
},
}),
},
} satisfies NextAuthConfig;
================================================
FILE: cli/template/extras/src/server/auth/index.ts
================================================
import NextAuth from "next-auth";
import { cache } from "react";
import { authConfig } from "./config";
const { auth: uncachedAuth, handlers, signIn, signOut } = NextAuth(authConfig);
const auth = cache(uncachedAuth);
export { auth, handlers, signIn, signOut };
================================================
FILE: cli/template/extras/src/server/better-auth/client.ts
================================================
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient();
export type Session = typeof authClient.$Infer.Session;
================================================
FILE: cli/template/extras/src/server/better-auth/config/base.ts
================================================
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
// Make sure nextCookies() is the last plugin in the array
plugins: [nextCookies()],
});
export type Session = typeof auth.$Infer.Session;
================================================
FILE: cli/template/extras/src/server/better-auth/config/with-drizzle.ts
================================================
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { env } from "~/env";
import { db } from "~/server/db";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg", // or "pg" or "mysql"
}),
emailAndPassword: {
enabled: true,
},
socialProviders: {
github: {
clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID,
clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
redirectURI: "http://localhost:3000/api/auth/callback/github",
},
},
// Make sure nextCookies() is the last plugin in the array
plugins: [nextCookies()],
});
export type Session = typeof auth.$Infer.Session;
================================================
FILE: cli/template/extras/src/server/better-auth/config/with-prisma.ts
================================================
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { nextCookies } from "better-auth/next-js";
import { env } from "~/env";
import { db } from "~/server/db";
export const auth = betterAuth({
database: prismaAdapter(db, {
provider: "postgresql", // or "sqlite" or "mysql"
}),
emailAndPassword: {
enabled: true,
},
socialProviders: {
github: {
clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID,
clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
redirectURI: "http://localhost:3000/api/auth/callback/github",
},
},
// Make sure nextCookies() is the last plugin in the array
plugins: [nextCookies()],
});
export type Session = typeof auth.$Infer.Session;
================================================
FILE: cli/template/extras/src/server/better-auth/index.ts
================================================
export { auth } from "./config";
================================================
FILE: cli/template/extras/src/server/better-auth/server.ts
================================================
import { auth } from ".";
import { headers } from "next/headers";
import { cache } from "react";
export const getSession = cache(async () =>
auth.api.getSession({ headers: await headers() })
);
================================================
FILE: cli/template/extras/src/server/db/db-prisma-planetscale.ts
================================================
import { PrismaPlanetScale } from "@prisma/adapter-planetscale";
import { env } from "~/env";
import { PrismaClient } from "../../generated/prisma";
const createPrismaClient = () =>
new PrismaClient({
log:
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
adapter: new PrismaPlanetScale({ url: env.DATABASE_URL }),
});
const globalForPrisma = globalThis as unknown as {
prisma: ReturnType | undefined;
};
export const db = globalForPrisma.prisma ?? createPrismaClient();
if (env.NODE_ENV !== "production") globalForPrisma.prisma = db;
================================================
FILE: cli/template/extras/src/server/db/db-prisma.ts
================================================
import { env } from "~/env";
import { PrismaClient } from "../../generated/prisma";
const createPrismaClient = () =>
new PrismaClient({
log:
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
});
const globalForPrisma = globalThis as unknown as {
prisma: ReturnType | undefined;
};
export const db = globalForPrisma.prisma ?? createPrismaClient();
if (env.NODE_ENV !== "production") globalForPrisma.prisma = db;
================================================
FILE: cli/template/extras/src/server/db/index-drizzle/with-mysql.ts
================================================
import { drizzle } from "drizzle-orm/mysql2";
import { createPool, type Pool } from "mysql2/promise";
import { env } from "~/env";
import * as schema from "./schema";
/**
* Cache the database connection in development. This avoids creating a new connection on every HMR
* update.
*/
const globalForDb = globalThis as unknown as {
conn: Pool | undefined;
};
const conn = globalForDb.conn ?? createPool({ uri: env.DATABASE_URL });
if (env.NODE_ENV !== "production") globalForDb.conn = conn;
export const db = drizzle(conn, { schema, mode: "default" });
================================================
FILE: cli/template/extras/src/server/db/index-drizzle/with-planetscale.ts
================================================
import { Client } from "@planetscale/database";
import { drizzle } from "drizzle-orm/planetscale-serverless";
import { env } from "~/env";
import * as schema from "./schema";
export const db = drizzle(new Client({ url: env.DATABASE_URL }), { schema });
================================================
FILE: cli/template/extras/src/server/db/index-drizzle/with-postgres.ts
================================================
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { env } from "~/env";
import * as schema from "./schema";
/**
* Cache the database connection in development. This avoids creating a new connection on every HMR
* update.
*/
const globalForDb = globalThis as unknown as {
conn: postgres.Sql | undefined;
};
const conn = globalForDb.conn ?? postgres(env.DATABASE_URL);
if (env.NODE_ENV !== "production") globalForDb.conn = conn;
export const db = drizzle(conn, { schema });
================================================
FILE: cli/template/extras/src/server/db/index-drizzle/with-sqlite.ts
================================================
import { createClient, type Client } from "@libsql/client";
import { drizzle } from "drizzle-orm/libsql";
import { env } from "~/env";
import * as schema from "./schema";
/**
* Cache the database connection in development. This avoids creating a new connection on every HMR
* update.
*/
const globalForDb = globalThis as unknown as {
client: Client | undefined;
};
export const client =
globalForDb.client ?? createClient({ url: env.DATABASE_URL });
if (env.NODE_ENV !== "production") globalForDb.client = client;
export const db = drizzle(client, { schema });
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/base-mysql.ts
================================================
// Example model schema from the Drizzle docs
// https://orm.drizzle.team/docs/sql-schema-declaration
import { index, mysqlTableCreator } from "drizzle-orm/mysql-core";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [index("name_idx").on(t.name)]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/base-planetscale.ts
================================================
// Example model schema from the Drizzle docs
// https://orm.drizzle.team/docs/sql-schema-declaration
import { index, mysqlTableCreator } from "drizzle-orm/mysql-core";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [index("name_idx").on(t.name)]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/base-postgres.ts
================================================
// Example model schema from the Drizzle docs
// https://orm.drizzle.team/docs/sql-schema-declaration
import { index, pgTableCreator } from "drizzle-orm/pg-core";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = pgTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.integer().primaryKey().generatedByDefaultAsIdentity(),
name: d.varchar({ length: 256 }),
createdAt: d
.timestamp({ withTimezone: true })
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),
}),
(t) => [index("name_idx").on(t.name)]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/base-sqlite.ts
================================================
// Example model schema from the Drizzle docs
// https://orm.drizzle.team/docs/sql-schema-declaration
import { sql } from "drizzle-orm";
import { index, sqliteTableCreator } from "drizzle-orm/sqlite-core";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = sqliteTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.integer({ mode: "number" }).primaryKey({ autoIncrement: true }),
name: d.text({ length: 256 }),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [index("name_idx").on(t.name)]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-auth-mysql.ts
================================================
import { relations, sql } from "drizzle-orm";
import { index, mysqlTableCreator, primaryKey } from "drizzle-orm/mysql-core";
import { type AdapterAccount } from "next-auth/adapters";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdById: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const users = createTable("user", (d) => ({
id: d
.varchar({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
name: d.varchar({ length: 255 }),
email: d.varchar({ length: 255 }).notNull(),
emailVerified: d
.timestamp({
mode: "date",
fsp: 3,
})
.default(sql`CURRENT_TIMESTAMP(3)`),
image: d.varchar({ length: 255 }),
}));
export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
sessions: many(sessions),
}));
export const accounts = createTable(
"account",
(d) => ({
userId: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
type: d.varchar({ length: 255 }).$type().notNull(),
provider: d.varchar({ length: 255 }).notNull(),
providerAccountId: d.varchar({ length: 255 }).notNull(),
refresh_token: d.text(),
access_token: d.text(),
expires_at: d.int(),
token_type: d.varchar({ length: 255 }),
scope: d.varchar({ length: 255 }),
id_token: d.text(),
session_state: d.varchar({ length: 255 }),
}),
(t) => [
primaryKey({
columns: [t.provider, t.providerAccountId],
}),
index("account_user_id_idx").on(t.userId),
]
);
export const accountsRelations = relations(accounts, ({ one }) => ({
user: one(users, { fields: [accounts.userId], references: [users.id] }),
}));
export const sessions = createTable(
"session",
(d) => ({
sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),
userId: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
expires: d.timestamp({ mode: "date" }).notNull(),
}),
(t) => [index("session_user_id_idx").on(t.userId)]
);
export const sessionsRelations = relations(sessions, ({ one }) => ({
user: one(users, { fields: [sessions.userId], references: [users.id] }),
}));
export const verificationTokens = createTable(
"verification_token",
(d) => ({
identifier: d.varchar({ length: 255 }).notNull(),
token: d.varchar({ length: 255 }).notNull(),
expires: d.timestamp({ mode: "date" }).notNull(),
}),
(t) => [primaryKey({ columns: [t.identifier, t.token] })]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-auth-planetscale.ts
================================================
import { relations, sql } from "drizzle-orm";
import { index, mysqlTableCreator, primaryKey } from "drizzle-orm/mysql-core";
import { type AdapterAccount } from "next-auth/adapters";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdById: d.varchar({ length: 255 }).notNull(),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const users = createTable("user", (d) => ({
id: d
.varchar({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
name: d.varchar({ length: 255 }),
email: d.varchar({ length: 255 }).notNull(),
emailVerified: d
.timestamp({
mode: "date",
fsp: 3,
})
.default(sql`CURRENT_TIMESTAMP(3)`),
image: d.varchar({ length: 255 }),
}));
export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
sessions: many(sessions),
}));
export const accounts = createTable(
"account",
(d) => ({
userId: d.varchar({ length: 255 }).notNull(),
type: d.varchar({ length: 255 }).$type().notNull(),
provider: d.varchar({ length: 255 }).notNull(),
providerAccountId: d.varchar({ length: 255 }).notNull(),
refresh_token: d.text(),
access_token: d.text(),
expires_at: d.int(),
token_type: d.varchar({ length: 255 }),
scope: d.varchar({ length: 255 }),
id_token: d.text(),
session_state: d.varchar({ length: 255 }),
}),
(account) => [
primaryKey({ columns: [account.provider, account.providerAccountId] }),
index("accounts_user_id_idx").on(account.userId),
]
);
export const accountsRelations = relations(accounts, ({ one }) => ({
user: one(users, { fields: [accounts.userId], references: [users.id] }),
}));
export const sessions = createTable(
"session",
(d) => ({
sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),
userId: d.varchar({ length: 255 }).notNull(),
expires: d.timestamp({ mode: "date" }).notNull(),
}),
(session) => [index("session_user_id_idx").on(session.userId)]
);
export const sessionsRelations = relations(sessions, ({ one }) => ({
user: one(users, { fields: [sessions.userId], references: [users.id] }),
}));
export const verificationTokens = createTable(
"verification_token",
(d) => ({
identifier: d.varchar({ length: 255 }).notNull(),
token: d.varchar({ length: 255 }).notNull(),
expires: d.timestamp({ mode: "date" }).notNull(),
}),
(vt) => [primaryKey({ columns: [vt.identifier, vt.token] })]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-auth-postgres.ts
================================================
import { relations } from "drizzle-orm";
import { index, pgTableCreator, primaryKey } from "drizzle-orm/pg-core";
import { type AdapterAccount } from "next-auth/adapters";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = pgTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.integer().primaryKey().generatedByDefaultAsIdentity(),
name: d.varchar({ length: 256 }),
createdById: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
createdAt: d
.timestamp({ withTimezone: true })
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const users = createTable("user", (d) => ({
id: d
.varchar({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
name: d.varchar({ length: 255 }),
email: d.varchar({ length: 255 }).notNull(),
emailVerified: d
.timestamp({
mode: "date",
withTimezone: true,
})
.$defaultFn(() => /* @__PURE__ */ new Date()),
image: d.varchar({ length: 255 }),
}));
export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
}));
export const accounts = createTable(
"account",
(d) => ({
userId: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
type: d.varchar({ length: 255 }).$type().notNull(),
provider: d.varchar({ length: 255 }).notNull(),
providerAccountId: d.varchar({ length: 255 }).notNull(),
refresh_token: d.text(),
access_token: d.text(),
expires_at: d.integer(),
token_type: d.varchar({ length: 255 }),
scope: d.varchar({ length: 255 }),
id_token: d.text(),
session_state: d.varchar({ length: 255 }),
}),
(t) => [
primaryKey({ columns: [t.provider, t.providerAccountId] }),
index("account_user_id_idx").on(t.userId),
]
);
export const accountsRelations = relations(accounts, ({ one }) => ({
user: one(users, { fields: [accounts.userId], references: [users.id] }),
}));
export const sessions = createTable(
"session",
(d) => ({
sessionToken: d.varchar({ length: 255 }).notNull().primaryKey(),
userId: d
.varchar({ length: 255 })
.notNull()
.references(() => users.id),
expires: d.timestamp({ mode: "date", withTimezone: true }).notNull(),
}),
(t) => [index("t_user_id_idx").on(t.userId)]
);
export const sessionsRelations = relations(sessions, ({ one }) => ({
user: one(users, { fields: [sessions.userId], references: [users.id] }),
}));
export const verificationTokens = createTable(
"verification_token",
(d) => ({
identifier: d.varchar({ length: 255 }).notNull(),
token: d.varchar({ length: 255 }).notNull(),
expires: d.timestamp({ mode: "date", withTimezone: true }).notNull(),
}),
(t) => [primaryKey({ columns: [t.identifier, t.token] })]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-auth-sqlite.ts
================================================
import { relations, sql } from "drizzle-orm";
import { index, primaryKey, sqliteTableCreator } from "drizzle-orm/sqlite-core";
import { type AdapterAccount } from "next-auth/adapters";
/**
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
* database instance for multiple projects.
*
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
*/
export const createTable = sqliteTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.integer({ mode: "number" }).primaryKey({ autoIncrement: true }),
name: d.text({ length: 256 }),
createdById: d
.text({ length: 255 })
.notNull()
.references(() => users.id),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const users = createTable("user", (d) => ({
id: d
.text({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
name: d.text({ length: 255 }),
email: d.text({ length: 255 }).notNull(),
emailVerified: d.integer({ mode: "timestamp" }).default(sql`(unixepoch())`),
image: d.text({ length: 255 }),
}));
export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
}));
export const accounts = createTable(
"account",
(d) => ({
userId: d
.text({ length: 255 })
.notNull()
.references(() => users.id),
type: d.text({ length: 255 }).$type().notNull(),
provider: d.text({ length: 255 }).notNull(),
providerAccountId: d.text({ length: 255 }).notNull(),
refresh_token: d.text(),
access_token: d.text(),
expires_at: d.integer(),
token_type: d.text({ length: 255 }),
scope: d.text({ length: 255 }),
id_token: d.text(),
session_state: d.text({ length: 255 }),
}),
(t) => [
primaryKey({
columns: [t.provider, t.providerAccountId],
}),
index("account_user_id_idx").on(t.userId),
]
);
export const accountsRelations = relations(accounts, ({ one }) => ({
user: one(users, { fields: [accounts.userId], references: [users.id] }),
}));
export const sessions = createTable(
"session",
(d) => ({
sessionToken: d.text({ length: 255 }).notNull().primaryKey(),
userId: d
.text({ length: 255 })
.notNull()
.references(() => users.id),
expires: d.integer({ mode: "timestamp" }).notNull(),
}),
(t) => [index("session_userId_idx").on(t.userId)]
);
export const sessionsRelations = relations(sessions, ({ one }) => ({
user: one(users, { fields: [sessions.userId], references: [users.id] }),
}));
export const verificationTokens = createTable(
"verification_token",
(d) => ({
identifier: d.text({ length: 255 }).notNull(),
token: d.text({ length: 255 }).notNull(),
expires: d.integer({ mode: "timestamp" }).notNull(),
}),
(t) => [primaryKey({ columns: [t.identifier, t.token] })]
);
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-better-auth-mysql.ts
================================================
import { relations } from "drizzle-orm";
import {
boolean,
index,
mysqlTable,
mysqlTableCreator,
text,
timestamp,
varchar,
} from "drizzle-orm/mysql-core";
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdById: d
.varchar({ length: 255 })
.notNull()
.references(() => user.id),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const user = mysqlTable("user", {
id: varchar("id", { length: 36 }).primaryKey(),
name: text("name").notNull(),
email: varchar("email", { length: 255 }).notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const session = mysqlTable("session", {
id: varchar("id", { length: 36 }).primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: varchar("token", { length: 255 }).notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: varchar("user_id", { length: 36 })
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
});
export const account = mysqlTable("account", {
id: varchar("id", { length: 36 }).primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: varchar("user_id", { length: 36 })
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const verification = mysqlTable("verification", {
id: varchar("id", { length: 36 }).primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
updatedAt: timestamp("updated_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
});
export const usersRelations = relations(user, ({ many }) => ({
accounts: many(account),
sessions: many(session),
}));
export const accountsRelations = relations(account, ({ one }) => ({
user: one(user, { fields: [account.userId], references: [user.id] }),
}));
export const sessionsRelations = relations(session, ({ one }) => ({
user: one(user, { fields: [session.userId], references: [user.id] }),
}));
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-better-auth-planetscale.ts
================================================
import { relations } from "drizzle-orm";
import {
boolean,
index,
mysqlTable,
mysqlTableCreator,
text,
timestamp,
varchar,
} from "drizzle-orm/mysql-core";
export const createTable = mysqlTableCreator((name) => `project1_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.bigint({ mode: "number" }).primaryKey().autoincrement(),
name: d.varchar({ length: 256 }),
createdById: d
.varchar({ length: 255 })
.notNull()
.references(() => user.id),
createdAt: d
.timestamp()
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: d.timestamp().onUpdateNow(),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const user = mysqlTable("user", {
id: varchar("id", { length: 36 }).primaryKey(),
name: text("name").notNull(),
email: varchar("email", { length: 255 }).notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const session = mysqlTable("session", {
id: varchar("id", { length: 36 }).primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: varchar("token", { length: 255 }).notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: varchar("user_id", { length: 36 })
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
});
export const account = mysqlTable("account", {
id: varchar("id", { length: 36 }).primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: varchar("user_id", { length: 36 })
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const verification = mysqlTable("verification", {
id: varchar("id", { length: 36 }).primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
updatedAt: timestamp("updated_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
});
export const usersRelations = relations(user, ({ many }) => ({
accounts: many(account),
sessions: many(session),
}));
export const accountsRelations = relations(account, ({ one }) => ({
user: one(user, { fields: [account.userId], references: [user.id] }),
}));
export const sessionsRelations = relations(session, ({ one }) => ({
user: one(user, { fields: [session.userId], references: [user.id] }),
}));
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-better-auth-postgres.ts
================================================
import { relations } from "drizzle-orm";
import {
boolean,
index,
pgTable,
pgTableCreator,
text,
timestamp,
} from "drizzle-orm/pg-core";
export const createTable = pgTableCreator((name) => `pg-drizzle_${name}`);
export const posts = createTable(
"post",
(d) => ({
id: d.integer().primaryKey().generatedByDefaultAsIdentity(),
name: d.varchar({ length: 256 }),
createdById: d
.varchar({ length: 255 })
.notNull()
.references(() => user.id),
createdAt: d
.timestamp({ withTimezone: true })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
});
export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
updatedAt: timestamp("updated_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
});
export const userRelations = relations(user, ({ many }) => ({
account: many(account),
session: many(session),
}));
export const accountRelations = relations(account, ({ one }) => ({
user: one(user, { fields: [account.userId], references: [user.id] }),
}));
export const sessionRelations = relations(session, ({ one }) => ({
user: one(user, { fields: [session.userId], references: [user.id] }),
}));
================================================
FILE: cli/template/extras/src/server/db/schema-drizzle/with-better-auth-sqlite.ts
================================================
import { relations, sql } from "drizzle-orm";
import { index, sqliteTable } from "drizzle-orm/sqlite-core";
/**
* Multi-project schema prefix helper
*/
// Posts example table
export const posts = sqliteTable(
"post",
(d) => ({
id: d.integer({ mode: "number" }).primaryKey({ autoIncrement: true }),
name: d.text({ length: 256 }),
createdById: d
.text({ length: 255 })
.notNull()
.references(() => user.id),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [
index("created_by_idx").on(t.createdById),
index("name_idx").on(t.name),
]
);
// Better Auth core tables
export const user = sqliteTable("user", (d) => ({
id: d
.text({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
name: d.text({ length: 255 }),
email: d.text({ length: 255 }).notNull().unique(),
emailVerified: d.integer({ mode: "boolean" }).default(false),
image: d.text({ length: 255 }),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}));
export const userRelations = relations(user, ({ many }) => ({
account: many(account),
session: many(session),
}));
export const account = sqliteTable(
"account",
(d) => ({
id: d
.text({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
userId: d
.text({ length: 255 })
.notNull()
.references(() => user.id),
accountId: d.text({ length: 255 }).notNull(),
providerId: d.text({ length: 255 }).notNull(),
accessToken: d.text(),
refreshToken: d.text(),
accessTokenExpiresAt: d.integer({ mode: "timestamp" }),
refreshTokenExpiresAt: d.integer({ mode: "timestamp" }),
scope: d.text({ length: 255 }),
idToken: d.text(),
password: d.text(),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [index("account_user_id_idx").on(t.userId)]
);
export const accountRelations = relations(account, ({ one }) => ({
user: one(user, { fields: [account.userId], references: [user.id] }),
}));
export const session = sqliteTable(
"session",
(d) => ({
id: d
.text({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
userId: d
.text({ length: 255 })
.notNull()
.references(() => user.id),
token: d.text({ length: 255 }).notNull().unique(),
expiresAt: d.integer({ mode: "timestamp" }).notNull(),
ipAddress: d.text({ length: 255 }),
userAgent: d.text({ length: 255 }),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [index("session_user_id_idx").on(t.userId)]
);
export const sessionRelations = relations(session, ({ one }) => ({
user: one(user, { fields: [session.userId], references: [user.id] }),
}));
export const verification = sqliteTable(
"verification",
(d) => ({
id: d
.text({ length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
identifier: d.text({ length: 255 }).notNull(),
value: d.text({ length: 255 }).notNull(),
expiresAt: d.integer({ mode: "timestamp" }).notNull(),
createdAt: d
.integer({ mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
updatedAt: d.integer({ mode: "timestamp" }).$onUpdate(() => new Date()),
}),
(t) => [index("verification_identifier_idx").on(t.identifier)]
);
================================================
FILE: cli/template/extras/src/styles/globals.css
================================================
@import "tailwindcss";
@theme {
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
================================================
FILE: cli/template/extras/src/trpc/query-client.ts
================================================
import {
defaultShouldDehydrateQuery,
QueryClient,
} from "@tanstack/react-query";
import SuperJSON from "superjson";
export const createQueryClient = () =>
new QueryClient({
defaultOptions: {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
staleTime: 30 * 1000,
},
dehydrate: {
serializeData: SuperJSON.serialize,
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === "pending",
},
hydrate: {
deserializeData: SuperJSON.deserialize,
},
},
});
================================================
FILE: cli/template/extras/src/trpc/react.tsx
================================================
"use client";
import { QueryClientProvider, type QueryClient } from "@tanstack/react-query";
import { httpBatchStreamLink, loggerLink } from "@trpc/client";
import { createTRPCReact } from "@trpc/react-query";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import { useState } from "react";
import SuperJSON from "superjson";
import { type AppRouter } from "~/server/api/root";
import { createQueryClient } from "./query-client";
let clientQueryClientSingleton: QueryClient | undefined = undefined;
const getQueryClient = () => {
if (typeof window === "undefined") {
// Server: always make a new query client
return createQueryClient();
}
// Browser: use singleton pattern to keep the same query client
clientQueryClientSingleton ??= createQueryClient();
return clientQueryClientSingleton;
};
export const api = createTRPCReact();
/**
* Inference helper for inputs.
*
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs;
/**
* Inference helper for outputs.
*
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs;
export function TRPCReactProvider(props: { children: React.ReactNode }) {
const queryClient = getQueryClient();
const [trpcClient] = useState(() =>
api.createClient({
links: [
loggerLink({
enabled: (op) =>
process.env.NODE_ENV === "development" ||
(op.direction === "down" && op.result instanceof Error),
}),
httpBatchStreamLink({
transformer: SuperJSON,
url: getBaseUrl() + "/api/trpc",
headers: () => {
const headers = new Headers();
headers.set("x-trpc-source", "nextjs-react");
return headers;
},
}),
],
})
);
return (
{props.children}
);
}
function getBaseUrl() {
if (typeof window !== "undefined") return window.location.origin;
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
return `http://localhost:${process.env.PORT ?? 3000}`;
}
================================================
FILE: cli/template/extras/src/trpc/server.ts
================================================
import "server-only";
import { createHydrationHelpers } from "@trpc/react-query/rsc";
import { headers } from "next/headers";
import { cache } from "react";
import { createCaller, type AppRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import { createQueryClient } from "./query-client";
/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(async () => {
const heads = new Headers(await headers());
heads.set("x-trpc-source", "rsc");
return createTRPCContext({
headers: heads,
});
});
const getQueryClient = cache(createQueryClient);
const caller = createCaller(createContext);
export const { trpc: api, HydrateClient } = createHydrationHelpers(
caller,
getQueryClient
);
================================================
FILE: cli/template/extras/src/utils/api.ts
================================================
/**
* This is the client-side entrypoint for your tRPC API. It is used to create the `api` object which
* contains the Next.js App-wrapper, as well as your type-safe React Query hooks.
*
* We also create a few inference helpers for input and output types.
*/
import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";
import { type AppRouter } from "~/server/api/root";
const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};
/** A set of type-safe react-query hooks for your tRPC API. */
export const api = createTRPCNext({
config() {
return {
/**
* Links used to determine request flow from client to server.
*
* @see https://trpc.io/docs/links
*/
links: [
loggerLink({
enabled: (opts) =>
process.env.NODE_ENV === "development" ||
(opts.direction === "down" && opts.result instanceof Error),
}),
httpBatchLink({
/**
* Transformer used for data de-serialization from the server.
*
* @see https://trpc.io/docs/data-transformers
*/
transformer: superjson,
url: `${getBaseUrl()}/api/trpc`,
}),
],
};
},
/**
* Whether tRPC should await queries when server rendering pages.
*
* @see https://trpc.io/docs/nextjs#ssr-boolean-default-false
*/
ssr: false,
transformer: superjson,
});
/**
* Inference helper for inputs.
*
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs;
/**
* Inference helper for outputs.
*
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs;
================================================
FILE: cli/template/extras/start-database/mysql.sh
================================================
#!/usr/bin/env bash
# Use this script to start a docker container for a local development database
# TO RUN ON WINDOWS:
# 1. Install WSL (Windows Subsystem for Linux) - https://learn.microsoft.com/en-us/windows/wsl/install
# 2. Install Docker Desktop or Podman Deskop
# - Docker Desktop for Windows - https://docs.docker.com/docker-for-windows/install/
# - Podman Desktop - https://podman.io/getting-started/installation
# 3. Open WSL - `wsl`
# 4. Run this script - `./start-database.sh`
# On Linux and macOS you can run this script directly - `./start-database.sh`
set -a
source .env
DB_PASSWORD=$(echo "$DATABASE_URL" | awk -F':' '{print $3}' | awk -F'@' '{print $1}')
DB_PORT=$(echo "$DATABASE_URL" | awk -F':' '{print $4}' | awk -F'\/' '{print $1}')
DB_NAME=$(echo "$DATABASE_URL" | awk -F'/' '{print $4}')
DB_CONTAINER_NAME="$DB_NAME-mysql"
if ! [ -x "$(command -v docker)" ] && ! [ -x "$(command -v podman)" ]; then
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"
exit 1
fi
# determine which docker command to use
if [ -x "$(command -v docker)" ]; then
DOCKER_CMD="docker"
elif [ -x "$(command -v podman)" ]; then
DOCKER_CMD="podman"
fi
if ! $DOCKER_CMD info > /dev/null 2>&1; then
echo "$DOCKER_CMD daemon is not running. Please start $DOCKER_CMD and try again."
exit 1
fi
if command -v nc >/dev/null 2>&1; then
if nc -z localhost "$DB_PORT" 2>/dev/null; then
echo "Port $DB_PORT is already in use."
exit 1
fi
else
echo "Warning: Unable to check if port $DB_PORT is already in use (netcat not installed)"
read -p "Do you want to continue anyway? [y/N]: " -r REPLY
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting."
exit 1
fi
fi
if [ "$($DOCKER_CMD ps -q -f name=$DB_CONTAINER_NAME)" ]; then
echo "Database container '$DB_CONTAINER_NAME' already running"
exit 0
fi
if [ "$($DOCKER_CMD ps -q -a -f name=$DB_CONTAINER_NAME)" ]; then
$DOCKER_CMD start "$DB_CONTAINER_NAME"
echo "Existing database container '$DB_CONTAINER_NAME' started"
exit 0
fi
if [ "$DB_PASSWORD" == "password" ]; then
echo "You are using the default database password"
read -p "Should we generate a random password for you? [y/N]: " -r REPLY
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Please change the default password in the .env file and try again"
exit 1
fi
# Generate a random URL-safe password
DB_PASSWORD=$(openssl rand -base64 12 | tr '+/' '-_')
if [[ "$(uname)" == "Darwin" ]]; then
# macOS requires an empty string to be passed with the `i` flag
sed -i '' "s#:password@#:$DB_PASSWORD@#" .env
else
sed -i "s#:password@#:$DB_PASSWORD@#" .env
fi
fi
$DOCKER_CMD run -d \
--name $DB_CONTAINER_NAME \
-e MYSQL_ROOT_PASSWORD="$DB_PASSWORD" \
-e MYSQL_DATABASE="$DB_NAME" \
-p "$DB_PORT":3306 \
docker.io/mysql && echo "Database container '$DB_CONTAINER_NAME' was successfully created"
================================================
FILE: cli/template/extras/start-database/postgres.sh
================================================
#!/usr/bin/env bash
# Use this script to start a docker container for a local development database
# TO RUN ON WINDOWS:
# 1. Install WSL (Windows Subsystem for Linux) - https://learn.microsoft.com/en-us/windows/wsl/install
# 2. Install Docker Desktop or Podman Deskop
# - Docker Desktop for Windows - https://docs.docker.com/docker-for-windows/install/
# - Podman Desktop - https://podman.io/getting-started/installation
# 3. Open WSL - `wsl`
# 4. Run this script - `./start-database.sh`
# On Linux and macOS you can run this script directly - `./start-database.sh`
# import env variables from .env
set -a
source .env
DB_PASSWORD=$(echo "$DATABASE_URL" | awk -F':' '{print $3}' | awk -F'@' '{print $1}')
DB_PORT=$(echo "$DATABASE_URL" | awk -F':' '{print $4}' | awk -F'\/' '{print $1}')
DB_NAME=$(echo "$DATABASE_URL" | awk -F'/' '{print $4}')
DB_CONTAINER_NAME="$DB_NAME-postgres"
if ! [ -x "$(command -v docker)" ] && ! [ -x "$(command -v podman)" ]; then
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"
exit 1
fi
# determine which docker command to use
if [ -x "$(command -v docker)" ]; then
DOCKER_CMD="docker"
elif [ -x "$(command -v podman)" ]; then
DOCKER_CMD="podman"
fi
if ! $DOCKER_CMD info > /dev/null 2>&1; then
echo "$DOCKER_CMD daemon is not running. Please start $DOCKER_CMD and try again."
exit 1
fi
if command -v nc >/dev/null 2>&1; then
if nc -z localhost "$DB_PORT" 2>/dev/null; then
echo "Port $DB_PORT is already in use."
exit 1
fi
else
echo "Warning: Unable to check if port $DB_PORT is already in use (netcat not installed)"
read -p "Do you want to continue anyway? [y/N]: " -r REPLY
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Aborting."
exit 1
fi
fi
if [ "$($DOCKER_CMD ps -q -f name=$DB_CONTAINER_NAME)" ]; then
echo "Database container '$DB_CONTAINER_NAME' already running"
exit 0
fi
if [ "$($DOCKER_CMD ps -q -a -f name=$DB_CONTAINER_NAME)" ]; then
$DOCKER_CMD start "$DB_CONTAINER_NAME"
echo "Existing database container '$DB_CONTAINER_NAME' started"
exit 0
fi
if [ "$DB_PASSWORD" = "password" ]; then
echo "You are using the default database password"
read -p "Should we generate a random password for you? [y/N]: " -r REPLY
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Please change the default password in the .env file and try again"
exit 1
fi
# Generate a random URL-safe password
DB_PASSWORD=$(openssl rand -base64 12 | tr '+/' '-_')
if [[ "$(uname)" == "Darwin" ]]; then
# macOS requires an empty string to be passed with the `i` flag
sed -i '' "s#:password@#:$DB_PASSWORD@#" .env
else
sed -i "s#:password@#:$DB_PASSWORD@#" .env
fi
fi
$DOCKER_CMD run -d \
--name $DB_CONTAINER_NAME \
-e POSTGRES_USER="postgres" \
-e POSTGRES_PASSWORD="$DB_PASSWORD" \
-e POSTGRES_DB="$DB_NAME" \
-p "$DB_PORT":5432 \
docker.io/postgres && echo "Database container '$DB_CONTAINER_NAME' was successfully created"
================================================
FILE: cli/tsconfig.eslint.json
================================================
{
"extends": "./tsconfig.json",
"include": ["src", "template/**/*.ts", "template/**/*.tsx"]
}
================================================
FILE: cli/tsconfig.json
================================================
{
"extends": "../tsconfig.json",
"compilerOptions": {
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
},
"checkJs": true
},
"include": ["src", "tsup.config.ts", "../reset.d.ts", "prettier.config.mjs"]
}
================================================
FILE: cli/tsup.config.ts
================================================
import { defineConfig } from "tsup";
const isDev = process.env.npm_lifecycle_event === "dev";
export default defineConfig({
clean: true,
entry: ["src/index.ts"],
format: ["esm"],
minify: !isDev,
target: "esnext",
outDir: "dist",
onSuccess: isDev ? "node dist/index.js" : undefined,
});
================================================
FILE: package.json
================================================
{
"name": "@ct3a/root",
"version": "0.0.0",
"description": "Quickest way to start a new web app with full stack typesafety",
"author": "Shoubhit Dash (https://nexxel.dev)",
"maintainers": [
"Julius Marminge (https://jumr.dev)"
],
"type": "module",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/t3-oss/create-t3-app.git"
},
"keywords": [
"create-t3-app",
"init.tips",
"next.js",
"t3-stack",
"tailwind",
"tRPC",
"typescript"
],
"engines": {
"node": ">=20.0.0"
},
"packageManager": "pnpm@10.8.0",
"scripts": {
"typecheck": "turbo typecheck",
"build:cli": "turbo --filter=create-t3-app build",
"build:www": "turbo --filter=www build",
"build": "turbo build",
"start:cli": "turbo --filter=create-t3-app start",
"start:www": "turbo --filter=www start",
"dev:cli": "turbo --filter=create-t3-app dev",
"dev:www": "turbo --filter=www dev",
"clean": "turbo clean && rm -rf node_modules",
"lint": "turbo lint && manypkg check",
"lint:fix": "turbo lint:fix && manypkg fix",
"format": "turbo format && prettier --write '*.{cjs,json}' --ignore-unknown --no-error-on-unmatched-pattern",
"format:check": "turbo format:check && prettier --check '*.{cjs,json}' --ignore-unknown --no-error-on-unmatched-pattern",
"check": "turbo lint typecheck format:check && manypkg check",
"release": "changeset version",
"pub:beta": "cd cli && pnpm pub:beta",
"pub:release": "cd cli && pnpm pub:release"
},
"dependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.27.3",
"@eslint/compat": "^1.2.7",
"@eslint/eslintrc": "^3.3.1",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@manypkg/cli": "^0.20.0",
"@total-typescript/ts-reset": "^0.3.7",
"@types/node": "^24.10.1",
"eslint": "^9.23.0",
"eslint-plugin-import-x": "^4.9.1",
"eslint-plugin-isaacscript": "^4.0.0",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.2.0",
"prettier": "^3.5.3",
"turbo": "1.13.3-canary.3",
"typescript": "^5.8.2",
"typescript-eslint": "^8.27.0"
}
}
================================================
FILE: pnpm-workspace.yaml
================================================
packages:
- cli
- www
onlyBuiltDependencies:
- '@prisma/client'
- '@prisma/engines'
- esbuild
- prisma
- sharp
================================================
FILE: prettier.config.mjs
================================================
/**
* @type {import('prettier').Config & import("@ianvs/prettier-plugin-sort-imports").PluginConfig}
*/
const config = {
arrowParens: "always",
printWidth: 80,
singleQuote: false,
jsxSingleQuote: false,
semi: true,
trailingComma: "all",
tabWidth: 2,
};
export default config;
================================================
FILE: reset.d.ts
================================================
import "@total-typescript/ts-reset";
================================================
FILE: tsconfig.json
================================================
{
"include": [".eslintrc.cjs", "prettier.config.mjs"],
"compilerOptions": {
/* LANGUAGE COMPILATION OPTIONS */
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2021"],
"module": "Node16",
"moduleResolution": "nodenext",
"resolveJsonModule": true,
"allowJs": true,
"checkJs": true,
/* EMIT RULES */
"outDir": "./dist",
"noEmit": true, // TSUP takes care of emitting js for us, in a MUCH faster way
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
/* TYPE CHECKING RULES */
"strict": true,
// "noImplicitAny": true, // Included in "Strict"
// "noImplicitThis": true, // Included in "Strict"
// "strictBindCallApply": true, // Included in "Strict"
// "strictFunctionTypes": true, // Included in "Strict"
// "strictNullChecks": true, // Included in "Strict"
// "strictPropertyInitialization": true, // Included in "Strict"
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"useUnknownInCatchVariables": true,
"noUncheckedIndexedAccess": true, // TLDR - Checking an indexed value (array[0]) now forces type as there is no confirmation that index exists
// THE BELOW ARE EXTRA STRICT OPTIONS THAT SHOULD ONLY BY CONSIDERED IN VERY SAFE PROJECTS
// "exactOptionalPropertyTypes": true, // TLDR - Setting to undefined is not the same as a property not being defined at all
// "noPropertyAccessFromIndexSignature": true, // TLDR - Use dot notation for objects if youre sure it exists, use ['index'] notaion if unsure
/* OTHER OPTIONS */
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
// "emitDecoratorMetadata": true,
// "experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"useDefineForClassFields": true
}
}
================================================
FILE: turbo.json
================================================
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"outputs": ["dist/**", ".vercel/output/**", ".next/**"],
"dependsOn": ["^build"]
},
"dev": {
"cache": false,
"persistent": true
},
"start": {
"dependsOn": ["^build"]
},
"lint": {
"cache": false
},
"lint:fix": {
"cache": false
},
"format": {
"cache": false
},
"format:check": {
"cache": false
},
"clean": {
"cache": false
},
"typecheck": {}
}
}
================================================
FILE: www/.env.example
================================================
# For developers who would like the data to be pulled correctly,
# generate these tokens from the provider and add them to a .gitignored .env file
# You can run `pnpm dev` without them, and dummy data (or no data) will be used instead
# Github - for grabbing star count in navbar, and commit history for docs pages
# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
PUBLIC_GITHUB_TOKEN=
# Twitter (API v2)- for grabbing Twitter card data
# https://developer.twitter.com/en/docs/authentication/overview
TWITTER_BEARER_TOKEN=
# For enabling debug mode in satori (for OG images)
DEBUG_OG=
================================================
FILE: www/.gitignore
================================================
# build output
dist/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
!.env.example
# macOS-specific files
.DS_Store
================================================
FILE: www/README.md
================================================
# create-t3-app Documentation Site
Based on the [Astro Starter Kit: Docs Site](https://github.com/withastro/astro/tree/latest/examples/docs). New to Astro?
- Check out [their documentation](https://docs.astro.build).
- Jump into their [Discord server](https://astro.build/chat).
- Deploy a site to production with the guide, [Deploy an Astro Website](https://docs.astro.build/guides/deploy).
## Outline
- [Features](#features)
- [Run Site Locally](#run-site-locally)
- [Command Cheat Sheet](#command-cheat-sheet)
- [Customize This Theme](#customize-this-theme)
- [Site Metadata](#site-metadata)
- [CSS Styling](#css-styling)
- [Page Metadata](#page-metadata)
- [Sidebar Navigation](#sidebar-navigation)
- [Multiple Languages Support](#multiple-languages-support)
## Features
- ✅ **Full Markdown support**
- ✅ **Responsive mobile-friendly design**
- ✅ **Sidebar navigation**
- ✅ **Search (powered by Algolia)**
- ✅ **Multi-language i18n**
- ✅ **Automatic table of contents**
- ✅ **Automatic list of contributors**
- ✅ (and, best of all) **dark mode**
## Run Site Locally
```bash
git clone https://github.com/t3-oss/create-t3-app.git
cd create-t3-app/www
pnpm i
pnpm dev
```
## Command Cheat Sheet
All commands are run from the root of the project, from a terminal.
| Command | Action |
| :--------------------- | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:3000` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro --help` | Get help using the Astro CLI |
## Customize This Theme
### Site Metadata
`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.
### CSS Styling
The 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.
This 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:
```diff
/* public/theme.css */
:root {
color-scheme: light;
- --theme-accent: hsla(var(--color-blue), 1);
+ --theme-accent: hsla(var(--color-red), 1); /* or: hsla(#FF0000, 1); */
```
### Page Metadata
Astro 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.
```markdown
---
title: Example title
description: Really cool docs example that uses Astro
layout: ../../layouts/MainLayout.astro
---
# Page content...
```
This 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.
### Sidebar Navigation
The 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.
```ts
// src/config.ts
export const SIDEBAR = {
en: [
{ text: "Section Header", header: true },
{ text: "Introduction", link: "en/introduction" },
{ text: "Page 2", link: "en/page-2" },
{ text: "Page 3", link: "en/page-3" },
{ text: "Another Section", header: true },
{ text: "Page 4", link: "en/page-4" },
],
};
```
Note 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.
### Multiple Languages Support
The 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]/...`:
```diff
📂 src/pages
┣ 📂 en
┃ ┣ 📜 page-1.md
┃ ┣ 📜 page-2.md
┃ ┣ 📜 page-3.astro
+ ┣ 📂 es
+ ┃ ┣ 📜 page-1.md
+ ┃ ┣ 📜 page-2.md
+ ┃ ┣ 📜 page-3.astro
```
You'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.
```diff
// src/config.ts
export const KNOWN_LANGUAGES = {
English: 'en',
+ Spanish: 'es',
};
```
Last 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.
> Make sure the sidebar `link` value points to the correct language!
```diff
// src/config.ts
export const SIDEBAR = {
en: [
{ text: 'Section Header', header: true, },
{ text: 'Introduction', link: 'en/introduction' },
// ...
],
+ es: [
+ { text: 'Encabezado de sección', header: true, },
+ { text: 'Introducción', link: 'es/introduction' },
+ // ...
+ ],
};
// ...
```
If 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):
```diff
```
What 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`.
================================================
FILE: www/TRANSLATIONS.md
================================================
# Contributing Guidelines for our docs
Are you a native speaker of a language other than English? We'd love to have your help!
## How to contribute
(Read the [contribution guidelines](../CONTRIBUTING.md) first for general information about contributing to this project.)
### Initial Translation
If the docs are not available in your language yet and you would like to translate them, you can do so by following these steps:
1. 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).)
2. 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.
3. File by file, translate the content of the files.
4. 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.
5. If the language you are translating into is read right-to-left (for example, Arabic or Hebrew), also add `dir: rtl` to the frontmatter.
6. 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.
7. When you're done, mark the pull request as ready for review.
### Reviewing
We 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.
We'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.
### Maintaining
Naturally, 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!
We 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.
Becoming 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).
================================================
FILE: www/astro.config.mjs
================================================
import mdx from "@astrojs/mdx";
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
import vercel from "@astrojs/vercel";
import { defineConfig } from "astro/config";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeExternalLinks from "rehype-external-links";
import rehypeSlug from "rehype-slug";
import remarkCodeTitles from "remark-code-titles";
/** @link https://astro.build/config */
export default defineConfig({
site: `https://create.t3.gg/`,
output: "server",
adapter: vercel(),
markdown: {
remarkPlugins: [remarkCodeTitles],
rehypePlugins: [
[
rehypeExternalLinks,
{
target: "_blank",
rel: ["noreferrer noopener"],
content: {
type: "text",
value: "↗",
},
},
],
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: {
class: "heading-link heading-link--hidden---effects",
"data-heading-link": true,
},
behavior: "wrap",
},
],
],
shikiConfig: {
theme: "rose-pine",
wrap: true,
},
},
integrations: [react(), sitemap(), mdx()],
vite: {
optimizeDeps: {
exclude: ["@resvg/resvg-js"],
},
},
});
================================================
FILE: www/package.json
================================================
{
"name": "@ct3a/www",
"version": "0.0.1",
"private": true,
"scripts": {
"typecheck": "tsc --noEmit",
"dev": "astro dev",
"start": "astro dev",
"check": "astro check",
"clean": "rm -rf node_modules .turbo dist .eslintcache",
"format": "prettier '**/*.{cjs,mjs,ts,tsx,md,json,astro}' --ignore-path ../.gitignore --ignore-unknown --write",
"format:check": "prettier '**/*.{cjs,mjs,ts,tsx,md,json,astro}' --ignore-path ../.gitignore --ignore-unknown --check",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@algolia/client-search": "^5.21.0",
"@astrojs/check": "^0.9.4",
"@astrojs/mdx": "^4.2.1",
"@astrojs/sitemap": "^3.3.0",
"@astrojs/vercel": "^8.1.3",
"@docsearch/css": "^3.9.0",
"@docsearch/react": "^3.9.0",
"@fontsource-variable/inter": "^5.2.5",
"@headlessui/react": "^2.2.0",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@resvg/resvg-js": "^2.6.2",
"@stackblitz/sdk": "^1.11.0",
"@vercel/analytics": "^1.5.0",
"clsx": "^2.1.1",
"embla-carousel": "^8.5.2",
"embla-carousel-autoplay": "^8.5.2",
"satori": "^0.12.1",
"sharp": "^0.33.5",
"tailwind-scrollbar": "^3.0.0",
"treeify": "^1.1.0",
"unist-util-visit": "^5.0.0",
"zod": "^3.24.2"
},
"devDependencies": {
"@astrojs/react": "^4.2.1",
"@astrojs/tailwind": "^6.0.1",
"@types/node": "^24.10.1",
"@types/react": "~19.1.0",
"@types/react-dom": "~19.1.0",
"@types/react-typist": "^2.0.6",
"@types/treeify": "^1.0.3",
"astro": "^5.5.4",
"prettier": "^3.5.3",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.11",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-typist": "^2.0.5",
"rehype-autolink-headings": "^7.1.0",
"rehype-external-links": "^3.0.0",
"rehype-slug": "^6.0.0",
"remark-code-titles": "^0.1.2",
"tailwindcss": "npm:tailwindcss@^3",
"typescript": "^5.8.2"
}
}
================================================
FILE: www/postcss.config.cjs
================================================
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
module.exports = config;
================================================
FILE: www/prettier.config.mjs
================================================
import baseConfig from "../prettier.config.mjs";
/**
* @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions &
* import("@ianvs/prettier-plugin-sort-imports").PluginConfig}
*/
const config = {
...baseConfig,
plugins: [
"@ianvs/prettier-plugin-sort-imports",
"prettier-plugin-astro",
"prettier-plugin-tailwindcss", // MUST come last
],
overrides: [
{
files: "*.astro",
options: {
parser: "astro",
},
},
],
astroAllowShorthand: false,
tailwindConfig: "./tailwind.config.ts",
importOrder: ["", "", "^~/", "^[.][.]/", "^[.]/"],
importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
importOrderTypeScriptVersion: "4.4.0",
};
export default config;
================================================
FILE: www/public/makeScrollableCodeFocusable.js
================================================
Array.from(document.getElementsByTagName("pre")).forEach((element) => {
element.setAttribute("tabindex", "0");
});
================================================
FILE: www/public/robots.txt
================================================
# Algolia-Crawler-Verif: 013A1A14AB9EE32B
User-agent: *
Allow: /
Sitemap: https://create.t3.gg/sitemap-index.xml
================================================
FILE: www/src/.vscode/settings.json
================================================
{
"workbench.editor.wrapTabs": false,
"editor.wordWrap": "on"
}
================================================
FILE: www/src/components/accessibility/jumpToContent.astro
================================================
---
import Button from "../landingPage/button.astro";
---
================================================
FILE: www/src/components/branding/Asset.astro
================================================
---
import Button from "../landingPage/button.astro";
export interface Props {
title: string;
bg: "white" | "black";
description: string;
assets: {
svg: string | null;
png: string | null;
};
attribution?: boolean;
}
const {
title,
bg,
description,
assets: { svg, png },
attribution = false,
} = Astro.props;
function getDownloadName(path: string) {
const lastIndex = path.lastIndexOf("/");
return path.slice(lastIndex + 1, path.length - 4);
}
---
);
}
================================================
FILE: www/src/components/docs/outdatedDocsBanner.astro
================================================
---
import { fetchGithub } from "../../utils/fetchGithub";
export interface Props {
path: string;
}
const { path } = Astro.props;
const [_1, _2, _3, ...rest] = path.split("/");
const englishPath = `src/pages/en/${rest.join("/")}`;
const engHref = `/en/${rest.join("/").replace(/\.[^/.]+$/, "")}`;
const url = `https://api.github.com/repos/t3-oss/create-t3-app/commits?path=www/${path}&per_page=1`;
const engUrl = `https://api.github.com/repos/t3-oss/create-t3-app/commits?path=www/${englishPath}&per_page=1`;
// File may not be on Github yet, so we only throw an error if we're in production
async function getCommitDiff() {
try {
const thisLangCommit = await fetchGithub(url, { fetchType: "commits" });
const englishCommit = await fetchGithub(engUrl, { fetchType: "commits" });
const thisLangDate = thisLangCommit?.length
? new Date(thisLangCommit[0]?.commit.author.date ?? "")
: new Date();
const englishDate = englishCommit?.length
? new Date(englishCommit[0]?.commit.author.date ?? "")
: new Date();
const diffInDays = Math.round(
(englishDate.getTime() - thisLangDate.getTime()) / (1000 * 3600 * 24),
);
return diffInDays;
} catch (e) {
console.warn(`[warn] /src/components/outDatedDocsBanner.astro
${(e as Error)?.message ?? e}
If you're in production, this is a problem. If you're in dev, it's probably fine.
If this warning appears on a translated file that's not yet on origin, it's fine.`);
return 0;
}
}
const diffInDays = await getCommitDiff();
const ONE_WEEK = 1000 * 60 * 60 * 24 * 7;
Astro.response.headers.set("Cache-Control", `s-max-age=${ONE_WEEK}`);
---
{
diffInDays > 0 && (
Attention: This page is{" "}
{diffInDays} {diffInDays === 1 ? "day" : "days"}
older than the English version and might be outdated. If you're a native
speaker of this language and would like to contribute to the project,
please consider updating this page to match the latest English version.
);
}
================================================
FILE: www/src/components/landingPage/about.astro
================================================
---
import CliPreview from "./cli";
import PageSection from "./pageSection.astro";
---
Typesafe From The Start
We made create-t3-app to do one thing: Streamline the setup of typesafe
Next.js apps WITHOUT compromising modularity.
After 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.
This is NOT an all-inclusive template. We expect you to bring your own libraries. Check out our other recommendations for things like state management and deployment.
================================================
FILE: www/src/components/landingPage/banner.astro
================================================
---
import Button from "./button.astro";
import ClipboardSelect from "./ClipboardSelect";
---
The best way to start a
full-stack,
typesafeNext.js app
? What will your project be called? (my-t3-app)
my-t3-app
? Will you be using JavaScript or TypeScript? (Use arrow keys)
❯ TypeScript
JavaScript
? Will you be using JavaScript or TypeScript?TypeScript
Good choice! Using TypeScript!
{`? Which packages would you like to enable? (Press to select, to toggle all, to invert selection, and
to proceed)`} ❯◯ nextAuth ◯ prisma ◯ tailwind ◯ trpc? Which packages would you like to enable?
nextAuth, prisma, tailwind, trpc
❯◉ nextAuth◉ better-auth
◉ prisma
◉ tailwind
◉ trpc
? Initialize a new git repository? (Y/n)
n
No
Sounds good! You can come back and run git init later.
? Would you like us to run npm install? (Y/n)
y
Yes
Alright. We'll install the dependencies for you!
);
}
================================================
FILE: www/src/components/landingPage/community/community.astro
================================================
---
import PageSection from "../pageSection.astro";
import CommunityCard from "./communityCard.astro";
// eslint-disable-next-line -- need to export something to make it a module
export interface Props {}
---
Community
Join our community to get help, share your projects, and even contribute
to the project!
================================================
FILE: www/src/components/landingPage/stack/stack.astro
================================================
---
import PageSection from "../pageSection.astro";
import Feature from "./card.astro";
---
The best of the full stack TypeScript ecosystem...
...but ONLY the parts you need
Take what you want and nothing more!
Next.js offers a lightly opinionated, heavily optimized approach to
creating applications using React. It's the industry standard and
we're proud to build on top of it :)
Prisma is the best way to work with databases in TypeScript. It
provides a simple, type-safe API to query your database, and it can
be used with most SQL dialects (and Mongo too!).
We firmly believe TypeScript will help you be a better web
developer. Whether you're new to JS or a seasoned pro, the
"strictness" of TypeScript leads to smoother building.
Tailwind CSS is a utility-first CSS framework that helps you build
beautiful, responsive designs without any extra configuration. It’s
built with utility-first principles, and is completely customizable
and extendable.
If your frontend and backend are TypeScript, it's really hard to
beat the DX of tRPC. Kinda like GraphQL but without the work -
seriously this lib is magic.
When you need flexible, secure, and scalable auth, NextAuth.js is
top notch. It ties into your existing database and provides a simple
API to manage users and sessions.
================================================
FILE: www/src/components/landingPage/tweets/featuredTweets.ts
================================================
export interface Tweet {
id: string;
handle: string;
verified: boolean;
author: string;
avatar: string;
date: Date;
text: string;
likes: number;
retweets: number;
replies: number;
quotes: number;
}
// featured tweets for the testimonials on the landing page
export const featuredTweets: Tweet[] = [
// https://twitter.com/ajcwebdev/status/1544909672137867264
{
id: "1544909672137867264",
handle: "ajcwebdev",
author: "❤️ Anthony (ajcwebdev.x)",
verified: false,
avatar:
"https://pbs.twimg.com/profile_images/1549247631867711488/hK_Qr-Dx_normal.png",
date: new Date("2022-07-07T05:02:23.000Z"),
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.",
likes: 32,
retweets: 3,
replies: 9,
quotes: 2,
},
// https://twitter.com/tomdoes_tech/status/1595652166173458434
{
id: "1595652166173458434",
handle: "tomdoes_tech",
author: "Tom",
verified: false,
avatar:
"https://pbs.twimg.com/profile_images/1551907445856997385/3m8M35Cn_400x400.png",
date: new Date("2022-11-24T08:34:00.000Z"),
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",
likes: 194,
retweets: 6,
replies: 10,
quotes: 2,
},
// https://twitter.com/synecdokey/status/1553580714591158272
{
id: "1553580714591158272",
handle: "synecdokey",
author: "Emilia Zapata",
verified: false,
avatar:
"https://pbs.twimg.com/profile_images/1426010455055638531/xUFu5JP7_400x400.jpg",
date: new Date("2022-07-31T07:18:00.000Z"),
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.",
likes: 76,
retweets: 10,
replies: 2,
quotes: 0,
},
// https://twitter.com/royanger/status/1553191258771841024
{
id: "1553191258771841024",
handle: "royanger",
author: "Roy Anger",
verified: false,
avatar:
"https://pbs.twimg.com/profile_images/1346968887/dsc652499-2_400x400.jpg",
date: new Date("2022-07-30T05:30:00.000Z"),
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.",
likes: 19,
retweets: 2,
replies: 0,
quotes: 0,
},
// https://twitter.com/jonhigger/status/1570054715240763393
{
id: "1570054715240763393",
handle: "jonhigger",
author: "jon",
verified: false,
avatar:
"https://pbs.twimg.com/profile_images/1466866060007723008/QXEf5Vbs_400x400.jpg",
date: new Date("2022-09-14T18:19:00.000Z"),
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.",
likes: 5,
retweets: 1,
replies: 1,
quotes: 0,
},
];
================================================
FILE: www/src/components/landingPage/tweets/tweetCard.astro
================================================
---
import { Image } from "astro:assets";
import { type Tweet } from "./featuredTweets";
const {
id,
handle,
author,
verified,
avatar,
date,
text,
likes,
retweets,
replies,
} = Astro.props as Tweet;
---
{
headings.map((heading) => {
const { depth, slug, text } = heading;
//add data-component-type to headings to be able to filter them in the sidebar
let dataComponentType = "";
switch (text) {
case "prisma":
dataComponentType = "prisma";
break;
case "src/types":
case "src/server/auth.ts":
dataComponentType = "nextauth";
break;
case "postcss.config.js":
case "prettier.config.mjs":
dataComponentType = "tailwind";
break;
case "src/server/api":
case "src/server/api/routers":
case "src/utils":
dataComponentType = "trpc";
break;
}
return (
================================================
FILE: www/src/layouts/landingPage.astro
================================================
---
import Footer from "../components/footer/footer.astro";
import LeftSidebar from "../components/navigation/leftSidebar.astro";
import Navbar from "../components/navigation/navbar.astro";
import "../styles/global.css";
import "../styles/algolia/style.css";
import "../styles/accessibility.css";
import HeadCommon from "../components/headCommon.astro";
import HeadSeo from "../components/headSeo.astro";
import { SITE } from "../config";
import "@fontsource-variable/inter";
import JumpToContent from "../components/accessibility/jumpToContent.astro";
export interface Props {
isNotFound?: boolean;
}
const currentPage = Astro.url.pathname;
const { isNotFound } = Astro.props;
---
{SITE.title}
================================================
FILE: www/src/pages/404.astro
================================================
---
import Button from "../components/landingPage/button.astro";
import LandingPage from "../layouts/landingPage.astro";
---
Page not found...
404!
================================================
FILE: www/src/pages/ar/deployment/docker.md
================================================
---
title: Docker
description: النشر مع Docker
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
يمكنك إستخدام الـ Stack داخل Docker Container أو كجزء من مجموعة containers عن طريق docker-compose، إقرأ المزيد هنا [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker)
## تهيئة مشروع Docker
يَجب أن تضع في حُسبانك أن Next.js يتطلب process مُنفصلة لـ buildtime و runtime.
يمكنك الوصول لـ runtime environment فقط في الـ Server.
في هذا المثال نستخدم مُتغيرين فقط لذلك عليك أن تٌبقي في بالك موقعها في الـ `Dockerfile` والـ command-line arguments, والـ `docker-compose.yml`:
- `DATABASE_URL` (تُستخدم في الـ server)
- `NEXT_PUBLIC_CLIENTVAR` (تُستخدم في الـ client)
### 1. إعداد Next
في ملف [`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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. إنشاء ملف dockerignore
إضغط هنا لتقرأ محتوي الملف .dockerignore:
### 3. إنشاء Dockerfile
> بما أننا لا نقوم بجلب الـ server environment variables إلى داخل الـ container، فإن [environment schema validation](/en/usage/env-variables) سيفشل لتجنب هذا أضف علم `SKIP_ENV_VALIDATION=1` الي الـ command حتى تُوقف عملية الـ validation
إضغط هنا لتقرأ محتوي الملف Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# تثبيت Prisma Client - أزلها إن لم تكن تُستخدم Prisma
COPY prisma ./
# تثبيت المتطلبات وفقا للـ package manager الذي تُفضلة
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_مُلاحظات_**
>
> - مُحاكاة `--platform=linux/amd64` قد لا تكون ضرورية في Node 18
> - إقرأ [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) لتعلم لماذا قد تحتاج `libc6-compat`.
> - تقوم Next.js بجمع [بيانات خفية عن الاستختدام](https://nextjs.org/telemetry).
> - قٌم بإالغاء تعليق الـ instance الاولي من ENV NEXT_TELEMETRY_DISABLED 1 حتي تُعيق الـ telemetry أثناء الـ build، قٌم بإلغاء تعليق الـ instance الثانية تٌعيق الـ telemetry أثناء الـ runtime
## البناء والتشغيل locally
قم ببناء وتشغيل هذه الصورة Locally باستخدام الأوامر التالية:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
إفتح [localhost:3000](http://localhost:3000/) لتري تطبيقك يَعمل
## الـ Docker Compose
يُمكنك أيضا إستخدام Docker Compose لبناء وتشغيل الـ Container
بعد إتباع الخطوات من 1 إلى 4 في الاعلي إضغط هنا وأضف الملفات الي docker-compose.yml:
## الـ Deploy علي Railway
يُمكنك أن تستخدم PaaS كـ [Railway's](https://railway.app) كـ [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles)
إذا أردت أن تستخدم [Railway CLI installed](https://docs.railway.app/develop/cli#install) يُمكنك أن تُشغل هذا الأمر:
```bash
railway login
railway init
railway link
railway up
railway open
```
إذهب الي "Variables" وأضف `DATABASE_URL` ثُم الي "Settings" واختر "Generate Domain." لتري أمثلة علي Railway زُر [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).
## مصدر مُفيدة
| المصدر | الرابط |
| ------------------------------------ | -------------------------------------------------------------------- |
| Dockerfile reference | https://docs.docker.com/engine/reference/builder/ |
| Compose file version 3 reference | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Docker CLI reference | https://docs.docker.com/engine/reference/commandline/docker/ |
| Docker Compose CLI reference | https://docs.docker.com/compose/reference/ |
| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image |
| Next.js in Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Next.js with Docker Example | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/ar/deployment/vercel.md
================================================
---
title: Vercel
description: النَشر الي Vercel
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
ننصحك بنشر تطبيقك عبر [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) فهو أسهل، خاصة لتطبيقات Next.js.
## إعداد المشروع
بطبيعة الأمر فإن vercel ستقوم بإعداد المشروع عنك لكن بإمكانك التعديل عليها من خلال إنشاء ملف [`vercel.json`](https://vercel.com/docs/project-configuration)
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## استخدام لوحة تحكم Vercel
1. بعد دفع مشروعك الي Github سجل الدخول إلى [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) عن طريق Github واضغط علي **Add New Project**

2. قم بإستيراد GitHub repository

3. إضف environment variables.

4. إضغط علي **Deploy** الان مع كل مرة تعمل فيها Push ستقوم vercel بإعادة بناء المشوع تلقائيا
## إستخدام Vercel CLI
حتي تنشر مشروع عن طريق CLI [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
شَغل أمر [`vercel`](https://vercel.com/docs/cli/deploying-from-cli)
```bash
vercel
```
لا تنس اضافة environment variables مثل `--env DATABASE_URL=YOUR_DATABASE_URL_HERE`، أضف عَلم `--yes` لتخطي كل الاسئلة
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
بطبيعة الامر فإن النشر سيطون علي `preview branch` لكن إذا ما كُنت تريد النشر الي `production` فقُم بإضافة علم `--prod`
```bash
vercel --prod
```
================================================
FILE: www/src/pages/ar/faq.md
================================================
---
title: الأسئلة الشائعة
description: الأسئلة المتكررة حول إنشاء تطبيق T3
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
---
إليك ما يَكثُر من سٌؤاله عن Create T3 App.
## ماذا بعد؟ كيف استعمل `create-t3-app` لإنشاء تطبيق؟
نحن نحاول أن نُبقي هذا المشروع بَسيطاًً قدر الإمكان، لذلك فَقد وضعنا حَجر الأساس لك، ويمكن إضافة ما تريد وقتما تُريد.
إذا كًنت غير مُلم ببعض التقنيات المُستخدمة في هذا المَشروع فأتجه إلى الـ Docs المَعنية بها، فإذا واجهتك مُشكلة ما فالرجاء الانضمام إلى سيرفر الديسكورد [Discord](https://t3.gg/discord) وأطلب المُساعدة.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [TailwindCSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## ما هي مصادر التعلم المتاحة في الوقت الحالي؟
بالرغم من أن المصادر المذكورة في الأسفل هي من أفضل المصادر الموجودة لتعلم مسار T3، فإننا (و [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) ننصحك أن تبدأ باستخدام الـ Stack وتَعلمه عن طريق أن تبني شيئاَ به.
إذا كُنت تخطط لاستخدام Create T3 App فَربما تكون دِراية ببعض أجزاء هذا الـ Stack، فلماذا لا تَستغل مَعرفتك تِلك لتبدأ العمل مباشرة.
نَحن نُدرك أن هذا المسار لا يَصلح للجميع. لِذلك ، إذا كنت تشعر أنك قد جَربت ما أوصيناك به وما زلت ترغب في المزيد من مصادر التَعلم، أو في حال أن لم تكن واثقًا من قَدرتك علي ذلك وَحدك، فراجع هذه البرامج التعليمية الرائعة عن Create T3 App:
### مقالات
- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)
- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
### فيديوهات
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## لماذا هُناك ملفات بامتداد `.js` في هذا المشروع؟
وِفقًا لـ [T3-Axiom #3](/en/introduction#typesafety-isnt-optional) ، نَحن نَعتبر Typesafety مواطناََ مِن الدرجة الأولى. لِسوء الحَظ، لا يُدعم TypeScript في بَعض الـ Frameworks والاضافات مما يعني ضرورى أن تكتب بعض ملفات للإعدادات (configuration) بلغة JS وهو مُر لابُد منة.
نُحن نُحاول التأكيد على أن هذه الملفات هي `Javascript` لأسباب خَارجة عن إرادتنا وذلك عن طريق إستخدام (cjs أو mjs)، لكن لا تزال جميع البيانات في ملفات js في هذا المشروع، تخضع لفحص باستخدام تعليق `@ts-check` في الأعلى.
## أجد صعوبة في إضافة i18n إلى تطبيقي. هل هناك أي مرجع يمكنني الرجوع إلية؟
لقد قررنا عدم تضمين i18n افتراضيًا في Create T3 App وذلك لأنه موضوع شائك للغاية وهناك العديد من الطرق لتنفيذه.
ومع ذلك، إذا كنان لابُد من تَنفيذه وترغب في رؤية مشروع مَرجعي، فلدينا [مَرجع](https://github.com/juliusmarminge/t3-i18n) يُوضح كيف يمكنك إضافة i18n إلى تَطبيق T3 باستخدام [next-i18next](https://github.com/i18next/next-i18next).
## لماذا نستخدم `/pages` وليس `/app` في Next.js 13؟
كما ذكرنا مُسبقا في [T3-Axiom #2](/en/introduction#bleed-responsibly)، نحن نُحب الأشياء المتطورة لكننا نُقدر الاستقرار، فمن الصعب تَحويل الـ router إلي النظام الجديد، شاهد [not a great place to bleed](https://youtu.be/mnwUbtieOuI?t=1662).
فإن `/app` [مُجرد لَمحة من المستقبل](https://youtu.be/rnsC-12PVlM?t=818)، فهو ليس جاهزًا للإنتاج؛ غير إن (API) في مَرحلة تجريبية ومن المتوقع أن تحدث له تغييرات جذرية.
لمعرفة الميزات المدعومة والمخطط العمل عليها في dir المسمى `/app`، زر [beta Next.js docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
================================================
FILE: www/src/pages/ar/folder-structure-pages.mdx
================================================
---
title: (Pages)بِنية المجلد
description: بنية مجلد T3 App
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
اختار أدواتك لترى بنية المجلد عند إنشاء تطبيقك بواسطة تلك ألاختيارات. بالأسفل ستجد وصف عن غرض كلاً منهم.
## `prisma`
مجلد prisma يحتوي على `prisma.schema` الذي بدوره يحتوي ملف تكوين الاتصال مع قاعدة البيانات كما يحتوي أيضا علي schema التي تحدد شكل الـ tables هذا إلى جانب ملفات الـ migrations و/أو كود لإضافة المعلومات إلى Database، اقرآ [كيفية استخدام Prisma](/ar/usage/prisma).
## `public`
يحتوي مُجلد Public على الملفات الثابتة التي يقوم السيرفر بتقديمها، يكون ملف `favicon.ico` مثال على ذلك.
## `src/env`
يستخدم للتحقق من صحة الـ environment variable وتحديد الأنواع (types)، اقرأ المزيد [Environment Variables](usage/env-variables)
## `src/pages`
مجلد `pages` يحتوي علي كل الصفحات التي يحتوي عليها تطبيق Next.js، يعمل ملف `index.tsx` في مستند root من `/pages` كالصفحة الأساسية للتطبيق، يعمل ملف `__app.tsx` لإمداد التطبيق بما تحتاجه من موفر، لقراءة المزيد [Next.js documentation](https://nextjs.org/docs/basic-features/pages).
### `src/pages/api`
يحتوي مجلد `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/).
#### `src/pages/api/auth/[...nextauth].ts`
إن ملف `[...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.
#### `src/pages/api/trpc/[trpc].ts`
يُعتبر ملف `[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.
## `src/server`
يُستخدم مجلد `server` للفصل بوضوح بين الكود من جانب السيرفر (Server Side) والكود من جانب العميل (Client Side).
### `src/server/auth.ts`
يحتوي على الوظائف الخادمة (utilities) التي تقوم بالتوثيق مثل استرداد جلسة المستخدم (user session) من جانب السيرفر. اقرأ [NextAuth.js](https://create.t3.gg/ar/usage/next-auth#usage-with-trpc) للمزيد من المعلومات.
#### `src/server/db.ts`
يستخدم ملف `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) لمزيد من المعلومات.
#### `src/server/db/client.ts`
يستخدم ملف `client.ts` لإنشاء نُسخة لـ Prisma Client علي مستوي التطبيق كلة، اقرأ [Prisma usage](usage/prisma#prisma-client) لمزيد من المعلومات.
### `src/server/api`
مجلد tRPC يحتوي على كود tRPC للسيرفر.
#### `src/server/api/routers`
يُحتوي مجلد `routers` على كل وطائفك الوصول الفرعية (sub-routers) لمكتبة tRPC.
#### `src/server/api/routers/example.ts`
إن ملف `example.ts` مثال عن وظيفة الوصول tRPC التي تستخدم `publicProcedure` الوطيفة المساعدة (helper) لتوضيح كيف ينشئ وظيفة وصول من tRPC.
سوف يحتوي الملف على وظائف بأعداد مختلفة طبقا لأختيراتك، لتوضيح الاستخدام حسب احتياجك.
#### `src/server/api/trpc.ts`
إن ملف `trpc.ts` الملف الرئيسي لإعدادات back-end في tRPC. هنا:
1. يحدد المحتوى المستخدم في طلبات tRPC. اقرأ [استعمال tRPC](https://create.t3.gg/ar/usage/trpc#-serverapitrpcts) للمزيد من المعلومات.
2. يورد (export) نهج الوطيفة المساعدة. اقرأ [استعمال tRPC](https://create.t3.gg/ar/usage/trpc#-serverapitrpcts) للمزيد من المعلومات.
#### `src/server/api/root.ts`
يُستخدم ملف `root.ts` لدمج وظائف tRPC للوصول, وتوريدهم كوظيفة وصول واحدة، وكذلك أنواع بيانات الوظيفة المحددة، اقرأ المزيد هنا [tRPC usage](https://create.t3.gg/ar/usage/trpc#-serverapirootts).
### `src/styles`
يحتوي مجلد `styles` على التصميمات العامة للتطبيق.
### `src/types`
يحتوي مجلد `types` على الأنواع البيانات (Types) أو الأنواع المحددة (type declarations).
#### `src/types/next-auth.d.ts`
يُستخدم ملف `next-auth.d.ts` للتعديل على إعدادات NextAuth الافتراضية، لمزيد من المعلومات [NextAuth.js usage](usage/next-auth#inclusion-of-userid-on-the-session).
### `src/utils`
يُستخدم مجلد `utils` لحفظ الـ functions التي يكثر استخدامها.
#### `src/utils/trpc.ts`
يُستخدم ملف `trpc.ts` كـ entrypoint لـ front-end إلى tRPC، اقرآ المزيد هنا [tRPC usage](usage/trpc#-utilstrpcts).
### `.env`
يُستخدم ملف `.env` لتخزين environment variables، اقرأ المزيد [Environment Variables](usage/env-variables). يجب ألا يضاف هذا الملف في تاريخ Git.
### `.env.example`
ملف `.env.example` هو مثال لاستخدام example environment مبني على المكتبات المختارة. يجب أن يضاف هذا الملف في تاريخ Git.
### `.eslintrc.cjs`
يٌستخدم ملف `.eslintrc.cjs` لإعداد ESLint، اقرأ المزيد هنا [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files).
### `next-env.d.ts`
يحقق ملف `next-env.d.ts` أن Typescript تأخذ Types في Next.js في الحسبان. **لا تُعدل عليها ولا تحذفها لأنها تتغير باستمرار**، لمزيد من المعلومات [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects).
### `next.config.js`
يستخدم ملف `next.config.js` لإعداد Next.js، لمزيد من المعلومات [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction). تلميح: يسمح تمديد `.mjx` باستخدام ESM imports.
### `postcss.config.js`
إن ملف `postcss.config.js` ضروري عند استخدام TailwindCSS PostCSS، لمزيد من المعلومات [Taiwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss).
### `prettier.config.js`
إن ملف `prettier.config.js` ضروري عند استخدام Prettier ولإضافة prettier-plugin-tailwindcss لتنظيم الفئات (classes) مع Tailwind CSS، لمزيد من المعلومات [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier).
### `tsconfig.json`
إن ملف `tsconfig.json` ضروري عند استخدام TypeScript. فعيلت بعض الإعدادات الغير افتراضية، مثل `strict mode`، لتوفير أفضل إمكانية للاستخدام الـ TypeScript في Create T3 App ومكتباتها، لمزيد من المعلومات اقرأ [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) أو [TypeScript Usage](usage/typescript).
================================================
FILE: www/src/pages/ar/installation.mdx
================================================
---
title: التثبيت
description: تعليمات التثبيت لـ Create T3 App
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
لإنشاء تَطبيق بإستخدام `create-t3-app`، نفيذ أي من الأوامر الثلاث التالية وأجب عن أسئلة مٌوجه الأوامر (command prompt):
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
بعد أن تَنتهي عَملية إنشاء التطبيق، اَلق نَظرة عَلي [الخطوات الأولى](/ar/usage/first-steps) للبدء في تطبيقك الجديد.
## الخصائص المَتقدمة
| خصائص | الوظيفة |
| ----------------- | ------------------------------------------------------------ |
| `[dir]` | تحتوي على معطى الملف الذي سيسما عليه التطبيق |
| `--noGit` | أخبار الـ CLI إلا يهيئ GIT repo للتطبيق قصداً |
| `-y`, `--default` | تعدي أسئلة الـ CLI وإنشاء تطبيق t3 مع اختيار جميع الاختيارات |
| `--noInstall` | إنشاء تطبيق دون تثبيت الـ dependencies |
## خصائص تجريبية
هُناك بعض خصائص التجريبية (Flags) التي تسمح لك بإنشاء أي تطبيق دون أي أسئلة من مُوجة الأوامر. إذا كانت حالة الاستخدام هذه تنطبق عليك ، فيمكنك إستخدام هذه خصائص. يٌرجى مٌلاحظة أن هذه خصائص تجريبية وقد تتغير في المستقبل دون أن نُخصص لها semver versioning.
| خصائص | الوظيفة |
| ------------ | ---------------------------- |
| `--CI` | دع CLI يعرف أنك في وضع CI |
| `--trpc` | أضف tRPC إلى التطبيق |
| `--prisma` | أضف Prisma إلى التطبيق |
| `--nextAuth` | أضف NextAuth.js الي التطبيق |
| `--tailwind` | أضف Tailwind CSS الي التطبيق |
ملاحظة: إذا لم تضع الخاصية `CI` ، فلن يكون لبقية هذه الخصائص أي تأثير.
يمكنك الا تُضيف الخيارات في حال لم تكن تريد ذلك، لكننا ننصحك بذلك تحرياََ للدقة فعليك
تمرير `false` مع الخاصية مثل `--nextAuth false`.
### أمثلة
الامر التالي سَيٌنشئ تطبيق T3 باستخدام tRPC و Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/ar/introduction.md
================================================
---
title: مقدمة
description: مقدمة إلى T3 Stack
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
---
## T3 Stack
الـ T3 Stack هو Stack لتطوير تطبيقات الويب بُني علي فَلسفة البساطة، قابلية إعادة الاستخدام (فصل المركبات وإعادة استخدامها) و الحصول على typesafety في جميع أزكان التطبيق.
الأجزاء الأساسية هم [**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/).
لعلك لاحظت أن هناك الكثير من... الأجزاء. هذا ما رغبنا بتصميمه, لك مُطلق الحرية أن تُضف جزء وتَحذف أُخرى كما تحتاج - يكون أساس Stack خاضع لاحتياجاتك.
## حسنا… ما هو create-t3-app؟ أهو قالب (template)؟
نوعا من. أُنشئ `create-t3-app` بواسطة مطورون متمرسون ليبسط CLI إعداد تطبيق T3 قَدر الإمكان. فَكُل جزء اختياري، هذا يعني أنك تنشئ قالبك حسب احتياجك.
بعد أنشاء العديد من المشروعات وممارسة تلك الأدوات لسنين، كسبنا العديد من الخبرات والآراء، وفعلنا قدر المستطاع لوضعهم داخل CLI.
**أنه ليس** بقالب شامل علي كل ما تحتاجة، نتوقع منك أن تُضيف مكتباتك الخاصة لحل ما سيواجهك من مشكلات **في تطبيقك**. علي الرغم من أننا نريد أن نترك لك مُطلق الحرية في حل المشاكل مثل state management ونشر التطبيق، [لكن لدينا بعض الترشيحات لك](/ar/other-recs).
## T3 Axioms
لنكون شفافون - هذا _مشروع متعدد الآراء_. نتشارك جميعاََ في عدد قليل من المعتقدات الأساسية حَول كيفية البناء ونتخذها كأساس قراراتنا.
### Solve Problems
من السهل أن تَقع في فخ فتُضيف "كل شيئ" - لكننا لا نريد ذَلك صراحتاً، يَجب أن يكون لكل شيئ مَغزي وهدف مُحدد كما هو الحال في ما أضفناه مُسبقا ويَترتب علي ذلك عدم إضافة مكتبات مِثل (`zustand`, `redux`)، لكننا نُضيف مكتبات أُخري مُثل NextAuth.js, و Prisma و tRPC.
### غامر، لكن علي مسؤوليتك
نحن نحب التقنيات الحديثة، تجرِبة الأشياء الجديدة تجلب السعادة، لكن عليك تَوخى الحذر فلا تَستخدام التقنيات الغير مستقرة في الأماكن الحساسة، فمثلا نحن لا نراهن ⛔️ على قواعد بيانات حديثة (فإن SQL رائعة)، لكننا نراهن ✅ علي tRPC لأنها مجرد Functions ومن السهل الاستغناء عنها.
### Typesafety ليس خياراََ
قد حددنا مُسبقاَ أن الهدف الأوحد من `create-t3-app` هو أن نوفر بِداية سَريعة لتطوير تطبيقات full-stack مع اتخاذ **typesafe** كأولوية, فهو أمر لابد منه لتحسين فاعليتك كمطور بواسطة تقليل عدد Bugs قدر الإمكان.
أي حل وسط يضر typesafe في `create-t3-app` يَجب اتخاذه في مشروع مختلف.
================================================
FILE: www/src/pages/ar/other-recs.md
================================================
---
title: ترشيحات أخرى
description: مكتبات وخدمات نرشحها لك
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
---
نٌدرك تمام الإدراك أن المَكتبات الإفتراضية في `create-t3-app` لا تَحٌل كُل المشاكل التي قد تواجهك، بغض النظر عن ذلك فنحن ننصحك أن تبدأ بالأشياء التي نٌقدمها، فعاجلاََ أم أجلا سيأتي عليك وقت تحتاج فيه الي إستخدام مكتبات خَارجية، أنت وَحدك مَن يدري إحتياجات مشروعك.
هَاك بَعضٌ المَصادر التي نٌشجعك على أن تّتبعها.
بَعض الترشيحات التالية قَدمها مٌساهمون مٌنفردون فلا يَجب أن تُؤخذ على أنها تَرشيحات رَسمية من فريق T3 أو T3-OSS، لذلك **قُم بالبحث، خاصة قبل أن تشترك في خدمات مدفوعة**
## State Management
**ملحوظة المحرر**: مكتبات الـ State Management رائعة لكنها في مٌعظم الحالات ليست ضَرورية، فـ tRPC و ReactQuery تقوم بالوظيفة بشكل جيد، لذلك إبدأ بـ`useState` وانتقل إلى أحد البدائل المتاحة فقط عندما يلزم الأمر.
### Zustand
**حتي لا تستعمل Redux أبداََ مرة اخرى**
بديل Redux الذي لم تكن تعلم إنك تحتاجة، غير إمكانية الوثوق بها فأنة بإستخدام [Poimandres](https://github.com/pmndrs) يمكنك صُنع **كل شي** من تطبيقات المكالمات الي الالعاب وغيرها.
- [Zustand Homepage](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
## Component Libraries
تحتاج مٌعظم التطبيقات إلى نَفس مَجمٌوعة المٌكونات - أزرار التبديل والقوائم المنسدلة وغيرها.
تٌوفر هَذه المَكتبات مُكونات رَائعة يُمكنك إستخدامها وتَخصيصها حَسب رَغبتك.
### Unstyled Component Libraries
تُعرف أيضًا باسم Headless libraries ، فهي تٌوفر مٌكونات رائعة يمكنك عمل styling لها كما تشاء, هذا الي جانب كونها Accessible و يمكنك تخصيصها حسب رغبتك.
- [Radix UI](https://www.radix-ui.com/)
- [Headless UI](https://headlessui.com/)
- [React Aria](https://react-spectrum.adobe.com/react-aria/)
### Styled Component Libraries
في بعض الأحيان تقوم ببناء مشروع وكل ما تريدة هو أن تبدو واجهة المستخدم جيدة. كـ لوحات التحكم وغيرها ، سَتٌنجز أي هذه المكتبات هذه المهمة على أكمل وجه
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
### Class Variance Authority
** لبناء مكتبات UI **
تُساعدك علي إنشاء مكتبات واجهة مستخدم بشكل تصريحي (Declarative) بألوان وأحجام مختلفة ومتغيرات مختلفة. عندما يصل مشروعك إلى حجم يلزمك فيه مجموعة موحدة من مكونات الـ UI مع مُتغيرات مٌتعددة لـ Tailwind CSS ، فإن CVA هي أداة رائعة.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Animations
### AutoAnimate
**الانميشن بسطر كود واحد**
تحاول معظم مكتبات الانميشن إرضاء كل حالات الاستخدام الممكنة ، نتيجة لذلك تصبح غير مرغوب فيها. AutoAnimate هي أداة لا تحتاج إلى تكوين تٌوفر تَحسينًا كبيرًا في UX دون بَذل جٌهد إضافي من المطور.
- [AutoAnimate Homepage](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**الرسوم المتحركة المعقدة**
تٌوفر FramerMotion اٌسلوبا بَسيطا لكتابة الكود، فَتسمح لك بكتابة رسوميات معقدة بكود أقل
- [Framer Motion Homepage](https://framer.com/motion)
- [Framer Motion Documentation](https://www.framer.com/docs/)
## Deployments، و Infrastructure، و Databases، و CI
### Vercel
**إستضافة موقعك**
قامت Vervel بتسهيل استضافة موقعك بعد أن كان جِحِيماََ في الماضي، فإنها تَعتمد عََلي AWS لكن مع واجهة أفضل.
- [Vercel Homepage](https://vercel.com/)
- [Create T3 App Vercel deployment guide](/en/deployment/vercel)
### PlanetScale
**حتي لا تقلق علي قواعد بياناتك بعد الآن**
تُعد PlanetScale أحد أفضل مٌزودي خِدمة قَواعد البيانات عَلي الإطلاق لقٌدرتها عَلى التَوسع وتجربة المطور الممتازة والأسعار المعقولة.
- [PlanetScale Homepage](https://planetscale.com/)
### Railway
**لإستضافة البنية التحتية للموقع**
فهي Heroku العصر الحديث، إذا كان Vercelli , PlanetScale غير كافيين لك، فـ Railway سَتكون خيارك المناسب.
- [Railway Homepage](https://railway.app/)
### Upstash
نحن نٌحب Prisma و Planet Scale لكن بعض المشاريع تتطلب حٌلولا أكثر سٌرعة.
فإن **Upstash** تٌعطيك القٌدرة علي إستخدام Redis في مشروعك دون الحاجة أن تٌدير البنية التحتية.
- [Upstash موقع](https://upstash.com/)
### Pusher
**For serverless WebSockets**
إذا كان الـ WebSockets مُهمة بالنسبة لك، فإنه مِن الأفضل الإعتماد على سيرفر تقليدي مثل [Fastify](https://www.fastify.io/) والتي أيضا تدعم [tRPC](https://trpc.io/docs/v10/fastify)
لكن إذا كانت السرعة مهمة لك فإن Pusher هو الخيار المناسب لك.
- [Pusher Homepage](https://pusher.com/)
### Soketi
Soketi هو بديل بسيط وسريع للاستضافة الذاتية لـ Pusher. إنه متوافق تمامًا مع Pusher SDK الذي يمكنك استخدامه للاتصال بالخادم. Soketi serverless هو أيضًا في مرحلة تجريبية.
- [Soketi Homepage](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Analytics
تعتبر بيانات المستخدم ذات قيمة كبيرة عند إنشاء تطبيق. فيما يلي بعض موفري التحليلات الذين نوصيك بهم.
### Plausible
هل تحتاج إلى تحليلات؟ Plausible هو أحد أسرع الطرق للحصول عليها [simple plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs).
- [Plausible Homepage](https://plausible.io/)
### Umami
يعد Umami بديلًا بسيطًا وسريعًا لبرنامج Google Analytics. يمكنك استخدامه بسهولة في Vercel و Railway وما إلى ذلك باستخدام PlanetScale كقاعدة بيانات.
- [Umami Homepage](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
## غيرها
### Next Bundle Analyzer
قد يكون من الصعب أحيانًا تحديد ما سيتم تضمينه في الإصدار النهائي لتطبيقك. يُعد Next Bundle Analyzer طريقة سهلة لتصور وتحليل حزم JavaScript التي تم إنشاؤها.
- [next/bundle-analyzer](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/ar/t3-collection.mdx
================================================
---
title: اعمال بواسطة T3
description: تطبيقات مفتوحة المصدر صنعت باستخدام Stack T3
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
isMdx: true
---
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
هل قٌمت بعمل تطبيق بإستخدام T3 Stack وتريد مشاركته؟ أضافه إلى القائمة التالية!
## تطبيقات مفتوحة المصدر صُنعت بواسطة T3
## شركات تَستخدم T3 Stack
نَوَدٌ مَعرفة الشَركات التي تَستخدم Stack T3 لتَطبيقاتها. إذا كانت شَركتك تَستخدم Stack T3 وتَرغب في مشاركته؟ أضافه إلى القائمة التالية!
_أصنعت مشروعاً باستخدام T3 Stack؟ أنشئ [Pull Request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx). وضفه هنا!_
================================================
FILE: www/src/pages/ar/usage/env-variables.md
================================================
---
title: Environment Variables
description: بدء الاستخدام مع create-t3-app
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
إن `Create-T3-App` تستخدم [Zod](https://github.com/colinhacks/zod) للتأكد من صلاحية الـ environment variables أثناء الـ runtime عن طريق توفير بعض الملفات الاضافة
📁 src/env
┫ 📄 client.mjs
┫ 📄 schema.mjs
┫ 📄 server.mjs
قد يبدو محتوى هذه الملفات مخيفًا للوهلة الأولى ، لكن لا تقلق ، فهو ليس معقدًا كما يبدو. دعنا نلقي نظرة عليها واحدة تلو الأخرى ، ونسير خلال عملية إضافة environment variables إضافية.
إذا كنت تريد إضافة environment variable جديد ، فيجب عليك إضافته إلى كل من ".env" وكذلك في `env / schema.mjs`.\_
## ملف schema.mjs
هذا هو الملف الذي ستعمل علية. يَحتوي على مُخططين ، أحدهما environment variables من جانب الخادم والآخر من جانب العميل بالإضافة إلى Object الـ "clientEnv".
```ts:env/schema.mjs
export const serverSchema = z.object({
// DATABASE_URL: z.string().url(),
});
export const serverEnv = {
// DATABASE_URL: process.env.DATABASE_URL,
};
export const clientSchema = z.object({
// NEXT_PUBLIC_WS_KEY: z.string(),
});
export const clientEnv = {
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
};
```
### الـ Server Schema
أنشئ الـ environment variables schema من جانب الخادم هنا.
تأكد أن لا تضيف `NEXT_PUBLIC` قبل اسم المتغير، سيفشل الـ Validation إذا ما فعلت هذا.
### الـ Client Schema
أنشئ الـ client-side environment variables هنا، حتى تجعلهم متاحيت للـ client أضف `NEXT_PUBLIC` قبل الاسم.
### الـ clientEnv Object
هُنا حيثُ تقوم بعمل Destruct لـ `process.env`
تحتاج Zod الي Object لتكون قادرة على تصحيح المُدخلات وبسبب طريقة عمل Next.js فلن نستطيع فعل هذا تلقائيا لذلك يجب أن تتم هذة العملية يدويا، لا تقلق فـ Typescript تقوم بتحذيرك إذا ارتكبت خطاّ.
```ts
// ❌ This doesn't work, we need to destruct it manually
const schema = z.object({
NEXT_PUBLIC_WS_KEY: z.string(),
});
const validated = schema.parse(process.env);
```
## الـ server.mjs & client.mjs
هذا هو المكان الذي يتم فيه التحقق من الـ Object ومن ثم تصديرها. لن تحتاج إلى تعديل هذه الملفات.
## إستخدام الـ Environment Variables
إذا أردت إستخدام الـ env vars فيمكنك إستيراد` env.js` واستعمالهم طبيعيا. إذا إستيرادت الملف في Client وحولت استعمال قيم الserver-side، ستنذر بوجود خطأ في run-time.
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` is fully typesafe and provides autocompletion
const dbUrl = env.DATABASE_URL;
```
## الـ .env.example
بما أن ملف `.env` ليس مُضمناَ في الـ version control، فقد أضفنا ملف `.env.example` والذي يمكنك أن تتركه، وأضياََ ننصحك أن تُبقي هذا الملف متزامنا مع الملف الاساسي حتي تحصل علي أفضل تجربة تطوير ممكنة
## أضف Environment Variables
حتى نتأكد من أنك ستضيف الـ environment variables، يجب عليك أن تضيفها في مكانين مختلفين
📄 ملف `.env`: هنا نضيف المتغيرات بشكل طبيعي كانك تتعامل مع ملف `.env` عادي
📄 ملف `schema.mjs`: هنا تضيف الـ Logic التي ستستخدمة Zod لفحص صلاحية المتغيرات
📄 ملف `.env.example`: هنا تضيف المتغيرات لكن بدون أي كلمات سرية للحفاظ على أمانك
### أمثلة
1. أضف the environment variable الي `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. أضف environment variable to `schema.mjs`:
```ts
export const serverSchema = z.object({
// ...
TWITTER_API_TOKEN: z.string(),
});
export const serverEnv = {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
};
```
**ملحوطة:** أضف إسم المُتغيير `TWITTER_API_TOKEN` في example.env ولكن لا تُضف الـ token
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/ar/usage/first-steps.md
================================================
---
title: الخطوات الاول
description: الخطوات الاولي في create-t3-app
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
لقد أنشأت للتو مَشروعا باستخدام T3 Stack ، هذة هي الخُطوات الاجبارية التي يجب إتباعها قبل أن تتمكن من تشغيل المشروع.
## قواعد البيانات
اذا كان مشروعك يحتوي على Prisma فعليك ان تقوم بتشغيل أمر `npx prisma db push` ، هذا الأمر يقوم بمزامنة الـ Schema مع قاعدة البيانات ليضمن الـ Typesafety عند الـ Client، **لاحظ أن هذه الخطوة تتطلب إعادة تشغيل الخادم**
## الـمصادقة
إذا كان تطبيقك يتضمن NextAuth.js ، سنبدأ مع Discord Provider. يُعد هذا أحد أبسط مُزودي الخدمة التي تدععمها NextAuth.js ، لكنه لا يزال يتطلب القليل من الإعداد الأولي من جانبك.
بالطبع ، إذا كنت تفضل استخدام موفر مصادقة مختلف ، فيمكنك أيضًا استخدام أحد المزودين العديدين الذين يقدمهم NextAuth.js.
ستحتاج إلى حساب Discord ، أنشئ واحداََ إذا لم تكن قد قمت بذلك بالفعل.
اذهب https://discord.com/developers/applications واضغط علي New Application في الجانب الايمن الاعلي .
ثم اذهب **<** Settings **<** OAuth2 **<** General
قم بنسخ Client ID وضعه في `.env `كـ `AUTH_DISCORD_ID`
اضغط علي Reset Secret ثم انسخ كلمة السر الجديدة وضعها في .env كـ AUTH_DISCORD_SECRET
اضغط علي Add Redirect واضف http://localhost:3000/api/auth/callback/discord
اضف AUTH_SECRET الي .env كـ String، في الـ Production اضف كلمة سر قوية.
================================================
FILE: www/src/pages/ar/usage/next-auth.md
================================================
---
title: NextAuth.js
description: إستخدام NextAuth.js
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
عندما تُريد نِظام مُصادقة في تَطبيق Next.js ، فإن NextAuth.js يُعد حلاً ممتازًا دون الحاجة إلى إنشائة بنفسك. يأتي مزودًا بقائمة واسعة من الموفرين لإضافة مصادقة OAuth بسرعة ويوفر Adapters للعديد من قواعد البيانات و ORMs.
## Context Provider
في نقطة الدُخول إلي تطبيقك ، سترى أن تطبيقك في [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
```
يسمح الـ context Provider لـ تطبيقك ان يصل إلى بيانات المستخدم دون الحاجة الى ادخال اي بيانات اضافيه
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return ;
}
return
Welcome {session.user.name}!
;
};
```
## تضمين `user.id` في الـ Session
يُستخدم `create-t3-app` الـ Session callback الموجودة في ملف تكوين NextAuth.js ليضيف الـ User ID الي Session Object.
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
بنفس الطريقة يمكن اضافة اي بيانات الى الـ Session Object
## Usage with tRPC
عند استخدام NextAuth.js مع tRPC، يمكنك إنشاء producers وحمايتها باستخدام [middleware](https://trpc.io/docs/v10/middlewares)، وهذا يسمح لك بإنشاء procedures لا يمكن الوصول لها إلا بواسطة أشخاص معينين
يُمكن فَعل هذا في خطوتين:
1. للحصول علي Object الـ Session يمكنك استخدام getServerSession،
نفضل getServerSession عن getSession لانها تعمل علي الخام فلا يحدث invoke غير مرغوب فيه ، قد تحملت `create-t3-app` عناء إنشاء هذه المادة عنك :
```ts:server/common/get-server-auth-session.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, nextAuthOptions);
};
```
باستخدام هذه الاداة يمكنك الحصول علي الـ Session وتمريرها إلى الـ tRPC Context
```ts:server/trpc/context.ts
import { getServerAuthSession } from "../common/get-server-auth-session";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. أنشئ tRPC Middleware وتأكد ما اذا كان هذا المستخدم يملك الصلاحيات اللازمة أم لا.
```ts:server/trpc/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
```
الـ Session Object صغير ويحتوي علي عدد قليل من الخانات، وعند استخدامك لـ `protectedProcedures`يمكنك الوصول الى هذة البيانات منها الـ UserId وعندها يمكنك عمل fetch لبيانات اخرى من قاعدة البيانات.
```ts:server/trpc/router/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## الاستخدام مع Prisma
يتطلب إستخدام NextAuth.js للعمل مع Prisma الكثير من الإعداد الأولي. يتعامل تطبيق create-t3-app مع كل هذا من أجلك ، وإذا حددت كل من Prisma و NextAuth.js ، فستحصل على نظام مصادقة يعمل بكامل طاقته مع جميع النماذج المطلوبة التي تم تكوينها مسبقًا. نقوم بشحن تطبيقك الاولي مع مزود Discord OAuth المكون مسبقًا ، والذي اخترناه لأنه من أسهل البدء معة - ما عليك سوى توفير الرموز المميزة في .env وستكون جاهزًا للبدء. ومع ذلك ، يمكنك بسهولة إضافة المزيد من مقدمي الخدمة باتباع NextAuth.js Docs. لاحظ أن بعض مقدمي الخدمة يطلبون إضافة حقول إضافية إلى نماذج معينة. نوصيك بقراءة الـ Docs الخاصة بالموفر الذي ترغب في استخدامه للتأكد من أن لديك جميع الحقول المطلوبة.
### إضافة المزيد من الحقول إلى الـ models
عند الحاجة إلى إضافة حقول إضافية الي `User` أو `Account` أو `Session` -على اغلب الظن انك لن تحتاج الى تعديل شئ غير `User` اَ بق في بالك أن Prisma Adapter سينشئ هذا الحقل تلقائيا مع كل مستخدم جديد لذا عليك أن تضيف قيمة افتراضية Default Value.
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## الاستخدام مع Next.js Middleware.
يتطلب استخدام NextAuth.js مع Middleware Next.js استخدام [JWT Session Strategy](https://next-auth.js.org/configuration/nextjs#caveats). هذا لأن الـ Middleware قادرة فقط على الوصول إلى ملف تعريف ارتباط JWT
بشكل افتراضي ، يتم تكوين التطبيق create-t3-app لاستخدام استراتيجية قاعدة البيانات Database Strategy ، بالاشتراك مع Prisma كـ Adapter لـ قاعدة البيانات.
## إعداد DiscordProvider
1. اتجه الى [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications) واضغط على New Application.
2. في settings menu اضغط على OAuth2 ثم General
3. إنسخ الـ Client ID وضعة في `.env` كـ AUTH_DISCORD_ID
4. تحت Client Secret اضغط على "Reset Secret" ونسخ النص الجديد وضعه في `.env` كـ `AUTH_DISCORD_SECRET `.
كن حذرًا لأنك لن تتمكن من رؤية هذا كلمة السر مرة أخرى ، ستؤدي إعادة تعيينها إلى انتهاء صلاحية كلمة السر الحالية
5. اضغط على Add Redirect واضف رابط إعادة التوجيه`http://localhost:3000/api/auth/callback/discord` كمثال
6. احفظ التعديلات
- 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.
## مصادر مُفيدة
| المَصدر | الرابط |
| --------------------------------- | --------------------------------------- |
| NextAuth.js Docs | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/ar/usage/next-js.md
================================================
---
title: Next.js
description: إستخدام Next.js
lang: ar
dir: rtl
layout: ../../../layouts/docs.astro
---
Next.js هو إطار عمل Backend لتطبيقات React
شاهد هذا الفيديو لتعرف المزيد عن [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw)
## لماذا عَلي أن أستخدمها ؟
نحن نحب React. لقد جعلت تطوير واجهة المستخدم سهلا بطرية لم نتخيلها من قبل. لكنها يمكن أن تؤدي بالمطورين إلى أن يتبع بعض المسارات الصعبة. تقدم Next.js أسلوبًا سلساََ لإنشاء التطبيقات باستخدام React. بداية بالـ Routing انتقالا إلى الـ Api ومن ثم الصور ، نضع ثقتنا فى Next.js لتقود المطورين نحو قرارات جيدة.
إقران Next.js مع Vercel يجعل تطوير تطبيقات الويب ونشرها أسهل من أي وقت مضى. فتوفر طرية مجانية لنشر موقعك (نحن ❤️ Vercel)
## Get Static/Server Props
الميزة الرئيسية لـ Next.js هي الـ Data Fetching. نوصيك بشدة أن تقرأ الـ Docs لكي تفهم كيفية استخدام كل واحدة منهما. لا يُنصح باستخدام getServerSideProps عمومًا ما لم يكن هناك سبب وجيه لذلك ، نظرًا لأنها مُكلفة ماديا وتُؤدي إلى إبطاء موقعك. Incremental Static Regeneration هو بديل رائع لـ getServerSideProps عندما تكون البيانات ديناميكية ويمكن جلبها بشكل متزايد.
## مصادر مفيدة
| المَصدر | الرابط |
| ------------------------------ | ---------------------------------- |
| Next.js Documentation | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Next.js Blog | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/ar/usage/prisma.md
================================================
---
title: Prisma
description: إستخدام Prisma
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
مكتبة Prisma هي ORM مكتوب لغة TypeScript والتي تسمح للمطور أن يُخصص Schema لقاعدة البيانات في ملف `schema.prisma` من ثَم يقوم بتوليد type-safe client والذي بدوره يتفاعل مع قاعدة البيانات.
## ما هو Prisma Client
يقع في `/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)
## الـ Schema
سوف تجد الـ Schema في `/prisma/schema.prisma` حيث تقوم بتخصيص الـ schema الخاص بقاعدة البيانات والتي يتم استخدامها لتوليد Prisma Client.
### مع NextAuth.js
عندما تستخدم Prisma مع NextAuth فان الـ Adapter يتحمل عنك عناء توليد الـ `User`, `Session`, `Account`, and `VerificationToken` mo، إقرأ المزيد هنا [NextAuth.js documentation](https://next-auth.js.org/adapters/prisma).
## Default Database
قاعدة البيانات الافتراضية هي قاعدة بيانات SQLite ، وهي رائعة لتطوير وتسريع عملية proof-of-concept ولكن لا يوصى بها للإنتاج. يمكنك تغيير قاعدة البيانات لاستخدامها عن طريق تغيير `provider` في الـ DataSource Object إلى `postgresql` أو `mysql` ، ثم تحديث URL داخل `.env` إلى قاعدة البيانات الخاصة بك.
## Seeding your Database
[يُعد زرع قاعدة البيانات](https://www.prisma.io/docs/guides/database/seed-database)
طريقة رائعة لملء قاعدة البيانات بسرعة ببيانات الاختبار لمساعدتك على البدء. من أجل إعداد البذور
من أجل إعداد البذر ، ستحتاج إلى إنشاء `seed.ts` في مُجلد `prisma/` ، ثم قم بإضافة `seed` script إلى ملف package.json الخاص بك. ستحتاج أيضًا إلى مُشغل TypeScript يمكنه تنفيذ الـ script. نحن نُوصي بـ tsx ، وهو عِبارة عَن مُشغل TypeScript عالي الأداء يَستخدم esbuild ولا يتطلب أي تكوين ESM ، ولكن ts-node أو أي من المُشغلين الاخرين سيفي بالغرض.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db/client";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
ثُم قُم بتشغيل `pnpm db-seed` او `npm` او `yarn`
## مصادر مُفيدة
| المَصدر | الرابط |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prisma Docs | https://www.prisma.io/docs/ |
| Prisma GitHub | https://github.com/prisma/prisma |
| NextAuth.JS Prisma Adapter | https://next-auth.js.org/adapters/prisma |
| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/ar/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: إستخدام Tailwind CSS
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
## ما هي Tailwind CSS ؟
مكتبة 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)
فهي تجعل عملية التصميم سريعة بشكل لا يُصدق.
1. في الماضي كنا نكتب css في ملفات منفصلة
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. ثم نقوم استدعائها في مكان آخر
```jsx
import "./my-class.css";
```
3. ثم نُضيف الـ class الي HTML
```html
...
```
المقابل لكل الخطوات السابقة في Tailwind CSS
1. فقط اكتب الـ Class في HTML وانتهى الموضوع
```html
...
```
إستخدام هذة الخصائص جَنبا إلى جَنب مع React Components يُعطيك قُوة هائلة لا مَثيل لها.
تأتي Tailwind CSS بنظام مُدمج وجميل مُزود بمجموعة الوان واحجام و styles مُختارة بعناية كالطول والعرض والحواف، كما أيضا تاني مع breakpoints لإنشاء تصميم متوافق.
أعطي [mewtru](https://twitter.com/trunarla) خطابا رائعا عن [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).
## الاستخدام
تأكد من تثبيت إضافة Tailwind CSS لمحرر اكوادك لتُحسن جودة العمل.
### الاضافات
- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### الـ Formatting
الـ 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)
### إضافة الـ classes إختبارياَ
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## مصادر مفيدة
| المصدر | الرابط |
| ---------------------------- | -------------------------------------------------------- |
| Tailwind Docs | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Tailwind Discord Server | https://tailwindcss.com/discord/ |
| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/ar/usage/trpc.md
================================================
---
title: tRPC
description: Usage of tRPC
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
تسمح لك tRPC بكتابة type safe api دُون الحَاجة إلى تَوليد كود فتُنحي عنك حَدوث أخطاء مفاجئة أثناء الـ runtime، حيث إنها تَستغل خاصية الـ inference في Typescript حتى تضمن الـ type safety عِند نداء الـ Api من الـ Frontend
"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."
## Files
لسوء الحظ فإن tRPC تتطلب قليلاً من الـ boilerplate ولكن لحسن الحظ فان `create-t3-app` تحمل عنك هذا العبء.
### 📄 ملف `pages/api/trpc/[trpc].ts`
هذة هي نقطة دخولك الي 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)
مما يعني أنك قادر على استخدام `createNextApiHandler` في أي middleware تريده، إقرأ [example snippet](#enabling-cors)
### ملف 📄 `server/trpc/context.ts`
في هذا الملف تقوم بانشاء الـ Context التي سيتم تمريره الي tRPC Procedure ، الـ Context هو عبارة عن البيانات التي سيكون لكل الـ Procedures وصول لها وهي مكان مُناسب لتضع أشياء مثل database connections ومعلومات المصادقة وغيرها.
- ما هو `createContextInner`: هُنا تَقوم بإنشاء الـ Context الذي لا يَعتمد عَلى الـ request مِثل إتصال قاعدة البيانات. ويمكنك إستخدام function لـ [integration testing](#sample-integration-test) او [ssg-helpers](https://trpc.io/docs/v10/ssg-helpers)
- ما هو `createContext` ؟ هُنا حَيث تَقوم بإنشاء الـ Context الذي يعتمد على الـ request فيمكنك الوصول الى الـ `req Object` عن طريق `opts.req` ومن ثُم تَمريرة الي `createContextInner`لإنشاء الـ Context النهائي
### 📄ملف `server/trpc/trpc.ts`
في هذا حَيثُ يمكنك تحديد الـ [procedures](https://trpc.io/docs/v10/procedures) و [middlewares](https://trpc.io/docs/v10)، من الافضل ان لا تقوم بعمل export لـ t Object كاملا
/middlewares) بل قم بتصدير procedures و middlewares
ستلاحظ أننا نستخدم `superjson` كـ [data transformer](https://trpc.io/docs/v10/data-transformers)، ذلك حتى نحفظ الـ Types لحين إستخدامها في في الـ client، فمثلا إذا كان الـ Type هو Date فإن الـ client سَيُعيد Date ,gds string
### 📄 ملف `server/trpc/router/*.ts`
هنا يمكنك تحديد الـ route ,والـ procedure للـ API، من الافضل [أن تُنشئ routers](https://trpc.io/docs/v10/router) مُنفصلة للـ procedures المتقاربة ومن ثَم [دمجها](https://trpc.io/docs/v10/merging-routers) في router واحد في `server/trpc/router/_app.ts`
### 📄 ملف `utils/trpc.ts`
هذه هي نقطة دخول الواجهة الأمامية لـ tRPC. هذا هو المكان الذي ستقوم فيه باستيراد **type definition** الخاص بالـ procedure وإنشاء tRPC client الخاص بك جنبًا إلى
جنب مع react query hooks. نظرًا لأننا قمنا بتفعيل "superjson" في الواجهة الخلفية
فنحن بحاجة إلى تفعيلة على الواجهة الأمامية أيضًا. هذا لان البيانات التي يحدث لها serialized في الـ client يتم عمل deserialized لها في الـ client.
هنا تقوم بتحديد [روابط](https://trpc.io/docs/v10/links) الـ tRPC حيث تُُحدد المسار الذي سيمر به الـ request من الـ client إلى الـ server
نحن نستخدم [`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)
وفي الاخير نقوم بتصدير [helper type](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type) حتى نستعمل الـ type infre في الـ frontend
## كيف أستخدم tRPC ؟
ننصحك بمشاهدة هذا[a killer talk at Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) من [trashh_dev](https://twitter.com/trashh_dev)
مع tRPCتكتب Function في الـ backend والتي يمكن مناداتها من الـ frontend
```ts:server/trpc/router/user.ts
const userRouter = t.router({
getById: t.procedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
في نهاية الأمر تتحول tRPC procedure الي backend عادي فيقوم بفحص الـ input ويمرر الـ request إذا كان صحيحاًويعيد رسالة خطأ إذا كانت المدخلات غير صحيحة.
بعد التأكد من صحة البيانات يتم نداء function والتي إما لجلب بيانات ([query](https://trpc.io/docs/v10/react-queries)) أو أن تغير في البانات ([mutation](https://trpc.io/docs/v10/react-mutations))
أنت
```ts:server/trpc/router/_app.ts
const appRouter = t.router({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
لاحظ أننا نقوم بعمل export فقط لـ router's type أي أننا لا نستخدم اي من الـ server code في الـ client
الان دعنا ننادي الـ procedure من الـ frontend ، tRPC توفر wrapper لمكتبة `@tanstack/react-query` مما يسمح لك بإستخدام المكتبة بكامل قوتها.
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
const UserPage = () => {
const { query } = useRouter();
const userQuery = trpc.user.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
ستلاحظ على الفور مدى جودة الإكمال التلقائي والـ typesafety. بمجرد كتابة "trpc." ، ستظهر `router` الخاصة بك في الإكمال التلقائي ، وعندما تحدد الـ `router`،
ستظهر الـ procedures. وستحصل أيضًا على خطأ TypeScript إذا كانت المُدخلات الخاص بك لا يتطابق مع الـ schema الذي حددته مسبقا.
## كيف اُنادي API خارجي ؟
باستخدام الـ API العادية ، يمكنك استدعاء الـ End point الخاصة بك باستخدام أي عميل HTTP مثل `curl` أو` Postman` أو `fetch` أو مباشرة من متصفحك.
مع tRPC ، الأمر مختلف بعض الشيء. إذا كنت ترغب في الاتصال بالـ procedure بدون عميل tRPC ، فهناك طريقتان موصى بهما للقيام بذلك:
### Expose a single procedure externally
إذا أردت أن تُتيح procedure للـ Apis الخارجية الق نظرة علي [server side calls](https://trpc.io/docs/v10/server-side-calls)، مما سيسمح لك بعمل Next.js Api إعتيادية
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### تحول كل الـ Procedures الي REST endpoint ؟
إذا كنت ترغب في كشف كل الـ ؛قخؤثيعقثس ، الق نظرة علي [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master).
### It's just HTTP Requests
tRPC 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.
## Comparison to a Next.js API endpoint
دعنا نقارن " Next.js Endpoint" بـ "tRPC procedure". لنفترض أننا نريد جلب "Object" مستخدم معين من قاعدة بياناتنا وإعادته إلى الواجهة الأمامية.
يمكننا كتابة Next.js API Endpoint مثل هذا:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db/client";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
قارن هذا بمثال tRPC أعلاه ويمكنك رؤية بعض مزايا tRPC:
- بدلاً من تحديد عنوان url لكل مسار ، والذي يمكن أن يصبح مزعجًا إذا حاولت نقل شيء ما ، فإن الـ `router` بأكمله عبارة عن `Object` مع الإكمال التلقائي.
- لست بحاجة إلى التحقق من HTTP method التي تم استخدامها.
- لا تحتاج إلى التحقق من أن الطلب أو الـ `query` ، لأن Zod يعتني بذلك.
- بدلاً من إنشاء الـ responde object ، يمكنك إرجاع أخطاء او قيمة أو Object كما تفعل في أي function.
## snippets مفيدة
### تفعيل CORS
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/trpc/router/_app";
import { createContext } from "~/server/trpc/context";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Enable cors
await cors(req, res);
// Create and call the tRPC handler
return createNextApiHandler({
router: appRouter,
createContext,
})(req, res);
};
export default handler;
```
### Optimistic updates
الـ Optimistic updates هي تحديثات تحديث واجهة المستخدم قبل أن ينتهي الـ Request مما يُحسن تجربة المستخدم، لكن التطبيقات التي تُفضل دقة المعلومات يجب أن تتجنب الـ Optimistic updates، للمزيد من المعلومات إقرا [React Query docs](https://tanstack.com/query/v4/docs/guides/optimistic-updates).
```tsx
const MyComponent = () => {
const listPostQuery = trpc.post.list.useQuery();
const utils = trpc.useContext();
const postCreate = trpc.post.create.useMutation({
async onMutate(newPost) {
// Cancel outgoing fetches (so they don't overwrite our optimistic update)
await utils.post.list.cancel();
// Get the data from the queryCache
const prevData = utils.post.list.getData();
// Optimistically update the data with our new post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Return the previous data so we can revert if something goes wrong
return { prevData };
},
onError(err, newPost, ctx) {
// If the mutation fails, use the context-value from onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sync with server once mutation has settled
utils.post.list.invalidate();
},
});
};
```
### عينة من Integration Test
إقرأ [Vitest](https://vitest.dev)
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/router/_app";
import { createContextInner } from "~/server/router/context";
test("example router", async () => {
const ctx = await createContextInner({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
## Useful Resources
| Resource | Link |
| ---------------------- | ------------------------------------------------------- |
| tRPC Docs | https://www.trpc.io |
| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples |
| React Query Docs | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/ar/usage/typescript.md
================================================
---
title: TypeScript
description: إستخدام TypeScript
layout: ../../../layouts/docs.astro
lang: ar
dir: rtl
---
سواءََ كُنت مُبرمجا مُبتدئاََ أو مُتمرسًا ، فعلبك أن تتأكد تمام الثقة أن TypeScript أمر لا بد منه. قد تبدو مخيفتاََ في البداية ، ولكنها في الواقع فحالها كحال الأدوات الأخرى، وهي شيء لا يَنظر فية الكثيرون أبدًا بعد البدء في استخدامها.
فتُوفر مٌلاحظات مٌباشرة أثناء كِتابة الكود عَن طَريق تَحديد أنواع البيانات المتوقعة ، وأيضا تٌوفر خاصية الإكمال التلقائي في الـ Editor الخاص بك ، أو ربما ستصرخ عَليك بِخطوط مُتعرجة حمراء إذا حاولت الوصول إلى خاصية غير موجودة أو إذا قمت بتمرير قيمة من النوع الخطأ ، التي قد تضطر إلى تصحيحها.
## الـ Type Inference
يميل الكثير من مٌطوري Typescript إلى كِتابة الكثير من الـ types وفي واقع الامر أن هذا ليس ضرورياََ أبداََخاصتاََ مع وجود الـ Inference.
لكن ... إنتظر لحظة .. ، ما هو الـ Inference اصلا ؟ حسنا .. الـ Inference هو تَتَبُع الـ Types لك في كل مكان في الكود، يُفيدك في أنه يُغنيك عن تِكرار كتابة الـ Types في أماكن أخرى.
الق نظرة علي [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## إستخدامات الـ type inference
### مكتبة Zod
مكتبة [Zod](https://github.com/colinhacks/zod) هي schema validation library تم بِنائوها بـ Typescript. فَقط اٌكتب الـ Schema التي تٌمثل مَصدر الحقيقة الاساسي single source of truth ودع الباقي لـ zod وهي ستتكفل بة.
### مكتبة Tanstack Query
تُسهل عليك كِتابة وإدارة الـ queries و الـ mutations مما يٌدوي الي تحسين تجربة المٌطور والمستخدم.
## مصادر مفيدة
| المصدر | الرابط |
| --------------------------------------------------------- | ----------------------------------------------------------------- |
| TypeScript Handbook | https://www.typescriptlang.org/docs/handbook/ |
| Beginners TypeScript Tutorial | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/ar/why.md
================================================
---
title: لماذا CT3A؟
description: لماذا يجب عليك اختيار Create T3 App لتطبيقك المقبل
layout: ../../layouts/docs.astro
lang: ar
dir: rtl
---
لقد أنشئنا Create T3 App لان [Theo](https://twitter.com/t3dotgg) رفض أن يصنع قالب محضَر لتِقنيته المُفضلة. ألهمنا حُبنا لـ typesafety، جَنباََ إلى جَنب مع create-next-app، و [Astro's CLI](https://astro.build)، للعمل عَلى قَدم وساق لصُنع أفضل نُقطة بِداية مُمكنة لمشروعات T3.
إذا كُنت مُهتمًا باستخدام Next.js بطريقةِِ آمنة، فَهذا هو المكان المُناسب للبدء. إذا كُنت مهتمًا بأي من تِلك التقنيات، فاقرأ :)
## لماذا TypeScript؟
إن JavaScript صَعبة. لماذا نُضيف المزيد من القوَاعد؟
لأننا نَعتقد اعتقادًا راسخًا أن التَجربة التي توفرها TypeScript سَتدفعك إلى أن تَكون مٌبرمجا أَفضل، فَتوفر لك المُلاحظات مُباشرة خلال كِتابة الكُود من خِلال تحديد أنواع البيانات المُتوقعة (Types)، هذا إلى جانب ميزة الإكمال التلقائي، غَير أنهُ يُنبهك في حَال ارتكبت خطأَ بوضع خط أحمر تحت الخطأ عند المحاولة لوصول إلى خاصية غَير مَوجودة أو تُمرير قِيمة من النوع الخَطأ فَيجبرك أن تصححها. سَواء كُنت مٌبتدئًا في تَطوير الويب أو محترفًا متمرسًا، فإن "صَرامة" TypeScript سَتُوفر لك تَجربة أقل إحباطًا وأكثر اتساقًا من Vanilla JS.
هل مازلت غَير مُقتنع إن Typesafety تجعلك أسرع؟ إذاََ شَاهد هَذا [might be using TypeScript wrong…](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## لماذا Next.js؟
نَحن نُحب React، بفضلها أصبح تَطوير واجهات المُستخدم UI سَهل المَنال بَطريقة لم نَكن نَتخيلها. لقد أَخَذَت بِيد المُطورين وعَبرت به أوديةَ سَحيقة وطرقاََ وَعرة.
عَلي الرَغم أن Next.js تِقنية عَنيدة قليلاَ، إلا أنها تُقدم تَجربة أقرب إلى الكَمال مع React في شَتى النَواحي، من routing و API حَتي عَرض الصُور، فَنحن نَثق تمام الثِقةٍٍ أن Next.js سَتقود المُطورين إلى الأمام بِقراراتها الحَكيمة.
## لماذا tRPC/Prisma/Tailwind وغيرها؟
بينما نؤمن بالحفاظ عَلى بَساطة الأشياء قَدرَ الإمكان، فإن هُناك أجزاء بَرمجيةَّ صَغيرة تَتكرر في كُل "تَطبيق" مثل المشروعات التي ننشئها، `create-t3-app` تَسمح لك بتبني الجزء بصورةِِ رائعة.
### لماذا tRPC؟
توفر tRPC تجرِبة سلسة في تطوير تطبيقات المستخدم (Client Side) كما في GraphQl دون الحاجة لكتابة كود متداول (boilarplate)، فإنها نستعمل TypeScript قدر ألإمكان لتوفر تجرِبة ممتازة للمطور.
### لماذا Prisma؟
إن Prisma بالنسبة لـ SQL كـ Typescript بالنسبة لـ Javascript، فإنها تخلق تجربة لمطور لم تكن موجودة من قبل، فتولد الأنواع (Types) من Schema يقوم المطور بوضعها، ذلك إلى جانب توافقها مع [العديد من قواعد البيانات](https://www.prisma.io/docs/concepts/database-connectors)
فبذلك تضمن Prisma الـ TypeSafety بين التطبيق وقاعدة البيانات
توفر Prisma [مجموعة كاملة من الأدوات](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) ملائمة لقاعدة بياناتك التي تتيح لك قراءة بياناتك ومعالجتها بسرعة دون الحاجة إلى كتابة الكود.
### لماذا Tailwind CSS؟
يوفر Tailwind "أسلوب مرن مع CSS"
توفر لك Tailwind العناصر الإنشائية اللازمة من الألوان وتباعد وغيرها، فتُسهل أنشاء تطبيق جيد المظهر. وعلى خلاف المكتبات الأخرى فإنها لا تعيقك عندما تريد نقل تطبيقك إلى مستوي اعلي و أنشاء شيئ جميل وفريد من نوعه.
بالإضافة، باتخاذها أسلوب كتابة التصميم داخل المكون (inline-like)، تشجعك Tailwind على عمل دون قلق على عبء التسمية، أو تنظيم الملفات، أو مواجهة معدلة ليست بصلة بالمشكلة التي تريد حلها.
### لماذا NextAuth.js؟
إذا كنت تريد نظام توثيق صالحيه في تطبيقك NextJS، فإن NextAuth.js يعد حلاً ممتازًا دون الحاجة إلى إنشاءه بنفسك. فيأتي مزودًا بقائمة واسعة من المزودين (Providers) إضافة مصادقة OAuth بسرعة ويوفر محولات (Adapters) للعديد من قواعد البيانات و ORMs.
================================================
FILE: www/src/pages/branding.astro
================================================
---
import JumpToContent from "../components/accessibility/jumpToContent.astro";
import Asset from "../components/branding/Asset.astro";
import LandingPage from "../layouts/landingPage.astro";
---
Brand assets
================================================
FILE: www/src/pages/en/deployment/docker.md
================================================
---
title: Docker
description: Deployment with Docker
layout: ../../../layouts/docs.astro
lang: en
---
You 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.
## Docker Project Configuration
Please 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`:
- `DATABASE_URL` (used by the server)
- `NEXT_PUBLIC_CLIENTVAR` (used by the client)
### 1. Next Configuration
In 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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Create dockerignore file
Click here and include contents in .dockerignore:
### 3. Create Dockerfile
> 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.
Click here and include contents in Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:20-alpine AS deps
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:20-alpine AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 gcr.io/distroless/nodejs20-debian12 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
ENV PORT 3000
CMD ["server.js"]
```
> **_Notes_**
>
> - _Emulation of `--platform=linux/amd64` may not be necessary after moving to Node 18._
> - _See [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) to understand why `libc6-compat` might be needed._
> - _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)._
> - _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._
## Build and Run Image Locally
Build and run this image locally with the following commands:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Open [localhost:3000](http://localhost:3000/) to see your running application.
## Docker Compose
You can also use Docker Compose to build the image and run the container.
Follow steps 1-3 above, click here, and include contents in docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Build and run this using the `docker compose up --build` command:
```bash
docker compose up --build
```
Open [localhost:3000](http://localhost:3000/) to see your running application.
## Deploy to Railway
You 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:
```bash
railway login
railway init
railway link
railway up
railway open
```
Go 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/).
## Useful Resources
| Resource | Link |
| ------------------------------------ | -------------------------------------------------------------------- |
| Dockerfile reference | https://docs.docker.com/engine/reference/builder/ |
| Compose file version 3 reference | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Docker CLI reference | https://docs.docker.com/engine/reference/commandline/docker/ |
| Docker Compose CLI reference | https://docs.docker.com/compose/reference/ |
| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image |
| Next.js in Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Next.js with Docker Example | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/en/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Deployment",
layout: "docs",
description: "Learn how to deploy your T3 app to production.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/en/deployment/netlify.mdx
================================================
---
title: Netlify
description: Deploying to Netlify
layout: ../../../layouts/docs.astro
lang: en
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Netlify 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.
## Why Host on Netlify
Conventional 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.
There'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/).
There 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).
To track the status of non-stable Next 13 features see [Using the Next 13
`app` directory on
Netlify](https://github.com/netlify/next-runtime/discussions/1724).
## Project Configuration
There 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Using the Netlify Dashboard
1. 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**.

2. Connect your Git provider.

3. Select your project's repository.

4. Netlify will detect if you have a `netlify.toml` file and automatically configure your build command and publish directory.

5. Click **Show advanced** and then **New variable** to add your environment variables.

6. Click **Deploy site**, wait for the build to complete, and view your new site.
## Using the Netlify CLI
To 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:
```bash
npm i -g netlify-cli
```
To 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:
```bash
ntl dev
```
Run the [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) command to configure your project:
```bash
ntl init
```
Import your project's environment variables from your `.env` file with [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Deploy 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:
```bash
ntl deploy --prod --build
```
To view a running example on Netlify, visit [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/en/deployment/vercel.md
================================================
---
title: Vercel
description: Deploying to Vercel
layout: ../../../layouts/docs.astro
lang: en
---
We 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.
## Project Configuration
Vercel 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.**
```json
{
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Using the Vercel Dashboard
1. 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**.

2. Import the GitHub repository with your project.

3. Add your environment variables.

4. Click **Deploy**. Now whenever you push a change to your repository, Vercel will automatically redeploy your app!
## Using the Vercel CLI
To deploy from the command line you must first [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
Run the [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) command to deploy your project.
```bash
vercel
```
Include `--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.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
After 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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/en/examples.mdx
================================================
---
title: Examples
description: Examples of different live apps
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
import Form from "../../components/docs/exampleOptionForm.astro";
You can try out different combinations of technologies that create-t3-app offers.
You cannot select `prisma` and `drizzle` at the same time.
Some features might not work unless you create an env file
================================================
FILE: www/src/pages/en/faq.mdx
================================================
---
title: FAQ
description: Frequently asked questions about Create T3 App
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Here are some commonly asked questions about Create T3 App.
## What's next? How do I make an app with this?
We 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.
If 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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
- [Drizzle](https://orm.drizzle.team/docs/overview)
## How do I keep my app up to date?
Create 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.
## What learning resources are currently available?
Although 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.
If 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?
Now, 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:
### Articles
Some of these might be outdated.
- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Videos
- [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)*
- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)
- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Why are there `.js` files in the project?
As 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.
We 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).
## I'm struggling to add i18n to my app. Is there any reference I can use?
We 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.
However, 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).
## Should I use `/app` from Next.js 13 or the more mature `/pages` paradigm?
You 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).
Nevertheless, 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.
For a list of supported, planned, and worked on features in the `/app` dir,
visit the [beta Next.js
docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
================================================
FILE: www/src/pages/en/folder-structure-app.mdx
================================================
---
title: Folder Structure (App)
description: Folder structure of a newly scaffolded T3 App with the App Router
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramApp.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Please 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.
### `prisma`
The `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.
### `public`
The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset.
### `src/env`
Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables).
### `src/app`
The `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.
#### `src/app/_components/post.tsx`
The `post.tsx` file is an example of a client component that calls a tRPC mutation.
#### `src/app/api/auth/[...nextauth]/route.ts`
The `[...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.
#### `src/app/api/trpc/[trpc]/route.ts`
The `[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.
### `src/server`
The `server` folder is used to clearly separate code that is only used on the server.
#### `src/server/auth.ts`
The 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.
#### `src/server/db.ts`
The `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.
### `src/server/db`
The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below).
#### `src/server/db/index.ts`
The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information.
#### `src/server/db/schema.ts`
The `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.
### `src/server/api`
The `api` folder contains the tRPC server-side code.
#### `src/server/api/routers`
The `routers` folder contains all your tRPC sub-routers.
#### `src/server/api/routers/example.ts`
The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route.
Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs.
#### `src/server/api/trpc.ts`
The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we:
1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.
2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.
#### `src/server/api/root.ts`
The `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.
### `src/trpc`
The `trpc` folder contains the setup to let you call tRPC procedures from server components and client components.
#### `src/trpc/query-client.ts`
The `query-client.ts` file creates the Query Client that tRPC uses to cache and deduplicate data in client components.
#### `src/trpc/react.tsx`
The `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.
#### `src/trpc/server.ts`
The `server.ts` file is the entrypoint for using tRPC in Server Components.
### `.env`
The `.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.
### `.env.example`
The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history.
### `.eslintrc.cjs`
The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information.
### `db.sqlite (sqlite only)`
The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git.
### `drizzle.config.ts`
The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information.
### `next-env.d.ts`
The `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.
### `next.config.mjs`
The `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.
### `postcss.config.js`
The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information.
### `prettier.config.mjs`
The `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.
### `start-database.sh (mysql or postgres only)`
The `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.
### `tsconfig.json`
The `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.
================================================
FILE: www/src/pages/en/folder-structure-pages.mdx
================================================
---
title: Folder Structure (Pages)
description: Folder structure of a newly scaffolded T3 App with the Pages Router
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Please 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.
### `prisma`
The `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.
### `public`
The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset.
### `src/env`
Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables).
### `src/pages`
The `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.
#### `src/pages/api`
The `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.
#### `src/pages/api/auth/[...nextauth].ts`
The `[...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.
#### `src/pages/api/trpc/[trpc].ts`
The `[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.
### `src/server`
The `server` folder is used to clearly separate code that is only used on the server.
#### `src/server/auth.ts`
The 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.
#### `src/server/db.ts`
The `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.
### `src/server/db`
The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below).
#### `src/server/db/index.ts`
The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information.
#### `src/server/db/schema.ts`
The `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.
### `src/server/api`
The `api` folder contains the tRPC server-side code.
#### `src/server/api/routers`
The `routers` folder contains all your tRPC sub-routers.
#### `src/server/api/routers/example.ts`
The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route.
Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs.
#### `src/server/api/trpc.ts`
The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we:
1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.
2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information.
#### `src/server/api/root.ts`
The `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.
### `src/styles`
The `styles` folder contains the global styles of the application.
### `src/utils`
The `utils` folder is used to store commonly re-used utility functions.
#### `src/utils/api.ts`
The `api.ts` file is the front-end entrypoint to tRPC. See [tRPC usage](usage/trpc#-utilsapits) for more information.
### `.env`
The `.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.
### `.env.example`
The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history.
### `.eslintrc.cjs`
The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information.
### `db.sqlite (sqlite only)`
The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git.
### `drizzle.config.ts`
The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information.
### `next-env.d.ts`
The `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.
### `next.config.mjs`
The `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.
### `postcss.config.js`
The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information.
### `prettier.config.mjs`
The `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.
### `start-database.sh (mysql or postgres only)`
The `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.
### `tsconfig.json`
The `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.
================================================
FILE: www/src/pages/en/installation.mdx
================================================
---
title: Installation
description: Installation instructions for Create T3 App
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
To scaffold an app using `create-t3-app`, run any of the following commands and answer the command prompt questions:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
After your app has been scaffolded, check out the [first steps](/en/usage/first-steps) to get started on your new application.
## Advanced usage
| Option/Flag | Description |
| ----------------- | ----------------------------------------------------------------------- |
| `[dir]` | Include a directory argument with a name for the project |
| `--noGit` | Explicitly tell the CLI to not initialize a new git repo in the project |
| `-y`, `--default` | Bypass the CLI and bootstrap a new t3-app with all options selected |
| `--noInstall` | Generate project without installing dependencies |
## Experimental usage
For 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.
| Flag | Description |
| ------------------------- | -------------------------------------------- |
| `--CI` | Let the CLI know you're in CI mode |
| `--trpc` | Include tRPC in the project |
| `--prisma` | Include Prisma in the project |
| `--drizzle` | Include Drizzle in the project |
| `--nextAuth` | Include NextAuth.js in the project |
| `--tailwind` | Include Tailwind CSS in the project |
| `--dbProvider [provider]` | Include a configured database in the project |
| `--appRouter` | Use Next.js App Router in the project |
If you don't provide the `CI` flag, the rest of these flags have no effect.
You 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`.
The --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.
### Example
The following would scaffold a T3 App with tRPC and Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
The following would scaffold a T3 App with NextAuth.js, Tailwind CSS, Drizzle, and PostgreSQL.
```bash
pnpm dlx create-t3-app@latest --CI --nextAuth --tailwind --drizzle --dbProvider postgres
```
================================================
FILE: www/src/pages/en/introduction.mdx
================================================
---
title: Introduction
description: Introduction to the T3 Stack
layout: ../../layouts/docs.astro
lang: en
---
import { IntroductionTab } from "../../components/docs/introductionTab";
## The T3 Stack
The _"T3 Stack"_ is a web development stack made by [Theo](https://twitter.com/t3dotgg) focused on simplicity, modularity, and full-stack typesafety.
The 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.
You 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 :)
## So... what is create-t3-app? A template?
Kind 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.
After 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.
This 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).
## T3 Axioms
We'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.
### Solve Problems
It'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.
### Bleed Responsibly
We 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.
### Typesafety Isn't Optional
The 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.
================================================
FILE: www/src/pages/en/other-recs.md
================================================
---
title: Other Recommendations
description: Libraries and Services that we recommend for many projects
layout: ../../layouts/docs.astro
lang: en
---
We 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.
These 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**_.
## State Management
_**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.
### Zustand
**For never using Redux again**
The "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.
- [Zustand Homepage](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
### Jotai
**For never using Context again**
For 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.
- [Jotai Homepage](https://jotai.org/)
- [Jotai GitHub](https://github.com/pmndrs/jotai)
## Component Libraries
Most 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.
### Unstyled Component Libraries
Also known as headless libraries, they provide great unstyled, and accessible components that you can customize to your liking. Here are a few recommendations.
- [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.
- [Headless UI](https://headlessui.com/) made by the Tailwind CSS team also provides unstyled, accessible components that integrate seamlessly with Tailwind CSS.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) provides accessible UI primitives for your design system. Their Date Picker component is top tier.
### Styled Component Libraries
**For when you just want your app to look OK**
Sometimes 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.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
- [@shadcn/ui](https://ui.shadcn.com/)
### Class Variance Authority
**For building UI Libraries**
Declaratively 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.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Animations
For when you need animations in your app, here are our recommendations.
### AutoAnimate
**For animations with a single line of code**
Most 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.
- [AutoAnimate Homepage](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**For complex animations with declarative code**
Framer Motion provides a simple, declarative syntax and allows you to write less code to craft everything from complex animations to even gestures.
- [Framer Motion Homepage](https://framer.com/motion)
- [Framer Motion Documentation](https://www.framer.com/docs/)
## Deployments, Infrastructure, Databases and CI
### Vercel
**For hosting your app**
Vercel 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 :)
- [Vercel Homepage](https://vercel.com/)
- [Create T3 App Vercel deployment guide](/en/deployment/vercel)
### PlanetScale
**For databases without the worry**
PlanetScale 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.
- [PlanetScale Homepage](https://planetscale.com/)
### Railway
**For hosting your infra**
"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.
- [Railway Homepage](https://railway.app/)
### Upstash
**For serverless Redis**
We 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.
- [Upstash Homepage](https://upstash.com/)
### Pusher
**For serverless WebSockets**
If 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.
- [Pusher Homepage](https://pusher.com/)
### Soketi
Soketi 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.
- [Soketi Homepage](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Analytics
User data is very valuable when you're building an app. Here are some analytics providers we recommend.
### PostHog
PostHog 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.
- [PostHog Homepage](https://posthog.com/)
### Plausible
Need 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).
- [Plausible Homepage](https://plausible.io/)
### Umami
Umami 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.
- [Umami Homepage](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
- [Umami Cloud](https://cloud.umami.is/)
## Other
### Next Bundle Analyzer
It 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.
- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/en/t3-collection.mdx
================================================
---
title: T3 Collection
description: Cool open source projects and companies using the T3 stack
layout: ../../layouts/docs.astro
lang: en
isMdx: true
---
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
import Callout from "../../components/docs/callout.tsx";
Made a project using the T3 stack and want to share it? Add it to the list!
## Open Source apps made using the T3 Stack
## Companies using the T3 Stack
We'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!
Have a cool project using the T3 stack? Make a [pull
request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)
and add it here!
================================================
FILE: www/src/pages/en/usage/_next-auth-app-router.mdx
================================================
import Callout from "../../../components/docs/callout.tsx";
import Tabs from "../../../components/docs/tabs.astro";
The newest version of NextAuth has migrated to [Auth.js](https://authjs.dev/)
## Retrieving session server side
Sometimes you might want to request the session on the server. To do so, use the `auth` helper function that `create-t3-app` provides.
```tsx:app/page.tsx
import { auth } from "~/server/auth";
export default async function Home() {
const session = await auth();
...
}
```
## Inclusion of `user.id` on the Session
Create 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.
```ts:server/auth/config.ts
callbacks: {
session: ({ session, user }) => ({
...session,
user: {
...session.user,
id: user.id,
},
}),
},
```
This 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.
```ts:server/auth/config.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
} & DefaultSession["user"];
}
```
The 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.
## Usage with tRPC
When 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.
This is done in a two step process:
1. Pass the authentication session into the tRPC context:
```ts:server/api/trpc.ts
import { auth } from "~/server/auth";
import { db } from "~/server/db";
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth();
return {
db,
session,
...opts,
};
};
```
2. 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.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure
.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
session: { ...ctx.session, user: ctx.session.user },
},
});
});
```
The 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.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Usage with a database provider
Getting 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 [Auth.js
docs](https://authjs.dev/getting-started/authentication/oauth). 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.
Getting NextAuth.js to work with Drizzle requires a lot of [initial
setup](https://authjs.dev/getting-started/adapters/drizzle). `create-t3-app`
handles all of this for you, and if you select both Drizzle 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 [Auth.js
docs](https://authjs.dev/getting-started/authentication/oauth). 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.
### Adding new fields to your models
When 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.
If 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:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Usage with Next.js middleware
With 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.
```middleware.ts
export { auth as middleware } from "@/auth"
```
Then define authorized callback in your auth.ts file. For more details check out the [reference docs.](https://authjs.dev/reference/nextjs#authorized)
```app/auth.ts
async authorized({ request, auth }) {
const url = request.nextUrl
if(request.method === "POST") {
const { authToken } = (await request.json()) ?? {}
// If the request has a valid auth token, it is authorized
const valid = await validateAuthToken(authToken)
if(valid) return true
return NextResponse.json("Invalid auth token", { status: 401 })
}
// Logged in users are authenticated, otherwise redirect to login page
return !!auth.user
}
```
You should not rely on middleware exclusively for authorization. Always ensure
that the session is verified as close to your data fetching as possible.
## Setting up the default DiscordProvider
1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application"
2. In the settings menu, go to "OAuth2 => General"
- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`.
- 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.
- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord)
- Save your changes
- 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.
## Useful Resources
| Resource | Link |
| --------------------------------- | --------------------------------------- |
| NextAuth.js Docs | https://authjs.dev/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/en/usage/_next-auth-pages.mdx
================================================
import Callout from "../../../components/docs/callout.tsx";
## Context Provider
In your app's entrypoint, you'll see that your application is wrapped in a [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
```
This context provider allows your application to access the session data from anywhere in your application, without having to pass it down as props:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Retrieving session server-side
Sometimes 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`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTE: `session` wont have a loading state since it's already prefetched on the server
...
}
```
## Inclusion of `user.id` on the Session
Create 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.
```ts:server/auth.ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
This 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.
```ts:server/auth.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
The 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.
## Usage with tRPC
When 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.
This is done in a two step process:
1. 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.
```ts:server/auth.ts
export const getServerAuthSession = (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return getServerSession(ctx.req, ctx.res, authOptions);
};
```
Using this helper function, we can grab the session and pass it through to the tRPC context:
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
})
```
The 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.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Usage with Prisma
Getting 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.
### Adding new fields to your models
When 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.
If 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:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Usage with Next.js middleware
Usage 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.
Using database sessions is the recommended approach and you should read up on
JWTs before switching to the JWT session strategy to avoid any security
issues.
After switching to the JWT session strategy. Make sure to update the `session` callback in `src/server/auth.ts`.
The `user` object will be `undefined`. Instead, retrieve the user's ID from the `token` object.
I.e.:
```diff:server/auth.ts
export const authOptions: NextAuthOptions = {
+ session: {
+ strategy: "jwt",
+ },
callbacks: {
- session: ({ session, user }) => ({
+ session: ({ session, token }) => ({
...session,
user: {
...session.user,
- id: user.id,
+ id: token.sub,
},
}),
},
}
```
## Setting up the default DiscordProvider
1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application"
2. In the settings menu, go to "OAuth2 => General"
- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`.
- 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.
- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord)
- Save your changes
- 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.
## Useful Resources
| Resource | Link |
| --------------------------------- | --------------------------------------- |
| NextAuth.js Docs | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/en/usage/drizzle.mdx
================================================
---
title: Drizzle
description: Usage of Drizzle
layout: ../../../layouts/docs.astro
lang: en
isMdx: true
---
Drizzle 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.
## Drizzle Client
The 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.
```ts:src/server/db/index.ts
import { env } from "~/env";
import * as schema from "./schema";
import postgres from "postgres";
const conn = postgres(env.DATABASE_URL)
export const db = drizzle(conn, { schema });
```
We reccommend including the database client in your tRPC Context:
```ts:src/server/api/trpc.ts
import { db } from "~/server/db";
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await auth();
return {
db,
session,
...opts,
};
};
```
## Schema
The 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.
When 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).
## Drizzle Kit
Drizzle 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.
```json:package.json
"scripts": {
...
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio",
...
},
```
### Script Explanations
`db:generate`
Generates TypeScript types and models from your database schema, ensuring type safety and easy integration with Drizzle ORM.
`db:migrate`
Applies pending migrations to your database, keeping your schema in sync with changes and updates in your project.
`db:push`
Pushes local schema changes directly to the database without needing explicit migration files. This can be useful for quick syncing in development.
`db:studio`
Opens a visual interface for managing and inspecting your database tables, data, and relationships.
## Useful Resources
| Resource | Link |
| --------------------------- | --------------------------------------------------- |
| Drizzle Docs | https://orm.drizzle.team/docs/overview |
| Drizzle GitHub | https://github.com/drizzle-team/drizzle-orm |
| Auth.JS Drizzle Adapter | https://authjs.dev/getting-started/adapters/drizzle |
| Drizzle Kit Migration Guide | https://orm.drizzle.team/docs/kit-overview |
================================================
FILE: www/src/pages/en/usage/env-variables.mdx
================================================
---
title: Environment Variables
description: Getting started with Create T3 App
layout: ../../../layouts/docs.astro
lang: en
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Create 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`.
## env.js
_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`_
```ts:env.js
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
},
});
```
T3 Env uses the `createEnv` function to create the schema validate both client and server-side environment variables.
For more information about how `createEnv` works internally, check out the [T3
Env](https://env.t3.gg/docs/introduction) docs
## Using Environment Variables
When 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.
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` is fully typesafe and provides autocompletion
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ This will throw a runtime error
const dbUrl = env.DATABASE_URL;
// ✅ This is fine
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Since 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.
Some 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.
## Adding Environment Variables
To ensure your build never completes without the environment variables the project needs, you will need to add new environment variables in **two** locations:
📄 `.env`: Enter your environment variable like you would normally do in a `.env` file, i.e. `KEY=VALUE`
📄 `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`
Why do I need to destructure the environment variable in the `runtimeEnv`?
This is due to how Next.js bundles environment variables in certain runtimes.
By destructuring it manually, you ensure that the variable will never be
stripped out from the bundle.
Optionally, you can also keep `.env.example` updated:
📄 `.env.example`: Enter your environment variable, but be sure to not include the value if it is secret, i.e. `KEY=VALUE` or `KEY=`
### Example
_I want to add my Twitter API Token as a server-side environment variable_
1. Add the environment variable to `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Add the environment variable to `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.string(),
},
// ...
runtimeEnv: {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
},
});
```
3. _Optional:_ Add the environment variable to `.env.example` and make sure not to include the secret in the `runtimeEnv` option
```bash
TWITTER_API_TOKEN=
```
## Type Coercion
All 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.
Add the variables to your `.env`:
```
SOME_NUMBER=123
SOME_BOOLEAN=true
```
Then, validate them in `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
SOME_NUMBER: z.coerce.number(),
SOME_BOOLEAN: z.coerce.boolean(),
},
// ...
runtimeEnv: {
SOME_NUMBER: process.env.SOME_NUMBER,
SOME_BOOLEAN: process.env.SOME_BOOLEAN,
},
});
```
================================================
FILE: www/src/pages/en/usage/first-steps.md
================================================
---
title: First Steps
description: Getting started with your new T3 App
layout: ../../../layouts/docs.astro
lang: en
---
You just scaffolded a new T3 App and are ready to go. Here is the bare minimum to get your app working.
## Database
### MySQL, PostgreSQL
If 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.
### Prisma
If 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.
### Drizzle
If 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.
## Authentication
If 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.
Of 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.
1. You will need a Discord account, so register one if you haven't already.
2. 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.
3. Once your application has been created, navigate to "Settings → OAuth2 → General".
4. Copy the "Client ID" and add it to your `.env` as `AUTH_DISCORD_ID`.
5. Click "Reset Secret", copy the new secret, and add it to your `.env` as `AUTH_DISCORD_SECRET`.
6. Click "Add Redirect" and type in `http://localhost:3000/api/auth/callback/discord`.
- 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.
7. Save Changes.
You should now be able to log in.
## Editor Setup
The following extensions are recommended for an optimal developer experience. The links below provide editor specific plugin support.
- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)
- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)
- [Prettier Extension](https://prettier.io/docs/en/editors.html)
## Next Steps
- If your app includes tRPC, check out `src/pages/index.tsx` and `src/server/api/routers/post.ts` to see how tRPC queries work.
- Have a look around the Create T3 App docs, as well as the docs of the packages that your app includes.
- Join our [Discord](https://t3.gg/discord) and give us a star on [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/en/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Usage",
layout: "docs",
description: "Learn how to use the different technology from the T3 Stack.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/en/usage/next-auth.mdx
================================================
---
title: NextAuth.js
description: Usage of NextAuth.js
layout: ../../../layouts/docs.astro
lang: en
isMdx: true
---
import Tabs from "../../../components/docs/tabs.astro";
import AppRouter from "./_next-auth-app-router.mdx";
import Pages from "./_next-auth-pages.mdx";
When 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.
================================================
FILE: www/src/pages/en/usage/next-js.md
================================================
---
title: Next.js
description: Usage of Next.js
layout: ../../../layouts/docs.astro
lang: en
---
Next.js is a backend framework for your React applications.
Check 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.
## Why should I use it?
We 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.
Pairing 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)
## Get Static/Server Props
A 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.
If 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)
## Useful Resources
| Resource | Link |
| ------------------------------ | ---------------------------------- |
| Next.js Documentation | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Next.js Blog | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/en/usage/prisma.md
================================================
---
title: Prisma
description: Usage of Prisma
layout: ../../../layouts/docs.astro
lang: en
---
Prisma 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.
## Prisma Client
Located 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.
## Schema
You 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.
### With NextAuth.js
When 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).
## Default Database
The 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.
## Seeding your Database
[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.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Then, just run `pnpm db-seed` (or `npm`/`yarn`) to seed your database.
## Useful Resources
| Resource | Link |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prisma Docs | https://www.prisma.io/docs/ |
| Prisma GitHub | https://github.com/prisma/prisma |
| Prisma Migrate Playground | https://playground.prisma.io/guides |
| NextAuth.JS Prisma Adapter | https://next-auth.js.org/adapters/prisma |
| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/en/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Usage of Tailwind CSS
layout: ../../../layouts/docs.astro
lang: en
---
## What is Tailwind CSS?
Tailwind 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.
It makes CSS incredibly easy and quick to write, as shown by the following example:
Old CSS:
1. Write CSS, often in a separate file
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Import CSS into your component
```jsx
import "./my-class.css";
```
3. Add the class to your HTML
```html
...
```
Equivalent in Tailwind:
1. Just write classes in your HTML
```html
...
```
When used together with React Components, it is extremely powerful for quickly building UIs.
Tailwind 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.
Tru 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).
## Usage
Make sure you have editor plugins for Tailwind installed to improve your experience writing Tailwind.
### Extensions and Plugins
- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formatting
Tailwind 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.
### Conditionally Applying Classes
Conditionally adding classes using ternaries can get very messy and hard to read. These packages help in organizing your classes when using some conditional logic.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Useful Resources
| Resource | Link |
| ---------------------------- | -------------------------------------------------------- |
| Tailwind Docs | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Tailwind Discord Server | https://tailwindcss.com/discord/ |
| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/en/usage/trpc.md
================================================
---
title: tRPC
description: Usage of tRPC
layout: ../../../layouts/docs.astro
lang: en
---
tRPC 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.
"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."
tRPC 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.
With tRPC, you write TypeScript functions on your backend, and then call them from your frontend. A simple tRPC procedure could look like this:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
This 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.
After 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.
You 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`:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Notice that we only need to export our router's type definitions, which means we are never importing any server code on our client.
Now 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:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
You'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.
## Inferring errors
By 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.
Example usage:
```tsx
function MyComponent() {
const { mutate, error } = api.post.create.useMutation();
return (
);
}
```
## Files
tRPC requires quite a lot of boilerplate that `create-t3-app` sets up for you. Let's go over the files that are generated:
### 📄 `pages/api/trpc/[trpc].ts`
This 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.
### 📄 `server/api/trpc.ts`
This file is split up in two parts, context creation and tRPC initialization:
1. 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.
- `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.
- `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.
2. 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.
You'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.
### 📄 `server/api/routers/*.ts`
This 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.
### 📄 `server/api/root.ts`
Here we [merge](https://trpc.io/docs/v11/server/merging-routers) all the sub-routers defined in `routers/**` into a single app router.
### 📄 `utils/api.ts`
This 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.
You'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.
Lastly, we export a [helper type](https://trpc.io/docs/client/vanilla/infer-types) which you can use to infer your types on the frontend.
Create 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.
## How do I call my API externally?
With 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:
### Expose a single procedure externally
If 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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Exposing every procedure as a REST endpoint
If 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.
### It's just HTTP Requests
tRPC 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.
## Comparison to a Next.js API endpoint
Let'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:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Compare this to the tRPC example above and you can see some of the advantages of tRPC:
- 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.
- You don’t need to validate which HTTP method was used.
- 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.
- Instead of creating a response, you can throw errors and return a value or object as you would in any other TypeScript function.
- Calling the procedure on the frontend provides autocompletion and type safety.
## Useful snippets
Here are some snippets that might come in handy.
### Enabling CORS
If 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:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Enable cors
await cors(req, res);
// Create and call the tRPC handler
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Optimistic updates
Optimistic 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).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useUtils();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Cancel outgoing fetches (so they don't overwrite our optimistic update)
await utils.post.list.cancel();
// Get the data from the queryCache
const prevData = utils.post.list.getData();
// Optimistically update the data with our new post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Return the previous data so we can revert if something goes wrong
return { prevData };
},
onError(err, newPost, ctx) {
// If the mutation fails, use the context-value from onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sync with server once mutation has settled
utils.post.list.invalidate();
},
});
};
```
### Sample Integration Test
Here 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
If your procedure is protected, you can pass in a mocked `session` object when you create the context:
```ts
test("protected example router", async () => {
const ctx = await createInnerTRPCContext({
session: {
user: { id: "123", name: "John Doe" },
expires: "1",
},
});
const caller = appRouter.createCaller(ctx);
// ...
});
```
## Useful Resources
| Resource | Link |
| ---------------------- | ----------------------------------------------- |
| tRPC Docs | https://www.trpc.io |
| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples |
| React Query Docs | https://tanstack.com/query/latest/docs |
================================================
FILE: www/src/pages/en/usage/typescript.md
================================================
---
title: TypeScript
description: Usage of TypeScript
layout: ../../../layouts/docs.astro
lang: en
---
Whether 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.
It 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.
It 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.
## Type Inference
While 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.
Check out Theo's video on how [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Powerful uses of type inference
### Zod
[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.
### Tanstack Query
[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.
## Useful Resources
| Resource | Link |
| --------------------------------------------------------- | ----------------------------------------------------------------- |
| TypeScript Handbook | https://www.typescriptlang.org/docs/handbook/ |
| Beginners TypeScript Tutorial | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/en/why.md
================================================
---
title: Why CT3A?
description: Why you should pick Create T3 App for your next project
layout: ../../layouts/docs.astro
lang: en
---
We 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.
If 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 :)
## Why TypeScript?
JavaScript is hard. Why add more rules?
We 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.
Typesafety makes you faster. If you're not convinced, you [might be using TypeScript wrong...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## Why Next.js?
We 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 toward good decisions.
## Why tRPC/Prisma/Tailwind/etc?
While 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.
### tRPC
tRPC 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.
### Prisma
Prisma 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.
Prisma 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.
### Tailwind CSS
Tailwind feels like "zen-mode CSS".
By 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.
Additionally, 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.
### NextAuth.js
When 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.
================================================
FILE: www/src/pages/es/deployment/docker.md
================================================
---
title: Docker
description: Desplegando con Docker
layout: ../../../layouts/docs.astro
lang: es
---
Puedes 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.
## Configuración del proyecto Docker
Ten 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`:
- `DATABASE_URL` (utilizado por el servidor)
- `NEXT_PUBLIC_CLIENTVAR` (utilizado por el cliente)
### 1. Configuración de Next.js
En 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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Crear archivo dockerignore
Haz clic aquí e incluye el contenido en .dockerignore:
### 3. Crear archivo Docker
> 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.
Haz clic aquí e incluye el contenido en Dockerfile:
```docker
##### DEPENDENCIAS
FROM --platform=linux/amd64 node:16-alpine AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Instala el Prisma Client - quitar si no estás usando Prisma
COPY prisma ./
# Instala dependencias basadas en tu administrador de paquetes preferido
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### CONSTRUCTOR
FROM --platform=linux/amd64 node:16-alpine AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### LANZADOR
FROM --platform=linux/amd64 node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Notas_**
>
> - _La emulación de `--platform=linux/amd64` puede no ser necesaria tras moverse a Node 18._
> - _Puedes ver [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) para entender porqué `libc6-compat` puede ser necesario._
> - _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._
## Crea y ejecuta la imagen localmente
Crea y ejecuta esta imagen localmente con los siguientes comandos:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Abre [localhost:3000](http://localhost:3000/) para ver tu aplicación en ejecución.
## Docker Compose
También puedes usar Docker Compose para crear la imagen y ejecutar el contenedor.
Sigue los pasos 1-4 anteriores, haz clic aquí e incluye el contenido en docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Ejecuta esto usando el comando `docker compose up`:
```bash
docker compose up
```
Abre [localhost:3000](http://localhost:3000/) para ver tu aplicación en ejecución.
## Desplegar en Railway
Puedes 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:
```bash
railway login
railway init
railway link
railway up
railway open
```
Dirí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/).
## Otros recursos útiles
| Recurso | Link |
| ------------------------------------------------- | -------------------------------------------------------------------- |
| Referencia Docker | https://docs.docker.com/engine/reference/builder/ |
| Referencia archivo Compose version 3 | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Referencia Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ |
| Referencia Docker Compose CLI | https://docs.docker.com/compose/reference/ |
| Despligue Next.js utilizando una imagen de Docker | https://nextjs.org/docs/deployment#docker-image |
| Next.js en Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Ejemplo Next.js con Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Crear una imagen Docker de una aplicación Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/es/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Despliegue",
layout: "docs",
description: "Aprende a desplegar tu aplicación T3 a producción.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/es/deployment/netlify.md
================================================
---
title: Netlify
description: Desplegando en Netlify
layout: ../../../layouts/docs.astro
lang: es
---
Netlify 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.
## ¿Por qué desplegar en Netlify?
La 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.
Tambié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/).
Hay 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).
> _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)._
## Configuración del proyecto
Hay 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Usando el panel de control de Netlify
1. 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**.

2. Conecta tu proveedor de Git.

3. Selecciona el repositorio de tu proyecto.

4. Netlify detectará si tienes un archivo `netlify.toml` y configurará automáticamente tu comando de compilación y tu directorio de publicación.
5. Haz clic en **Show advanced** y luego en **New variable** para agregar tus variables de entorno.

6. Haz clic en **Deploy site** y espera a que se complete la compilación para ver tu nuevo sitio.
## Usando la CLI de Netlify
Para 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:
```bash
npm i -g netlify-cli
```
Para 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:
```bash
ntl dev
```
Corre el comando [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) para configurar tu proyecto:
```bash
ntl init
```
Importa las variables de entorno de tu proyecto desde tu archivo `.env` con [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Despliega 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:
```bash
ntl deploy --prod --build
```
Para ver un ejemplo en ejecución en Netlify, visita [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/es/deployment/vercel.md
================================================
---
title: Vercel
description: Desplegando en Vercel
layout: ../../../layouts/docs.astro
lang: es
---
Recomendamos 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.
## Configuración del proyecto
Es 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:
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Uso del panel de control de Vercel
1. 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**.

2. Importa el repositorio de GitHub con tu proyecto.

3. Agrega tus variables de entorno.

4. Haz clic en **Desplegar**. Ahora, cada vez que envíes un cambio a tu repositorio, ¡Vercel volverá a desplegar automáticamente tu aplicación!
## Uso de la CLI de Vercel
Para desplegar desde la línea de comandos, primero debes [instalar la CLI de Vercel globalmente](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
Ejecuta el comando [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) para desplegar tu proyecto.
```bash
vercel
```
Incluye `--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.
```bash
vercel --env DATABASE_URL=SU_URL_DE_BASE_DE_DATOS_AQUI --yes
```
Despué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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/es/faq.md
================================================
---
title: Preguntas Frecuentes
description: Preguntas frecuentes acerca de create T3 app
layout: ../../layouts/docs.astro
lang: es
---
Aquí hay algunas preguntas frecuentes sobre `create-t3-app`.
## ¿Qué sigue? ¿Cómo hago una aplicación con esto?
Tratamos 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.
Si 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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [TailwindCSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## ¿Qué recursos de aprendizaje están disponibles actualmente?
Aunque 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.
Si 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?
Ahora, 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 `:
### Artículos
- [Build a full stack app with create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)
- [A first look at create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
### Vídeos
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## ¿Por qué hay archivos `.js` en el proyecto?
De 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`.
Intentamos 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.
## Tengo problemas para agregar i18n a mi aplicación. ¿Hay alguna referencia que pueda usar?
Hemos decidido no incluir i18n por defecto en `create-t3-app` porque es un tema muy criticado y hay muchas formas de implementarlo.
Sin 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).
## ¿Por qué usamos `/pages` y no `/app` de Next.js 13?
Segú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.
Para 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).
================================================
FILE: www/src/pages/es/folder-structure-pages.mdx
================================================
---
title: Estructura de Carpetas (Pages)
description: Estructura de carpetas de una aplicación T3 recién creada
layout: ../../layouts/docs.astro
lang: es
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Por 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.
### `prisma`
La 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.
### `public`
La 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.
### `src/env`
Se utiliza para la validación de variables de entorno y definiciones de tipo; consulta [variables de entorno](usage/env-variables).
### `src/pages`
La 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.
#### `src/pages/api`
La 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/).
#### `src/pages/api/auth/[...nextauth].ts`
El 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_.
#### `src/pages/api/trpc/[trpc].ts`
El 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_.
### `src/server`
La carpeta `server` se usa para separar claramente el código del lado del servidor del código del lado del cliente.
#### `src/server/auth.ts`
La 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.
#### `src/server/db.ts`
El 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.
### `src/server/api`
La carpeta `api` contiene el código del lado del servidor de tRPC.
#### `src/server/api/routers`
La carpeta `routers` contiene todos tus sub-routers de tRPC.
#### `src/server/api/routers/example.ts`
El 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.
Dendiendo de tus paquetes elegidos este router contiene más o menos rutas para demostrar mejor el uso a tus necesidades.
#### `src/server/api/trpc.ts`
El archivo `trpc.ts` es el archivo de configuración principal de tu back-end tRPC. Aquí:
1. Define el contexto de tRPC. Consulta [uso de tRPC](usage/trpc#-serverapitrpcts) para obtener más información.
2. Exporta el router principal de tRPC. Consulta [uso de tRPC](usage/trpc#-serverapitrpcts) para obtener más información.
#### `src/server/api/root.ts`
El 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.
### `src/styles`
La carpeta `styles` contiene los estilos globales de la aplicación.
### `src/utils`
La carpeta `utils` se usa para almacenar funciones de utilidad comúnmente reutilizadas.
#### `src/utils/api.ts`
El 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.
### `.env`
El 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.
### `.env.example`
El archivo `.env.example` muestra las variables de entorno de ejemplo basadas en las bibliotecas elegidas. Este archivo debe ser enviado al historial de git.
### `.eslintrc.cjs`
El 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.
### `next-env.d.ts`
El 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.
### `next.config.mjs`
El 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.
### `postcss.config.js`
El 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.
### `prettier.config.mjs`
El 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.
### `tsconfig.json`
El 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.
================================================
FILE: www/src/pages/es/installation.mdx
================================================
---
title: Instalación
description: Instrucciones de instalación para Create T3 App
layout: ../../layouts/docs.astro
lang: es
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Para 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:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Después de que tu aplicación haya sido creada, consulta los [primeros pasos](/es/usage/first-steps) para comenzar con tu nueva aplicación.
## Uso avanzado
| Opción/Bandera | Descripción |
| ----------------- | ----------------------------------------------------------------------------------------- |
| `[dir]` | Incluye un argumento de directorio con un nombre para el proyecto |
| `--noGit` | Dile explícitamente a la CLI que no inicialice un nuevo repositorio de git en el proyecto |
| `-y`, `--default` | Omite la CLI y arranca una nueva aplicación t3 con todas las opciones seleccionadas |
| `--noInstall` | Generar proyecto sin instalar dependencias |
## Uso experimental
Para 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.
| Bandera | Descripción |
| ------------ | ------------------------------------- |
| `--CI` | Informar a la CLI que está en modo CI |
| `--trpc` | Incluir tRPC en el proyecto |
| `--prisma` | Incluir Prisma en el proyecto |
| `--nextAuth` | Incluir NextAuth.js en el proyecto |
| `--tailwind` | Incluir Tailwind CSS en el proyecto |
Si no proporcionas la bandera `CI`, el resto de estas banderas no tendrá efecto.
No 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`.
### Ejemplo
Lo siguiente sería una aplicación T3 con tRPC y Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/es/introduction.md
================================================
---
title: Introducción
description: Introducción al T3 Stack
layout: ../../layouts/docs.astro
lang: es
---
## El T3 Stack
El _"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.
Las piezas centrales son [**Next.js**](https://nextjs.org/) y [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) está casi siempre incluído.
Si 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.
Es 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 :)
## Entonces... ¿Qué es create-t3-app? ¿Una plantilla?
¿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.
Despué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.
Esta **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).
## Axiomas T3
Seremos francos: este es un _proyecto dogmático_. Compartimos muchas creencias fundamentales sobre la construcción y las tratamos como la base de nuestras decisiones.
### Resolver Problemas
Es 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.
### Responsablemente Vanguardista
Nos 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.
### La Seguridad de Tipos no es Opcional
El 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.
================================================
FILE: www/src/pages/es/other-recs.md
================================================
---
title: Otras Recomendaciones
description: Librerías y Servicios que nosotros recomendamos para todos los proyectos
layout: ../../layouts/docs.astro
lang: es
---
Reconocemos 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.
Estas 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**_.
## Administración de Estado
_**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.
### Zustand
**Para no volver a usar Redux nunca más**
El "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.
- [Página de inicio de Zustand](https://zustand-demo.pmnd.rs/)
- [GitHub de Zustand](https://github.com/pmndrs/zustand)
### Jotai
**Para nunca volver a usar Context**
Para 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.
- [Página de inicio de Jotai](https://jotai.org/)
- [GitHub de Jotai](https://github.com/pmndrs/jotai)
## Librerías de Componentes
La 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.
### Librerías de componentes sin estilo
También conocidas como librerías headless, proporcionan excelentes componentes sin estilo y accesibles que puedes personalizar a tu gusto. Aquí hay algunas recomendaciones.
- [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.
- [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.
- [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.
### Librerías de componentes con estilo
**Para cuando solo quieres que tu aplicación se vea bien**
A 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.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
### Class Variance Authority
**Para crear librerías de interfaz de usuario**
Crea 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.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Animaciones
Para cuando necesites animaciones en tu aplicación, aquí están nuestras recomendaciones.
### AutoAnimate
**Para animaciones con una sola línea de código**
La 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.
- [Página de inicio de AutoAnimate](https://auto-animate.formkit.com/)
- [GitHub de AutoAnimate](https://github.com/formkit/auto-animate)
- [Ejemplo de un Componente con AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Para animaciones complejas con código declarativo**
Framer Motion proporciona una sintaxis declarativa simple y te permite escribir menos código para crear todo, desde animaciones complejas hasta incluso gestos.
- [Página de inicio de Framer Motion](https://framer.com/motion)
- [Documentación de Framer Motion](https://www.framer.com/docs/)
## Despliegues, Infraestructura, Bases de Datos y CI
### Vercel
**Para alojar tu aplicación**
Vercel 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 :)
- [Página de inicio de Vercel](https://vercel.com/)
- [Guía Create T3 App para desplegar en Vercel](/es/deployment/vercel)
### PlanetScale
**Para bases de datos sin preocupaciones**
PlanetScale 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.
- [Página de inicio de PlanetScale](https://planetscale.com/)
### Railway
**Para alojar tu infraestructura**
"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.
- [Página de inicio de Railway](https://railway.app/)
### Upstash
**Para Redis sin servidor**
Nos 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.
- [Página de inicio de Upstash](https://upstash.com/)
### Pusher
**Para WebSockets sin servidor**
Si 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.
- [Página de inicio de Pusher](https://pusher.com/)
### Soketi
Soketi 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.
- [Página de inicio de Soketi](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Análisis de Datos
Los datos de los usuarios son muy valiosos cuando creas una aplicación. Aquí hay algunos proveedores de análisis que recomendamos.
### Plausible
¿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).
- [Página de inicio de Plausible](https://plausible.io/)
### Umami
Umami 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.
- [Página de inicio de Umami](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
## Otros
### Next Bundle Analyzer
A 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.
- [@next/bundle-analyzer en npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/es/t3-collection.mdx
================================================
---
title: Colección T3
description: Proyectos geniales open source y compañias utilizando el T3 Stack
layout: ../../layouts/docs.astro
lang: es
isMdx: true
---
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
¿Hiciste un proyecto usando el T3 Stack y quieres compartirlo? ¡Añádelo a la lista!
## Aplicaciones open source creadas con el T3 Stack
## Empresas que utilizan el T3 Stack
Nos 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!
_¿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í._
================================================
FILE: www/src/pages/es/usage/env-variables.md
================================================
---
title: Variables de Entorno
description: Empezando con create-t3-app
layout: ../../../layouts/docs.astro
lang: es
---
Create-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`:
📁 src/env
┣ 📄 client.mjs
┣ 📄 schema.mjs
┣ 📄 server.mjs
El 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.
_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`._
## schema.mjs
Este 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`.
```ts:env/schema.mjs
export const serverSchema = z.object({
// DATABASE_URL: z.string().url(),
});
export const clientSchema = z.object({
// NEXT_PUBLIC_WS_KEY: z.string(),
});
export const clientEnv = {
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
};
```
### Esquema del Servidor
Define tu esquema de variables de entorno del lado del servidor aquí.
Asegú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.
### Esquema del Cliente
Define tu esquema de variables de entorno del lado del cliente aquí.
Para 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.
### Objeto clientEnv
Destructuramos el `process.env` aquí.
Necesitamos 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.
TypeScript te ayudará a asegurarte de haber ingresado las claves tanto en `clientEnv` como en `clientSchema`.
```ts
// ❌ Esto no funciona, necesitamos destructurarlo manualmente
const schema = z.object({
NEXT_PUBLIC_WS_KEY: z.string(),
});
const validated = schema.parse(process.env);
```
## server.mjs & client.mjs
Aquí es donde ocurre la validación y se exporta los objetos validados. No deberías necesitar modificar estos archivos.
## Utilizando las Variables de Entorno
Cuando quieras utilizar tus variables de entorno, puedes importarlas desde `env/client.mjs` o `env/server.mjs` dependiendo de dónde quieras utilizarlas:
```ts:pages/api/hello.ts
import { env } from "../../env/server.mjs";
// `env` es completamente seguro en tipos y provee autocompletado
const dbUrl = env.DATABASE_URL;
```
## .env.example
Dado 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.
## Agregando Variables de Entorno
Para 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:
📄 `.env`: Introduce tu variable de entorno como lo harías normalmente en un archivo `.env`, es decir, `LLAVE=VALOR`
📄 `schema.mjs`: agrega la lógica de validación adecuada para la variable de entorno definiendo un esquema Zod, p. `CLAVE: z.string()`
Opcionalmente, también puedes mantener `.env.example` actualizado:
📄 `.env.example`: ingresa tu variable de entorno, pero asegúrate de no incluir el valor si es secreto, es decir, `KEY=VALUE` o `KEY=`
### Ejemplo
_Quiero agregar mi API token de Twitter como una variable de entorno del lado del servidor_
1. Agrega la variable de entorno a `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Agrega la variable de entorno a `schema.mjs`:
```ts
export const serverSchema = z.object({
// ...
TWITTER_API_TOKEN: z.string(),
});
```
3. Opcional: agrega la variable de entorno a `.env.example`, pero no incluyas el token
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/es/usage/first-steps.md
================================================
---
title: Primeros Pasos
description: Empezando con tu nueva aplicación T3
layout: ../../../layouts/docs.astro
lang: es
---
Acabas de crear una nueva aplicación T3 y estás listo para comenzar. Aquí está lo mínimo para que tu aplicación funcione.
## Base de datos
Si 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.
## Autenticación
Si 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.
Por 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.
1. Necesitarás una cuenta de Discord, así que crea una cuenta si aún no lo has hecho.
2. 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.
3. Una vez creada tu aplicación, dirígite a "Settings → OAuth2 → General".
4. Copia el "Client ID" y agrégalo a tu `.env` como `AUTH_DISCORD_ID`.
5. Haz clic en "Reset Secret", copia el nuevo valor secreto y agrégalo a tu `.env` como `AUTH_DISCORD_SECRET`.
6. Haz clic en "Add Redirect" y escribe `http://localhost:3000/api/auth/callback/discord`.
- 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.
7. Guarda los cambios.
Ahora deberías poder iniciar sesión.
## Siguientes pasos
- 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.
- Echa un vistazo a la documentación de `create-t3-app`, así como la documentación de los paquetes que incluye tu aplicación.
- ¡Únete a nuestro [Discord](https://t3.gg/discord) y danos una estrella en [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/es/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Uso",
layout: "docs",
description: "Aprende a utilizar las diferentes tecnologías del stack T3.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/es/usage/next-auth.md
================================================
---
title: NextAuth.js
description: Uso de NextAuth.js
layout: ../../../layouts/docs.astro
lang: es
---
Cuando 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.
## Proveedor de contexto
En 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):
```tsx:pages/_app.tsx
```
Este 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:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Manejar el estado no autenticado, ejemplo: renderizar un componente SignIn
return ;
}
return
Bienvenido {session.user.name}!
;
};
```
## Incluir `user.id` en la Sesió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`.
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Esto 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.
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
El 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.
## Uso con tRPC
Cuando 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.
Esto se hace en un proceso de dos pasos:
1. 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.
```ts:server/common/get-server-auth-session.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await unstable_getServerSession(ctx.req, ctx.res, nextAuthOptions);
};
```
Usando esta función auxiliar, podemos obtener la sesión y pasarla al contexto de tRPC:
```ts:server/trpc/context.ts
import { getServerAuthSession } from "../common/get-server-auth-session";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/trpc/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
})
```
El 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.
```ts:server/trpc/router/user.ts
const userRouter = router({
me: protectedProcedure.query(({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Uso con Prisma
Hacer 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.
### Agregar nuevos campos a tus modelos
Al 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.
Si, 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`:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Uso con el middleware Next.js
El 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.
## Configuración del DiscordProvider predeterminado
1. 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"
2. En el menú de configuración, dirígite a "OAuth2 => General"
- Copia el Client ID y pégalo en `AUTH_DISCORD_ID` en `.env`.
- 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.
- Haz clic en "Add Redirect" y pega en `/api/auth/callback/discord` (Ejemplo para desarrollo local: http://localhost:3000/api/auth/callback/discord)
- Guarda tus cambios
- 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.
## Recursos útiles
| Recurso | Enlace |
| --------------------------------- | --------------------------------------- |
| Documentación de NextAuth.js | https://next-auth.js.org/ |
| GitHub de NextAuth.js | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/es/usage/next-js.md
================================================
---
title: Next.js
description: Uso de Next.js
layout: ../../../layouts/docs.astro
lang: es
---
Next.js es un framework de backend para tus aplicaciones de React.
É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.
## ¿Por qué debería usarlo?
Amamos 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.
Utilizar 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)
## Get Static/Server Props
Una 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.
## Recursos útiles
| Recurso | Enlace |
| ---------------------------------- | ---------------------------------- |
| Documentación de Next.js | https://nextjs.org/docs |
| GitHub de Next.js | https://github.com/vercel/next.js |
| Blog de Next.js | https://nextjs.org/blog |
| Discord de Next.js | https://nextjs.org/discord |
| Twitter de Next.js | https://twitter.com/nextjs |
| Canal de Youtube de Vercel/Next.js | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/es/usage/prisma.md
================================================
---
title: Prisma
description: Uso de Prisma
layout: ../../../layouts/docs.astro
lang: es
---
Prisma 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.
## Prisma Client
Ubicado 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.
## Esquema
Encontrará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.
### Con NextAuth.js
Cuando 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).
## Base de datos predeterminada
La 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.
## Llenando (seeding) tu base de datos
[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.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db/client";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Luego, simplemente ejecuta `pnpm db-seed` (o `npm`/`yarn`) para llenar (_seed_) tu base de datos.
## Recursos útiles
| Recurso | Enlace |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Documentación de Prisma | https://www.prisma.io/docs/ |
| GitHub de Prisma | https://github.com/prisma/prisma |
| Adaptador Prisma para NextAuth.JS | https://next-auth.js.org/adapters/prisma |
| 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 |
================================================
FILE: www/src/pages/es/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Uso de Tailwind CSS
layout: ../../../layouts/docs.astro
lang: es
---
## ¿Qué es Tailwind CSS?
Tailwind 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.
Hace que CSS sea increíblemente fácil y rápido de escribir, como se muestra en el siguiente ejemplo:
Viejo CSS:
1. Escribir CSS, generalmente en un archivo separado
```css
.mi-clase {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Importar el CSS en tu componente
```jsx
import "./mi-clase.css";
```
3. Agrega la clase a tu HTML
```html
...
```
Equivalente en Tailwind:
1. Simplemente escribe clases en tu HTML
```html
...
```
Cuando se usa junto con los componentes de React, es extremadamente potente para construir UIs (_interfaces de usuario_) rápidamente.
Tailwind 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.
Tru 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).
## Uso
Asegúrate de tener complementos de editor para Tailwind CSS instalados para mejorar tu experiencia escribiendo Tailwind.
### Extensiones y complementos
- [Extensión VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [Integración de JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formateo
Las 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.
### Aplicando clases condicionalmente
Agregar 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.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Recursos útiles
| Recurso | Enlace |
| -------------------------------- | -------------------------------------------------------- |
| Documentación de Tailwind | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Comunidad de Tailwind | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Servidor Discord de Tailwind | https://tailwindcss.com/discord/ |
| Canal de Youtube de TailwindLabs | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/es/usage/trpc.md
================================================
---
title: tRPC
description: Uso de tRPC
layout: ../../../layouts/docs.astro
lang: es
---
tRPC 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.
"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."
## Archivos
tRPC requiere una gran cantidad de archivos que `create-t3-app` genera para ti. Revisemos los archivos que se generan:
### 📄 `pages/api/trpc/[trpc].ts`
Este 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.
### 📄 `server/trpc/context.ts`
Este 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.
- `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.
- `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.
### 📄 `server/trpc/trpc.ts`
Aquí 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.
Notará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.
### 📄 `server/trpc/router/*.ts`
Aquí 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`.
### 📄 `utils/trpc.ts`
Este 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.
Definirá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.
Por ú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.
## ¿Cómo uso tRPC?
El 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.
Con tRPC, escribes funciones TypeScript en tu backend y luego las llamas desde tu frontend. Un simple procedimiento de tRPC podría verse así:
```ts:server/trpc/router/user.ts
const userRouter = t.router({
getById: t.procedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Este 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.
Despué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.
Tu 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:
```ts:server/trpc/router/_app.ts
const appRouter = t.router({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Ten 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.
Ahora 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:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
const UserPage = () => {
const { query } = useRouter();
const userQuery = trpc.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Inmediatamente 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.
## ¿Cómo llamo a mi API externamente?
Con 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:
### Exponer un solo procedimiento externamente
Si 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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Exponer cada procedimiento como endpoints REST
Si 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.
### Son solo solicitudes HTTP
tRPC 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.
## Comparación con un API endpoint de Next.js
Comparemos 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:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db/client";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Compara esto con el ejemplo de tRPC anterior, para poder ver algunas de las ventajas de tRPC:
- 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.
- No necesitas validar qué método HTTP se utilizó.
- No necesitas validar que la consulta de solicitud o el cuerpo contenga los datos correctos en el procedimiento, porque Zod se encarga de esto.
- 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.
- Llamar al procedimiento en el frontend proporciona autocompletado y seguridad de tipos.
## Fragmentos útiles
Aquí hay algunos fragmentos que pueden ser útiles.
### Habilitando CORS
Si 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:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/trpc/router/_app";
import { createContext } from "~/server/trpc/context";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Habilita cors
await cors(req, res);
// Crea y llama al manejador tRPC
return createNextApiHandler({
router: appRouter,
createContext,
})(req, res);
};
export default handler;
```
### Actualizaciones optimistas
Las 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).
```tsx
const MyComponent = () => {
const listPostQuery = trpc.post.list.useQuery();
const utils = trpc.useContext();
const postCreate = trpc.post.create.useMutation({
async onMutate(newPost) {
// Cancela las solicitudes de salida (para que no sobrescriban nuestras actualizaciones optimistas)
await utils.post.list.cancel();
// Obtener los datos del queryCache
const prevData = utils.post.list.getData();
// Optimisticamente actualizamos los datos con nuestro nuevo post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Retornamos los datos previos para que podamos revertirlo si algo sale mal
return { prevData };
},
onError(err, newPost, ctx) {
// Si la mutación falla, utilizar el valor del contexto de onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sincronizamos el servidor una vez la mutación se haya completado
utils.post.list.invalidate();
},
});
};
```
### Prueba de integración de muestra
Aquí 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/router/_app";
import { createContextInner } from "~/server/router/context";
test("example router", async () => {
const ctx = await createContextInner({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
## Recursos útiles
| Recurso | Enlace |
| ----------------------------- | ------------------------------------------------------- |
| Documentación de tRPC | https://www.trpc.io |
| Un montón de ejemplos de tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Documentación de React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/es/usage/typescript.md
================================================
---
title: TypeScript
description: Uso de TypeScript
layout: ../../../layouts/docs.astro
lang: es
---
Ya 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.
Proporciona 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.
Es, 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.
## Inferencia de Tipos
Si 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.
Echa un vistazo al video de Theo sobre cómo [podrías estar usando TypeScript de manera incorrecta](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Usos poderosos de inferencia de tipos
### Zod
[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.
### Tanstack Query
[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.
## Recursos útiles
| Recurso | Enlace |
| ------------------------------------------------------------- | ----------------------------------------------------------------- |
| Manual de TypeScript | https://www.typescriptlang.org/docs/handbook/ |
| Tutorial de TypeScript para principiantes | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Canal de Youtube de Rodney Mullen de TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/es/why.md
================================================
---
title: ¿Por qué CT3A?
description: ¿Por qué deberías elegir Create T3 App para tu siguiente proyecto?
layout: ../../layouts/docs.astro
lang: es
---
Empezamos 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.
Si 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 :)
## ¿Por qué TypeScript?
JavaScript es difícil. ¿Por qué agregar más reglas?
Creemos 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.
La 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)
## ¿Por qué Next.js?
Nos 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.
Next.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.
## ¿Por qué tRPC/Prisma/Tailwind/etc?
Si 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.
### tRPC
tRPC 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.
### Prisma
Prisma 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.
Prisma 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.
### Tailwind CSS
Tailwind se siente como "CSS en modo zen".
Al 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.
Ademá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.
### NextAuth.js
Cuando 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.
================================================
FILE: www/src/pages/fr/deployment/docker.md
================================================
---
title: Docker
description: Déploiement avec Docker
layout: ../../../layouts/docs.astro
lang: fr
---
Vous 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.
## Configuration du projet sous Docker
Veuillez 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.
- `DATABASE_URL` (utiliser par le serveur)
- `NEXT_PUBLIC_CLIENTVAR` (utiliser par le client)
### 1. Configuration de Next
Dans 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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Créer un fichier dockerignore
Cliquez ici et incluez le contenue dans votre .dockerignore:
### 3. Créer un fichier Dockerfile
> É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à.
Cliquez ici et incluez le contenue dans votre Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Notes_**
>
> - _L'émulation de `--platform=linux/amd64` n'est pas nécessaire à partir de Node 18._
> - _Voir [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) pour comprendre pourquoi `libc6-compat` pourrait être nécessaire._
> - _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._
## Génération et exécution de l'image localement
Générer et exécuter l'image localement avec les commandes suivantes:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Ouvrez [localhost:3000](http://localhost:3000/) pour voir votre application s'exécuter.
## Docker Compose
Vous pouvez également utiliser Docker Compose pour générer l'image et exécuter le conteneur.
Suivez les étapes 1 à 4 ci-dessus, cliquez ici et incluez le contenue dans votre docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Exécutez ceci à l'aide de la commande `docker compose up` :
```bash
docker compose up
```
Ouvrez [localhost:3000](http://localhost:3000/) pour voir votre application en cours d'exécution.
## Déployer sur Railway
Vous 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:
```bash
railway login
railway init
railway link
railway up
railway open
```
Allez 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/).
## Ressources utiles
| Ressources | Liens |
| ------------------------------------------------ | -------------------------------------------------------------------- |
| Dockerfile référence | https://docs.docker.com/engine/reference/builder/ |
| Compose file version 3 référence | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Docker CLI référence | https://docs.docker.com/engine/reference/commandline/docker/ |
| Docker Compose CLI référence | https://docs.docker.com/compose/reference/ |
| Next.js déploiement avec une image Docker | https://nextjs.org/docs/deployment#docker-image |
| Next.js dans Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Next.js exemple avec Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Créer une image Docker d'une application Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/fr/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Déploiement",
layout: "docs",
description: "Apprenez comment déployer votre app T3 en production.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/fr/deployment/netlify.mdx
================================================
---
title: Netlify
description: Déploiement sur Netlify
layout: ../../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Netlify 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.
## Pourquoi héberger sur Netlify
La 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.
Il 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/).
Il 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).
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).
## Configurer le projet
Il 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Utilisation du tableau de bord Netlify
1. 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**.

2. Connectez votre fournisseur de dépôt.

3. Sélectionnez le dépôt de votre projet.

4. Netlify détectera si vous avez un fichier `netlify.toml` et configurera automatiquement votre commande de build et votre répertoire de publication.

5. Cliquez sur **Afficher les paramètres avancés**, puis sur **Nouvelle variable** pour ajouter vos variables d'environnement.

1. Cliquez sur **Déployer le site**, attendez la fin de la compilation, puis, affichez votre nouveau site.
## Utilisation de la CLI Netlify
Pour 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 :
```bash
npm i -g netlify-cli
```
Pour 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 :
```bash
ntl dev
```
Exécutez la commande [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) pour configurer votre projet :
```bash
ntl init
```
Importez les variables d'environnement de votre projet à partir de votre fichier `.env` avec [`ntl env:import`](https://cli.netlify.com/commands/env#envimport) :
```bash
ntl env:import .env
```
Dé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 :
```bash
ntl deploy --prod --build
```
Pour afficher un exemple d'exécution sur Netlify, visitez [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/fr/deployment/vercel.md
================================================
---
title: Vercel
description: Déploiement sur Vercel
layout: ../../../layouts/docs.astro
lang: fr
---
Nous 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.
## Configuration du projet
Vercel 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.**
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Utilisation du tableau de bord Vercel
1. 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**.

2. Importez votre projet GitHub.

3. Ajoutez vos variables d'environnement.

4. Cliquez sur **Deploy**. À partir de maintenant, à chaque fois que vous pousserez une modification, Vercel redéploiera automatiquement votre application !
## Utilisation de Vercel CLI
Pour 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).
```bash
npm i -g vercel
```
Exécutez la commande [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) pour déployer votre projet.
```bash
vercel
```
Ajoutez 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.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
Aprè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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/fr/examples.mdx
================================================
---
title: Exemples
description: Exemples d'application actives
layout: ../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
import Form from "../../components/docs/exampleOptionForm.astro";
Vous pouvez essayer plusieurs combinaisons de technologies que create-t3-app offre.
Vous ne pouvez pas sélectionner `prisma` et `drizzle` simultanément.
Certaines fonctionnalités peuvent ne pas fonctionner à moins que vous créer un
fichier d'environnement
================================================
FILE: www/src/pages/fr/faq.mdx
================================================
---
title: FAQ
description: Foire aux questions sur Create T3 App
layout: ../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Voici quelques questions fréquemment posées sur Create T3 App.
## Et après? Comment faire une application avec ça ?
Nous 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.
Si 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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## Quelles ressources d'apprentissage sont actuellement disponibles?
Bien 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.
Si 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 ?
Maintenant, 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 :
### Articles
- [Créez une application complète avec Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)
- [Un premier aperçu de Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrer votre application T3 vers un Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Intégrer Stripe dans votre application T3](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Vidéos
- [Créez un clone Twitter avec la stack T3 - tRPC, Next.js, Prisma, Tailwind et Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Créez un blog avec la stack T3 - tRPC, TypeScript, Next.js, Prisma et Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Créer une application de chat en direct avec la stack T3 - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [La stack T3 - Comment nous l'avons créez](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [Un aperçu de Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Pourquoi y a-t-il des fichiers `.js` dans le projet ?
Conformé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`.
Nous 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.
## J'ai du mal à ajouter i18n à mon application. Y a-t-il une référence que je peux utiliser?
Nous 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.
Cependant, 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).
## Pourquoi utilisons-nous `/pages` et non `/app` de Next.js 13 ?
Selon [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.
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).
================================================
FILE: www/src/pages/fr/folder-structure-pages.mdx
================================================
---
title: Structure des dossiers (Pages)
description: Structure des dossiers d'une application T3 nouvellement créée
layout: ../../layouts/docs.astro
lang: fr
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Veuillez 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.
### `prisma`
Le 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.
### `public`
Le dossier "public" contient des fichiers statiques qui sont servis par le serveur Web. Le fichier `favicon.ico` en est un exemple.
### `src/env`
Utilisé pour la validation des variables d'environnement et les définitions de types - voir [Variables d'environnement](usage/env-variables).
### `src/pages`
Le 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.
#### `src/pages/api`
Le 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/).
#### `src/pages/api/auth/[...nextauth].ts`
Le 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.
#### `src/pages/api/trpc/[trpc].ts`
Le 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.
### `src/server`
Le dossier `server` est utilisé pour séparer clairement le code côté serveur du code côté client.
### `src/server/auth.ts`
Contient 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.
#### `src/server/db.ts`
Le 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.
### `src/server/api`
Le dossier `api` contient le code côté serveur de tRPC.
#### `src/server/api/routers`
Le dossier `routers` contient tous vos sous-routeurs tRPC.
#### `src/server/api/routers/example.ts`
Le fichier `example.ts` est un exemple de routeur tRPC utilisant le helper `publicProcedure` pour montrer comment créer une route tRPC publique.
En fonction des packages choisis, ce routeur contient plus ou moins de routes pour démontrer au mieux l'utilisation à vos besoins.
#### `src/server/api/trpc.ts`
Le fichier `trpc.ts` est le fichier de configuration principal de votre back-end tRPC. Ici, vous trouverez:
1. La définissons du contexte utilisé dans les requêtes tRPC. Voir [utilisation de tRPC](usage/trpc#-serverapitrpcts) pour plus d'informations.
2. Le helper de procédure d'exportation. Voir [utilisation de tRPC](usage/trpc#-serverapitrpcts) pour plus d'informations.
#### `src/server/api/root.ts`
Le 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.
### `src/styles`
Le dossier `styles` contient les styles globaux de l'application.
### `src/types`
Le dossier `types` est utilisé pour stocker les types réutilisés ou les déclarations de type.
#### `src/types/next-auth.d.ts`
Le 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.
### `src/utils`
Le dossier `utils` est utilisé pour stocker les fonctions utilitaires couramment réutilisées.
#### `src/utils/api.ts`
Le fichier `api.ts` est le point d'entrée frontal de tRPC. Voir [utilisation de tRPC](usage/trpc#-utilsapits) pour plus d'informations.
### `.env`
Le 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.
### `.env.example`
Le 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.
### `.eslintrc.cjs`
Le 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.
### `next-env.d.ts`
Le 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.
### `next.config.mjs`
Le 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.
### `postcss.config.js`
Le 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.
### `prettier.config.mjs`
Le 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.
### `tsconfig.json`
Le 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.
================================================
FILE: www/src/pages/fr/installation.mdx
================================================
---
title: Installation
description: Instructions d'installation pour Create T3 App
layout: ../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Pour 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 :
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Une fois votre application configurée, consultez les [premières étapes](/fr/usage/first-steps) pour démarrer sur votre nouvelle application.
## Utilisation avancée
| Option | Description |
| ----------------- | ----------------------------------------------------------------------------------------------- |
| `[dir]` | Inclure un argument de répertoire avec un nom pour le projet |
| `--noGit` | Dites explicitement à la CLI de ne pas initialiser un nouveau dépôt git dans le projet |
| `-y`, `--default` | Contourner la CLI et démarrer une nouvelle application t3 avec toutes les options sélectionnées |
| `--noInstall` | Générer un projet sans installer de dépendances |
## Utilisation expérimentale
Pour 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.
| Flag | Description |
| ------------ | ----------------------------------------------- |
| `--CI` | Faites savoir à la CLI que vous êtes en mode CI |
| `--trpc` | Inclure tRPC dans le projet |
| `--prisma` | Inclure Prisma dans le projet |
| `--nextAuth` | Inclure NextAuth.js dans le projet |
| `--tailwind` | Inclure Tailwind CSS dans le projet |
Si vous ne fournissez pas l'option "CI", le reste de ces options n'a aucun
effet.
Vous n'avez pas besoin de vous désinscrire explicitement des packages que vous ne
voulez pas.Cependant, si vous préférez être explicite, vous pouvez passer `false`,
par exemple `--nextAuth false`.
### Exemple
Ce qui suit configurera une application T3 avec tRPC et Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/fr/introduction.md
================================================
---
title: Introduction
description: Introduction à la stack T3
layout: ../../layouts/docs.astro
lang: fr
---
## La stack T3
La _"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.
Les é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.
Vous 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 :)
## Alors... qu'est-ce que create-t3-app ? Un modèle?
`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.
Aprè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.
Ce 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).
## T3 Axioms
Nous 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.
### Résoudre des problèmes
Il 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.
### Être responsable
Nous 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.
### La sécurité de typage n'est pas facultative
L'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.
================================================
FILE: www/src/pages/fr/other-recs.md
================================================
---
title: Autres recommandations
description: Librairies et services que nous recommandons pour de nombreux projets
layout: ../../layouts/docs.astro
lang: fr
---
Nous 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.
Ce 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**_.
## State Management
_**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.
### Zustand
**Pour ne plus jamais utiliser Redux**
Le "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.
- [Page d'accueil Zustand](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
### Jotai
**Pour ne plus jamais utiliser Context**
Pour 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.
- [Page d'accueil Jotai](https://jotai.org/)
- [Jotai GitHub](https://github.com/pmndrs/jotai)
## Librairies de composants
La 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.
### Librairies de composants sans style
Aussi 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.
- [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.
- [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.
- [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.
### Librairies de composants stylisés
**Pour quand vous voulez juste que votre application ait l'air OK**
Parfois, 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.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
### Class Variance Authority
**Pour créer des librairies d'interface utilisateur**
Cré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.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Animations
Lorsque vous avez besoin d'animations dans votre application, voici nos recommandations.
### AutoAnimate
**Pour les animations avec une seule ligne de code**
La 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.
- [Page d'accueil AutoAnimate](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [Extrait de composant AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Pour les animations complexes avec du code déclaratif**
Framer 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.
- [Page d'accueil Framer Motion](https://framer.com/motion)
- [Documentation Framer Motion](https://www.framer.com/docs/)
## Déploiements, Infrastructure, Bases de données et CI
### Vercel
**Pour héberger votre application**
Vercel 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 :)
- [Page d'accueil Vercel](https://vercel.com/)
- [Guide de déploiement de Create T3 App sur Vercel](/fr/deployment/vercel)
### PlanetScale
**Pour des bases de données sans souci**
PlanetScale 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.
- [Page d'accueil PlanetScale](https://planetscale.com/)
### Railway
**Pour héberger votre infrastructure**
"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.
- [Page d'accueil Railway](https://railway.app/)
### Upstash
**Pour du Redis serverless**
Nous 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.
- [Page d'accueil Upstash](https://upstash.com/)
### Pusher
**Pour les WebSockets serverless**
Si 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.
- [Page d'accueil Pusher](https://pusher.com/)
### Soketi
Soketi 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.
- [Page d'accueil Soketi](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Analytics
Les données utilisateur sont très précieuses lorsque vous créez une application. Voici quelques fournisseurs d'analyse que nous recommandons.
### Plausible
Besoin 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).
- [Page d'accueil Plausible](https://plausible.io/)
### Umami
Umami 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.
- [Page d'accueil Umami](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
## Autre
### Next Bundle Analyzer
Il 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.
- [@next/bundle-analyzer sur npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/fr/t3-collection.mdx
================================================
---
title: Collection T3
description: Projets open source sympas et d'entreprises utilisant la stack T3
layout: ../../layouts/docs.astro
lang: fr
isMdx: true
---
Vous avez réalisé un projet à l'aide de la stack T3 et souhaitez le partager ? Ajoutez-le à la liste !
## Applications Open Source créées à l'aide de la stack T3
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
import Callout from "../../components/docs/callout.tsx";
## Entreprises utilisant la stack T3
Nous 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 !
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 !
================================================
FILE: www/src/pages/fr/usage/env-variables.mdx
================================================
---
title: Variables d'environnement
description: Débuter avec Create T3 App
layout: ../../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Create 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`.
## env.js
_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`._
```ts:env.js
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
},
});
```
T3 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.
Pour plus d'informations sur le fonctionnement interne de `createEnv`,
consultez la documentation de [T3 Env](https://env.t3.gg/docs/introduction).
## Utilisation de variables d'environnement
Lorsque 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.
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` is fully typesafe and provides autocompletion
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ This will throw a runtime error
const dbUrl = env.DATABASE_URL;
// ✅ This is fine
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Puisque 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.
Certains 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.
## Ajout des variables d’environnement
Pour 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:
📄 `.env`: Entrez votre variable d'environnement comme vous le feriez normalement dans un fichier `.env`, c'est-à-dire `CLEF=VALEUR`
📄 `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`
Pourquoi ai-je besoin de déstructurer la variable d'environnement dans
`runtimeEnv` ? Cela est dû à la façon dont Next.js rassemble les variables
d'environnement dans certains contextes d'exécution. En les déstructurant
manuellement, vous vous assurez que la variable ne sera jamais supprimée du
bundle.
En option, vous pouvez également maintenir à jour le fichier `.env.example`:
📄 `.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=`
### Exemple
_Je veux ajouter le jeton de l’API Twitter en tant que variable d’environnement côté serveur_
1. Ajouter la variable d'environnement dans `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Ajouter la variable d'environnement dans `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.string(),
},
// ...
runtimeEnv: {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
},
});
```
3. facultatif : ajoutez la variable d'environnement à `.env.example`, mais n'incluez pas le jeton
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/fr/usage/first-steps.md
================================================
---
title: Premiers pas
description: Premiers pas avec votre nouvelle application T3
layout: ../../../layouts/docs.astro
lang: fr
---
Vous 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.
## Base de données
Si votre application inclut Prisma, assurez vous de lancer la commande `npx prisma db push` depuis la racine de votre application
Cette 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.
## Authentification
Si 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.
Bien 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.
1. Vous aurez besoin d'un compte Discord, créez-en un si vous ne l'avez pas déjà fait.
2. 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.
3. Une fois votre application créée, accédez à "Settings → OAuth2 → General".
4. Copiez le "Client ID" et ajoutez-le à votre `.env` en tant que `AUTH_DISCORD_ID`.
5. Cliquez sur "Reset Secret", copiez le nouveau secret et ajoutez-le à votre `.env` en tant que `DISCORD CLIENT_SECRET`.
6. Cliquez sur "Add Redirect" et saisissez `http://localhost:3000/api/auth/callback/discord`.
- 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.
7. Sauvegarder les modifications.
Vous devriez maintenant pouvoir vous connecter.
## Prochaines étapes
- 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.
- Consultez la documentation Create T3 App, ainsi que la documentation des packages inclus dans votre application.
- Rejoignez notre [Discord](https://t3.gg/discord) et donnez-nous une étoile sur [GitHub](https://github.com/t3-oss/create-t3-app) ! :)
================================================
FILE: www/src/pages/fr/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Utilisation",
layout: "docs",
description:
"Apprenez comment utiliser les différentes technologies de la stack T3.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/fr/usage/next-auth.mdx
================================================
---
title: NextAuth.js
description: Utilisation de NextAuth.js
layout: ../../../layouts/docs.astro
lang: fr
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Lorsque 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.
## Context Provider
Dans 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) :
```tsx:pages/_app.tsx
```
Ce 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 :
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Récupérer la session côté serveur
Parfois, 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` :
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTE: `session` wont have a loading state since it's already prefetched on the server
...
}
```
## Inclusion de `user.id` dans la Session
Create 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".
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Ceci 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.
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
Le 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.
## Utilisation avec tRPC
Lorsque 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.
Cela se fait en deux étapes :
1. 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.
```ts:server/auth.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, nextAuthOptions);
};
```
En utilisant cette fonction d'assistance, nous pouvons récupérer la session et la transmettre au contexte tRPC :
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
})
```
L'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.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Utilisation avec Prisma
Faire 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.
### Ajout de nouveaux champs à vos modèles
Lors 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.
Si, 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` :
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Utilisation avec le middleware Next.js
Utilisation 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.
L'utilisation de sessions en base de données est l'approche recommandée et
vous devriez vous informer sur les JWT (JSON Web Token) avant de passer à la
stratégie de session JWT, et ce, afin d'éviter tout problème de sécurité.
Aprè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`.
Ex.:
```diff:server/auth.ts
export const authOptions: NextAuthOptions = {
+ session: {
+ strategy: "jwt",
+ },
callbacks: {
- session({ session, user }) {
+ session({ session, token }) {
- if (session.user) {
+ if (session.user && token.sub) {
- session.user.id = user.id;
+ session.user.id = token.sub;
}
return session;
}
},
};
```
## Configuration du DiscordProvider par défaut
1. Rendez-vous dans [la section Applications du portail des développeurs Discord](https://discord.com/developers/applications), et cliquez sur "New Application"
1. Dans le menu des paramètres, allez dans "OAuth2 => General"
- Copiez l'ID client et collez-le dans `AUTH_DISCORD_ID` dans `.env`.
- 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.
- Cliquez sur "Add Redirect" et collez `/api/auth/callback/discord` (exemple pour le développement local : http://localhost:3000/api/auth/rappel/discord)
- Enregistrez vos modifications
- 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.
## Ressources utiles
| Ressource | Lien |
| --------------------------------- | --------------------------------------- |
| Documentation NextAuth.js | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/fr/usage/next-js.md
================================================
---
title: Next.js
description: Utilisation de Next.js
layout: ../../../layouts/docs.astro
lang: fr
---
Next.js est un framework backend pour vos applications React.
Dé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.
## Pourquoi devrais-je l'utiliser ?
Nous 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.
L'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)
## Get Static/Server Props
Une 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.
## Ressources utiles
| Ressource | Lien |
| ------------------------------ | ---------------------------------- |
| Next.js Documentation | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Next.js Blog | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/fr/usage/prisma.md
================================================
---
title: Prisma
description: Utilisation de Prisma
layout: ../../../layouts/docs.astro
lang: fr
---
Prisma 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.
## Prisma Client
Situé 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.
## Schéma
Vous 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.
### Avec NextAuth.js
Lorsque 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).
## Base de données par défaut
La 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.
## Amorçage de votre base de données
[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.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Ensuite, exécutez simplement `pnpm db-seed` (ou `npm`/`yarn`) pour amorcer votre base de données.
## Ressources utiles
| Ressource | Lien |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Documentation Prisma | https://www.prisma.io/docs/ |
| Prisma GitHub | https://github.com/prisma/prisma |
| Adaptateur Prisma pour NextAuth.JS | https://next-auth.js.org/adapters/prisma |
| Guide de connexion à PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/fr/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Utilisation de Tailwind CSS
layout: ../../../layouts/docs.astro
lang: fr
---
## Qu'est-ce que Tailwind CSS ?
Tailwind 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.
Cela rend le CSS incroyablement facile et rapide à écrire, comme le montre l'exemple suivant :
Ancien CSS :
1. Écrire du CSS, souvent dans un fichier séparé
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Importer le CSS dans votre composant
```jsx
import "./my-class.css";
```
3. Ajouter la classe à votre code HTML
```jsx
...
```
Équivalent dans Tailwind :
1. Écrivez simplement des classes dans votre HTML
```jsx
...
```
Lorsqu'elle est utilisé avec des composantes React, cela permet de créer des interfaces utilisateur de façon extrêmement puissant et rapidement.
Tailwind 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.
Tru 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).
## Utilisation
Assurez-vous d'avoir installé des plugins pour Tailwind dans votre éditeur de code afin d'améliorer votre expérience d'écriture avec Tailwind.
### Extensions et plugins
- [Extension VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [Integration avec JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formatage
Les 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.
### Appliquez les classes de façon conditionnelle
L'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.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Ressources utiles
| Ressource | Lien |
| ------------------------------- | -------------------------------------------------------- |
| Documentation Tailwind | https://tailwindcss.com/docs/editor-setup/ |
| Feuille de triche pour Tailwind | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Communauté Tailwind | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Tailwind Discord Server | https://tailwindcss.com/discord/ |
| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/fr/usage/trpc.md
================================================
---
title: tRPC
description: utilisation de tRPC
layout: ../../../layouts/docs.astro
lang: fr
---
tRPC 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.
"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."
Le 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.
Avec tRPC, vous écrivez des fonctions TypeScript sur votre backend, puis vous les appelez depuis votre frontend. Une procédure tRPC simple pourrait ressembler à ceci :
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Il 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.
Aprè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.
Vous 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é :
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Notez 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.
Maintenant 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 :
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Vous 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.
## Fichiers
tRPC nécessite beaucoup de configuration que `create-t3-app` fait pour vous. Passons en revue les fichiers générés :
### 📄 `pages/api/trpc/[trpc].ts`
Il 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.
### 📄 `server/api/trpc.ts`
Ce fichier est divisé en deux parties, la création du contexte et l'initialisation de tRPC :
1. 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.
- `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 .
- `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.
1. 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.
Vous 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.
### 📄 `server/api/routers/*.ts`
C'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.
### 📄 `server/api/root.ts`
Ici, nous [fusionnons](https://trpc.io/docs/v10/merging-routers) tous les sous-routeurs définis dans `routers/**` en un seul routeur d'application.
### 📄 `utils/api.ts`
Il 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.
Vous 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.
Enfin, 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.
Le 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.
## Comment puis-je appeler mon API en externe ?
Avec 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 :
### Exposez une seule procédure vers l'extérieur
Si 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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Exposer chaque procédure en tant que point de terminaison REST
Si 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.
### Ce ne sont que des requêtes HTTP
tRPC 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.
## Comparaison avec un endpoint d'API Next.js
Comparons 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 :
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Comparez cela à l'exemple tRPC ci-dessus et vous pouvez voir certains des avantages de tRPC :
- 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.
- Vous n'avez pas besoin de valider la méthode HTTP utilisée.
- 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.
- 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.
- L'appel de la procédure sur le frontend fournit l'auto-complétion et la sécurité de typage.
## Extraits de code utiles
Voici quelques extraits de code qui pourraient être utiles.
### Activation de CORS
Si 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 :
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Enable cors
await cors(req, res);
// Create and call the tRPC handler
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Mises à jour optimistes
Les 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).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Cancel outgoing fetches (so they don't overwrite our optimistic update)
await utils.post.list.cancel();
// Get the data from the queryCache
const prevData = utils.post.list.getData();
// Optimistically update the data with our new post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Return the previous data so we can revert if something goes wrong
return { prevData };
},
onError(err, newPost, ctx) {
// If the mutation fails, use the context-value from onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sync with server once mutation has settled
utils.post.list.invalidate();
},
});
};
```
### Exemple de test d'intégration
Voici 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
## Ressources utiles
| Ressource | Lien |
| ------------------------- | ------------------------------------------------------- |
| Documentation tRPC | https://www.trpc.io |
| Un tas d'exemples de tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Documentation React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/fr/usage/typescript.md
================================================
---
title: TypeScript
description: Utilisation de TypeScript
layout: ../../../layouts/docs.astro
lang: fr
---
"Construisez des filets de sécurité, pas des garde-fous"
Que 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.
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 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.
C'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.
## Inférence de type
Alors 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.
Regardez la vidéo de Theo sur la façon dont [vous utilisez peut-être mal TypeScript](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Utilisations puissantes de l'inférence de type
### Zod
[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.
### Tanstack Query
[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.
## Ressources utiles
| Ressource | Lien |
| --------------------------------------------------------- | ----------------------------------------------------------------- |
| Manuel TypeScript | https://www.typescriptlang.org/docs/handbook/ |
| Tutoriel TypeScript pour débutants | https://github.com/total-typescript/beginners-typescript-tutorial |
| Défis de Type | https://github.com/type-challenges/type-challenges |
| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/fr/why.md
================================================
---
title: Pourquoi CT3A?
description: Pourquoi devriez-vous choisir Create T3 App pour votre prochain projet
layout: ../../layouts/docs.astro
lang: fr
---
Nous 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.
Si 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 :)
## Pourquoi TypeScript ?
JavaScript est difficile. Pourquoi ajouter plus de règles ?
Nous 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.
La 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)
## Pourquoi Next.js ?
Nous 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.
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.
## Pourquoi tRPC/Prisma/Tailwind/etc?
Bien 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.
### tRPC
tRPC 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.
### Prisma
Prisma 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.
Prisma 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.
### Tailwind CSS
Tailwind ressemble à un "CSS en mode zen".
En 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.
De 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.
### NextAuth.js
Lorsque 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.
================================================
FILE: www/src/pages/index.astro
================================================
---
import About from "../components/landingPage/about.astro";
import Banner from "../components/landingPage/banner.astro";
import Community from "../components/landingPage/community/community.astro";
import Features from "../components/landingPage/stack/stack.astro";
import LandingPage from "../layouts/landingPage.astro";
---
================================================
FILE: www/src/pages/ja/deployment/docker.md
================================================
---
title: Docker
description: Dockerへのデプロイ
layout: ../../../layouts/docs.astro
lang: ja
---
このスタックをコンテナ化し、Docker を使用して単一のコンテナとしてデプロイすることができます。または、 docker-compose を使用して複数のコンテナのグループの一部としてデプロイすることもできます。このドキュメントに基づいたサンプルリポジトリは [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) をご覧ください。
## Docker プロジェクトの設定
Next.js では、ビルド時の変数(フロントエンドで利用可能、接頭辞は`NEXT_PUBLIC`)と実行環境の変数(サーバサイドのみ)が異なる処理を必要とすることに注意してください。このデモでは 2 つの変数を使用しています。`Dockerfile`、コマンドライン引数、`docker-compose.yml`の中での位置に注意してください:
- `DATABASE_URL` (サーバーが使用する)
- `NEXT_PUBLIC_CLIENTVAR`(クライアントが使用する)
### 1. Next の設定
[`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`出力オプション設定を追加してください:
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. .dockerignore ファイルの作成
Click here and include contents in .dockerignore:
### 3. Dockerfile の作成
サーバ環境変数をコンテナに取り込んでいないため、[環境スキーマの検証](/en/usage/env-variables)が失敗します。これを防ぐために、ビルド時に環境スキーマが検証されないように、ビルドコマンドに `SKIP_ENV_VALIDATION=1` フラグを追加する必要があります。
Click here and include contents in Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-alpine3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-alpine3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-alpine3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_備考_**
>
> - _Node 18 への移行後は、`--platform=linux/amd64`のエミュレーションが不要になる場合があります。_
> - _なぜ `libc6-compat` が必要なのかについては [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) を参照してください。._
> - _[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)._
> - _Next.js は[一般的な使用方法に関する匿名のテレメトリーデータ](https://nextjs.org/telemetry)を収集します。ビルド時にテレメトリを無効にするには、`ENV NEXT_TELEMETRY_DISABLED 1` の最初のインスタンスのコメントを外してください。実行時にテレメトリを無効にするには、2 番目のインスタンスのコメントを外してください。_
## ローカルでイメージをビルドし、実行する
以下のコマンドでこのイメージをローカルでビルドして実行します:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
[localhost:3000](http://localhost:3000/)を開き、実行中のアプリケーションを確認します。
## Docker Compose
また、Docker Compose でイメージを構築し、コンテナを実行することもできます。
Follow steps 1-4 above, click here, and include contents in docker-compose.yml:
#### `src/pages/api`
`api`フォルダには、Next.js アプリケーションのすべての API ルーティングが格納されています。API ルートについては、[Next.js Api Routes Docs](https://nextjs.org/docs/api-routes/introduction)を参照してください。
[TypeScript の使い方が間違っているかもしれない](https://www.youtube.com/watch?v=RmGHnYUqQ4k)という Theo のビデオをチェックしてみてください。
## 型推論の強力な活用法
### Zod
[Zod](https://github.com/colinhacks/zod)は、TypeScript の上に構築されたスキーマ検証ライブラリです。データの「唯一の真実の情報源」を表すスキーマを書くと、Zod は、ネットワーク境界や外部 API を越えても、アプリケーション全体でデータが有効であることを保証します。
### Tanstack Query
[Tanstack Query](https://tanstack.com/query/v4/) は、宣言的で、常にデータが最新化される自動管理されたクエリとミューテーションを提供し、開発者体験と利用者体験の両方を直接改善します。
## お役立ち情報
| リソース | リンク |
| -------------------------------------------------------------- | ----------------------------------------------------------------- |
| TypeScript ハンドブック | https://www.typescriptlang.org/docs/handbook/ |
| TypeScript 初心者向けチュートリアル | https://github.com/total-typescript/beginners-typescript-tutorial |
| タイプチャレンジ | https://github.com/type-challenges/type-challenges |
| TypeScript の Rodney Mullen (Matt Pocock)の Youtube チャンネル | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/ja/why.md
================================================
---
title: CT3A を選ぶ理由
description: なぜあなたは次のプロジェクトで Create T3 App を選ぶべきなのか
layout: ../../layouts/docs.astro
lang: ja
---
私たちが Create T3 App の開発を始めたのは、[Theo](https://twitter.com/t3dotgg)が自分の好みの技術のテンプレートを作ることを拒んだからです。create-next-app や[Astro's CLI](https://astro.build)、そして型安全性への全面的な愛に触発されて、Create T3 App チームは新しく T3 Stack プロジェクトを始めるための最高の出発点を作るために懸命に働きました。
Next.js を型安全な方法で使うことに興味があるなら、こここそが始めるべき場所です。私たちが選択した技術的選択について興味がある方は、引き続きお読みください :)
## なぜ TypeScript なのか?
JavaScript は難しいですよね。なんだってこれ以上ルールを増やすのでしょうか?
私たちは、TypeScript が提供する体験が、より優れた開発者になるのに役立つと確信しています。TypeScript は、期待されるデータ型を定義することで、コードを書きながらのリアルタイムのフィードバックを提供し、存在しないプロパティにアクセスを試みたり、間違った型の値を渡そうとすると、エディタで役立つ自動補完を提供したり、赤い波線で警告を発してくれます。Web 開発の初心者であれ、熟練したプロであれ、TypeScript の「厳密さ」は、「バニラ JS」よりもフラストレーションが少なく、一貫した体験を提供してくれるでしょう。
型安全性はあなたをより速くします。もし納得できないなら、あなたは[TypeScript の使い方を間違っているかもしれません...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)。
## なぜ Next.js なのか?
私たちは React が大好きです。React はこれまで想像もしなかったような方法で UI 開発を身近なものにしてくれました。しかし、その反面、開発者を険しい道へ導くこともあります。
Next.js は、React を使ったアプリケーションを作成するための、思想に拘りすぎず、かつ強く最適化したアプローチを提供します。Next.js は、ルーティングから API 定義、画像レンダリングに至るまで、開発者が良い判断ができるように導いてくれると私たちは信じています。
## なぜ tRPC/Prisma/Tailwind/etc なのか?
私たちは物事をできるだけシンプルに保つべきだと信じてやってきましたが、これらの構成要素は私たちが作ってきた、「アプリ」っぽいすべてのプロジェクトで使ってきたことがわかりました。`create-t3-app`は、必要とする構成要素を導入できるように、すばらしく良い仕事をしてくれます。
### tRPC
tRPC は GraphQL が実現してくれるはずのもの、「サーバーに対するシームレスで型安全なクライアント開発」を、定型文を一切使わずに実現するものです。これは TypeScript を巧みに利用したもので、極上の開発体験が得られます。
### Prisma
SQL に対する Prisma は 「JS に対する TypeScript」のようなものです。Prisma はこれまでにない開発者体験を作り出しました。[複数のデータベース](https://www.prisma.io/docs/concepts/database-connectors)と互換性のあるユーザー定義スキーマから型を生成することで、Prisma はデータベースからアプリケーションまでのエンドツーエンドの型安全性を保証します。
Prisma は、データベースの日常的な操作をより簡単にするための[ツール群](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 で、コードを書くことなくデータを素早く表示したり操作したりすることができます。
### Tailwind CSS
Tailwind は「禅モードの CSS」みたいなものです。
Tailwind は、優れたデフォルトの色、間隔(spacing)、その他のプリミティブという形でビルディングブロックを提供することで、見栄えの良いアプリケーションを簡単に作成することができます。また、コンポーネントライブラリとは異なり、アプリケーションを次のレベルまで引き上げようとしたり、美しくユニークなものを作ろうとしたときに、足かせとなってにっちもさっちもいかなくなったりするようなことは Tailwind では起きません。
また、Tailwind ではインラインスタイルのような書きっぷりをするのですが、クラス名やファイルの編成など、「解決しようとしている問題には直接関係しないことがら」を気にせずにスタイリングできます。
### NextAuth.js
NextJS アプリケーションに認証システムを導入したいとき、NextAuth.js は、がんばって自分で構築する手間をかけずに、複雑なセキュリティ条件下に導入できる優れたソリューションです。NextAuth.js は、OAuth 認証をすばやく追加するための豊富なプロバイダーリストと、多くのデータベースや ORM のためのアダプターを提供しています。
================================================
FILE: www/src/pages/no/deployment/docker.md
================================================
---
title: Docker
description: Utrulling med Docker
layout: ../../../layouts/docs.astro
lang: no
---
Stakken 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.
## Docker-prosjektkonfigurasjon
Væ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.
- `DATABASE_URL` (brukes av serveren)
- `NEXT_PUBLIC_CLIENTVAR` (brukes av klienten)
### 1. Next.js-konfigurasjon
I [`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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Lag en dockerignore-fil
Klikk her og kopier innholdet til .dockerignore:
### 3. Lag Dockerfile
> 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".
Klikk her og kopier innholdet til Dockerfile:
```docker
##### AVHENGIGHETER
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# Installer Prisma-klienten - Fjern denne linjen hvis du ikke bruker Prisma
COPY prisma ./
# Installer avhengigheter basert på foretrukket pakkebehandler
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Notater_**
>
> - _Emulering av `--platform=linux/amd64` er kanskje ikke lenger nødvendig dersom man bruker Node 18._
> - \_Se [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) for å forstå hvorfor `libc6-compat` kan være nødvendig.
> - _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._
## Bygg og Kjør Bildet Lokalt
Bygg og start opp bildet lokalt med følgende kommandoer:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_her" ct3a-docker
```
Åpne [localhost:3000](http://localhost:3000/) for å se programmet som kjøres.
## Docker Compose
Du kan også bruke Docker Compose for å bygge bildet og kjøre det i kontaineren.
Følg trinn 1-4 ovenfor, klikk her og lim inn innholdet i docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_her
```
Kjør kommandoen `docker compose up`:
```bash
docker compose up
```
Åpne [localhost:3000](http://localhost:3000/) for å se programmet som kjører.
## Rull ut til Railway
Du 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:
```bash
railway login
railway init
railway link
railway up
railway open
```
Gå 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/).
## Nyttige Ressurser
| Ressurser | Link |
| -------------------------------------- | -------------------------------------------------------------------- |
| Dockerfile-referanse | https://docs.docker.com/engine/reference/builder/ |
| Compose file versjon 3-Referanse | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Docker CLI-referanse | https://docs.docker.com/engine/reference/commandline/docker/ |
| Docker Compose CLI-referanse | https://docs.docker.com/compose/reference/ |
| Rulle ut Next.js med Docker Image | https://nextjs.org/docs/deployment#docker-image |
| Next.js i Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Next.js med Docker-Eksempel | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Lag et Docker-bilde fra en Next.js-app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/no/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Utrulling",
layout: "docs",
description:
"Lær hvordan man ruller ut T3-applikasjonen til produksjonsmiljø.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/no/deployment/netlify.md
================================================
---
title: Netlify
description: Utrulling med Netlify
layout: ../../../layouts/docs.astro
---
Netlify 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.
## Hvorfor hoste på Netlify
Konvensjonell 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.
Det 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/).
Det 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).
> _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)._
## Prosjektkonfigurasjon
Det 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Bruk av Netlify-dashbordet
1. 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**.

2. Koble til Git-leverandøren din.

3. Velg prosjektets repository.

4. Netlify vil oppdage om du har en `netlify.toml`-fil og automatisk konfigurere build-kommandoen og publiseringskatalogen.

5. Klikk **Show advanced** og deretter **New variable** for å legge til miljøvariablene dine.

6. Klikk på **Deploy site**, vent til bygget er fullført, og se det nye nettstedet ditt.
## Bruk av Netlify CLI
For å 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:
```bash
npm i -g netlify-cli
```
For å 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:
```bash
ntl dev
```
Kjør [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) kommando for å konfigurere prosjektet:
```bash
ntl init
```
Importer prosjektets miljøvariabler fra `.env`-filen din med [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Rull 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:
```bash
ntl deploy --prod --build
```
For å se et kjørende eksempel på Netlify, besøk [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/no/deployment/vercel.md
================================================
---
title: Vercel
description: Utrulling med Vercel
layout: ../../../layouts/docs.astro
lang: no
---
Vi 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.
## Prosjektkonfigurasjon
Vercel 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:
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Bruk av Vercel Dashboard
1. 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**.

2. Importer GitHub-repoet med prosjektet du vil rulle ut.

3. Legg til miljøvariablene dine.

4. Klikk på **Deploy**. Hvis du nå _pusher_ repoet ditt vil Vercel automatisk rulle ut applikasjonen din på nytt!
## Bruke Vercel CLI
For å rulle ut applikasjonen din fra kommandolinjen, må du først [installere](https://vercel.com/docs/cli#installing-vercel-cli) Vercel CLI globalt.
```bash
npm i -g vercel
```
Kjør kommandoen [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) for å rulle ut prosjektet ditt.
```bash
vercel
```
Legg 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.
```bash
vercel --env DATABASE_URL=DIN_DATABASE_URL_HER --yes
```
Etter 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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/no/faq.md
================================================
---
title: FAQ
description: Ofte stilte spørsmål om Create T3 App
layout: ../../layouts/docs.astro
lang: no
---
Her er noen ofte stilte spørsmål om "create-t3-app".
## Hva nå? Hvordan lager jeg en app med dette?
Vi 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.
Hvis 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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## Hvilke læringsressurser er tilgjengelige for øyeblikket?
Selv 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.
Hvis 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å 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 `:
### Artikler
- [Bygg en full stakk-app med create-t3-app](https://www.nexxel.dev/blog/ct3a-guestbook)
- [En første titt på create-t3-app](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrering av T3-applikasjonen din til et Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrering av Stripe i T3-applikasjonen din](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Videoer
- [Bygg en Twitter-klone med T3-stakken - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
– [Bygg en Blogg Med T3-stakken – tRPC, TypeScript, Next.js, Prisma og Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Bygg en Live Chat-applikasjon med T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [T3-stakken - Hvordan Vi Bygget Den](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [En oversikt over create-T3-app (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Hvorfor er det `.js`-filer i prosjektet?
I 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.
Vi 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).
## Jeg sliter med å legge til i18n i applikasjonen min. Er det noen referanse jeg kan bruke?
Vi 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å.
Men 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).
## Hvorfor bruker vi `/pages` og ikke `/app` fra Next.js 13?
I 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_.
For 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).
================================================
FILE: www/src/pages/no/folder-structure-pages.mdx
================================================
---
title: Mappestruktur (Pages)
description: Mappestrukturen til en nylig opprettet T3 App
layout: ../../layouts/docs.astro
lang: no
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Velg pakkene dine for å se mappestrukturen til en app med disse valgene. Lenger ned finner du en beskrivelse av hver oppføring.
### `prisma`
`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.
### `public`
`public`-mappen inneholder statiske ressurser som betjenes av _webserveren_. `favicon.ico`-filen er et eksempel på en statisk ressurs.
### `src/env`
Brukes for validering av miljøvariabler og typedefinisjoner - se [Miljøvariabler](usage/env-variables).
### `src/pages`
`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.
#### `src/pages/api`
Mappen `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/).
#### `src/pages/api/auth/[...nextauth].ts`
`[...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.
#### `src/pages/api/trpc/[trpc].ts`
`[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.
### `src/server`
`server`-mappen brukes til å tydelig skille serverside-kode fra klientside-kode.
#### `src/server/auth.ts`
Hovedinngangspunktet 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.
#### `src/server/db.ts`
`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.
### `src/server/api`
`api`-mappen inneholder tRPC serverside-koden.
#### `src/server/api/routers`
`routers`-mappen inneholder alle dine tRPC-underrutere.
#### `src/server/api/routers/example.ts`
`example.ts`-filen er et eksempel på en tRPC-ruter som bruker `publicProcedure`-hjelperen for å demonstrere hvordan du oppretter en offentlig tRPC-rute.
Basert på dine valgte pakker inneholder denne ruteren flere eller færre ruter for best mulig å demonstrere bruken til dine behov.
#### `src/server/api/trpc.ts`
`trpc.ts`-filen er hovedkonfigurasjonsfilen for din tRPC-backend. Her inne vi:
1. Definerer kontekst brukt i tRPC-forespørsler. Se [Bruk av tRPC](usage/trpc#-serverapitrpcts) for mer informasjon.
2. Eksporter prosedyre hjelpere. Se [Bruk av tRPC](usage/trpc#-serverapitrpcts) for mer informasjon.
#### `src/server/api/root.ts`
`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.
### `src/styles`
`stiler`-mappen inneholder det globale stilsettet til applikasjonen.
### `src/utils`
`utils`-mappen brukes til å lagre ofte gjenbrukte verktøyfunksjoner.
#### `src/utils/api.ts`
`api.ts`-filen er frontendinngangspunktet til tRPC. Se [Bruk av tRPC](usage/trpc#-utilsapits) for mer informasjon.
### `.env`
`.env`-filen brukes til å lagre miljøvariabler. Se [Miljøvariabler](usage/env-variables) for mer informasjon. Denne filen skal **ikke** _commites_ til git-historikk.
### `.env.example`
`.env.example`-filen viser noen eksempler på miljøvariabler basert på valgte bibliotek. Denne filen skal _commites_ til git-historikk.
### `.eslintrc.json`
`.eslintrc.json`-filen brukes til å konfigurere ESLint. Se [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for mer informasjon.
### `next-env.d.ts`
`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.
### `next.config.mjs`
`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.
### `postcss.config.js`
`postcss.config.js`-filen er for bruk av Tailwind PostCSS. Se [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for mer informasjon.
### `prettier.config.mjs`
`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.
### `tsconfig.json`
Filen `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.
================================================
FILE: www/src/pages/no/installation.mdx
================================================
---
title: Installasjon
description: Installasjonsveiledning for Create T3 App
layout: ../../layouts/docs.astro
lang: no
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
For å lage en app med `create-t3-app`, kjør en av følgende tre kommandoer og svar på spørsmålene i veiviseren:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Etter at applikasjonen din har blitt opprettet, sjekk ut [første steg](/no/usage/first-steps) for å begynne å utvikle den nye applikasjonen.
## Avansert bruk
| Alternativ/Flagg | Beskrivelse |
| ----------------- | -------------------------------------------------------------------------------------- |
| `[dir]` | Inkluder et mappeargument med navnet på prosjektet |
| `--noGit` | Eksplisitt be CLI om ikke å initialisere et nytt git-repo i prosjektet |
| `-y`, `--default` | CLI vil bli hoppet over og en ny t3-app vil bli opprettet med alle alternativene valgt |
| `--noInstall` | Bygger prosjektet uten å installere avhengigheter |
## Eksperimentell bruk
For 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.
| Flagg | Beskrivelse |
| ------------ | ---------------------------------- |
| `--CI` | La CLI vite at du er i CI-modus |
| `--trpc` | Inkluder tRPC i prosjektet |
| `--prisma` | Inkluder Prisma i prosjektet |
| `--nextAuth` | Inkluder NextAuth.js i prosjektet |
| `--tailwind` | Inkluder Tailwind CSS i prosjektet |
Hvis du utelater CI-flagget har resten flaggene ingen effekt.
Du 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`.
### Eksempel
Følgende vil lage en T3-app med både tRPC og Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/no/introduction.md
================================================
---
title: Introduksjon
description: Introduksjon til T3-stakken
layout: ../../layouts/docs.astro
lang: no
---
## T3-Stakken
_"T3-Stakken"_ er en webutviklingsstakk inspirert av [Theo](https://twitter.com/t3dotgg) som fokuserer på enkelhet, modularitet og full typesikkerhet.
I 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.
Du 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 :)
## Så... hva er create-t3-app? En mal?
På 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.
Etter å 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.
Dette 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).
## T3-Prinsipper
Vi 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.
### Løs Problemer
Det 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.
### Moderne og Ansvarsbevisst
Vi 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.
### Typesikkerhet er ikke valgfritt
Det 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.
================================================
FILE: www/src/pages/no/other-recs.md
================================================
---
title: Flere anbefalinger
description: Biblioteker og tjenester som vi anbefaler til mange prosjekter
layout: ../../layouts/docs.astro
lang: no
---
Vi er klar over at bibliotekene som er inkludert i `create-t3-app` ikke løser alle problemer.
Selv 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.
Disse 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**_.
## Statehåndtering
_**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.
### Zustand
**For aldri å måtte bruke Redux igjen**
Den "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.
- [Zustand Hjemmeside](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
### Jotai
**For aldri å måtte bruke Context igjen**
Jotai 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.
- [Jotai Hjemmeside](https://jotai.org/)
- [Jotai GitHub](https://github.com/pmndrs/jotai)
## Komponentbibliotek
De 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.
### Ustilte Komponentbiblioteker
Slike 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.
- [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.
– [Headless UI](https://headlessui.com/) ble opprettet av Tailwind CSS-teamet og tilbyr også ustilte, tilgjengelige komponenter som enkelt kan lages med Tailwind CSS.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) en stor samling av React-hooks for å lage tilgjengelige komponenter. Datovelgeren deres er aldeles toppnivå.
### Stylede Komponentbiblioteker
**Hvis du bare vil ha en app som ser helt OK ut**
Noen 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.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
### Class Variance Authority
**For å lage UI-biblioteker**
Lar 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.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Animasjoner
Her er våre anbefalinger hvis du trenger animasjoner i applikasjon din.
### AutoAnimate
**For animasjoner med bare én kodelinje**
De 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.
- [AutoAnimate Hjemmeside](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [AutoAnimate Komponentkodebit](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**For komplekse animasjoner med deklarativ kode**
Framer Motion tilbyr en enkel, deklarativ syntaks og lar deg lage komplekse animasjoner og til og med gestikuleringer med bare noen få linjer kode.
- [Framer Motion Hjemmeside](https://framer.com/motion)
- [Framer Motion Dokumentasjon](https://www.framer.com/docs/)
## Implementeringer, Infrastruktur, Databaser og CI
### Vercel
**For å hoste applikasjonen din**
Vercel 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.
- [Vercels Hjemmeside](https://vercel.com/)
- [Create T3 App Vercel-utrullingsveiledning](/no/deployment/vercel)
### PlanetScale
**For databaser uten å måtte bekymre deg**
PlanetScale 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å.
- [PlanetScale Hjemmeside](https://planetscale.com/)
### Railway
**For å hoste infrastrukturen din**
"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.
- [Railway Homepage](https://railway.app/)
### Upstash
**For serverløse Redis**
Vi 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.
- [Upstash hjemmeside](https://upstash.com/)
### Pusher
**For serverløse WebSockets**
Hvis 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.
- [Pusher Hjemmeside](https://pusher.com/)
### Soketi
Soketi 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.
- [Soketi Hjemmeside](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Analytics
Brukerdata er svært verdifullt når du skal utvikle en app. Her er noen analyseleverandører vi anbefaler.
### Plausible
Trenger 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).
- [Plausible Hjemmeside](https://plausible.io/)
### Umami
Umami 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.
- [Umami Hjemmeside](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
## Annet
### Neste Bundle Analyzer
Noen 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å.
- [@next/bundle-analyzer på npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/no/t3-collection.mdx
================================================
---
title: T3-Kolleksjon
description: Kule open source-prosjekter og selskaper som bruker T3-stakken
layout: ../../layouts/docs.astro
lang: no
isMdx: true
---
Har du laget et prosjekt med T3-stakken og ønsker å dele det? Legg det til lista!
## Open source-prosjekter bygget med T3-stakken
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
## Selskaper som bruker T3-stakken
Vi vil gjerne vite hvilke selskaper som bruker T3-stakken for applikasjonene sine. Bruker du T3-stakken og vil dele den? Legg den til lista!
_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!_
================================================
FILE: www/src/pages/no/usage/env-variables.md
================================================
---
title: Miljøvariabler
description: Introduksjon til create-t3-app
layout: ../../../layouts/docs.astro
lang: no
---
`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:
📁 src/env
┣ 📄 client.mjs
┣ 📄 schema.mjs
┣ 📄 server.mjs
Innholdet 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.
_TLDR; Hvis du vil legge til en ny miljøvariabel, må du definere den i både `.env` og `env/schema.mjs`._
## schema.mjs
Endringene skjer i denne filen. Den inneholder to skjemaer, ett for servermiljøvariabler og ett for klientmiljøvariabler, og et `clientEnv`-objekt.
```ts:env/schema.mjs
export const serverSchema = z.object({
// DATABASE_URL: z.string().url(),
});
export const serverEnv = {
// DATABASE_URL: process.env.DATABASE_URL,
};
export const clientSchema = z.object({
// NEXT_PUBLIC_WS_KEY: z.string(),
});
export const clientEnv = {
// NEXT_PUBLIC_WS_KEY: process.env.NEXT_PUBLIC_WS_KEY,
};
```
### Oppsett av Serverskjema
Definer skjemaet for servermiljøvariablene her.
Pass 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.
### Oppsett av Klientskjema
Definer ditt skjema for klientmiljøvariabeler her.
For å 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.
### clientEnv-Objektet
I denne filen må vi få tilgang til verdiene fra `process.env`-objektet.
Vi 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.
TypeScript vil hjelpe deg med å sørge for at du legger nøklene i både `clientEnv` og `clientSchema`.
```ts
// ❌ Dette fungerer ikke. Vi må destrukturere den manuelt.
const schema = z.object({
NEXT_PUBLIC_WS_KEY: z.string(),
});
const validated = schema.parse(process.env);
```
## server.mjs & client.mjs
Her foregår valideringen og de validerte objektene eksporteres. Du bør ikke redigere disse filene.
## Bruk Miljøvariabler
Hvis 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:
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` er helt typesikker og tillater autofullføring
const dbUrl = env.DATABASE_URL;
```
## .env.example
Siden 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.
## Legg til Miljøvariabler
For å sikre at _builden_ aldri fullføres uten miljøvariablene som prosjektet trenger, må du legge til nye miljøvariabler **to** steder:
📄 `.env`: Skriv miljøvariabelen din her slik du vanligvis ville gjort i en `.env`-fil, f.eks. `KEY=VALUE`
📄 `schema.mjs`: Legg til riktig valideringslogikk for miljøvariabelen ved å definere et Zod-skjema, f.eks. `KEY: z.string()`
I tillegg kan du også oppdatere `.env.example`:
📄 `.env.example`: Legg til miljøvariabelen din, men ikke glem å fjerne verdien hvis den er hemmelig, for eksempel `KEY=VALUE` eller `KEY=`
### Eksempel
_Jeg vil legge til min Twitter API-token som en servermiljøvariabel_
1. Legg til miljøvariabelen i filen ".env":
```
TWITTER_API_TOKEN=1234567890
```
2. Legg til miljøvariabelen i `schema.mjs`:
```ts
export const serverSchema = z.object({
// ...
TWITTER_API_TOKEN: z.string(),
});
export const serverEnv = {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
};
```
3. Valgfritt: Inkluder miljøvariabelen i `.env.example`, men ikke glem å fjerne verdien
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/no/usage/first-steps.md
================================================
---
title: Komme i gang
description: De første stegene med din nye T3-app
layout: ../../../layouts/docs.astro
lang: no
---
Du 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.
## Database
Hvis 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.
## Autentisering
Hvis 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.
Hvis 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.
1. Du trenger en Discord-konto. Meld deg på hvis du ikke har en ennå.
2. 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.
3. Når applikasjonen din er opprettet, naviger til "Settings → OAuth2 → General".
4. Kopier "Client ID" og lim den inn i `.env` som `AUTH_DISCORD_ID`.
5. Klikk "Reset Secret", kopier den nye hemmeligheten og lim inn verdien i `.env` som `AUTH_DISCORD_SECRET`.
6. Klikk "Add Redirect" og skriv inn `http://localhost:3000/api/auth/callback/discord`.
- 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.
7. Lagre endringene.
Du skal nå kunne logge på.
## Editor Setup
Følgende utvidelser anbefales for en optimal utvikleropplevelse. Linkene nedenfor gir støtte for redigeringsprogram utvidelser.
- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)
- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)
- [Prettier Extension](https://prettier.io/docs/en/editors.html)
## Neste Steg
- 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.
- Ta en titt på dokumentasjonen for `create-t3-app` samt dokumentasjonen for pakkene applikasjonen din inkluderer.
- Bli med i [Discord](https://t3.gg/discord) og gi oss en stjerne på [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/no/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Bruk",
layout: "docs",
description:
"Lær hvordan man bruker de forskjellige teknologiene i T3-stakken.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/no/usage/next-auth.md
================================================
---
title: NextAuth.js
description: Bruk av NextAuth.js
layout: ../../../layouts/docs.astro
lang: no
---
Hvis 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.
## Kontekstleverandør
I applikasjonens inngangspunkt vil du se at applikasjonen er pakket inn av en [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider).
```tsx:pages/_app.tsx
```
Denne 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_:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Håndter uautentisert state f.eks. ved å vise en påloggingskomponent
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Henting av session på serversiden
Noen 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`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import type { GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// MERK: `session` vil ikke ha en lastestatus siden den allerede er prefetched på serveren
...
}
```
## Inkluder `user.id` i din Session
`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.
```ts:server/auth.ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Dette 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.
```ts:server/auth.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
Det 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**.
## Bruk med tRPC
Hvis 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.
Dette skjer i to trinn:
1. 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.
```ts:server/auth.ts
export const getServerAuthSession = (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return getServerSession(ctx.req, ctx.res, authOptions);
};
```
Med denne hjelpefunksjonen kan vi hente sesjonen og sende den videre til tRPC-konteksten:
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// inferer `session` som ikke-nullbar
session: { ...ctx.session, user: ctx.session.user },
},
});
}));
```
`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.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Bruk med Prisma
Mye [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.
### Legge til nye felt i modellene dine
Hvis 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.
Hvis 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:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Bruk med Next.js middleware
Bruk 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.
## Oppsett av DiscordProvider (standard)
1. Naviger til [Applications-delen i Discord Developer Portal](https://discord.com/developers/applications) og klikk på "New Application"
2. Bytt til "OAuth2 => Generelt" i settings-menyen
- Kopier klient-ID-en og lim den inn i `AUTH_DISCORD_ID` i `.env`.
- 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.
- Klikk på "Add Redirect" og lim inn `/api/auth/callback/discord` (eksempel for utvikling i lokal miljø: http://localhost:3000/api/auth/callback/discord)
- Lagre endringene dine
- 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.
## Nyttige Ressurser
| Ressurser | Link |
| -------------------------------- | --------------------------------------- |
| NextAuth.js Dokumentasjon | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - med NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/no/usage/next-js.md
================================================
---
title: Next.js
description: Bruk av Next.js
layout: ../../../layouts/docs.astro
lang: no
---
Next.js er et backend-rammeverk for dine React-applikasjoner.
Se [Theos Next.js Conf-prat](https://www.youtube.com/watch?v=W4UhNo3HAMw) for å bedre forstå hva Next.js er og hvordan det fungerer.
## Hvorfor skal jeg bruke det?
Vi 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.
Next.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)
## Get Static/Server Props
En 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.
## Nyttige Ressurser
| Ressurser | Link |
| ---------------------------- | ---------------------------------- |
| Next.js Dokumentasjon | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Next.js Blogg | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Vercel/Next.js YouTube-kanal | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/no/usage/prisma.md
================================================
---
title: Prisma
description: Bruk av Prisma
layout: ../../../layouts/docs.astro
lang: no
---
Prisma 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å.
## Prisma Client
Prisma-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.
## Skjema
Prisma-skjemafilen finner du i `/prisma/schema.prisma`. I denne filen definerer du databasens skjema og modeller. Denne filen brukes til å generere Prisma-klienten.
### Med NextAuth.js
Hvis 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).
## Standard Database
Standarddatabasen 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.
## Fyll Databasen ("Seeding")
["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.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db/client";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Deretter kan du kjøre `pnpm db-seed` (eller `npm`/`yarn`) for å fylle inn databasen.
## Nyttige Ressurser
| Ressurser | Link |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prisma Dokumentasjon | https://www.prisma.io/docs/ |
| Prisma GitHub | https://github.com/prisma/prisma |
| Prisma Migrate Playground | https://playground.prisma.io/guides |
| NextAuth.JS Prisma Adapter | https://next-auth.js.org/adapters/prisma |
| PlanetScale Tilkoblingsveiledning | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/no/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Bruk av TailwindCSS
layout: ../../../layouts/docs.astro
lang: no
---
## Hva er Tailwind CSS?
Tailwind 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.
Det gjør det utrolig enkelt og raskt å skrive CSS, som vist i eksemplet nedenfor:
Gammel CSS:
1. Skriv CSS (ofte i en egen fil)
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Importer CSS til komponenten din
```jsx
import "./my-class.css";
```
3. Legg til klassen i HTML-koden din
```html
...
```
Tilsvarende i Tailwind:
1. Bare skriv klassen i HTML-koden din
```html
...
```
React-komponenter er en sterk kombinasjon for å raskt lage brukergrensesnitt.
Tailwind 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.
Tru 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).
## Bruk
Sørg for at du har installert editor-plugins for Tailwind for å forbedre utvikleropplevelsen.
### Utvidelser og plugins
- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains-integrasjon](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formatering
Tailwind 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.
### Betinget Bruk av Klasser
Å 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.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Nyttige Ressurser
| Ressurser | Link |
| -------------------------- | -------------------------------------------------------- |
| Tailwind Dokumentasjon | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Tailwind Discord-server | https://tailwindcss.com/discord/ |
| TailwindLabs Youtube-kanal | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/no/usage/trpc.md
================================================
---
title: tRPC
description: Bruk av tRPC
layout: ../../../layouts/docs.astro
lang: no
---
tRPC lar oss skrive ende-til-ende typesikre APIer, helt uten kodegenerering eller runtime-bloat.
tRPC 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.
""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."
tRPC-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.
Med tRPC skriver du TypeScript-funksjoner i backend, og kaller dem deretter fra frontend. En enkel tRPC-prosedyre kan se slik ut:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Dette 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.
Etter 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.
Du 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`:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Merk at vi bare trenger å eksportere vår ruters typedefinisjoner, noe som betyr at vi aldri importerer noen serverkode i klienten vår.
La 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:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Du 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.
## Filer
tRPC krever mye _boilerplate_, som `create-t3-app` setter opp for deg. La oss gå gjennom filene som vil bli opprettet:
### 📄 `pages/api/trpc/[trpc].ts`
Dette 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.
### 📄 `server/api/trpc.ts`
Denne filen er delt opp i to deler, kontekstoppretting og tRPC-initialisering:
1. 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.
- `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.
- `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.
2. 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.
Du 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.
### 📄 `server/api/routers/*.ts`
Det 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.
### 📄 `server/api/root.ts`
Her slår vi sammen alle underruterne definert i `routers/**` [merge](https://trpc.io/docs/v10/merging-routers) til et enkelt app-ruter.
### 📄 `utils/api.ts`
Dette 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_.
Du 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.
Til 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.
## Hvordan påkaller jeg API-et mitt eksternt?
Med 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:
### Gjør en enkelt prosedyre tilgjengelig eksternt
Hvis 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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Vis alle prosedyrer som et REST-endepunkt
Hvis 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.
### Dette er kun HTTP-requests
tRPC 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.
## Sammenligning med et Next.js API-endepunkt
La 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:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Hvis vi nå sammenligner dette med tRPC-eksemplet fra lenger opp i dokumentasjonen, kan følgende fordeler med tRPC sees:
- 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.
- Du trenger ikke å validere hvilken HTTP-metode som ble brukt.
- Du trenger ikke å validere at request eller _body_ inneholder riktige data i prosedyren, fordi Zod tar seg av dette.
- 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.
- Å kalle prosedyren på frontend gir autofullføring og typesikkerhet.
## Nyttige Kodeutdrag
Her er noen kodesnutter som kan hjelpe deg.
### Aktivering av CORS
Hvis 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:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Aktiver cors
await cors(req, res);
// Oprett og påkall tRPC-handler
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Optimistiske oppdateringer
Optimistiske 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).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Avbryt utgående henting (slik at de ikke overskriver vår optimistiske oppdatering)
vent utils.post.list.cancel();
// Få dataene fra queryCache
const prevData = utils.post.list.getData();
// Oppdater dataene optimistisk med vårt nye innlegg
utils.post.list.setData(udefinert, (gammel) => [...gammel, nyinnlegg]);
// Returner forrige data slik at vi kan gå tilbake hvis noe går galt
return { prevData };
},
onError(err, newPost, ctx) {
// Hvis mutasjonen mislykkes, bruk kontekstverdien fra onMutate
utils.post.list.setData(udefinert, ctx.prevData);
},
onSettled() {
// Synkroniser med server når mutasjonen er fullført
utils.post.list.invalidate();
},
});
};
```
### Eksempel på Integrasjonstest
Her 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
## Nyttige Ressurser
| Ressurser | Link |
| ------------------------- | ------------------------------------------------------- |
| tRPC Dokumentasjon | https://www.trpc.io |
| Noen tRPC-eksempler | https://github.com/trpc/trpc/tree/next/examples |
| React Query Dokumentasjon | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/no/usage/typescript.md
================================================
---
title: TypeScript
description: Bruk av TypeScript
layout: ../../../layouts/docs.astro
lang: no
---
Enten 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.
Det 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å.
Det 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.
## Typeinferens
Mange 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.
Se videoen av Theo, hvorfor [det kan hende at du bruker TypeScript feil](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Gode bruksområder for typeinferens
### Zod
[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.
### Tanstack Query
[Tanstack Query](https://tanstack.com/query/v4/) gir deg deklarative, alltid oppdaterte, automatisk administrerte `queries` og `mutations` som direkte forbedrer utvikler- og brukeropplevelsen.
## Nyttige Ressurser
| Ressurser | Link |
| -------------------------------------------------------- | ----------------------------------------------------------------- |
| TypeScript håndbok | https://www.typescriptlang.org/docs/handbook/ |
| TypeScript opplæring for nybegynnere | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type-utfordringer | https://github.com/type-challenges/type-challenges |
| Rodney Mullen fra TypeScript (Matt Pocock) Youtube-kanal | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/no/why.md
================================================
---
title: Hvorfor CT3A?
description: Hvorfor du bør velge Create T3 App for ditt neste prosjekt
layout: ../../layouts/docs.astro
lang: no
---
Vi 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.
Hvis 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 :)
## Hvorfor TypeScript?
JavaScript er vanskelig. Hvorfor legge til enda flere regler?
Vi er overbevist om at opplevelsen som TypeScript gir vil gjøre deg til en bedre utvikler.
Man 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.
Typesikkerhet gjør deg raskere. Hvis du ikke er overbevist, [kan det hende du bruker TypeScript feil...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## Hvorfor Next.js?
Vi 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.
Next.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.
## Hvorfor tRPC/Prisma/Tailwind/osv?
Selv 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.
### tRPC
tRPC 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.
### Prisma
Prisma er for SQL det TypeScript er for JS. Det skaper en utvikleropplevelse som ikke har eksistert før.
Prisma 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).
Prisma 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.
### Tailwind CSS
Tailwind føles som "zen-modus CSS".
Tailwind 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.
I 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.
### NextAuth.js
Hvis 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.
================================================
FILE: www/src/pages/og.ts
================================================
import { Resvg } from "@resvg/resvg-js";
import { type APIRoute } from "astro";
import satori from "satori";
import OpenGraph from "../components/openGraph";
import { SITE } from "../config";
import { getIsRtlFromLangCode, getLanguageFromURL } from "../languages";
import { getFont } from "../utils/ogFont";
import { SITE_URL } from "../utils/siteUrl";
const removeEndingSlash = (str: string) => str.replace(/\/$/, "");
export const get: APIRoute = async (request) => {
const params = request.url.searchParams;
const title = params.get("title") ?? SITE.title;
const description = params.get("description") ?? SITE.description;
const pagePath = params.get("pagePath") ?? "";
// Used for most languages
const inter = await getFont({
family: "Inter",
weights: [400, 700] as const,
});
// Used for arabic text
const bonaNova = await getFont({
family: "Bona Nova",
weights: [400, 700] as const,
});
// Used for chinese
const notoSans = await getFont({
family: "Noto Sans SC",
weights: [400, 700] as const,
});
const hostname = request.site?.hostname.replace(/^https?:\/\//, "");
const pageLang = getLanguageFromURL(pagePath);
const svg = await satori(
OpenGraph({
title,
description,
imageBase: SITE_URL,
pageUrl: `${hostname}${removeEndingSlash(pagePath)}`,
rtl: getIsRtlFromLangCode(pageLang),
}),
{
width: 1200,
height: 630,
fonts: [
{ name: "Inter", data: inter[400], weight: 400 },
{ name: "Inter", data: inter[700], weight: 700 },
{ name: "Noto Sans SC", data: notoSans[400], weight: 400 },
{ name: "Noto Sans SC", data: notoSans[700], weight: 700 },
{ name: "Bona Nova", data: bonaNova[400], weight: 400 },
{ name: "Bona Nova", data: bonaNova[700], weight: 700 },
],
debug: import.meta.env.DEBUG_OG === "true",
},
);
const resvg = new Resvg(svg, {});
const pngData = resvg.render();
const pngBuffer = pngData.asPng();
return new Response(pngBuffer, {
headers: {
"Content-Type": "image/png",
"cache-control": "public, max-age=31536000, immutable",
},
});
};
================================================
FILE: www/src/pages/pl/deployment/docker.md
================================================
---
title: Docker
description: Deployment with Docker
layout: ../../../layouts/docs.astro
lang: pl
---
Stack 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).
## Konfiguracja Projektu z Dockerem
Należ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`:
- `DATABASE_URL` (używany przez serwer)
- `NEXT_PUBLIC_CLIENTVAR` (używany przez klienta)
### 1. Konfiguracja Next.js
W 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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Stwórz plik dockerignore
Kliknij tutaj i dodaj poniższą zawartość do pliku .dockerignore:
### 3. Stwórz plik Dockerfile
> 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.
Kliknij tutaj i dodaj poniższą zawartość do pliku Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Uwagi_**
>
> - _Emulacja platformy z flagą `--platform=linux/amd64` może nie być potrzebna podczas korzystania z Node'a w wersji 18._
> - _Aby zrozumieć, dlaczego `libc6-compat` może być potrzebny, zobacz [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine)._
> - _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)._
> - _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._
## Zbuduj oraz Uruchom Obraz Lokalnie
Zbuduj i uruchom ten obraz lokalnie korzystając z następujących komend:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Otwórz [localhost:3000](http://localhost:3000/) aby zobaczyć uruchomioną aplikację.
## Docker Compose
Możesz także skorzystać z narzędzia Docker Compose, aby zbudować obraz i uruchomić kontener.
Podążaj za krokami 1-4 powyżej, kliknij tutaj i dodaj poniższą zawartość do pliku docker-compose.yml:
## Deployment na Railway'a
Moż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.
```bash
railway login
railway init
railway link
railway up
railway open
```
Przejdź 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/).
## Przydatne Zasoby
| Nazwa odnośnika | Link |
| --------------------------------------------- | -------------------------------------------------------------------- |
| Odnośnik do pików Dockerfile | https://docs.docker.com/engine/reference/builder/ |
| Odnośnik do plików "Compose file" w wersji 3 | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Odnośnik do Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ |
| Odnośnik do Docker Compose CLI | https://docs.docker.com/compose/reference/ |
| Wdrażanie aplikacji Next.js z obrazem Dockera | https://nextjs.org/docs/deployment#docker-image |
| Next.js z Dockerem | https://benmarte.com/blog/nextjs-in-docker/ |
| Przykład Next.js z Dockerem | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Stwórz obraz Dockera aplikacji Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/pl/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Deployment",
layout: "docs",
description: "Naucz się deploy'ować produkcyjną wersję swojej aplikacji T3.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/pl/deployment/netlify.md
================================================
---
title: Netlify
description: Deployment na platformie Netlify
layout: ../../../layouts/docs.astro
lang: pl
---
Netlify, 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).
## Dlaczego hostować na Netlify'u?
Racjonalizm 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.
Czę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/).
Zależ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).
> _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)._
## Konfiguracja Projektu
Jest 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Korzystanie z Dashboardu Netlify
1. 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).

2. Połącz swojego dostawcę Gita.

3. Wybierz repozytorium swojego projektu.

4. Netlify wykryje, czy posiadasz plik `netlify.toml` i automatycznie skonfiguruje polecenia budowania i publikowany folder.

5. Kliknij na **Show advanced** (pokaż zaawansowane) a następnie na **New variable** (nowa zmienna), aby dodać swoje zmienne środowiskowe.

6. Kliknij na **Deploy site** (opublikuj stronę), poczekaj aż budowanie się zakończy i otwórz swoją nową stronę.
## Korzystanie z nadzędzia CLI Netlify
Aby 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:
```bash
npm i -g netlify-cli
```
Aby 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.
```bash
ntl dev
```
Uruchom polecenie [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) aby skonfgurować swój projekt:
```bash
ntl init
```
Zaimportuj zmienne środowiskowe swojego projektu z pliku `.env` poleceniem [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Wrzuć 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`:
```bash
ntl deploy --prod --build
```
Aby zobaczyć działający przykład na Netlify, odwiedź stronę [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/pl/deployment/vercel.md
================================================
---
title: Vercel
description: Deployment na platformie Vercel
layout: ../../../layouts/docs.astro
lang: pl
---
Polecamy 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.
## Konfiguracja Projektu
Vercel 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.**
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Korzystanie z Dashboardu Vercela
1. 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**.

2. Importuj repozytorium z GitHuba z projektem.

3. Dodaj zmienne środowiskowe.

4. Kliknij **Deploy**. Od teraz, kiedykolwiek wrzucisz zmianę w kodzie w repozytorium, Vercel automatycznie opublikuje twoją aplikację!
## Korzystanie z Vercel CLI
Aby wykonać deploy z konsoli, musisz najpierw [zainstalować Vercel CLI globalnie](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
Uruchom komendę [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) aby opublikować swój projekt.
```bash
vercel
```
Dołą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.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
Po 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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/pl/examples.mdx
================================================
---
title: Przykłady
description: Przykłady różnych aplikacji na żywo
layout: ../../layouts/docs.astro
lang: pl
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
import Form from "../../components/docs/exampleOptionForm.astro";
Możesz wypróbować różne kombinacje technologii, które oferuje create-t3-app.
Nie można wybrać `prisma` i `drizzle` jednocześnie.
Niektóre funkcje mogą nie działać, chyba że utworzysz plik env
================================================
FILE: www/src/pages/pl/faq.md
================================================
---
title: FAQ
description: Najczęściej zadawane pytania dotyczące Create T3 App
layout: ../../layouts/docs.astro
lang: pl
---
Tu znajdziesz najczęściej zadawane pytania dotyczące Create T3 App.
## Co dalej? Jak mam napisać aplikację?
Staramy 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.
Jeż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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
- [Drizzle](https://orm.drizzle.team/docs/overview)
## Jak sprawić, by aplikacja była ciągle aktualna?
Create 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.
## Jakie zasoby do nauki są dostępne?
Poniż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ę.
Jeż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!
Zdajemy 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):
### Artykuły
- [Zbuduj aplikację full stack z Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)
- [Pierwsze spojrzenie na Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrowanie aplikacji T3 do Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrowanie Stripe'a z Aplikacją T3](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Filmy
- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(recommended)**
- [Jack Herrington - Zbuduj aplikację do sporządzania notatek z T3 Stackiem](https://www.youtube.com/watch?v=J1gzN1SAhyM)
- [Zbuduj klon Twittera z T3 Stackiem - tRPC, Next.js, Prisma, Tailwind oraz Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Zbuduj blog z T3 Stackiem - tRPC, TypeScript, Next.js, Prisma i Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Zbuduj live chat z T3 Stackiem - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [T3 Stack - Jak go zbudowaliśmy](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [Przegląd Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Dlaczego w projekcie są pliki `.js`?
Tak 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.
Staramy 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).
## Mam problem z dodaniem i18n do aplikacji. Czy istnieje jakiś projekt, do którego mógłbym się odnieść przy jej budowaniu?
Zdecydowaliśmy się nie umieszczać i18n w `create-t3-app`, ponieważ jest to bardzo kontrowersyjny temat i istnieje wiele sposobów, aby element ten zaimplementować.
Jeż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).
## Dlaczego korzystamy z folderu `/pages` a nie `/app` z Next.js 13?
Tak 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!).
Ż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).
================================================
FILE: www/src/pages/pl/folder-structure-pages.mdx
================================================
---
title: Struktura projektu (Pages)
description: Struktura projektu nowej aplikacji T3
layout: ../../layouts/docs.astro
lang: pl
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Wybierz paczkę, aby zobaczyć strukturę folderów nowo utworzonej z nią aplikacji. Poniżej znajdziesz opis każdego elementu.
### `prisma`
Folder `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).
### `public`
Folder `public` zawiera zasoby statyczne, które "serwowane" są przez serwer webowy. Plik `favicon.ico` jest przykładem jednego z takich zasobów.
### `src/env`
Używany do walidacji zmiennych środowiskowych i definiowania ich typów - zobacz [zmienne środowiskowe](/pl/usage/env-variables).
### `src/pages`
Folder `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).
#### `src/pages/api`
Folder `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).
#### `src/pages/api/auth/[...nextauth].ts`
Plik `[...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).
#### `src/pages/api/trpc/[trpc].ts`
Plik `[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).
### `src/server`
Folder `server` używany jest do stworzenia wyraźnego podziału między kodem działającym na serwerze, a tym po stronie klienta.
### `src/server/auth.ts`
Jest 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).
#### `src/server/db.ts`
Plik `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).
### `src/server/api`
Folder `api` zawiera kod tRPC po stronie serwera.
#### `src/server/api/routers`
Folder `routers` zawiera wszystkie "sub-routery" tRPC.
#### `src/server/api/routers/example.ts`
Plik `example.ts` zawiera przykład routera tRPC wykorzystującego funkcję pomocniczą `publicProcedure` do zaprezentowania, jak stworzyć publiczny route tRPC.
Zależnie od wybranych paczek, router ten zawiera więcej lub mniej route'ów, aby najlepiej zaprezentować jego sposób użycia.
#### `src/server/api/trpc.ts`
Plik `trpc.ts` jest głównym plikiem konfiguracyjnym dla tRPC po stronie serwera. W pliku tym:
1. Definiujemy kontekst używany w zapytaniach tRPC. Po więcej informacji, zobacz [korzystanie z tRPC](usage/trpc#-serverapitrpcts).
2. Eksportujemy funkcje pomocnicze helperów. Po więcej informacji, zobacz [korzystanie z tRPC](usage/trpc#-serverapitrpcts).
#### `src/server/api/root.ts`
Plik `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).
### `src/styles`
Folder `styles` zawiera globalne style aplikacji.
### `src/utils`
Folder `utils` jest używany do przechowywania często powielanych funkcji pomocniczych.
#### `src/utils/api.ts`
Plik `api.ts` to plik wejścia tRPC od strony klienta. Po więcej informacji, zobacz [korzystanie z tRPC](/pl/usage/trpc#-utilsapits).
### `.env`
Plik `.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.
### `.env.example`
Plik `.env.example` pokazuje przykładowe zmienne środowiskowe bazując na wybranych bibliotekach. Plik ten powinien być commitowany do historii gita.
### `.eslintrc.cjs`
Plik `.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).
### `next-env.d.ts`
Plik `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).
### `next.config.mjs`
Plik `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.
### `postcss.config.js`
Plik `postcss.config.js` jest używany przez Tailwind PostCSS. Po więcej informacji, zobacz [dokumentację Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss).
### `prettier.config.mjs`
Plik `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).
### `tsconfig.json`
Plik `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).
### `drizzle.config.ts`
Plik `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)
================================================
FILE: www/src/pages/pl/installation.mdx
================================================
---
title: Instalacja
description: Instrukcje instalacji dla Create T3 App.
layout: ../../layouts/docs.astro
lang: pl
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Aby zacząć używać szablonu `create-t3-app`, uruchom którąkolwiek z poniższych trzech komend i odpowiedz na pytania w konsoli:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Po tym, jak szablon aplikacji zostanie utworzony, sprawdź [pierwsze kroki](/pl/usage/first-steps) aby zacząć budować swoją nową aplikację.
## Zaawansowane użycie
| Opcja/Flaga | Opis |
| ----------------- | ------------------------------------------------------------------------------------ |
| `[dir]` | Argument z nazwą dla projektu |
| `--noGit` | Wyraźnie poinformuj narzędzie, aby nie inicjalizować nowego repozytorium w projekcie |
| `-y`, `--default` | Pomiń CLI i stwórz nową aplikację z wszystkimi wybranymi opcjami |
| `--noInstall` | Wygeneruj projekt bez instalowania zależności (npm) |
## Eksperymentalne użycie
Z 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.
| Flaga | Opis |
| ------------ | ------------------------------------------- |
| `--CI` | Poinformuj narzędzie, że jesteś w trybie CI |
| `--trpc` | Zawrzyj tRPC w projekcie |
| `--prisma` | Zawrzyj Prisma w projekcie |
| `--nextAuth` | Zawrzyj NextAuth.js w projekcie |
| `--tailwind` | Zawrzyj Tailwind CSS w projekcie |
Jeżeli nie podasz flagi `CI`, pozostałe flagi nie zostaną użyte.
Nie musisz wyraźnie wskazywać paczek, z których nie chcesz korzystać. Jeżeli jednak
wolisz jasno wskazać czego używasz, możesz podać wartość `false` - np. `--nextAuth
false`.
### Przykład
Poniższy przykład stworzy aplikację T3 z bibliotekami tRPC oraz Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/pl/introduction.md
================================================
---
title: Wstęp
description: Wstęp do stacka T3
layout: ../../layouts/docs.astro
lang: pl
---
## T3 Stack
_"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.
Jego 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.
Mogł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.
## A więc... co to Create T3 App? Jakiś szablon?
Moż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.
Po 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.
**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).
## Aksjomaty T3
Będziemy z tobą szczerzy - jest to _kontrowersyjny_ projekt. Posiadamy garść założeń dotyczących budowania aplikacji i traktujemy je jako bazę naszych decyzji.
### Rozwiązuj Problemy
Ł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.
### "Bleed Responsibly" (Korzystaj Rozważnie z Nowych Technologii)
Kochamy 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.
### Typesafety NIE Jest Opcjonalne
Celem 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.
================================================
FILE: www/src/pages/pl/other-recs.md
================================================
---
title: Inne Rekomendacje
description: Biblioteki i usługi, które polecamy dla wielu projektów
layout: ../../layouts/docs.astro
lang: pl
---
Zdajemy 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.
Są 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.
_**Zrób swój research, szczególnie zanim skorzystasz z płatnych usług**_.
## State Management
_**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.
### Zustand
**Aby nigdy więcej nie używać Reduxa**
"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.
- [Strona główna Zustanda](https://zustand-demo.pmnd.rs/)
- [GitHub Zustanda](https://github.com/pmndrs/zustand)
### Jotai
**Aby nigdy więcej nie używać kontekstu**
Przy 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.
- [Strona główna Jotai](https://jotai.org/)
- [GitHub Jotai](https://github.com/pmndrs/jotai)
## Biblioteki Komponentów
Wiele 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.
### Biblioteki Komponentów Bez Narzuconych Stylów
Znane 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.
- [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.
- [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.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) zaopatrzy cię w przystępne prymitywy do UI dla twojego design systemu.
### Biblioteki Komponentów Z Gotowymi Stylami
**W przypadku, kiedy chcesz żeby twoja aplikacja wyglądała OK**
Czasem 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ę.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
- [@shadcn/ui](https://ui.shadcn.com/)
### Class Variance Authority
**Gdy budujesz własną bibliotekę UI**
Zbuduj 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.
- [GitHub Class Variance Authority](https://github.com/joe-bell/cva)
## Animacje
Rekomendacje na sytuacje, kiedy w aplikacji potrzebować będziesz animacji :)
### AutoAnimate
**Aby animacje były pojedynczą linią kodu**
Wiele 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.
- [Strona główna AutoAnimate](https://auto-animate.formkit.com/)
- [GitHub AutoAnimate](https://github.com/formkit/auto-animate)
- [Snippet komponentu AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Złożone animacje z deklaratywnym kodem**
Framer 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.
- [Strona główna Framer Motion](https://framer.com/motion)
- [Dokumentacja Framer Motion](https://www.framer.com/docs/)
## Wdrażanie, Infrastruktura, Bazy Danych i CI
### Vercel
**Aby zhostować swoją aplikację**
Vercel 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 :)
- [Strona główna Vercel](https://vercel.com/)
- [Poradnik deploymentu aplikacji T3 z Vercelem](/pl/deployment/vercel)
### PlanetScale
**Bazy danych bez obaw**
PlanetScale 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ć.
- [Strona główna PlanetScale](https://planetscale.com/)
### Railway
**Aby hostować swoją infrastrukturę**
"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.
- [Strona główna Railway](https://railway.app/)
### Upstash
**Redis dla aplikacji "serverless"**
Kochamy 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.
- [Strona główna Upstash](https://upstash.com/)
### Pusher
**WebSockety "serverless"**
Jeż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.
- [Strona głowna Pushera](https://pusher.com/)
### Soketi
Soketi 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.
- [Strona główna Soketi](https://soketi.app)
- [GitHub Soketi](https://github.com/soketi/soketi)
## Statystyki Stron (Analytics)
Budując aplikację, dane użytkowników są bardzo cenne. Znajdziesz tu parę serwisów do ich zbierania, które polecamy.
### Plausible
Potrzebujesz 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).
- [Strona główna Plausible](https://plausible.io/)
### Umami
Umami 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.
- [Strona główna Umami](https://umami.is/)
- [GitHub Umami](https://github.com/umami-software/umami)
## Inne
### Next Bundle Analyzer
Okreś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.
- [@next/bundle-analyzer na npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/pl/t3-collection.mdx
================================================
---
title: Kolekcja T3
description: Ciekawe projekty open source oraz firmy korzystające ze stacka T3
layout: ../../layouts/docs.astro
lang: pl
isMdx: true
---
Zrobiłeś projekt korzystając z T3 stacka i chcesz się nim podzielić? Dodaj go do listy!
## Aplikacje open source wykonane z T3 Stackiem
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
## Firmy korzystające ze stacka T3
Bardzo 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!
_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!_
================================================
FILE: www/src/pages/pl/usage/env-variables.md
================================================
---
title: Zmienne Środowiskowe
description: Jak zacząć z Create T3 App
layout: ../../../layouts/docs.astro
lang: pl
---
Create 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`.
## env.js
_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`._
Plik ten podzielony jest na dwie części - schemat zmiennych i wykorzystywanie obiektu `process.env`, jak i logika walidacji. Logika ta nie powinna być zmieniana.
```ts:env.js
const server = z.object({
NODE_ENV: z.enum(["development", "test", "production"]),
});
const client = z.object({
// NEXT_PUBLIC_CLIENTVAR: z.string(),
});
const processEnv = {
NODE_ENV: process.env.NODE_ENV,
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
};
```
### Schemat Dla Serwera
Zdefiniuj tutaj zmienne środowiskowe dla serwera.
Koniecznie **nie** prefixuj tutejszych kluczy `NEXT_PUBLIC_`, aby przypadkiem nie ujawnić ich do klienta.
### Schemat Dla Klienta
Zdefiniuj tutaj zmienne środowiskowe dla klienta.
Aby 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.
### Obiekt `processEnv`
Wykorzystaj destrukturyzację obiektu `process.env`.
Potrzebny 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.
TypeScript zapewni poprawność destrukturyzacji obiektu i zapobiegnie sytuacji, w której zapomnisz o jakimś kluczu.
```ts
// ❌ To nie zadziała, musimy ręcznie "rozbić" `process.env`
const schema = z.object({
NEXT_PUBLIC_WS_KEY: z.string(),
});
const validated = schema.parse(process.env);
```
### Logika Walidacji
_Dla zainteresowanego czytelnika:_
Zaawansowane: Logika walidacji
W 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.
```ts:env.js
const isServer = typeof window === "undefined";
const merged = server.merge(client);
const parsed = isServer
? merged.safeParse(processEnv) // <-- na serwerze, sprawdź oba schematy
: client.safeParse(processEnv); // <-- na kliencie, sprawdź tylko zmienne klienta
if (parsed.success === false) {
console.error(
"❌ Invalid environment variables:\n",
...formatErrors(parsed.error.format()),
);
throw new Error("Invalid environment variables");
}
```
Następnie korzystamy z obiektu proxy, aby wyrzucać błędy, jeśli chcesz skorzystać z serwerowych zmiennych środowiskowych na kliencie.
```ts:env.js
// proxy pozwala na zmianę gettera
export const env = new Proxy(parsed.data, {
get(target, prop) {
if (typeof prop !== "string") return undefined;
// na kliencie pozwalamy jedynie na zmienne NEXT_PUBLIC_
if (!isServer && !prop.startsWith("NEXT_PUBLIC_"))
throw new Error(
"❌ Attempted to access serverside environment variable on the client",
);
return target[prop]; // <-- w przeciwnym razie, zwróć wartość
},
});
```
## Korzystanie Ze Zmiennych Środowiskowych
Jeż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.
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` jest w pełni typesafe i zapewnia autouzupełnianie
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ Wyrzuci to błąd runtime
const dbUrl = env.DATABASE_URL;
// ✅ To jest ok
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Ponieważ 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.
Niektó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`.
## Dodawanie Zmiennych Środowiskowych
Aby upewnić się, że twój projekt nie zbuduje się bez wymaganych zmiennych środowiskowych, będziesz musiał dodać nową zmienną w **dwóch** miejscach:
📄 `.env`: Wprowadź swoją zmienną środ. tak, jak to zwykle robisz (np. `KLUCZ=WARTOŚĆ`)
📄 `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`.
Opcjonalnie możesz zaktualizować plik `.env.example`:
📄 `.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=`
### Przykład
_Chcę dodać mój token do API Twittera jako zmienną środowiskową po stronie serwera_
1. Dodaj zmienną środ. do pliku `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Dodaj zmienną środowiskową do pliku `env.js`:
```ts
export const server = z.object({
// ...
TWITTER_API_TOKEN: z.string(),
});
export const processEnv = {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
};
```
3. opcjonalnie: Dodaj zmienną środowiskową do `.env.example`. Usuń jednak token.
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/pl/usage/first-steps.md
================================================
---
title: Pierwsze Kroki
description: Jak zacząć pracę z nową aplikacją T3
layout: ../../../layouts/docs.astro
lang: pl
---
Skorzytał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ę.
## Baza Danych
### Prisma
Jeż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ć.
### Drizzle
Jeż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.
## Uwierzytelnianie
Jeż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.
Oczywiś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.
1. Potrzebować będziesz konta Discord, więc utwórz je, jeśli jeszcze tego nie zrobiłeś.
2. 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.
3. Po stworzeniu aplikacji, przejdź do "Settings → OAuth2 → General".
4. Skopiuj "Client ID" i dodaj go do pliku `.env` pod kluczem `AUTH_DISCORD_ID`.
5. Kliknij "Reset Secret", skopiuj nowy secret i dodaj go do pliku `.env` pod kluczem `AUTH_DISCORD_SECRET`.
6. Kliknij "Add Redirect" i wpisz `http://localhost:3000/api/auth/callback/discord`.
- 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.
1. Zapisz zmiany
2. 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.
Powinieneś być w stanie się zalogować.
## Konfiguracja Edytora
Następujące rozszerzenia są przez nas polecane dla optymalnego DX'u. Poniższe linki dostarczają pluginy dla odpowiednich edytorów.
- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)
- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)
- [Prettier Extension](https://prettier.io/docs/en/editors.html)
## Następne Kroki
- 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.
- Rozejrzyj się po dokumentacji Create T3 App oraz dokumentacji paczek, z których korzysta twój projekt.
- Dołącz do naszego serwera [Discord](https://t3.gg/discord) i dodaj gwiazdkę na repozytorium [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/pl/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Korzystanie z technologii",
layout: "docs",
description:
"Naucz się, jak korzystać z poszczególnych technologii w T3 Stacku.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/pl/usage/next-auth.md
================================================
---
title: NextAuth.js
description: Korzystanie z NextAuth.js
layout: ../../../layouts/docs.astro
lang: pl
---
Kiedy 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.
## Context Provider
W pliku `pages/_app.tsx` zobaczyć możesz, iż twoja aplikacja znajduje się w [SessionProviderze](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
```
Ten oto provider kontekstu pozwala twojej aplikacji na dostęp do danych sesji z każdego miejsca, bez potrzeby przesyłania ich po "propsach":
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Obsłuż status nie bycia zalogowanym, np. wyświetl komponent `SignIn`
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Otrzymywanie sesji po stronie serwera
Czasem 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`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// UWAGA: obiekt `session` nie będzie miał stanu ładowania, ponieważ jest już pobrany na serwerze
...
}
```
## Dołączanie `user.id` do sesji
Create 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`.
```ts:server/auth.ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Łą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.
```ts:server/auth.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
Ten 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.
## Korzystanie wraz z tRPC
Jeż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.
Konfiguracja ta zachodzi w dwóch krokach:
1. 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ę.
```ts:server/auth.ts
export const getServerAuthSession = (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return getServerSession(ctx.req, ctx.res, authOptions);
};
```
Korzystając z tej funkcji pomocniczej, możemy otrzymać sesję i przesłać ją do kontekstu tRPC:
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../common/get-server-auth-session";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// inferer `session` som ikke-nullbar
session: { ...ctx.session, user: ctx.session.user },
},
});
}));
```
Obiekt `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.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Korzystanie wraz z Prismą
Przygotowanie 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.
### Dodawanie nowych pól do modeli
Kiedy 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.
Jeż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`:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Korzystanie wraz z middlewarem Next.js
Wykorzystanie 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.
## Konfigurowanie domyślnego providera Discord (`DiscordProvider`)
1. Przejdź do [sekcji Aplikacje w Panelu Discord Developer Portal](https://discord.com/developers/applications), a następnie kliknij na "New Application"
2. W menu ustawień, przejdź do "OAuth2 => General"
- Skopiuj Client ID i wklej go do pliku `.env` pod kluczem `AUTH_DISCORD_ID`.
- 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.
- Dodaj "Add Redirect" i wklej tam `/api/auth/callback/discord` (przykładowo dla lokalnej aplikacji: http://localhost:3000/api/auth/callback/discord)
- Zapisz zmiany
- 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.
## Przydatne Zasoby
| Zasób | Link |
| ----------------------------------- | --------------------------------------- |
| Dokumentacja NextAuth.js | https://next-auth.js.org/ |
| GitHub NextAuth.js | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - wraz z NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/pl/usage/next-js.md
================================================
---
title: Next.js
description: Korzystanie z Next.js
layout: ../../../layouts/docs.astro
lang: pl
---
Next.js to backend framework dla aplikacji React.
Zapoznaj 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.
## Dlaczego powinienem go używać?
Kochamy 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.
Połą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).
## Get Static/Server Props
Kluczową 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".
## Przydatne Zasoby
| Zasób | Link |
| ----------------------------- | ---------------------------------- |
| Dokumentacja Next.js | https://nextjs.org/docs |
| GitHub Next.js | https://github.com/vercel/next.js |
| Blog Next.js | https://nextjs.org/blog |
| Discord Next.js | https://nextjs.org/discord |
| Twitter Next.js | https://twitter.com/nextjs |
| Kanał YouTube Vercela/Next.js | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/pl/usage/prisma.md
================================================
---
title: Prisma
description: Korzystanie z Prismy
layout: ../../../layouts/docs.astro
lang: pl
---
Prisma 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.
## Prisma Client
Zlokalizowany 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.
## Schema (Schemat)
Znajdziesz 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.
### Z NextAuth.js
Jeż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).
## Domyślna Baza Danych
Domyś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.
## Seedowanie Bazy Danych
[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ą.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db/client";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Następnie uruchom po prostu `pnpm db-seed` (lub `npm`/`yarn`) aby wykonać seedowanie bazy danych.
## Przydatne Zasoby
| Zasób | Link |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Dokumentacja Prismy | https://www.prisma.io/docs/ |
| GitHub Prismy | https://github.com/prisma/prisma |
| Prisma Migrate Playground | https://playground.prisma.io/guides |
| Adapter NextAuth.JS dla Prismy | https://next-auth.js.org/adapters/prisma |
| 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 |
================================================
FILE: www/src/pages/pl/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Korzystanie z Tailwind CSS
layout: ../../../layouts/docs.astro
lang: pl
---
## Co to Tailwind CSS?
TailwindCSS 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.
Sprawia on, iż pisanie CSSa staje się wyjątkowo łatwe i szybkie, jak widać z resztą na poniższym przykładzie:
Stary CSS:
1. Napisz kod CSSa, często w osobnym pliku
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Zaimportuj CSSa do swojego komponentu
```jsx
import "./my-class.css";
```
3. Dodaj klasę do swojego kodu HTMLa
```html
...
```
Odpowiednik z Tailwindem:
1. Po prostu dodaj klasy do HTMLa
```html
...
```
Kiedy korzystasz z Tailwinda w połączeniu z komponentami Reacta, staje się on niezwykle silnym sposobem na szybkie pisanie interfejsów użytkownika (UI).
Tailwind 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.
Tru 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).
## Korzystanie z Tailwinda
Upewnij się, że zainstalowałeś pluginy dla Tailwinda. Zwięszą one komfort pisania kodu korzystając z tego narzędzia.
### Rozszerzenia i Pluginy
- [Rozszerzenie dla VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formatowanie
Klasy 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.
### Warunkowe Dodawanie Klas
Warunkowe 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.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Przydatne Zasoby
| Zasób | Link |
| -------------------------- | -------------------------------------------------------- |
| Dokumentacja Tailwinda | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Serwer Discrod Tailwinda | https://tailwindcss.com/discord/ |
| Kanał Youtube TailwindLabs | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/pl/usage/trpc.md
================================================
---
title: tRPC
description: Korzystanie z tRPC
layout: ../../../layouts/docs.astro
lang: pl
---
tRPC 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).
"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." "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."
Kontrybutor 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ć.
Z tRPC, piszesz funkcje w TypeScript'cie na backendzie a następnie wywołujesz je z frontendu. Prosta procedura tRPC wyglądać może tak:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Jest 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.
Po 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`.
Swoje 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`:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Zwróć uwagę na to, iż musimy eksportować jedynie definicje typów tego routera - oznacza to, iż nigdy nie importujemy kodu serwera po stronie klienta.
Wywoł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:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Natychmiast 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.
## Korzystanie z błędów biblioteki Zod
Domyś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.
Przykładowe użycie:
```tsx
function MyComponent() {
const { mutate, error } = api.post.create.useMutation();
return (
);
}
```
## Pliki
tRPC 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:
### 📄 `pages/api/trpc/[trpc].ts`
Jest 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.
### 📄 `server/api/trpc.ts`
Plik ten podzielony jest na dwie części - tworzenie kontekstu oraz inicjalizacji tRPC:
1. 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.
- `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.
- `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.
2. 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.
Zwróć 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.
### 📄 `server/api/routers/*.ts`
Tutaj definiujesz routery i procedury swojego API. Umownie, powinieneś tworzyć [osobne routery](https://trpc.io/docs/v10/router) dla odpowiadających im procedur.
### 📄 `server/api/root.ts`
Tutaj [łączymy](https://trpc.io/docs/v10/merging-routers) wszystkie "sub-routery" zdefiniowane w folderze `routers/**` w jeden router aplikacji.
### 📄 `utils/api.ts`
Jest 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.
Zdefiniujesz 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.
Na 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.
## Jak wykonać zewnętrzne zapytania do mojego API?
Korzystają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:
### Ujawnianie zewnętrznie pojedynczej procedury tRPC
Jeż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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Ujawnianie wszystkich procedur tRPC jako endpointów REST
Jeż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.
### To tylko zapytania HTTP
tRPC 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.
## Porównanie do endpointu API Next.js
Poró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>+:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Porównaj to do powyższego przykładu z tRPC - zobaczysz zalety korzystanie właśnie z tego sposobu:
- 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.
- Nie musisz walidować użytej metody HTTP.
- Nie musisz walidować zawartości zapytania pod kątem pooprawności zawartych danych - zajmuje się tym Zod.
- 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.
- Wywoływanie procedury na frontendzie dostarcza Ci autouzupełniania i type-safety.
## Przydatne fragmenty
Znajdziesz tutaj fragmenty kodu, które mogą Ci się przydać.
### Aktywacja CORS
Jeżeli chcesz korzystać z API z różnych domen, np. w monorepo zawierającym aplikację React Native, możesz chcieć włączyć CORS:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Włącz cors
await cors(req, res);
// Stwórz i wywołaj handler tRPC
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### "Optimistic updates"
Aktualizacje 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).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Anuluj wychodzące zapytania (aby nie nadpisały one "optimistic update'u")
await utils.post.list.cancel();
// Otrzymaj dane z queryCache
const prevData = utils.post.list.getData();
// Zaktualizuj dane z naszego nowego postu
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Zwróć poprzednie dane, aby w razie błędu można było z nich przywrócić stan aplikacji
return { prevData };
},
onError(err, newPost, ctx) {
// Jeżeli mutacja wyrzuci błąd, skorzystaj z wartości kontekstu z onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Zsynchronizuj z serwerem po ukończonej mutacji
utils.post.list.invalidate();
},
});
};
```
### Przykładowy Test Integracji
Tu 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
Jeżeli twoja procedura jest chroniona, możesz przesłać stworzony obiekt `session` tworząc kontekst:
```ts
test("protected example router", async () => {
const ctx = await createInnerTRPCContext({
session: {
user: { id: "123", name: "John Doe" },
expires: "1",
},
});
const caller = appRouter.createCaller(ctx);
// ...
});
```
## Przydatne Zasoby
| Zasób | Link |
| ------------------------ | ------------------------------------------------------- |
| Dokumentacja tRPC | https://www.trpc.io |
| Parę przykładów z tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Dokumentacja React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/pl/usage/typescript.md
================================================
---
title: TypeScript
description: Korzystanie z TypeScripta
layout: ../../../layouts/docs.astro
lang: pl
---
"Buduj siatki bezpieczeństwa, nie barierki" "Oryginał: Build safety nets, not guard rails"
Bez 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ć.
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.
Jest 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.
## Type Inference
Podczas 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ą.
Sprawdź film od Theo - [korzystasz z TypeScripta źle...](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Wykorzystanie mocnych stron type inference w projektach
### Zod
[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.
### Tanstack Query
[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.
## Przydatne Zasoby
| Zasób | Link |
| --------------------------------------------------------- | ----------------------------------------------------------------- |
| TypeScript Handbook | https://www.typescriptlang.org/docs/handbook/ |
| Poradnik TypeScripta dla Początkujących | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Kanał YouTube - Rodney Mullen of TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/pl/why.md
================================================
---
title: Dlaczego CT3A?
description: Dlaczego powinieneś wybrać Create T3 App dla swojego następnego projektu
layout: ../../layouts/docs.astro
lang: pl
---
Stworzyliś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.
Jeż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 :)
## Dlaczego TypeScript?
JavaScript jest ciężki. Dlaczego dodajemy więcej zasad?
Stanowczo 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.
Typesafety 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).
## Dlaczego Next.js?
Kochamy 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.
Next.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.
## Dlaczego tRPC/Prisma/Tailwind/itp.?
Staramy 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.
### tRPC
tRPC 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.
### Prisma
Prisma 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.
Prisma 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.
### Tailwind CSS
Tailwind sprawia wrażenie "CSSa w trybie zen".
Zaopatrują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.
Dodatkowo, 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ć.
### NextAuth.js
Kiedy 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.
================================================
FILE: www/src/pages/pt/deployment/docker.md
================================================
---
title: Docker
description: Deploy com Docker
layout: ../../../layouts/docs.astro
lang: pt
---
Você 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.
## Configuração do Projeto Docker
Por 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`:
- `DATABASE_URL` (usado pelo servidor)
- `NEXT_PUBLIC_CLIENTVAR` (usado pelo cliente)
### 1. Configuração do Next
Em 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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Criar arquivo dockerignore
Clique aqui e inclua esse conteúdo no arquivo .dockerignore:
### 3. Criação do arquivo Dockerfile
> 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.
Clique aqui e inclua esse conteúdos no .dockerignore:
```docker
##### DEPENDÊNCIAS
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Instalação do Prisma Client - remova se não estiver usando o Prisma
COPY prisma ./
# Instalação de dependências com base no package manager padrão
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile não encontrado." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Observações_**
>
> - _A emulação de `--platform=linux/amd64` pode não ser necessária após a mudança para o Node 18._
> - _Consulte [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) para entender por que `libc6-compat` pode ser necessário._
> - _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)._
> - _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._
## Execute build e run da imagem localmente
Execute `build` e `run` desta imagem localmente com os seguintes comandos:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Abra [localhost:3000](http://localhost:3000/) para ver sua aplicação rodando.
## Docker Compose
Você também pode usar o Docker Compose para criar a imagem e executar o contêiner.
Siga as etapas 1 a 4 acima, clique aqui e inclua o conteúdo no arquivo docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Execute isso usando o comando `docker compose up`:
```bash
docker compose up
```
Abra [localhost:3000](http://localhost:3000/) para ver sua aplicação rodando.
## Deploy na Railway
Você 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:
```bash
railway login
railway init
railway link
railway up
railway open
```
Vá 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/).
## Recursos Úteis
| Recurso | Link |
| ----------------------------------------------- | -------------------------------------------------------------------- |
| Referência do Dockerfile | https://docs.docker.com/engine/reference/builder/ |
| Referência da versão 3 do arquivo Compose | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Referência da CLI do Docker | https://docs.docker.com/engine/reference/commandline/docker/ |
| Referência da CLI do Docker Compose | https://docs.docker.com/compose/reference/ |
| Deploy do Next.js com imagem do Docker | https://nextjs.org/docs/deployment#docker-image |
| Next.js no Docker | https://benmarte.com/blog/nextjs-in-docker/ |
| Exemplo de Next.js com Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Criar imagem do Docker de um aplicativo Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/pt/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Deployment",
layout: "docs",
description: "Aprenda como fazer deploy para produção na sua aplicação T3.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/pt/deployment/netlify.mdx
================================================
---
title: Netlify
description: Fazendo deploy para a Netlify
layout: ../../../layouts/docs.astro
lang: pt
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Netlify é 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.
## Por que hospedar na Netlify
A 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.
Há 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/)
Existem 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).
Para verificar o status de recursos não estáveis do Next 13 veja [Using the
Next 13 `app` directory on
Netlify](https://github.com/netlify/next-runtime/discussions/1724).
## Configuração do Projeto
Há 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.
```toml
[build]
command = "next build"
publish = ".next"
```
## Usando o Netlify Dashboard
1. 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**.

2. Conecte o seu provedor Git.

3. Selecione o repositório de seu projeto.

4. 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.

5. Clique em **Show advanced** e então **New variable** para adicionar suas variáveis de ambiente.

6. Clique em **Deploy site**, aguarde até o processo de build terminar, e então veja seu novo site.
## Usando a Netlify CLI
Para 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:
```bash
npm i -g netlify-cli
```
Para 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:
```bash
ntl dev
```
Rode o comando [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) para configurar seu projeto:
```bash
ntl init
```
Importe 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):
```bash
ntl env:import .env
```
Faç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:
```bash
ntl deploy --prod --build
```
Para ver um exemplo rodando na Netlify, visite [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/pt/deployment/vercel.md
================================================
---
title: Vercel
description: Fazendo deploy para a Vercel
layout: ../../../layouts/docs.astro
lang: pt
---
Recomendamos 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.
## Configuração do projeto
A 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:
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Usando o painel de controle da Vercel
1. 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**.

2. Importe o repositório GitHub com seu projeto.

3. Adicione suas variáveis de ambiente.

4. Clique em **Deploy**. Agora, sempre que você enviar uma alteração ao seu repositório, a Vercel reimplementará automaticamente seu aplicativo!
## Usando a CLI da Vercel
Para 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).
```bash
npm i -g vercel
```
Execute o comando [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) para implantar seu projeto.
```bash
vercel
```
Inclua `--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.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
Apó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.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/pt/faq.mdx
================================================
---
title: FAQ
description: Perguntas frequentes sobre o Create T3 App
layout: ../../layouts/docs.astro
lang: pt
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Aqui estão algumas perguntas frequentes sobre o Create T3 App.
## O que vem a seguir? Como eu faço uma aplicação com isso?
Nó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.
Caso 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.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## Como faço para manter minha aplicação atualizada?
Create 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.
## Onde aprender sobre a stack?
Por 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.
Se 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?
Agora, 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:
### Artigos
- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)
- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Vídeos
- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(recomendado)**
- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)
- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Por que tem arquivos `.js` no projeto?
Conforme 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ó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).
## Estou tendo dificuldades em adicionar o i18n ao meu projeto. Existe alguma referência que eu possa usar?
Nó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.
De 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).
## Por que nós estamos usando `/pages` e não `/app` do Next.js 13?
Conforme 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_.
Para obter uma lista de recursos suportados, planejados e trabalhados no
diretório `/app`, visite a [Documentação beta do
Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
================================================
FILE: www/src/pages/pt/folder-structure-pages.mdx
================================================
---
title: Estrutura de Pastas (Pages)
description: Estrutura de pastas de um novo T3 App inicializado
layout: ../../layouts/docs.astro
lang: pt
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Por 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.
### `prisma`
A 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.
### `public`
A pasta `public` contém recursos estáticos que são servidos pelo servidor web. O `favicon.ico` é um exemplo de um recurso estático.
### `src/env`
Usado para a validação de variáveis ambiente e definição de tipos - veja [Variáveis de Ambiente](usage/env-variables).
### `src/pages`
A 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.
#### `src/pages/api`
A 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/).
#### `src/pages/api/auth/[...nextauth].ts`
O 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.
#### `src/pages/api/trpc/[trpc].ts`
O 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.
### `src/server`
A pasta `server` é usada para de maneira clara separar código do servidor e código do cliente.
#### `src/server/auth.ts`
Conté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.
#### `src/server/db.ts`
O 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.
### `src/server/api`
A pasta api contém o código do lado do servidor do tRPC.
#### `src/server/api/routers`
A pasta routers contém todos as sub-rotas do tRPC.
#### `src/server/api/routers/example.ts`
O arquivo `example.ts` é um exemplo de roteador tRPC que utiliza o utilitário `publicProcedure` para demonstrar como criar uma rota tRPC pública.
Dependendo dos pacotes escolhidos, este roteador contém mais ou menos rotas para melhor demonstrar o uso de acordo com suas necessidades.
#### `src/server/trpc/trpc.ts`
O arquivo `trpc.ts` é o arquivo de configuração principal para seu back-end tRPC. Aqui nós:
1. Definimos o contexto usado nas requests tRPC. Veja [uso do tRPC](usage/trpc#-serverapitrpcts) para mais informações.
2. Exportamos os auxiliares de procedures. Veja [uso do tRPC](usage/trpc#-serverapitrpcts) para mais informações.
#### `src/server/api/root.ts`
O 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.
### `src/styles`
A pasta `styles` contém os estilos globais da aplicação.
### `src/types`
A pasta `types` é usada para guardar tipos ou definições de tipos reutilizáveis.
#### `src/types/next-auth.d.ts`
O 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.
### `src/utils`
A pasta `utils` é usada para guardar funções utilitárias comuns reutilizáveis.
#### `src/utils/api.ts`
O arquivo `api.ts` é o ponto de entrada front-end para o tRPC. Veja [uso do tRPC](usage/trpc#-utilsapits) para mais informações.
### `.env`
O 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.
### `.env.example`
O 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.
### `.eslintrc.cjs`
O 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.
### `next-env.d.ts`
O 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.
### `next.config.mjs`
O 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.
### `postcss.config.js`
O 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.
### `prettier.config.mjs`
O 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.
### `tsconfig.json`
O 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.
================================================
FILE: www/src/pages/pt/installation.mdx
================================================
---
title: Instalação
description: Instruções de Instalação do Create T3 App
layout: ../../layouts/docs.astro
lang: pt
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Para estruturar uma aplicação usando `create-t3-app`, rode qualquer um dos comandos seguintes e responda as perguntas:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Após sua aplicação ter sido estruturada, verifique os [Primeiros Passos](/pt/usage/first-steps) para começar a usar sua nova aplicação.
## Uso avançado
| Opção/Flag | Descrição |
| ----------------- | --------------------------------------------------------------------------------- |
| `[dir]` | Inclua um argumento de diretório com um nome para o projeto |
| `--noGit` | Diga explicitamente à CLI para não inicializar um novo repositório git no projeto |
| `-y`, `--default` | Ignore a CLI e inicialize um novo aplicativo t3 com todas as opções selecionadas |
| `--noInstall` | Gera um projeto sem instalar as dependências |
## Uso experimental
Para 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.
| Flag | Descrição |
| ------------ | -------------------------------------- |
| `--CI` | Informa a CLI que você está no modo CI |
| `--trpc` | Inclui o tRPC no projeto |
| `--prisma` | Inclui o Prisma no projeto |
| `--nextAuth` | Inclui o NextAuth.js no projeto |
| `--tailwind` | Inclui o Tailwind CSS no projeto |
Se você não providenciar a flag `CI`, o resto dessas flags não possui efeito.
Você 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`.
### Exemplo
O comando a seguir irá inicializar um T3 App com tRPC e Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/pt/introduction.md
================================================
---
title: Introdução
description: Introdução à T3 Stack
layout: ../../layouts/docs.astro
lang: pt
---
## A T3 Stack
A _"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).
As 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.
Talvez 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 :)
## Então... o que é o create-t3-app? Um modelo?
Basicamente. 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.
Depois 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.
Isto **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).
## Axiomas T3
Sejamos 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.
### Resolver Problemas
É 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ê.
### Agir com Responsabilidade
Nó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.
## Tipos seguros e bem definidos não são opcionais
O 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.
================================================
FILE: www/src/pages/pt/other-recs.md
================================================
---
title: Outras Recomendações
description: Bibliotecas e Serviços que nós recomendamos para vários projetos.
layout: ../../layouts/docs.astro
lang: pt
---
Nó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.
Estas 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**_.
## Gerenciamento de Estado
_**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.
### Zustand
**Para nunca mais usar Redux**
O "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.
- [Página inicial do Zustand](https://zustand-demo.pmnd.rs/)
- [GitHub do Zustand](https://github.com/pmndrs/zustand)
### Jotai
**Para nunca mais usar Context**
Para 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.
- [Página inicial do Jotai](https://jotai.org/)
- [GitHub do Jotai](https://github.com/pmndrs/jotai)
## Biblioteca de Componentes
A 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.
### Bibliotecas de Componentes não estilizados
També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
- [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.
- [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.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) fornece primitivos de UI acessíveis para seu design system. Seu componente Date Picker é animal.
### Bibliotecas de Componentes estilizados
**Para quando você quer apenas que seu aplicativo seja OK**
À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.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
- [@shadcn/ui](https://ui.shadcn.com/)
### Class Variance Authority
**Para criar bibliotecas de UI**
Crie 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.
- [GitHub do Class Variance Authority](https://github.com/joe-bell/cva)
## Animações
Para quando você precisar de animações em seu aplicativo, aqui estão nossas recomendações.
### AutoAnimate
**Para animações com uma única linha de código**
A 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.
- [Página inicial do AutoAnimate](https://auto-animate.formkit.com/)
- [GitHub do AutoAnimate](https://github.com/formkit/auto-animate)
- [Snippet de um componente com AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Para animações complexas com código declarativo**
O 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.
- [Página inicial do Framer Motion](https://framer.com/motion)
- [Documentation do Framer Motion](https://www.framer.com/docs/)
## Deploy, Infraestrutura, Bancos de Dados e CI
### Vercel
**Para hospedar a sua aplicação**
A 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 :)
- [Página inicial da Vercel](https://vercel.com/)
- [Guia de Deploy Create T3 App na Vercel](/pt/deployment/vercel)
### PlanetScale
**Para bancos de dados sem preocupações**
PlanetScale é 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.
- [Página inicial do PlanetScale](https://planetscale.com/)
### Railway
**Para hospedar sua infra**
É 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.
- [Página inicial da Railway](https://railway.app/)
### Upstash
**Para Redis serverless**
Nó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.
- [Página inicial do Upstash](https://upstash.com/)
### Pusher
**Para WebSockets serverless**
Se 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.
- [Página inicial do Pusher](https://pusher.com/)
### Soketi
O 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.
- [Página inicial do Soketi](https://soketi.app)
- [GitHub do Soketi](https://github.com/soketi/soketi)
## Analytics
Os dados do usuário são muito valiosos quando você está criando um aplicativo. Aqui estão alguns provedores de análise que recomendamos.
### Plausible
Precisa 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).
- [Página inicial do Plausible](https://plausible.io/)
### Umami
Umami é 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.
- [Página inicial do Umami](https://umami.is/)
- [GitHub do Umami](https://github.com/umami-software/umami)
## Outros
### Next Bundle Analyzer
À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.
- [@next/bundle-analyzer no npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/pt/t3-collection.mdx
================================================
---
title: Coleção T3
description: Projetos bacanas open source e empresas usando a T3 stack
layout: ../../layouts/docs.astro
lang: pt
isMdx: true
---
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
import Callout from "../../components/docs/callout.tsx";
Fez um projeto usando a T3 stack e deseja comparilhar? Adicione ele na lista!
## Aplicações Open Source desenvolvidas usando a T3 Stack
## Empresas usando a T3 Stack
Nó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!
Tem um projeto legal usando a T3 stack? Faça uma [pull
request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)
e adicione-o aqui!
================================================
FILE: www/src/pages/pt/usage/env-variables.mdx
================================================
---
title: Variáveis de Ambiente
description: Iniciando com Create T3 App
layout: ../../../layouts/docs.astro
lang: pt
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
O 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`:
## env.js
_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`._
Este 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.
```ts:env.js
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
},
});
```
T3 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.
Para mais informações sobre como o `createEnv` funciona internamente, confira
a documentação de [T3 Env](https://env.t3.gg/docs/introduction)
## Usando Variáveis de Ambiente
Quando 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).
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` é totalmente tipado e fornece preenchimento automático
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ Isso lançará um erro em tempo de execução
const dbUrl = env.DATABASE_URL;
// ✅ Isso está correto
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Como 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.
Alguns 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.
## Adicionando Variáveis Ambiente
Para 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:
📄 `.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`.
📄 `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()`
Opcionalmente, você também pode manter `.env.example` atualizado:
📄 `.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=`
### Exemplo
_Quero adicionar meu token da API do Twitter como uma variável de ambiente do lado do servidor_
1. Adicione a variável de ambiente a `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Adicione a variável de ambiente a `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.string(),
},
// ...
});
```
3. opcional: adicione a variável de ambiente a `.env.example`, mas não inclua o token
```
export const env = createEnv({
// ...
runtimeEnv: {
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
},
});
```
================================================
FILE: www/src/pages/pt/usage/first-steps.md
================================================
---
title: Primeiros passos
description: Começando com seu novo T3 App
layout: ../../../layouts/docs.astro
lang: pt
---
Você acabou de criar um novo aplicativo T3 e está pronto para começar. Aqui está o mínimo para que seu aplicativo funcione.
## Banco de dados
Se 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.
## Autenticação
Se 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.
Claro, 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.
1. Você precisará de uma conta no Discord, então crie uma se ainda não tiver.
2. 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.
3. Depois de criar seu aplicativo, navegue até "Configurações → OAuth2 → Geral".
4. Copie o "ID do cliente" e adicione-o ao seu `.env` como `AUTH_DISCORD_ID`.
5. Clique em "Redefinir Segredo", copie o novo segredo e adicione-o ao seu `.env` como `AUTH_DISCORD_SECRET`.
6. Clique em "Adicionar redirecionamento" e digite `http://localhost:3000/api/auth/callback/discord`.
- 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.
7. Salve as alterações.
Agora você deve conseguir fazer login.
## Próximos passos
- 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.
- Dê uma olhada na documentação `create-t3-app`, bem como nos documentos dos pacotes que sua aplicação inclui.
- Junte-se ao nosso [Discord](https://t3.gg/discord) e dê-nos uma estrela no [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/pt/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Uso",
layout: "docs",
description: "Aprenda a usar as diferentes tecnologias da T3 Stack.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/pt/usage/next-auth.md
================================================
---
title: NextAuth.js
description: Uso do NextAuth.js
layout: ../../../layouts/docs.astro
lang: pt
---
Quando 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.
## Context Provider
No ponto de entrada do seu aplicativo, você verá que ele está envolvida pelo [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
```
Este 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:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Lida com o estado não autenticado, por exemplo renderizar um componente SignIn
return ;
}
return
Bem-vindo {session.user.name}!
;
};
```
## Recuperando a sessão do lado do servidor.
À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`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTA: `session` não terá um estado de carregamento, pois já foi pré-carregado no servidor
...
}
```
## Inclusão do `user.id` na Sessão
`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`.
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Isso é 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.
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
O 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.
## Uso com tRPC
Ao 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.
Isso é feito em um processo de duas etapas:
1. 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.
```ts:server/common/get-server-auth-session.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, nextAuthOptions);
};
```
Usando esta função auxiliar, podemos pegar a sessão e passá-la para o contexto tRPC:
```ts:server/trpc/context.ts
import { getServerAuthSession } from "../common/get-server-auth-session";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. 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.
```ts:server/trpc/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// inferer `session` som ikke-nullbar
session: { ...ctx.session, user: ctx.session.user },
},
});
}));
```
O 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.
```ts:server/trpc/router/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Uso com Prisma
Fazer 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.
### Adicionando novos campos aos seus modelos
Ao 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.
Se, 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`:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Uso com o middleware Next.js
Uso 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.
## Configurando o DiscordProvider padrão
1. Vá para [a seção Aplicativos no Portal do desenvolvedor do Discord](https://discord.com/developers/applications) e clique em "Novo aplicativo"
2. No menu de configurações, vá para "OAuth2 => Geral"
- Copie o Client ID e cole-o em `AUTH_DISCORD_ID` em `.env`.
- 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.
- Clique em "Add Redirect" e cole em `/api/auth/callback/discord` (exemplo para desenvolvimento local: http://localhost:3000/api/auth/callback/discord)
- Salve suas alterações
- É 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.
## Recursos Úteis
| Recurso | Link |
| -------------------------------- | --------------------------------------- |
| Documentação do NextAuth.js | https://next-auth.js.org/ |
| GitHub do NextAuth.js | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - com NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/pt/usage/next-js.md
================================================
---
title: Next.js
description: Uso do Next.js
layout: ../../../layouts/docs.astro
lang: pt
---
Next.js é um framework back-end para suas aplicações React.
Veja 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.
## Por que devo usá-lo?
Nó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.
Juntando 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)
## Get Static/Server Props
Um 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.
## Recursos Úteis
| Recurso | Link |
| ---------------------------------- | ---------------------------------- |
| Documetação do Next.js | https://nextjs.org/docs |
| GitHub do Next.js | https://github.com/vercel/next.js |
| Blog do Next.js | https://nextjs.org/blog |
| Discord do Next.js | https://nextjs.org/discord |
| Twitter do Next.js | https://twitter.com/nextjs |
| Canal do Youtube da Vercel/Next.js | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/pt/usage/prisma.md
================================================
---
title: Prisma
description: Uso do Prisma
layout: ../../../layouts/docs.astro
lang: pt
---
Prisma é 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.
## Prisma Client
Localizado 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.
## Schema
Você 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.
### Com NextAuth.js
Quando 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).
## Banco de dados padrão
O 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.
## Propagar seu banco de dados
[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.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db/client";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Em seguida, basta executar `pnpm db-seed` (ou `npm`/`yarn`) para propagar seu banco de dados.
## Recursos Úteis
| Recurso | Link |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Documentação do Prisma | https://www.prisma.io/docs/ |
| GitHub do Prisma | https://github.com/prisma/prisma |
| Adaptador de Prisma para NextAuth.js | https://next-auth.js.org/adapters/prisma |
| 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 |
================================================
FILE: www/src/pages/pt/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Uso do Tailwind CSS
layout: ../../../layouts/docs.astro
lang: pt
---
## O que é Tailwind CSS?
Tailwind 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.
Isso torna o CSS incrivelmente fácil e rápido de escrever, conforme mostrado no exemplo a seguir:
CSS Antigo:
1. Escreva CSS, geralmente em um arquivo separado
```css
.minha-classe {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Importe o CSS no seu componente
```jsx
import "./minha-classe.css";
```
3. Adicione a classe no seu HTML
```html
...
```
Equivalente com Tailwind:
1. Basta escrever classes em seu HTML
```html
...
```
Quando usado em conjunto com Componentes React, é extremamente poderoso para construir UIs rapidamente.
O 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.
Tru 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).
## Uso
Certifique-se de ter plug-ins de editor para Tailwind instalados para melhorar sua experiência de escrita Tailwind.
### Extensões e Plugins
- [Extensão para o VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [Integration com JetBrains](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Formatação
As 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ê.
### Aplicação de classe condicional
Adicionar 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.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Recursos Úteis
| Recurso | Link |
| ----------------------------- | -------------------------------------------------------- |
| Documentação Tailwind | https://tailwindcss.com/docs/editor-setup/ |
| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Comunidade do Tailwind | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Servidor Discord do Tailwind | https://tailwindcss.com/discord/ |
| Canal do Youtube TailwindLabs | https://www.youtube.com/tailwindlabs/ |
| Playground do Tailwind | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/pt/usage/trpc.md
================================================
---
title: tRPC
description: Uso do tRPC
layout: ../../../layouts/docs.astro
lang: pt
---
O 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.
"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."
o 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.
Com 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:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Este é 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.
Apó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.
Você 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:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Observe 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.
Agora 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:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Você 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.
## Inferindo erros
Por 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.
Exemplo de uso:
```tsx
function MyComponent() {
const { mutate, error } = api.post.create.useMutation();
return (
);
}
```
## Arquivos
O tRPC requer bastante do template que o `create-t3-app` configura para você. Vamos ver os arquivos que são gerados:
### 📄 `pages/api/trpc/[trpc].ts`
Este é 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.
### 📄 `server/api/trpc.ts`
Este arquivo é dividido em duas partes, criação de contexto e inicialização do tRPC:
1. 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.
- `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.
- `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.
2. 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.
Você 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.
### 📄 `server/api/routers/*.ts`
Aqui é 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.
### 📄 `server/api/root.ts`
Aqui [mesclamos](https://trpc.io/docs/v10/merging-routers) todos as sub-rotas definidas em `routers/**` em um único roteador de aplicativo.
### 📄 `utils/api.ts`
Este é 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.
Você 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.
Por 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.
Contribuidor 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.
## Como faço para chamar minha API externamente?
Com 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:
### Expor um único procedimento externamente
Se 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.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Expondo cada procedimento como um endpoint REST
Se 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.
### São apenas Requests HTTP
O 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.
## Comparação com um endpoint da API Next.js
Vamos 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:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Compare isso com o exemplo tRPC acima e você verá algumas das vantagens do tRPC:
- 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.
- Você não precisa validar qual método HTTP foi usado.
- 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.
- 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.
- Chamar o procedimento no frontend fornece preenchimento automático e segurança de tipo.
## Snippets úteis
Aqui estão alguns snippets que podem ser úteis.
### Ativando o CORS
Se 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:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Ativar CORS
await cors(req, res);
// Criar e chamar o handler do tRPC
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Atualizações otimistas
As 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).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Cancele as requisições de saída (para que não substituam nossa atualização otimista)
await utils.post.list.cancel();
// Obtenha os dados do queryCache
const prevData = utils.post.list.getData();
// Atualizar os dados de forma otimista com nosso novo post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Retornar os dados anteriores para que possamos reverter se algo der errado
return { prevData };
},
onError(err, newPost, ctx) {
// Se a mutation falhar, usar o valor de contexto de onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sincronizar com o servidor assim que a mutação for estabelecida
utils.post.list.invalidate();
},
});
};
```
### Exemplo de teste de integração
Aqui 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.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
Se seu procedimento estiver protegido, você pode passar um objeto `session` mockado quando criar o contexto:
```ts
test("protected example router", async () => {
const ctx = await createInnerTRPCContext({
session: {
user: { id: "123", name: "John Doe" },
expires: "1",
},
});
const caller = appRouter.createCaller(ctx);
// ...
});
```
## Recursos Úteis
| Recurso | Link |
| --------------------------- | ------------------------------------------------------- |
| Documentação do tRPC | https://www.trpc.io |
| Muitos exemplos de tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Documentação do React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/pt/usage/typescript.md
================================================
---
title: TypeScript
description: Uso do TypeScript
layout: ../../../layouts/docs.astro
lang: pt
---
""Construa redes de segurança, não grades de proteção""
(traduzido)
Seja 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.
Ele 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.
É, 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.
## Inferência de Tipos
Embora 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.
Confira o vídeo de Theo sobre como [você pode estar usando o TypeScript errado](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Usos poderosos da inferência de tipos
### Zod
O [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.
### Tanstack Query
O [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.
## Recursos Úteis
| Recurso | Link |
| ---------------------------------------------------------- | ----------------------------------------------------------------- |
| Manual do TypeScript | https://www.typescriptlang.org/docs/handbook/ |
| Tutorial de TypeScript para iniciantes | https://github.com/total-typescript/beginners-typescript-tutorial |
| Desafios de Tipos | https://github.com/type-challenges/type-challenges |
| Rodney Mullen do canal do YouTube TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/pt/why.md
================================================
---
title: Por que CT3A?
description: Porque você deve escolher o Create T3 App para o seu próximo projeto
layout: ../../layouts/docs.astro
lang: pt
---
Nó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.
Se 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 :)
## Por que TypeScript?
Javascript é difícil. Pra quê mais regras?
Nos 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.
Seguranç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)
## Por que Next.js?
Nó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.
o 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.
## Por que tRPC/Prisma/Tailwind/etc?
Enquanto 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.
### tRPC
O 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.
### Prisma
Prisma é 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.
O 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.
### Tailwind CSS
Tailwind é como o "CSS no modo zen".
Ao 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.
Alé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.
### NextAuth.js
Quando 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.
================================================
FILE: www/src/pages/ru/deployment/docker.md
================================================
---
title: Docker
description: Развертывание в Docker
layout: ../../../layouts/docs.astro
lang: ru
---
Вы можете контейнеризировать этот стек и развернуть его как один контейнер с помощью Docker или как часть группы контейнеров с помощью docker-compose. Смотрите [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) для примера репозитория на основе этой документации.
## Конфигурация проекта Docker
Пожалуйста обратите внимание, что Next.js нуждается в разных процессах для сборки (доступны во фронтенде, с префиксом `NEXT_PUBLIC`) и переменных окружения, доступных только на сервере. В этом примере мы используем две переменные, обратите внимание на их позиции в `Dockerfile`, аргументы командной строки и `docker-compose.yml`:
- `DATABASE_URL` (используется сервером)
- `NEXT_PUBLIC_CLIENTVAR` (используется клиентом)
### 1. Конфигурация Next
В вашем [`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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Создайте dockerignore file
Нажмите здесь и вставьте содержимое в .dockerignore:
### 3. Создайте Dockerfile
> Из-за того, что мы не извлекаем переменные окружения сервера в наш контейнер, [проверка схемы окружения](/ru/usage/env-variables) не пройдет. Чтобы этого избежать, мы должны добавить флаг `SKIP_ENV_VALIDATION=1` к команде сборки, чтобы схемы окружения не проверялись во время сборки.
Нажмите здесь и вставьте содержимое в Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Заметки_**
>
> - _Эмуляция `--platform=linux/amd64` может не быть необходимой после перехода на Node 18._
> - _Посмотрите [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) чтобы понять, почему `libc6-compat` может быть необходим._
> - _Использование образов, основанных на 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)._
> - _Next.js собирает [анонимные данные о телеметрии общего использования](https://nextjs.org/telemetry). Раскомментируйте первый экземпляр `ENV NEXT_TELEMETRY_DISABLED 1`, чтобы отключить телеметрию во время сборки. Раскомментируйте второй экземпляр, чтобы отключить телеметрию во время выполнения._
## Соберите и запустите образ локально
Соберите и запустите этот образ локально с помощью следующих команд:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Откройте [localhost:3000](http://localhost:3000/) чтобы увидеть запущенное приложение.
## Docker Compose
Вы также можете использовать Docker Compose для сборки образа и запуска контейнера.
Проследуйте шагам 1-4 выше, нажмите здесь и добавьте содержимое в docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Запустите с помощью команды `docker compose up`:
```bash
docker compose up
```
Откройте [localhost:3000](http://localhost:3000/) чтобы увидеть запущенное приложение.
## Развертывание на Railway
Вы можете использовать такой PaaS как автоматическое [развертывание Dockerfile](https://docs.railway.app/deploy/dockerfiles) от [Railway's](https://railway.app) для развертывания вашего приложения. Если у вас [установлен Railway CLI](https://docs.railway.app/develop/cli#install), вы можете развернуть свое приложение с помощью следующих команд:
```bash
railway login
railway init
railway link
railway up
railway open
```
Перейдите к "Variables" и включите ваш `DATABASE_URL`. Затем перейдите к "Settings" и выберите "Generate Domain." Чтобы увидеть работающий пример на Railway, перейдите к [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).
## Полезные ресурсы
| Ресурс | Ссылка |
| ----------------------------------------- | -------------------------------------------------------------------- |
| Пример для Dockerfile | https://docs.docker.com/engine/reference/builder/ |
| Пример для файла Compose 3 версии | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Пример Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ |
| Пример Docker Compose CLI | https://docs.docker.com/compose/reference/ |
| Развертывание Next.js с Docker Image | https://nextjs.org/docs/deployment#docker-image |
| Next.js в Docker'е | https://benmarte.com/blog/nextjs-in-docker/ |
| Пример Next.js с Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Создание Docker образа Next.js приложения | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/ru/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Развертывание",
layout: "docs",
description: "Научитесь развертывать ваше приложение T3 в продакшен.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/ru/deployment/netlify.md
================================================
---
title: Netlify
description: Развертывание в Netlify
layout: ../../../layouts/docs.astro
---
Netlify это альтернативый провайдер развертывания, похожий на Vercel. Вот [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) пример репозитория на основе этой документации.
## Зачем развертывать на Netlify
Принято считать, что Vercel имеет лучшую поддержку Next.js потому что Vercel разрабатывает Next.js. Они заинтересованы в том, чтобы платформа была настроена для оптимальной производительности и DX с Next.js. В большинстве случаев это будет правдой и в отклонении от стандартного пути не будет смысла.
Также существует общее мнение о том, что многие функции 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/).
У всех провайдеров развертывания есть преимущества и недостатки, поскольку ни один хост не может иметь лучшую поддержку для всех случаев использования. Например, 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).
> _Обратите внимание: Для того, чтобы отслеживать статус нестабильных функций Next 13, см. [Использование каталога `app` Next 13 на Netlify](https://github.com/netlify/next-runtime/discussions/1724)._
## Конфигурация проекта
Существует несколько способов настройки инструкций сборки, включая прямое использование Netlify CLI или Netlify Dashboard. Хотя это не обязательно, рекомендуется создать и включить файл [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Это гарантирует, что форкнутые и клонированные версии проекта будут легче повторно развернуть.
```toml
[build]
command = "next build"
publish = ".next"
```
## Использование Netlify Dashboard
1. Запушьте свой код в репозиторий GitHub и зарегистрируйтесь на [Netlify](https://app.netlify.com/signup). После того, как вы создали аккаунт, нажмите **Add new site** и затем **Import an existing project**.

2. Подключите свой Git-провайдер.

3. Выберите репозиторий вашего проекта.

4. Netlify обнаружит, если у вас есть файл `netlify.toml` и автоматически настроит команду сборки и каталог публикации.

5. Нажмите **Show advanced** и затем **New variable**, чтобы добавить свои переменные среды.

6. Нажмите **Deploy site**, подождите, пока сборка завершится, и просмотрите свой новый сайт.
## Использование Netlify CLI
Для того, чтобы развернуть проект из командной строки, вы должны сначала запушить свой проект в репозиторий GitHub и [установить Netlify CLI](https://docs.netlify.com/cli/get-started/). Вы можете установить `netlify-cli` как зависимость проекта или установить его глобально на вашем компьютере с помощью следующей команды:
```bash
npm i -g netlify-cli
```
Для того, чтобы протестировать свой проект локально, запустите команду [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) и откройте [`localhost:8888`](http://localhost:8888/) для просмотра вашего локально запущенного приложения Netlify:
```bash
ntl dev
```
Запустите команду [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment), чтобы настроить ваш проект:
```bash
ntl init
```
Импортируйте переменные среды вашего проекта из вашего файла `.env` с помощью [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Разверните ваш проект с помошью [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Вам нужно будет передать флаг `--build`, чтобы запустить команду сборки перед развертыванием, и флаг `--prod`, чтобы развернуть на основном URL вашего сайта:
```bash
ntl deploy --prod --build
```
Для просмотра примера на Netlify, перейдите на [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/ru/deployment/vercel.md
================================================
---
title: Vercel
description: Развертывание на Vercel
layout: ../../../layouts/docs.astro
lang: ru
---
Мы рекомендуем развертывать ваше приложение на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Он позволяет очень легко развертывать Next.js приложения.
## Конфигурация проекта
Скорее всего Vercel настроит вашу команду сборки и каталог публикации автоматически. Однако вы также можете уточнить эту информацию вместе с другими конфигурациями, создав файл [`vercel.json`](https://vercel.com/docs/project-configuration) и включив в него следующие команды. **В большинстве проектов это делать необязательно.**
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Использование Vercel Dashboard
1. После отправки вашего кода в репозиторий GitHub зарегистрируйтесь на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) с GitHub и нажмите **Add New Project**.

2. Импортируйте репозиторий GitHub с вашим проектом.

3. Добавьте ваши переменные среды.

4. Нажмите **Deploy**. Теперь каждый раз, когда вы отправляете изменение в ваш репозиторий, Vercel автоматически переразвернет ваше приложение!
## Использование Vercel CLI
Для того, чтобы развернуть приложение из командной строки, вам сначала нужно [установить Vercel CLI глобально](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
Запустите команду [`vercel`](https://vercel.com/docs/cli/deploying-from-cli), чтобы развернуть ваш проект.
```bash
vercel
```
Добавьте `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` для переменных среды, таких как строка подключения к базе данных. Используйте `--yes`, если хотите пропустить вопросы развертывания и дать ответ по умолчанию для каждого.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
После первого развертывания эта команда развернет изменения в ветку предварительного просмотра. Вам нужно будет включить `--prod`, чтобы отправить изменения напрямую на сайт в продакшене для будущих развертываний.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/ru/faq.md
================================================
---
title: FAQ
description: Часто задаваемые вопросы про Create T3 App
layout: ../../layouts/docs.astro
lang: ru
---
Это некоторые часто задаваемые вопросы о `create-t3-app`.
## Что дальше? Как я могу создать приложение?
Мы стараемся сделать этот проект как можно проще, поэтому вы можете начать с того, что мы настроили для вас, а затем добавлять дополнительные вещи позже, когда они станут необходимыми.
Если вы не знакомы с различными технологиями, используемыми в этом проекте, обратитесь к соответствующей документации. Если что то все еще не понятно, присоединяйтесь к нашему [Discord](https://t3.gg/discord) и попросите помощи.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## Какие учебные ресурсы сейчас доступны?
Не смотря на то, что перечисленные ниже ресурсы являются одиними из лучших для T3 Stack, сообщество (и [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) рекомендует просто начать использовать стек и учиться в процессе разработки с его помощью.
Если вы рассматриваете `create-t3-app`, скорее всего, вы уже использовали некоторые части стека. Так почему бы не погрузиться в проект с головой и узнать остальные технологии в процессе разработки?
Мы понимаем, что этот путь не подходит для каждого. Поэтому, если вы чувствуете, что рекомендации не достаточно, и вам все еще нужны ресурсы, или вы просто не уверены в своих силах и/или чувствуете себя перегруженным этим стеком, ознакомьтесь с этими потрясающими учебными материалами по `create-t3-app`:
### Статьи
- [Build a full stack app with Create T3 App](https://www.nexxel.dev/blog/ct3a-guestbook)
- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Видео
- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Почему в проекте есть файлы `.js`?
Согласно [T3-Аксиоме #3](/ru/introduction#typesafety-isnt-optional), мы считаем типобезопасность объектом первого класса. К сожалению, не все фреймворки и плагины поддерживают TypeScript, поэтому некоторые файлы конфигурации должны быть файлами `.js`.
Мы пытаемся подчеркнуть, что эти файлы являются файлами JavaScript не без причины, явно объявляя тип каждого файла (`cjs` или `mjs`), в зависимости от того, что поддерживается библиотекой, которой он используется. Кроме того, все файлы `js` в этом проекте все еще проверяются на типы с помощью комментария `@ts-check` вверху.
## У меня не получается добавить i18n в мое приложение. Есть ли какие-либо рекомендации?
Мы решили не включать i18n по умолчанию в `create-t3-app`, потому что это очень субъективная тема, и есть много способов ее реализации.
В тоже время, если вы столкнулись с проблемами при реализации и хотите увидеть проект-образец, у нас есть [ссылка на репозиторий](https://github.com/juliusmarminge/t3-i18n) который показывает как вы можете добавить i18n в T3 App с помощью [next-i18next](https://github.com/i18next/next-i18next).
## Почему мы используем `/pages` а не `/app` из Next.js 13?
Согласно [T3-Аксиоме #2](/ru/introduction#bleed-responsibly), мы любим новинки, но ценим стабильность, вам будет сложно перенести весь маршрутизатор, [не лучшеее место для экспериментов](https://youtu.be/mnwUbtieOuI?t=1662). Хотя `/app` [представляет собой взгляд в будущее](https://youtu.be/rnsC-12PVlM?t=818), он еще не готов к использованию в продакшене; API находится в бета-версии и ожидается, что он будет иметь обратно несовместимые изменения.
Список поддерживаемых, запланированных и находящихся в разработке функций в каталоге `/app` можно найти в [бета-документации Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
================================================
FILE: www/src/pages/ru/folder-structure-pages.mdx
================================================
---
title: Файловая структура (Pages)
description: Файловая структура нового T3 приложения
layout: ../../layouts/docs.astro
lang: ru
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Пожалуйста выберите пакеты, чтобы увидеть файловую структуру нового приложения с выбранными пакетами. Ниже вы найдете описание каждого элемента.
### `prisma`
Папка `prisma` содержит файл `schema.prisma`, который используется для настройки соединения с базой данных и схемы базы данных. Также это место для хранения файлов миграции и/или сценариев заполнения, если они используются. Смотрите [Использование Prisma](/ru/usage/prisma) для получения дополнительной информации.
### `public`
Папка `public` содержит статические файлы, которые обслуживаются веб-сервером. Файл `favicon.ico` - это пример статического файла.
### `src/env`
Используется для проверки переменных окружения и определения типов - смотрите [Переменные окружения](/ru/usage/env-variables).
### `src/pages`
Папка `pages` содержит все страницы приложения Next.js. Файл `index.tsx` в корневой папке `/pages` является домашней страницей приложения. Файл `_app.tsx` используется для оборачивания приложения провайдерами. Смотрите [документацию Next.js](https://nextjs.org/docs/basic-features/pages) для получения дополнительной информации.
#### `src/pages/api`
Папка `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/).
#### `src/pages/api/auth/[...nextauth].ts`
Файл `[...nextauth].ts` - это слаг-маршрут NextAuth.js для аутентификации. Он используется для обработки запросов аутентификации. Смотрите [Использование NextAuth.js](/ru/usage/next-auth) для получения дополнительной информации о NextAuth.js и [документацию Next.js о динамических маршрутах](https://nextjs.org/docs/routing/dynamic-routes) для получения информации о маршрутах catch-all/slug.
#### `src/pages/api/trpc/[trpc].ts`
Файл `[trpc].ts` - это точка входа tRPC API. Он используется для обработки запросов tRPC. Смотрите [Использование tRPC](/ru/usage/trpc#-pagesapitrpctrpcts) для получения дополнительной информации об этом файле и [документацию Next.js о динамических маршрутах](https://nextjs.org/docs/routing/dynamic-routes) для получения информации о маршрутах catch-all/slug.
### `src/server`
Папка `server` используется для четкого разделения серверного кода от клиентского кода.
#### `src/server/auth.ts`
Содержит утилиты для аутентификации, такие как получение сеанса пользователя на стороне сервера. Смотрите [Использование NextAuth.js](/ru/usage/next-auth#usage-with-trpc) для получения дополнительной информации.
#### `src/server/db.ts`
Файл `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) для получения дополнительной информации.
### `src/server/api`
Папка `api` содержит серверный код tRPC.
#### `src/server/api/routers`
Папка `routers` содержит все ваши под-маршрутизаторы tRPC.
#### `src/server/api/routers/example.ts`
Файл `example.ts` - это пример маршрутизатора tRPC, использующий вспомогательную функцию `publicProcedure` для демонстрации того, как создать публичный маршрут tRPC.
Основываясь на выбранных вами пакетах, этот маршрутизатор содержит больше или меньше маршрутов для лучшего демонстрирования использования ваших потребностей.
#### `src/server/api/trpc.ts`
Файл `trpc.ts` - это основной файл конфигурации для вашего tRPC-бэкэнда. В нем мы:
1. Определяем контекст используемый в запросах tRPC. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapitrpcts) для получения дополнительной информации.
2. Экспортируем вспомогательные функции процедур. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapitrpcts) для получения дополнительной информации.
#### `src/server/api/root.ts`
Файл `root.ts` используется для слияния маршрутизаторов tRPC и экспорта их как единого маршрутизатора, а также определения типа маршрутизатора. Смотрите [Использование tRPC](/ru/usage/trpc#-serverapirootts) для получения дополнительной информации.
### `src/styles`
Папка `styles` содержит глобальные стили приложения.
### `src/types`
Папка `types` используется для хранения повторно используемых типов или объявлений типов.
#### `src/types/next-auth.d.ts`
Файл `next-auth.d.ts` используется для расширения типа сеанса по умолчанию NextAuth на включение идентификатора пользователя. Смотрите [Использование NextAuth.js](/ru/usage/next-auth#включение-userid-в-сеанс) для получения дополнительной информации.
### `src/utils`
Папка `utils` используется для хранения повторно используемых функций утилит.
#### `src/utils/api.ts`
Файл `api.ts` является точкой входа для tRPC на стороне клиента. Смотрите [Использование tRPC](/ru/usage/trpc#-utilsapits) для получения дополнительной информации.
### `.env`
Файл `.env` используется для хранения переменных среды. Смотрите [Переменные среды](/ru/usage/env-variables) для получения дополнительной информации. Этот файл **не** должен быть добавлен в историю git.
### `.env.example`
Файл `.env.example` показывает пример переменных среды на основе выбранных библиотек. Этот файл должен быть добавлен в историю git.
### `.eslintrc.cjs`
Файл `.eslintrc.cjs` используется для настройки ESLint. Смотрите [документацию ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) для получения дополнительной информации.
### `next-env.d.ts`
Файл `next-env.d.ts` гарантирует, что типы Next.js будут обнаружены компилятором TypeScript. **Вы не должны удалять его или редактировать, поскольку он может измениться в любое время.** Смотрите [документацию Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) для получения дополнительной информации.
### `next.config.mjs`
Файл `next.config.mjs` используется для настройки Next.js. Смотрите [Документацию Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) для получения дополнительной информации. Примечание: Расширение .mjs используется для разрешения импортов ESM.
### `postcss.config.js`
Файл `postcss.config.js` используется для использования Tailwind PostCSS. Смотрите [документацию Taiwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) для получения дополнительной информации.
### `prettier.config.mjs`
Файл `prettier.config.mjs` используется для настройки Prettier для включения prettier-plugin-tailwindcss для форматирования классов Tailwind CSS. Смотрите [пост блога Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) для получения дополнительной информации.
### `tsconfig.json`
Файл `tsconfig.json` используется для настройки TypeScript. Некоторые значения по умолчанию, такие как `strict mode`, были включены для обеспечения лучшего использования TypeScript для create-t3-app и его библиотек. Смотрите [документацию TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) или [Использование TypeScript](usage/typescript) для получения дополнительной информации.
================================================
FILE: www/src/pages/ru/installation.mdx
================================================
---
title: Установка
description: Инструкции по установке Create T3 App
layout: ../../layouts/docs.astro
lang: ru
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Для создания приложения с помощью `create-t3-app`, запустите одну из следующих трёх команд и ответьте на вопросы командной строки:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
После того, как приложение будет создано, ознакомьтесь с [первыми шагами](/ru/usage/first-steps), чтобы начать работу над вашим новым приложением.
## Дополнительные параметры
| Опции/Флаги | Описание |
| ----------------- | ---------------------------------------------------------------------------- |
| `[dir]` | Добавьте аргумент каталога с именем проекта |
| `--noGit` | Явно сообщите CLI не инициализировать новый git репозиторий в проекте |
| `-y`, `--default` | Обойти CLI и создать новое t3-приложение с помощью всех выбранных параметров |
| `--noInstall` | Сгенерировать проект без установки зависимостей |
## Экспериментальное использование
Для нашего CI мы имеем некоторые экспериментальные флаги, которые позволяют создавать любое приложение без каких-либо запросов. Если это применимо к вашему случаю, вы можете использовать эти флаги. Обратите внимание, что эти флаги являются экспериментальными и могут измениться в будущем без следования версированию semver.
| Опции/Флаги | Описание |
| ------------ | ------------------------------------------- |
| `--CI` | Сообщите CLI, что вы находитесь в режиме CI |
| `--trpc` | Добавить tRPC в проект |
| `--prisma` | Добавить Prisma в проект |
| `--nextAuth` | Добавить NextAuth в проект |
| `--tailwind` | Добавить Tailwind CSS в проект |
если вы не указываете флаг `CI`, то остальные флаги не имеют эффекта.
Вам не нужно явно отказываться от пакетов, которые вам не нужны. Однако, если вы предпочитаете быть явным, вы можете передать `false`, например `--nextAuth false`.
### Например
Следующий пример создаст приложение T3 с tRPC и Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/ru/introduction.md
================================================
---
title: Введение
description: Введение в T3 стек
layout: ../../layouts/docs.astro
lang: ru
---
## T3 Stack
_«T3 Stack»_ - это стек веб-разработки, созданный [Theo](https://twitter.com/t3dotgg), с упором на простоту, модульность и full-stack типизацию.
Основные части - [**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/) - отличные дополнения.
Вы могли заметить, что существует… много частей. Это сделано намеренно. Меняйте части в зависимости от ваших потребностей - этот стек является модульным по своей сути :)
## И... что такое create-t3-app? Шаблон?
Возможно? `create-t3-app` это CLI, созданный опытными разработчиками T3 стека, чтобы упростить настройку модульного приложения T3 стека. Это означает, что каждая часть является необязательной, и «шаблон» генерируется на основе ваших конкретных потребностей.
После множества проектов и многих лет с этой технологией у нас есть множество мнений и знаний. Мы постарались зафиксировать их в этом CLI.
Это **НЕ** всеобъемлющий шаблон. Мы **ожидаем**, что вы будете использовать свои собственные библиотеки, которые решают потребности **ВАШЕГО** приложения. Хотя мы не хотим назначать решения для более конкретных проблем, таких как управление состоянием и развертывание, мы [имеем некоторые рекомендации, перечисленные здесь](/ru/other-recs).
## Аксиомы T3
Будем честными - это _субъективный проект_. Мы поделились несколькими основными убеждениями вокруг создания и рассматриваем их как основу для наших решений.
### Решайте проблемы
Легко попасть в ловушку "добавления всего" - мы явно не хотим этого делать. Все, что добавляется в `create-t3-app`, должно решать конкретную проблему, которая существует в основных технологиях, включенных в него. Это означает, что мы не добавим библиотеки менеджмента состояния (`zustand`, `redux`), но мы добавим NextAuth.js и интегрируем Prisma и tRPC для вас.
### Ответственность к новинкам
Мы любим технологические новинки. Получаемые скорость и, честно говоря, веселье от новых фиговин, действительно круто. Мы считаем важным использовать их ответственно, используя более рискованные технологии в менее рискованных частях. Это означает, что мы не будем ⛔️ делать ставку на рискованную новую технологию базы данных (SQL - это здорово!). Но мы с удовольствием ✅ сделаем ставку на tRPC, поскольку это просто функции, которые легко перенести.
### Типобезопасность не является опциональной
Указаная цель `create-t3-app` - это предоставить самый быстрый способ начать новое полнофункциональное, **типобезопасное** веб-приложение. Мы серьезно относимся к типобезопасности в этих частях, поскольку она повышает нашу продуктивность и помогает нам отправлять меньше ошибок. Любое решение, которое снижает типобезопасность `create-t3-app`, должно быть принято в другом проекте.
================================================
FILE: www/src/pages/ru/other-recs.md
================================================
---
title: Дополнительные рекомендации
description: Библиотеки и сервисы, которые мы рекомендуем для многих проектов
layout: ../../layouts/docs.astro
lang: ru
---
Мы понимаем, что библиотеки, включенные в `create-t3-app`, не решают каждую проблему. Хотя мы рекомендуем начать свой проект с того, что мы предоставляем, придет время, когда вам нужно будет установить другие пакеты. Только вы можете знать, в чем нуждается ваш проект, но вот некоторые решения, которые мы часто рекомендуем.
Это рекомендации отдельных участников create-t3-app и не должны рассматриваться как "официальные" одобрения команды create-t3-app или T3-OSS. _**Пожалуйста, проведите собственное исследование, особенно перед тем, как привязываться к платным услугам**_.
## Управление состоянием
_**Примечание редактора**_: Библиотеки управления состоянием могут быть отличными, но часто не требуются. Хуки React Query tRPC должны справиться с вашим серверным состоянием. Для клиентского состояния начните с `useState` React, и обратитесь к одному из этих вариантов, когда вам нужно больше.
### Zustand
**Для того, чтобы больше никогда не писать Redux**
"Современный простой Redux", который вы не знали, что вам нужен. [Poimandres](https://github.com/pmndrs) всегда можно доверять. Вы можете создавать все, от видеозвонков до игр и серверов с этой маленькой библиотекой.
- [Zustand Homepage](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
### Jotai
**Для того, чтобы больше никогда не писать Context**
В атомарном подходе Jotai трудно превзойти. Также от [Poimandres](https://github.com/pmndrs), Jotai позволяет определять синглтоны, которые кажутся глобальными useState. Отличный вариант для состояний, которые не требуют машины состояний прямо сейчас.
- [Jotai Homepage](https://jotai.org/)
- [Jotai GitHub](https://github.com/pmndrs/jotai)
## Библиотеки компонентов
Большинство приложений нуждаются в некотором наборе компонентов: переключатели, выпадающие меню, модальные окна и т.д. Эти библиотеки предоставляют отличные, доступные компоненты, которые вы можете использовать и настраивать по своему усмотрению.
### Библиотеки компонентов без стилей
Также известны как headless библиотеки, они предоставляют отличные, нестилизованные и доступные компоненты, которые вы можете настроить по своему усмотрению. Вот несколько рекомендаций.
- [Radix UI](https://www.radix-ui.com/) предоставляет вам мощный набор удобных и доступных примитивов, которые вы можете стилизовать с помощью обычного CSS или Tailwind CSS.
- [Headless UI](https://headlessui.com/) от команды Tailwind CSS также предоставляет нестилизованные, доступные компоненты, которые интегрируются безупречно с Tailwind CSS.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) предоставляет доступные примитивы UI для вашей системы дизайна. Их компонент выбора даты - это высший уровень.
### Библиотеки компонентов со стилями
**Когда вам просто нужно, чтобы ваше приложение выглядело неплохо**
Иногда вы создаете проект, где вам просто нужно, чтобы пользовательский интерфейс выглядел нормально из коробки. Для административных панелей управления и других подобных проектов любая из этих библиотек компонентов справится с этой задачей.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
- [@shadcn/ui](https://ui.shadcn.com/)
### Class Variance Authority
**Для создания библиотек пользовательского интерфейса**
Декларативно создавайте библиотеку пользовательского интерфейса с различными цветовыми, размерными и т.д. вариантами. Когда ваш проект достигает масштаба, где вам нужен стандартизированный набор компонентов пользовательского интерфейса с несколькими вариантами с использованием Tailwind CSS, CVA - отличный инструмент.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Анимации
Наши рекомендации для создания анимаций в вашем приложении.
### AutoAnimate
**Для анимаций с одной строкой кода**
Большенство библиотек анимации пытаются удовлетворить каждый возможный случай использования и в результате становятся громоздкими. AutoAnimate - это инструмент без конфигурации, который даст вам значительное улучшение UX без дополнительных усилий разработчика.
- [Главная страница AutoAnimate](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [Компонент для AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Для сложных анимаций с декларативным кодом**
Framer Motion предоставляет простой, декларативный синтаксис и позволяет вам писать меньше кода для создания всего: от сложных анимаций и даже до жестов.
- [Framer Motion Homepage](https://framer.com/motion)
- [Framer Motion Documentation](https://www.framer.com/docs/)
## Развертывание, инфраструктура, базы данных и CI
### Vercel
**Для хостинга (размещения) вашего приложения**
Vercel убрал мучения из процесса развертывания веб-приложений и сделал его простой "установил-и-забыл" интеграцией GitHub. Мы масштабировались до сотен тысяч пользователей без проблем. Работает на базе AWS, но имеет простой и удобный интерфейс :)
- [Главная страница Vercel](https://vercel.com/)
- [Гайд по развертыванию T3 приложения на Vercel](/ru/deployment/vercel)
### PlanetScale
**Для баз данных без беспокойства**
PlanetScale - лучшая serverless платформа для баз данных, которую мы использовали до сих пор. Невероятная масштабируемость, отличный DX и фантастическая цена. Если вы используете SQL (и, надеюсь, Prisma), это трудно превзойти.
- [Главная страница PlanetScale](https://planetscale.com/)
### Railway
**Для размещения вашей инфраструктуры**
"Современный Heroku". Самый простой способ запустить реальный сервер. Если вам не хватает функционала Vercel и PlanetScale, то Railway, вероятно, вам подойдет. Укажите его на репозиторий GitHub и готово.
- [Главная страница Railway](https://railway.app/)
### Upstash
**Для безсерверного Redis**
Мы любим Prisma и PlanetScale, но некоторые проекты требуют более производительного решения. Upstash позволяет вам получить in-memory производительность Redis в вашем безсерверном проекте, не заботясь о самостоятельном управлении инфраструктурой и масштабированием.
- [Главная страница Upstash](https://upstash.com/)
### Pusher
**Для безсерверных WebSocket**
Если WebSocket является основным фокусом вашего проекта, вы можете рассмотреть более традиционный бэкенд, такой как [Fastify](https://www.fastify.io/) (который [также работает с tRPC!](https://trpc.io/docs/v10/fastify)). Но для быстрого добавления WebSocket в T3 App, Pusher - отличный выбор.
- [Главная страница Pusher](https://pusher.com/)
### Soketi
Soketi - это само-развертываемая, простая и быстрая альтернатива Pusher. Он полностью совместим с Pusher SDK, который вы можете использовать для подключения к серверу. Soketi serverless также находится в бета-версии.
- [Главная страница Soketi](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Аналитика
Пользовательские данные очень ценны, когда вы создаете приложение. Вот несколько рекомендуемых провайдеров аналитики.
### Plausible
Нужна аналитика? Plausible - один из самых быстрых способов ее получить. Супер минималистичный. У него даже есть [простой плагин для Next.js](https://plausible.io/docs/proxy/guides/nextjs).
- [Главная страница Plausible](https://plausible.io/)
### Umami
Umami - это само-развертываемая, простая, быстрая и конфиденциальная альтернатива Google Analytics. Вы можете легко развернуть его на Vercel, Railway и т.д. с PlanetScale в качестве базы данных.
- [Главная страница Umami](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
## Другое
### Next Bundle Analyzer
Бывает сложно определить, что будет включено в сборку выходных данных для вашего приложения. Next Bundle Analyzer - это простой способ визуализировать и анализировать JavaScript-бандлы, которые генерируются.
- [@next/bundle-analyzer на npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/ru/t3-collection.mdx
================================================
---
title: T3 коллекция
description: Крутые open source проекты и компании использующие T3 стек
layout: ../../layouts/docs.astro
lang: ru
isMdx: true
---
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
import Callout from "../../components/docs/callout.tsx";
Сделали проект использующий T3 стек и хотите поделиться им? Добавьте его в список!
## Open Source приложения сделанные с использованием T3 стека
## Компании использующие T3 стек
Нам бы очень хотелось узнать о компаниях использующих T3 стек для своих приложений. Ваша компания использует T3 стек и вы хотите поделиться этим? Добавьте её в список!
Крутой проект использующий T3 стек? Сделайте [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) и добавьте его в список!
================================================
FILE: www/src/pages/ru/usage/env-variables.mdx
================================================
---
title: Переменные среды
description: Начало работы с Create T3 App
layout: ../../../layouts/docs.astro
lang: ru
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Create T3 App использует собственный пакет [@t3-oss/env-nextjs](https://env.t3.gg) вместе с [Zod](https://github.com/colinhacks/zod) для валидации переменных среды во время выполнения _и_ во время сборки, предоставляя простую логику в файле `src/env.js`:
## env.js
_TLDR; Если вы хотите добавить новую переменную среды, вам следует добавить валидатор в `src/env.js`, а затем пару ключ-значение в `.env`._
```ts:env.js
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
},
});
```
T3 Env использует `createEnv`, который отвечает за создание схемы и будет включать главную логику валидации для клиентских и серверных переменных среды.
Для получения дополнительной информации о том, как `createEnv` работает
изнутри, посмотрите документацию [T3 Env](https://env.t3.gg/docs/introduction)
(EN)
## Использование переменных среды
Когда вы хотите использовать переменные среды, вы можете импортировать их из `env.js` и использовать их как вы обычно использовали бы. Если вы импортируете этот файл на стороне клиента и попробуете получить серверную переменную, вы получите ошибку выполнения:
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` полностью типобезопасно и предоставляет автокомплит
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ Это даст ошибку
const dbUrl = env.DATABASE_URL;
// ✅ Тут все ОК
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Из-за того, что файл `.env` по умолчанию не добавляется в систему контроля версий, мы также добавили файл `.env.example`, в котором вы можете по желанию сохранить копию вашего файла `.env` с удаленными секретами. Это необязательно, но мы рекомендуем держать пример в актуальном состоянии, чтобы сделать процесс настройки среды для новых участников проекта как можно проще.
Некоторые фреймворки и инструменты сборки, такие как Next.js, предлагают хранить секреты в файле `.env.local` и коммитить файлы `.env` в ваш проект. Это не рекомендуется, поскольку это может облегчить случайный коммит секретов в ваш проект. Вместо этого мы рекомендуем хранить секреты в `.env`, держать ваш файл `.env` в `.gitignore` и коммитить только файлы `.env.example` в ваш проект.
## Добавление переменных среды
Для того, чтобы убедиться, что ваша сборка никогда не завершится без переменных среды, которые проект требует, вам нужно добавить новые переменные среды в **двух** местах:
📄 `.env`: Введите переменную среды, как обычно делаете в файле `.env`, т.е. `KEY=VALUE`
📄 `env.js`: Добавьте соответствующую логику валидации для переменных среды, определив для каждой из них Zod схему внутри `createEnv`, например `KEY: z.string()`. Кроме этого, убедитесь в том, что вы деструкткрировали их в опции `runtimeEnv`, например `KEY: process.env.KEY`.
Зачем нужно деструктурировать переменные среды внутри `runtimeEnv`? Это
связано с тем, как Next.js собирает переменные среды в некоторых рантаймах.
Деструктурируя их вручную, мы гарантируем, что эти переменные не будут убраны
из финальной сборки.
Опционально, вы также можете обновлять файл `.env.example`:
📄 `.env.example`: Введите вашу переменную среды, но убедитесь, что не включаете значение, если оно является секретным, т.е. `KEY=VALUE` или `KEY=`
### Пример
_Я хочу добавить мой Twitter API токен в качестве переменной среды на стороне сервера_
1. Добавьте переменную среды в `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Добавьте переменную среды в `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.string(),
},
// ...
runtimeEnv: {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
},
});
```
3. _Опционально:_ Добавьте переменную среды в `.env.example`, но не включайте токен в `runtimeEnv`
```
TWITTER_API_TOKEN=
```
================================================
FILE: www/src/pages/ru/usage/first-steps.md
================================================
---
title: Первые шаги
description: Начало работы с вашим новым T3 App
layout: ../../../layouts/docs.astro
lang: ru
---
Вы только что создали новое приложение T3 и готовы к работе. Вот минимальный набор для запуска вашего приложения.
## База данных
Если ваше приложение включает Prisma, убедитесь, что вы запустили `npx prisma db push` из корневого каталога вашего приложения. Эта команда синхронизирует схему Prisma с вашей базой данных и генерирует типы TypeScript для Prisma Client на основе вашей схемы. Обратите внимание, что вам нужно перезапустить сервер TypeScript после этого, чтобы он мог обнаружить сгенерированные типы.
## Аутентификация
Если ваше приложение включает NextAuth.js, мы начинаем с `DiscordProvider`. Это один из самых простых провайдеров, предлагаемый NextAuth.js, однако он все еще требует некоторой начальной настройки с вашей стороны.
Конечно, если вы предпочитаете использовать другой провайдер аутентификации, вы также можете использовать один из [многих провайдеров](https://next-auth.js.org/providers/), которые предлагает NextAuth.js.
1. Вам нужен аккаунт Discord, поэтому зарегистрируйтесь, если еще не зарегистрировались.
2. Перейдите на https://discord.com/developers/applications и нажмите «New Application» в правом верхнем углу. Дайте вашему приложению имя и согласитесь с Условиями использования.
3. Когда вы создадите приложение, перейдите к «Settings → OAuth2 → General».
4. Скопируйте «Client ID» и добавьте его в ваш `.env` как `AUTH_DISCORD_ID`.
5. Нажмите «Reset Secret», скопируйте новый секрет и добавьте его в ваш `.env` как `AUTH_DISCORD_SECRET`.
6. Нажмите «Add Redirect» и введите `http://localhost:3000/api/auth/callback/discord`.
- Для развертывания в продакшене следуйте предыдущим шагам для создания другого приложения Discord, но на этот раз замените `http://localhost:3000` на URL, на который вы развертываете.
7. Сохраните изменения.
Теперь у вас должна быть возможность войти в систему.
## Следующие шаги
- Если ваше приложение включает tRPC, ознакомьтесь с `src/pages/index.tsx` и `src/server/trpc/router/post.ts`, чтобы узнать, как работают запросы tRPC.
- Посмотрите на документацию `create-t3-app`, а также на документацию пакетов, которые включает ваше приложение.
- Присоединяйтесь к нашему [Discord](https://t3.gg/discord) и поставьте звезду на [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/ru/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Использование",
layout: "docs",
description: "Научитесь использовать различные технологии из T3 Stack.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/ru/usage/next-auth.md
================================================
---
title: NextAuth.js
description: Использование NextAuth.js
layout: ../../../layouts/docs.astro
lang: ru
---
Когда вы хотите иметь систему аутентификации в вашем приложении Next.js, NextAuth.js - отличное решение, чтобы не заморачиваться с реализацией сложной безопасности самостоятельно. Он имеет обширный список провайдеров для быстрого добавления аутентификации OAuth и предоставляет адаптеры для многих баз данных и ORM.
## Провайдер контекста
В точке входа вашего приложения вы увидите, что ваше приложение обернуто в [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
```
Этот провайдер контекста позволяет вашему приложению получить доступ к данным сессии из любого места вашего приложения, не передавая их как пропсы:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Получение сессии на сервере
Иногда вам может понадобиться запросить сессию на сервере. Чтобы сделать это, предварительно получите сессию с помощью функции-помощника `getServerAuthSession`, которую предоставляет `create-t3-app`, и передайте ее на клиент с помощью `getServerSideProps`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTE: `session` wont have a loading state since it's already prefetched on the server
...
}
```
## Включение `user.id` в сессию
`create-t3-app` настроен для использования [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) в конфигурации NextAuth.js для включения ID пользователя в объект `session`.
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Это связано с файлом объявления типов, чтобы убедиться, что `user.id` типизирован при доступе к объекту `session`. Подробнее о [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) в документации NextAuth.js.
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user?: {
id: string;
} & DefaultSession["user"];
}
}
```
Такой же шаблон может быть использован для добавления любых других данных в объект `session`, например, поля `role`, но **не следует злоупотреблять для хранения конфиденциальных данных** на клиенте.
## Использование с tRPC
При использовании NextAuth.js с tRPC вы можете создавать повторно используемые, защищенные процедуры с помощью [middleware](https://trpc.io/docs/v10/middlewares). Это позволяет вам создавать процедуры, которые могут быть доступны только аутентифицированным пользователям. `create-t3-app` настраивает все это для вас, позволяя вам легко получать доступ к объекту сессии в аутентифицированных процедурах.
Это делается в два шага:
1. Возьмите сессию из заголовков запроса с помощью функции [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Преимущество использования `getServerSession` вместо обычного `getSession` заключается в том, что это server-side функция и она не вызывает ненужных вызовов fetch. `create-t3-app` создает вспомогательную функцию, которая абстрагирует этот особый API.
```ts:server/auth.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, authOptions);
};
```
Используя эту вспомогательную функцию, мы можем получить сессию и передать ее в контекст tRPC:
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. Создайте tRPC middleware, которое проверяет, аутентифицирован ли пользователь. Затем мы используем middleware в `protectedProcedure`. Любой вызывающий эти процедуры должен быть аутентифицирован, иначе будет сгенерирована ошибка, которую можно правильно обработать на стороне клиента.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
})
```
Обект сессии - это легкое, минимальное представление пользователя и содержит только несколько полей. При использовании `protectedProcedures` у вас есть доступ к идентификатору пользователя, который можно использовать для получения большего количества данных из базы данных.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Использование с Prisma
Чтобы заставить 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/). Обратите внимание, что некоторые провайдеры требуют дополнительных полей для добавления в определенные модели. Мы рекомендуем вам прочитать документацию для провайдера, который вы хотите использовать, чтобы убедиться, что у вас есть все необходимые поля.
### Добавление новых полей в ваши модели
Когда вы добавляете новые поля в любую из моделей `User`, `Account`, `Session` или `VerificationToken` (в большинстве случаев вам потребуется только изменить модель `User`), вам нужно иметь в виду, что [адаптер Prisma](https://next-auth.js.org/adapters/prisma) автоматически создает поля в этих моделях при регистрации новых пользователей и входе в систему. Поэтому, добавляя новые поля в эти модели, вы должны предоставить значения по умолчанию для них, поскольку адаптер не знает о них.
Если например, вы хотите добавить `role` в модель `User`, вам нужно будет предоставить значение по умолчанию для поля `role`. Это делается путем добавления значения `@default` к полю `role` в модели `User`:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Использование с Next.js middleware
Использование NextAuth.js с Next.js middleware [требует использования стратегии сеанса JWT](https://next-auth.js.org/configuration/nextjs#caveats) для аутентификации. Это связано с тем, что middleware может получить доступ к сессионной cookie только в том случае, если это JWT. По умолчанию, `create-t3-app` настроен на использование **default** стратегии базы данных, в сочетании с Prisma в качестве адаптера базы данных.
## Настраиваем DiscordProvider по умолчанию
1. Перейдите в [раздел Applications в Discord Developer Portal](https://discord.com/developers/applications), и нажмите на "New Application"
2. В меню настроек перейдите к "OAuth2 => General"
- Скопируйте Client ID и вставьте его в `AUTH_DISCORD_ID` в `.env`.
- Возле Client Secret нажмите "Reset Secret" и скопируйте эту строку в `AUTH_DISCORD_SECRET` в `.env`. Будьте осторожны, поскольку вы больше не сможете увидеть этот секрет, и сброс его приведет к тому, что существующий истечет.
- Нажмите "Add Redirect" и вставьте `/api/auth/callback/discord` (пример для локальной разработки: http://localhost:3000/api/auth/callback/discord)
- Сохраните изменения
- Возможно, но не рекомендуется, использовать одно и то же приложение Discord для разработки и продакшена. Вы также можете рассмотреть [Mocking the Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) во время разработки.
## Полезные ресурсы
| Ресурс | Ссылка |
| --------------------------------- | --------------------------------------- |
| Документация NextAuth.js | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/ru/usage/next-js.md
================================================
---
title: Next.js
description: Использование Next.js
layout: ../../../layouts/docs.astro
lang: ru
---
Next.js это бэкенд фреймворк для ваших React приложений.
Посмотрите [выступление Theo на Next.js Conf](https://www.youtube.com/watch?v=W4UhNo3HAMw) чтобы получить более подробное понимание того, что такое Next.js и как он работает.
## Почему я должен это использовать?
Мы любим React. Он сделал разработку UI доступной в том смысле, в котором мы раньше этого не могли себе представить. Он также может провести разработчиков по некоторым тернистым тропам. Next.js предлагает слегка субъективный, но очень оптимизированный подход к созданию приложений с использованием React. От маршрутизации до определений API до рендеринга изображений, мы доверяем Next.js, чтобы вести разработчиков к правильным решениям.
Совмещая Next.js с [Vercel](https://vercel.com/), вы можете разрабатывать и разворачивать веб-приложения легче, чем когда-либо. Их чрезвычайно щедрый бесплатный тариф и супер интуитивный интерфейс предоставляют решение в один клик для развертывания вашего сайта (Мы ❤️ Vercel)
## Get Static/Server Props
Ключевые особенности 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`, когда данные динамичны и могут быть получены постепенно.
## Полезные ресурсы
| Ресурс | Ссылка |
| ------------------------------- | ---------------------------------- |
| Документация Next.js | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Блог Next.js | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Канал Vercel/Next.js на YouTube | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/ru/usage/prisma.md
================================================
---
title: Prisma
description: Использование Prisma
layout: ../../../layouts/docs.astro
lang: ru
---
Prisma это ORM для TypeScript, который позволяет определять схему и модели базы данных в файле `schema.prisma`, а затем генерировать клиент, который обеспечивает типобезопасность и может использоваться для взаимодействия с базой данных из вашего бэкенда.
## Prisma Client
Расположенный в `/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) по умолчанию и рекомендуем использовать его вместо отдельного импорта в каждом файле.
## Схема
Вы найдете файл схемы Prisma в `/prisma/schema.prisma`. Этот файл используется для определения схемы и моделей базы данных, а также для генерации Prisma Client.
### С NextAuth.js
Когда вы выбираете NextAuth.js в сочетании с Prisma, файл схемы генерируется и настраевается для вас с рекомендуемыми значениями для моделей `User`, `Session`, `Account` и `VerificationToken`, согласно [документации NextAuth.js](https://next-auth.js.org/adapters/prisma).
## База данных по умолчанию
База данных по умолчанию - это база данных SQLite, которая отлично подходит для разработки и быстрого создания proof-of-concept, но не рекомендуется для использования в продакшене. Вы можете изменить базу данных, используя `provider` в блоке `datasource` на `postgresql` или `mysql`, а затем обновить строку подключения в переменных окружения, чтобы указать на вашу базу данных.
## Заполнение (seeding) базы данных
[Заполнение (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` или другие раннеры также будут работать.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Затем, просто запустите `pnpm db-seed` (или `npm`/`yarn`), чтобы заполнить вашу базу данных.
## Полезные ресурсы
| Ресурс | Ссылка |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Документация Prisma | https://www.prisma.io/docs/ |
| Prisma GitHub | https://github.com/prisma/prisma |
| NextAuth.JS Адаптер для Prisma | https://next-auth.js.org/adapters/prisma |
| Гайд по подключению PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/ru/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Использование Tailwind CSS
layout: ../../../layouts/docs.astro
lang: ru
---
## Что такое Tailwind CSS?
Tailwind CSS - это небольшой, [utility first](https://tailwindcss.com/docs/utility-first) CSS фреймворк для создания собственного дизайна, без переключения контекста, которое требуется для обычного CSS. Это чисто CSS фреймворк и не предоставляет никаких предварительно собранных компонентов или логики, и предоставляет [принципиально иной набор преимуществ](https://www.youtube.com/watch?v=CQuTF-bkOgc) по сравнению с библиотекой компонентов, такой как Material UI.
Он делает CSS невероятно легким и быстрым для написания, как показано в следующем примере:
Старый CSS:
1. Напишите CSS, часто в отдельном файле
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Импортируйте CSS в ваш компонент
```jsx
import "./my-class.css";
```
3. Добавьте класс в ваш HTML
```html
...
```
Эквивалент в Tailwind:
1. Просто напишите классы в вашем HTML
```html
...
```
Используя вместе с React компонентами, он является чрезвычайно мощным для быстрого создания UI.
Tailwind CSS содержит встроенную красивую систему дизайна, которая поставляется из коробки с тщательно выбранной цветовой палитрой, размерами для стилей, таких как ширина/высота и отступы для единого дизайна, а также точками прерывания для создания адаптивных макетов. Эта система дизайна может быть настроена и расширена для создания точного набора стилей, которые необходимы вашему проекту.
Tru Narla лучше известна как [mewtru](https://twitter.com/trunarla) дала потрясающую лекцию о [создании системы дизайна с использованием Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).
## Использование
Убедитесь, что у вас установлены плагины редактора для Tailwind, чтобы улучшить ваш опыт написания Tailwind.
### Расширения и плагины
- [Расширение для VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Форматирование
Классы 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 мы установим и настроим это для вас.
### Добавление классов в зависимости от условий
Добавление классов в зависимости от условий с использованием тернарных операторов может стать очень беспорядочным и трудночитаемым. Эти пакеты помогают организовать ваши классы при использовании некоторой логики с условиями.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Полезные ресурсы
| Ресурс | Ссылка |
| ----------------------------- | -------------------------------------------------------- |
| Документация Tailwind | https://tailwindcss.com/docs/editor-setup/ |
| Шпаргалка по Tailwind | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Сервер Tailwind в Discord | https://tailwindcss.com/discord/ |
| Канал TailwindLabs на Youtube | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/ru/usage/trpc.md
================================================
---
title: tRPC
description: Использование tRPC
layout: ../../../layouts/docs.astro
lang: ru
---
tRPC позволяет нам писать типобезопасные API от конца до конца (end-to-end) без какой-либо генерации кода или накладных расходов на выполнение. Он использует отличную инференцию TypeScript для вывода типов маршрутизатора вашего API и позволяет вызывать процедуры API из вашего фронтенда с полной типобезопасностью и автодополнением. Используя tRPC, ваш фронтенд и бэкенд чувствуют себя ближе друг к другу, чем когда-либо, обеспечивая исключительный опыт разработчика.
"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."
## Файлы
tRPC требует много шаблонного кода, который `create-t3-app` настраивает для вас. Давайте рассмотрим файлы, которые генерируются:
### 📄 `pages/api/trpc/[trpc].ts`
Этот файл является точкой входа для вашего 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.
### 📄 `server/api/trpc.ts`
Этот файл разделен на две части: создание контекста и инициализация tRPC.
1. Мы определяем контекст, который передается вашим tRPC процедурам. Контекст - это данные, к которым у вас есть доступ во всех ваших tRPC процедурах, и это отличное место, чтобы поместить вещи, такие как соединения с базой данных, информация об аутентификации и т.д. В create-t3-app мы используем две функции, чтобы включить использование подмножества контекста, когда у нас нет доступа к объекту запроса.
- `createInnerTRPCContext`: Это то место, где вы определяете контекст, который не зависит от запроса, например, ваше соединение с базой данных. Вы можете использовать эту функцию для [интеграционного тестирования](#sample-integration-test) или [ssg-помощников](https://trpc.io/docs/v10/ssg-helpers), где у вас нет объекта запроса.
- `createTRPCContext`: Здесь вы определяете контекст, который зависит от запроса: например, сессия пользователя. Вы запрашиваете сессию с помощью объекта `opts.req`, а затем передаете сессию в функцию `createInnerTRPCContext` для создания окончательного контекста.
2. Мы инициализируем tRPC и определяем повторно используемые [процедуры](https://trpc.io/docs/v10/procedures) и [посредники](https://trpc.io/docs/v10/middlewares). По соглашению, вы не должны экспортировать весь объект `t`, а вместо этого создавать повторно используемые процедуры и посредники и экспортировать их.
Вы заметите что мы используем `superjson` как [преобразователь данных](https://trpc.io/docs/v10/data-transformers). Это позволяет сохранять типы данных, когда они достигают клиента, поэтому если вы, например, отправляете объект `Date`, клиент вернет `Date`, а не строку, что является случаем для большинства API.
### 📄 `server/api/routers/*.ts`
Это то место, где вы определяете маршруты и процедуры вашего API. Вы [создаете отдельные маршрутизаторы](https://trpc.io/docs/v10/router) для связанных процедур.
### 📄 `server/api/root.ts`
Здесь мы [объединяем](https://trpc.io/docs/v10/merging-routers) все под-маршрутизаторы, определенные в `routers/**` в единый маршрутизатор приложения.
### 📄 `utils/api.ts`
Это точка входа для tRPC на фронтенде. Здесь вы импортируете **определение типов** маршрутизатора и создаете клиент tRPC вместе с хуками react-query. Поскольку мы включили `superjson` в качестве преобразователя данных на бэкенде, нам также нужно включить его на фронтенде. Это связано с тем, что сериализованные данные с бэкенда десериализуются на фронтенде.
Здесь вы определите свои [ссылки](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), который выводит полезные журналы запросов во время разработки.
В конце концов, мы экспортируем [вспомогательный тип](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type), который вы можете использовать для вывода типов на фронтенде.
## Как я могу использовать tRPC?
tRPC контрибьютор [trashh_dev](https://twitter.com/trashh_dev) [выступил на Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) с рассказом о tRPC. Мы настоятельно рекомендуем вам посмотреть его, если вы еще не сделали это.
С tRPC вы пишете функции TypeScript на бэкенде, а затем вызываете их из фронтенда. Простая процедура tRPC может выглядеть так:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Это процедура tRPC (эквивалент обработчика маршрута в традиционном бэкенде), которая сначала проверяет входные данные с помощью Zod (который является той же библиотекой проверки, которую мы используем для [переменных окружения](./env-variables)) - в этом случае мы убеждаемся, что входные данные являются строкой. Если входные данные не являются строкой, он отправит информативную ошибку.
После входных данных мы применяем 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` совпадает с тем, который мы передали.
Вы определяете свои процедуры в `роутерах` которые представляют собой коллекцию связанных процедур с общим пространством имен. У вас может быть один роутер для `пользователей`, один для `постов` и еще один для `сообщений`. Эти роутеры затем можно объединить в единый централизованный `appRouter`:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Обратите внимание на то, что нам нужно экспортировать только типы наших роутеров, что означает, что мы никогда не импортируем серверный код на клиенте.
Теперь давайте вызовим процедуру на нашем фронтенде. tRPC предоставляет обертку для `@tanstack/react-query`, которая позволяет вам использовать все возможности хуков (hooks), которые он предоставляет, но с дополнительным преимуществом того, что ваши вызовы API типизированы и инферированы (inferred). Мы можем вызывать наши процедуры с нашего фронтенда следующим образом:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Вы сразу заметите, насколько хороши автодополнение и типобезопасность. Как только вы начнете писать `trpc.`, ваши роутеры появятся в автодополнении, и когда вы выберете роутер, его процедуры также появятся. Вы также получите ошибку TypeScript, если ваш ввод не соответствует валидатору, который вы определили на бэкенде.
## Как я могу вызывать свой API извне?
В обычных API, вы можете вызвать ваши конечные точки (endpoints) используя любой HTTP клиент, как `curl`, `Postman`, `fetch` или прямо из вашего браузера. С tRPC, это немного иначе. Если вы хотите вызывать ваши процедуры без клиента tRPC, есть два рекомендуемых способа сделать это:
### Раскройте одну процедуру внешне
Если вы хотите раскрыть вашу процедуру внешне, вы ищете [server side calls](https://trpc.io/docs/v10/server-side-calls). Это позволит вам создать обычную конечную точку (endpoint) API Next.js, но переиспользовать часть резолвера вашей tRPC процедуры.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Раскройте каждую процедуру внешне
Если вы хотите раскрыть каждую процедуру внешне, ознакомьтесь с плагином сообщества [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Предоставляя дополнительные метаданные вашим процедурам, вы можете сгенерировать соответствующее REST API из вашего tRPC роутера.
### Это всего лишь HTTP запросы
tRPC взаимодействует через HTTP, поэтому также возможно вызывать ваши процедуры tRPC используя "обычные" HTTP запросы. Однако синтаксис может быть неприятным из-за [RPC протокола](https://trpc.io/docs/v10/rpc), который использует tRPC. Если вам интересно, вы можете проверить, что tRPC запросы и ответы выглядят в вашей вкладке сети браузера, но мы рекомендуем делать это только в качестве образовательного упражнения и придерживаться одного из решений, описанных выше.
## Сравнение с конечной точкой (enpoint) Next.js API
Давайте сравним конечную точку (endpoint) Next.js API с процедурой tRPC. Допустим, мы хотим получить объект пользователя из нашей базы данных и вернуть его на фронтенд. Мы могли бы написать конечную точку (endpoint) Next.js API следующим образом:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Сравните это с примером tRPC выше и вы увидите некоторые преймущества tRPC:
- Вместо того, чтобы указывать URL для каждого маршрута, который может стать неудобным для отладки, если вы что-то переместите, ваш весь маршрутизатор - это объект с автозаполнением.
- Вам не нужно проверять, какой HTTP метод был использован.
- Вам не нужно проверять, что запрос или тело запроса содержат правильные данные в процедуре, потому что Zod позаботится об этом.
- Вместо создания ответа, вы можете выбрасывать ошибки и возвращать значение или объект, как в любой другой функции TypeScript.
- Вызывая процедуру на фронтенде, вы не получаете никакого автозаполнения или проверки типов.
## Полезные сниппеты
Здесь приведены некоторые сниппеты, которые могут пригодиться.
### Включение CORS
Если вам нужно использовать ваш API с другого домена, например в монорепозитории, который включает в себя приложение React Native, вам может потребоваться включить CORS:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Enable cors
await cors(req, res);
// Create and call the tRPC handler
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Оптимистические обновления
Оптимистическое обновление - это когда мы обновляем пользовательский интерфейс до того, как API-запрос завершится. Это предоставляет пользователю лучший опыт, потому что он не должен ждать завершения API-запроса, прежде чем пользовательский интерфейс отобразит результат его действия. Однако приложения, которые ценят корректность данных, должны избегать оптимистические обновления, поскольку они не являются «истинным» представлением состояния бэкенда. Вы можете прочитать больше в [документации React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Cancel outgoing fetches (so they don't overwrite our optimistic update)
await utils.post.list.cancel();
// Get the data from the queryCache
const prevData = utils.post.list.getData();
// Optimistically update the data with our new post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Return the previous data so we can revert if something goes wrong
return { prevData };
},
onError(err, newPost, ctx) {
// If the mutation fails, use the context-value from onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sync with server once mutation has settled
utils.post.list.invalidate();
},
});
};
```
### Простой Интеграционный Тест
Здесь преведен простой интеграционный тест, который использует [Vitest](https://vitest.dev), чтобы проверить, что ваш маршрутизатор tRPC работает должным образом, парсер входных данных выводит правильный тип и возвращаемые данные соответствуют ожидаемому результату.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
## Полезные ресурсы
| Ресурс | Ссылка |
| ------------------------------------- | ------------------------------------------------------- |
| Документация по tRPC | https://www.trpc.io |
| Несколько примеров использования tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Документация React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/ru/usage/typescript.md
================================================
---
title: TypeScript
description: Использование TypeScript
layout: ../../../layouts/docs.astro
lang: ru
---
Несмотря на то новичок вы или же опытный разработчик, мы считаем, что TypeScript - это маст-хэв. Поначалу он может выглядеть угнетающе, но, как и многие другие инструменты, многие разработчики не возвращаются назад после того как начали его использовать.
Он предоставляет обратную связь в режиме реального времени при написании кода, определяя ожидаемые типы данных, и предоставляет полезные подсказки в редакторе кода либо кричит красными волнистыми линиями, если вы пытаетесь получить доступ к свойству, которого не существует, или пытаетесь передать значение неправильного типа, которое в противном случае пришлось бы отлаживать дальше по линии.
Это инструмент, который, возможно, обеспечивает наибольшую производительность разработчикам; он предоставляет документацию для кода, который вы пишете или используете непосредственно в вашем редакторе и имеет мгновенную обратную связь, когда вы неизбежно делаете ошибки, что абсолютно бесценно.
## Выведение типов (Type Inference)
Пока многие новые разработчики на TypeScript обеспокоены _написанием_ TypeScript, многие из его преимуществ на самом деле не требуют от вас изменения вашего кода вообще, в частности вывод типов. Вывод типов означает, что если что-то типизировано, этот тип будет следовать за ним в течение потока приложения без необходимости повторного объявления в других местах. Это означает, что, например, после того, как вы определили типы аргументов, которые принимает функция, остальная часть функции обычно будет безопасной в отношении типов без необходимости ввода какого-либо дополнительного кода, специфичного для TypeScript. Разработчики библиотек тратят огромное количество времени на поддержание типов для своих библиотек, что означает, что мы, как разработчики приложений, можем получить выгоду от вывода типов и встроенной документации в вашем редакторе кода, которые эти типы предоставляют.
Посмотрите видео Theo о том, что [вы, возможно, используете TypeScript неправильно](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Мощные применения вывода типов
### Zod
[Zod](https://github.com/colinhacks/zod) - это библиотека проверки схем, построенная поверх TypeScript. Напишите схему, которая представляет собой единственный источник истины для ваших данных, и Zod гарантирует, что ваши данные будут действительными во всем приложении, даже вне границ сети и внешних API.
### Tanstack Query
[Tanstack Query](https://tanstack.com/query/v4/) предоставляет вам декларативные, всегда актуальные автоматически управляемые запросы и мутации, которые напрямую улучшают как Developer, так и User Experience.
## Полезные ресурсы
| Ресурс | Ссылка |
| --------------------------------------------------------------- | ----------------------------------------------------------------- |
| Руководство по TypeScript | https://www.typescriptlang.org/docs/handbook/ |
| Гайд по TypeScript для новичков | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Канал Родни Маллена из мира TypeScript (Matt Pocock) на YouTube | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/ru/why.md
================================================
---
title: Почему CT3A?
description: Почему вам следует выбрать Create T3 App для вашего следующего проекта
layout: ../../layouts/docs.astro
lang: ru
---
Мы начали создавать create-t3-app, потому что [Theo](https://twitter.com/t3dotgg) отказался делать шаблон своих любимых технологий. Вдохновленный create-next-app, [CLI Astro](https://astro.build) и общей любовью к типобезопасности, команда create-t3-app трудилась, чтобы создать лучшую возможную отправную точку для новых проектов T3 Stack.
Если вы заинтересованы в использовании Next.js в типобезопасном режиме, это то с чего нужно начать. Если вы интересуетесь любыми из конкретных технологических решений, которые мы приняли, читайте дальше :)
## Почему TypeScript?
JavaScript сложен. Зачем добавлять еще больше правил?
Мы всецело уверены, что опыт TypeScript позволяет вам быть лучшим разработчиком. Он предоставляет обратную связь во время написания кода, определяя ожидаемые типы данных, и либо предоставляет полезное автозаполнение в вашем редакторе, либо кричит вам красными волнистыми линиями, если вы пытаетесь получить доступ к свойству, которого не существует, или пытаетесь передать значение неправильного типа, что в противном случае пришлось бы отлаживать дальше по линии. Независимо от того, новичок вы в веб-разработке или опытный профессионал, «строгость» TypeScript обеспечивает менее раздражающий, более последовательный опыт, чем ванильный JS.
Типобезопасность делает вас быстрее. Если вы еще не убеждены, вы [можете использовать TypeScript неправильно ...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## Почему Next.js?
Мы любим React. Он сделал разработку UI доступной в том виде, в котором мы никогда не могли себе представить. Он также может привести разработчиков по некоторым тернистым путям.
Next.js предлагает мение субъективный, но более оптимизированный подход к созданию приложений с использованием React. От маршрутизации до определения API до рендеринга изображений мы доверяем Next.js, чтобы вести разработчиков к правильным решениям.
## Почему tRPC/Prisma/Tailwind/и т.д.?
Хотя мы верим, что все должно быть просто, мы находим, что эти части используются в каждом проекте, похожем на приложение. `create-t3-app` выполняет отличную работу, позволяя вам выбрать те части, которые вам нужны.
### tRPC
tRPC предоставляет все преимущества GraphQL, такие как бесшовная разработка клиента против типобезопасного сервера без всех шаблонов. Это умное злоупотребление TypeScript, которое обеспечивает невероятный опыт разработки.
### Prisma
Prisma для SQL то, что TypeScript для JS. Она создала опыт разработчика, которого раньше не было. Создавая типы из пользовательской схемы, совместимой с [несколькими базами данных](https://www.prisma.io/docs/concepts/database-connectors), Prisma гарантирует типобезопасность от начала до конца от вашей базы данных до вашего приложения.
Prisma предоставляет целый [набор инструментов](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 для вашей базы данных, который позволяет быстро читать и манипулировать данными без необходимости писать код.
### Tailwind CSS
Tailwind ощущается как "CSS в режиме дзен".
Благодаря предоставлению строительных блоков в виде хороших цветов по умолчанию, отступов и других примитивов Tailwind позволяет легко создавать приложение с хорошим внешним видом. И в отличие от библиотек компонентов, он не ограничивает вас, когда вы хотите вывести свое приложение на следующий уровень и создать что-то красивое и уникальное.
К тому же, благодаря инлайновому подходу, Tailwind побуждает вас стилизовать без беспокойства о названии классов, организации файлов или любой другой проблеме, не связаной с решением задачи.
### NextAuth.js
Когда вы хотите добавить систему аутентификации в ваше приложение NextJS, NextAuth.js - отличное решение, чтобы не заморачиваться с реализацией сложной системы безопасности. Она имеет обширный список провайдеров для быстрого добавления аутентификации через OAuth и предоставляет адаптеры для многих баз данных и ORM.
================================================
FILE: www/src/pages/themeTest.astro
================================================
---
import HeadCommon from "../components/headCommon.astro";
import ThemeToggleButton from "../components/navigation/themeToggleButton.astro";
import "../styles/global.css";
import "../styles/accessibility.css";
---
Colors
Neutral
Primary
Secondary
Accent
Warning
Error
Success
Info
Typography
Text 9xl
Text 8xl
Text 7xl
Text 6xl
Text 5xl
Text 4xl
Text 3xl
Text 2xl
Text xl
Text lg
Text base
Text sm
Text xs
bold
code
emphasized
underline
overline
line-through
no-underline
================================================
FILE: www/src/pages/uk/deployment/docker.md
================================================
---
title: Docker
description: Деплоймент в Docker
layout: ../../../layouts/docs.astro
lang: uk
---
Ви можете контейнеризувати цей стек і розгорнути його як один контейнер за допомогою Docker або як частину групи контейнерів за допомогою docker-compose. Дивіться [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) для прикладу репозиторію на основі цієї документації.
## Конфігурація проекту Docker
Будь ласка, зверніть увагу, що Next.js потребує різних процесів для білда (доступні у фронтенді, з префіксом `NEXT_PUBLIC`) та змінних середовища, доступних тільки на сервері. У цьому прикладі ми використовуємо дві змінні, зверніть увагу на їх позиції в `Dockerfile`, аргументи командного рядка та `docker-compose.yml`:
- `DATABASE_URL` (використовується сервером)
- `NEXT_PUBLIC_CLIENTVAR` (використовується клієнтом)
### 1. Конфігурація Next
У вашому [`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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. Створіть dockerignore file
Натисніть тут і вставте вміст у .dockerignore:
### 3. Створіть Dockerfile
> Через те, що ми не виймаємо змінні середовища сервера в наш контейнер, [перевірка схеми середовища](/uk/usage/env-variables) не пройде. Щоб цього уникнути, ми повинні додати прапор `SKIP_ENV_VALIDATION=1` до команди білда, щоб схеми оточення не перевірялися під час білда.
Натисніть тут і вставте вміст у Dockerfile:
```docker
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
# Install Prisma Client - remove if not using Prisma
COPY prisma ./
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
```
> **_Нотатки_**
>
> - _Емуляція `--platform=linux/amd64` може не бути необхідною після переходу на Node 18._
> - _Подивіться [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) щоб зрозуміти, чому `libc6-compat` може бути необхідним._
> - _Використання образів, заснованих на 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)._
> - _Next.js збирає [анонімні дані про телеметрію загального використання](https://nextjs.org/telemetry). Розкоментуйте перший екземпляр `ENV NEXT_TELEMETRY_DISABLED 1`, щоб вимкнути телеметрію під час білда. Розкоментуйте другий екземпляр, щоб вимкнути телеметрію під час виконання._
## Зберіть та запустіть образ локально
Зберіть і запустіть цей образ локально за допомогою наступних команд:
```bash
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
```
Відкрийте [localhost:3000](http://localhost:3000/) щоб побачити запущений додаток.
## Docker Compose
Ви також можете використовувати Docker Compose для збирання образу та запуску контейнера.
Пройдіть кроки 1-4 вище, натисніть тут і додайте вміст в docker-compose.yml:
```yaml
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
```
Запустіть за допомогою команди `docker compose up`:
```bash
docker compose up
```
Відкрийте [localhost:3000](http://localhost:3000/) щоб побачити запущений додаток.
## Деплоймент на Railway
Ви можете використовувати PaaS як автоматичний [деплоймент Dockerfile](https://docs.railway.app/deploy/dockerfiles) від [Railway's](https://railway.app) для деплою вашої програми. Якщо у вас [встановлений Railway CLI](https://docs.railway.app/develop/cli#install), ви можете задеплоїти свою програму за допомогою наступних команд:
```bash
railway login
railway init
railway link
railway up
railway open
```
Перейдіть до "Variables" і увімкніть ваш `DATABASE_URL`. Потім перейдіть до "Settings" і виберіть "Generate Domain." Щоб побачити працюючий приклад на Railway, перейдіть до [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).
## Корисні ресурси
| Ресурс | Посилання |
| ---------------------------------------- | -------------------------------------------------------------------- |
| Приклад для Dockerfile | https://docs.docker.com/engine/reference/builder/ |
| Приклад для файлу Compose 3 версії | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
| Приклад Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ |
| Приклад Docker Compose CLI | https://docs.docker.com/compose/reference/ |
| Розгортання Next.js із Docker Image | https://nextjs.org/docs/deployment#docker-image |
| Next.js в Docker'е | https://benmarte.com/blog/nextjs-in-docker/ |
| Приклад Next.js з Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
| Створення Docker образу Next.js програми | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
================================================
FILE: www/src/pages/uk/deployment/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Деплоймент",
layout: "docs",
description: "Навчіться деплоїти вашу програму T3 в продакшен.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/uk/deployment/netlify.md
================================================
---
title: Netlify
description: Деплоймент в Netlify
layout: ../../../layouts/docs.astro
---
Netlify - це альтернативний провайдер деплою, схожий на Vercel. Ось [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) приклад репозиторію на основі цієї документації.
## Навіщо деплоїти на Netlify
Вважають, що Vercel має кращу підтримку Next.js тому що Vercel розробляє Next.js. Вони зацікавлені в тому, щоб платформа була налаштована для оптимальної продуктивності та DX з Next.js. Найчастіше це так і у відхиленні від стандартного шляху не буде сенсу.
Також існує спільна думка про те, що багато функцій 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/).
Всі провайдери деплойменту мають переваги і недоліки, оскільки жоден хост не може мати кращу підтримку для всіх випадків використання. Наприклад, 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).
> _Зверніть увагу: Щоб відстежувати статус нестабільних функцій Next 13, див. [Використання каталогу `app` Next 13 на Netlify](https://github.com/netlify/next-runtime/discussions/1724)._
## Конфігурація проекту
Існує кілька способів налаштування інструкцій білда, включаючи пряме використання Netlify CLI або Netlify Dashboard. Хоча це не обов'язково, рекомендується створити та включити файл [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/). Це гарантує, що форкнуті та клоновані версії проекту будуть легше повторно задеплоєні.
```toml
[build]
command = "next build"
publish = ".next"
```
## Використання Netlify Dashboard
1. Запуште свій код до репозиторію GitHub і зареєструйтесь на [Netlify](https://app.netlify.com/signup). Після того, як ви створили обліковий запис, натисніть **Add new site** і потім **Import an existing project**.

2. Підключіть свій провайдер Git.

3. Виберіть репозиторій вашого проекту.

4. Netlify виявить, якщо у вас є файл `netlify.toml` і автоматично налаштує команду білда та директорію публікацій.

5. Натисніть **Show advanced**, а потім **New variable**, щоб додати свої змінні середовища.

6. Натисніть **Deploy site**, зачекайте, поки білд завершиться, і перегляньте свій новий сайт.
## Використання Netlify CLI
Для того, щоб задеплоїти проект із командного рядка, ви повинні спочатку запушити свій проект до репозиторію GitHub і [встановити Netlify CLI](https://docs.netlify.com/cli/get-started/). Ви можете встановити `netlify-cli` як залежність проекту або встановити його глобально на вашому комп'ютері за допомогою наступної команди:
```bash
npm i -g netlify-cli
```
Для того, щоб протестувати свій проект локально, запустіть команду [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) та відкрийте [`localhost :8888`](http://localhost:8888/) для перегляду вашої локально запущеної програми Netlify:
```bash
ntl dev
```
Запустіть команду [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment), щоб налаштувати ваш проект:
```bash
ntl init
```
Імпортуйте змінні середовища вашого проекту з вашого файлу `.env` за допомогою [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
```bash
ntl env:import .env
```
Задеплойте ваш проект за допомогою [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Вам потрібно буде передати прапор `--build`, щоб запустити команду білда перед деплойментом, та прапор `--prod`, щоб задеплоїти на основному URL вашого сайту:
```bash
ntl deploy --prod --build
```
Щоб переглянути приклад на Netlify, перейдіть на [ct3a.netlify.app](https://ct3a.netlify.app/).
================================================
FILE: www/src/pages/uk/deployment/vercel.md
================================================
---
title: Vercel
description: Деплоймент на Vercel
layout: ../../../layouts/docs.astro
lang: uk
---
Ми рекомендуємо деплоїти вашу програму на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Він дозволяє дуже легко деплоїти Next.js програми.
## Конфігурація проекту
Швидше за все Vercel налаштує вашу команду збірки та каталог публікації автоматично. Однак ви також можете уточнити цю інформацію разом з іншими конфігураціями, створивши файл [vercel.json](https://vercel.com/docs/project-configuration) і включивши в нього наступні команди. **У більшості проектів це робити необов'язково.**
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"devCommand": "npm run dev",
"installCommand": "npm install"
}
```
## Використання Vercel Dashboard
1. Після відправки вашого коду до репозиторію GitHub зареєструйтесь на [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) з GitHub і натисніть **Add New Project**.

2. Імпортуйте репозиторій GitHub із вашим проектом.

3. Додайте ваші змінні середовища.

4. Натисніть **Deploy**. Тепер щоразу, коли ви відправляєте зміни до вашого репозиторію, Vercel автоматично передеплоїть вашу програму!
## Використання Vercel CLI
Для того, щоб задеплоїти програму з командного рядка, вам спочатку потрібно [встановити Vercel CLI глобально](https://vercel.com/docs/cli#installing-vercel-cli).
```bash
npm i -g vercel
```
Запустіть команду [`vercel`](https://vercel.com/docs/cli/deploying-from-cli), щоб задеплоїти ваш проект.
```bash
vercel
```
Додайте `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` для змінних середовища, таких як рядок підключення до бази даних. Використовуйте `--yes`, якщо хочете пропустити питання деплою та дати відповідь за умовчанням для кожного.
```bash
vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
```
Після першого деплою ця команда задеплоїть зміни у гілку попереднього перегляду. Вам потрібно буде включити `-prod`, щоб відправити зміни безпосередньо на сайт у продакшені для майбутніх деплоїв.
```bash
vercel --prod
```
================================================
FILE: www/src/pages/uk/examples.mdx
================================================
---
title: Приклади
description: Приклади різних існуючих додатків
layout: ../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
import Form from "../../components/docs/exampleOptionForm.astro";
Ви можете випробувати різні комбінації технологій, які пропонує create-t3-app.
Ви не можете вибрати `prisma` та `drizzle` одночасно.
Деякі функції можуть не працювати, якщо ви не створите файл env
================================================
FILE: www/src/pages/uk/faq.mdx
================================================
---
title: FAQ
description: Найпоширеніші запитання про Create T3 App
layout: ../../layouts/docs.astro
lang: uk
---
import Callout from "../../components/docs/callout.tsx";
Це деякі часті запитання про `create-t3-app`.
## Що далі? Як я можу створити додаток?
Ми намагаємося зробити цей проект якомога простішим, тому ви можете почати з того, що ми налаштували для вас, а потім додавати додаткові вам речі, коли вони стануть вам необхідними.
Якщо ви не знайомі з різними технологіями, що використовуються в цьому проєкті, зверніться до відповідної документації. Якщо щось усе ще не зрозуміло, приєднуйтесь до нашого [Discord](https://t3.gg/discord) і попросіть допомоги.
- [Next.js](https://nextjs.org/)
- [NextAuth.js](https://next-auth.js.org)
- [Prisma](https://prisma.io)
- [Tailwind CSS](https://tailwindcss.com)
- [tRPC](https://trpc.io)
## Як мені тримати свій додаток оновленим?
Додаток 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) у нашому репозиторії. Зважаючи це, насправді не обов'язково вносити кожну зміну, яку ми вносимо в шаблон у вашій програмі.
## Які навчальні ресурси зараз доступні?
Не дивлячись на те, що перераховані нижче ресурси є одними з найкращих для T3 Stack, спільнота (і [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) рекомендує просто почати використовувати стек і вчитися в процесі розробки з його допомогою.
Якщо ви розглядаєте Create T3 App, швидше за все, ви вже використовували деякі частини стека. То чому б не зануритися в проєкт з головою і не вивчити решту технологій у процесі розробки?
Ми розуміємо, що цей шлях не підходить для кожного. Тому, якщо ви відчуваєте, що ви спробували рекомендований шлях і цього недостатньо, і вам все ще потрібні ресурси, або ви просто не впевнені у своїх силах та/або почуваєтесь перевантаженим цим стеком, ознайомтеся з цими приголомшливими навчальними матеріалами щодо Create T3 App:
### Статті
Деякі з них можуть бути застарілими.
- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
### Відео
- [T3 Stack Tutorial - FROM 0 TO PROD FOR $0 (Next.js, tRPC, TypeScript, Tailwind, Prisma & More)](https://www.youtube.com/watch?v=YkOSUVzOAA4) **(рекомендовано)**
- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)
- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
## Чому в проєкті є файли `.js`?
Згідно з [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`.
Ми намагаємося підкреслити, що ці файли є файлами JavaScript не без причини, явно оголошуючи тип кожного файлу (`cjs` або `mjs`), залежно від того, що підтримується бібліотекою, якою він використовується. Крім того, всі файли `js` у цьому проєкті все ще перевіряються на типи за допомогою коментаря `@ts-check` вгорі.
## У мене не виходить додати i18n до мого додатка. Чи є якісь рекомендації?
Ми вирішили не включати i18n за замовчуванням у `create-t3-app`, тому що це дуже суб'єктивна тема, і є багато способів її реалізації.
У той же час, якщо ви зіткнулися з проблемами під час реалізації та хочете побачити проєкт-зразок, у нас є [посилання на репозиторій](https://github.com/juliusmarminge/t3-i18n), яке показує, як ви можете додати i18n в T3 App за допомогою [next-i18next](https://github.com/i18next/next-i18next).
## Чому ми використовуємо `/pages` а не `/app` з Next.js 13?
Згідно з [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 перебуває в бета-версії, і очікується, що він матиме зворотно несумісні зміни.
Список підтримуваних, запланованих і тих, що перебувають у розробці, функцій у
каталозі `/app` можна знайти в [бета-документації
Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
================================================
FILE: www/src/pages/uk/folder-structure-pages.mdx
================================================
---
title: Файлова структура (Pages)
description: Файлова структура нового T3 додатка
layout: ../../layouts/docs.astro
lang: uk
isMdx: true
---
import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
import Form from "../../components/docs/folderStructureForm.astro";
Будь ласка, виберіть пакети, щоб побачити файлову структуру нового додатка з обраними пакетами. Нижче ви знайдете опис кожного елемента.
### `prisma`
Папка `prisma` містить файл `schema.prisma`, який використовується для налаштування з'єднання з базою даних і схеми бази даних. Також це місце для зберігання файлів міграції та/або сценаріїв заповнення, якщо вони використовуються. Дивіться [Використання Prisma](/uk/usage/prisma) для отримання додаткової інформації.
### `public`
Папка `public` містить статичні файли, які обслуговуються веб-сервером. Файл `favicon.ico` - це приклад статичного файлу.
### `src/env`
Використовується для перевірки змінних оточення і визначення типів - дивіться [Змінні оточення](/uk/usage/env-variables).
### `src/pages`
Папка `pages` містить усі сторінки додатка Next.js. Файл `index.tsx` у кореневій папці `/pages` є домашньою сторінкою додатка. Файл `_app.tsx` використовується для обертання додатка провайдерами. Дивіться [документацію Next.js](https://nextjs.org/docs/basic-features/pages) для отримання додаткової інформації.
#### `src/pages/api`
Папка `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/).
#### `src/pages/api/auth/[...nextauth].ts`
Файл `[...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.
#### `src/pages/api/trpc/[trpc].ts`
Файл `[trpc].ts` - це точка входу tRPC API. Він використовується для обробки запитів tRPC. Дивіться [Використання tRPC](/uk/usage/trpc#-pagesapitrpctrpcts) для отримання додаткової інформації про цей файл і [документацію Next.js про динамічні маршрути](https://nextjs.org/docs/routing/dynamic-routes) для отримання інформації про маршрути catch-all/slug.
### `src/server`
Папка `server` використовується для чіткого поділу серверного коду від клієнтського коду.
#### `src/server/auth.ts`
Містить утиліти для автентифікації, такі як отримання сесії користувача на стороні сервера. Дивіться [Використання NextAuth.js](/uk/usage/next-auth#usage-with-trpc) для отримання додаткової інформації.
#### `src/server/db.ts`
Файл `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) для отримання додаткової інформації.
### `src/server/api`
Папка `api` містить серверний код tRPC.
#### `src/server/api/routers`
Папка `routers` містить усі ваші під-маршрутизатори tRPC.
#### `src/server/api/routers/example.ts`
Файл `example.ts` - це приклад маршрутизатора tRPC, який використовує допоміжну функцію `publicProcedure` для демонстрації того, як створити публічний маршрут tRPC.
Базуючись на обраних вами пакетах, цей маршрутизатор містить більше або менше маршрутів для кращого демонстрування використання ваших потреб.
#### `src/server/api/trpc.ts`
Файл `trpc.ts` - це основний файл конфігурації для вашого tRPC-бекенду. У ньому ми:
1. Визначаємо контекст, який використовується в запитах tRPC. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapitrpcts) для отримання додаткової інформації.
2. Експортуємо допоміжні функції процедур. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapitrpcts) для отримання додаткової інформації.
#### `src/server/api/root.ts`
Файл `root.ts` використовується для мерджу маршрутизаторів tRPC і експорту їх як єдиного маршрутизатора, а також визначення типу маршрутизатора. Дивіться [Використання tRPC](/uk/usage/trpc#-serverapirootts) для отримання додаткової інформації.
### `src/styles`
Папка `styles` містить глобальні стилі додатка.
### `src/types`
Папка `types` використовується для зберігання повторно використовуваних типів або оголошень типів.
#### `src/types/next-auth.d.ts`
Файл `next-auth.d.ts` використовується для розширення типу сесії за замовчуванням NextAuth на включення ідентифікатора користувача. Дивіться [Використання NextAuth.js](/uk/usage/next-auth#включення-userid-в-сеанс) для отримання додаткової інформації.
### `src/utils`
Папка `utils` використовується для зберігання повторно використовуваних функцій утиліт.
#### `src/utils/api.ts`
Файл `api.ts` є точкою входу для tRPC на стороні клієнта. Дивіться [Використання tRPC](/uk/usage/trpc#-utilsapits) для отримання додаткової інформації.
### `.env`
Файл `.env` використовується для зберігання змінних середовища. Дивіться [Змінні середовища](/uk/usage/env-variables) для отримання додаткової інформації. Цей файл **не** повинен бути доданий в історію git.
### `.env.example`
Файл `.env.example` показує приклад змінних середовища на основі обраних бібліотек. Цей файл має бути доданий в історію git.
### `.eslintrc.cjs`
Файл `.eslintrc.cjs` використовується для налаштування ESLint. Дивіться [документацію ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) для отримання додаткової інформації.
### `next-env.d.ts`
Файл `next-env.d.ts` гарантує, що типи Next.js будуть виявлені компілятором TypeScript. **Ви не повинні видаляти його або редагувати, оскільки він може змінитися в будь-який час.** Дивіться [документацію Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) для отримання додаткової інформації.
### `next.config.mjs`
Файл `next.config.mjs` використовується для налаштування Next.js. Дивіться [Документацію Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) для отримання додаткової інформації. Примітка: Розширення .mjs використовується для дозволу імпорту ESM.
### `postcss.config.js`
Файл `postcss.config.js` використовується для використання Tailwind PostCSS. Дивіться [документацію Taiwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) для отримання додаткової інформації.
### `prettier.config.mjs`
Файл `prettier.config.mjs` використовується для налаштування Prettier для ввімкнення prettier-plugin-tailwindcss для форматування класів Tailwind CSS. Дивіться [пост блогу Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) для отримання додаткової інформації.
### `tsconfig.json`
Файл `tsconfig.json` використовується для налаштування TypeScript. Деякі значення за замовчуванням, такі як `strict mode`, були увімкнені для забезпечення кращого використання TypeScript для create-t3-app та його бібліотек. Дивіться [документацію TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) або [Використання TypeScript](usage/typescript) для отримання додаткової інформації.
### `drizzle.config.ts`
Файл `drizzle.config.ts` використовується для налаштування drizzle kit. Дивіться [документацію](https://orm.drizzle.team/kit-docs/config-reference) для отримання додаткової інформації.
================================================
FILE: www/src/pages/uk/installation.mdx
================================================
---
title: Встановлення
description: Інструкції зі встановлення Create T3 App
layout: ../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
Для створення додатка за допомогою `create-t3-app`, запустіть одну з наступних трьох команд і дайте відповідь на запитання командного рядка:
### npm
```bash
npm create t3-app@latest
```
### yarn
```bash
yarn create t3-app
```
### pnpm
```bash
pnpm create t3-app@latest
```
### bun
```bash
bun create t3-app@latest
```
Після того, як додаток буде створено, ознайомтеся з [першими кроками](/uk/usage/first-steps), щоб почати роботу над вашим новим додатком.
## Додаткові параметри
| Опції/Флаги | Опис |
| ----------------- | ------------------------------------------------------------------ |
| `[dir]` | Додання аргументу з директорії з ім'ям проекту |
| `--noGit` | Повідомлення CLI не ініціалізувати новий git репозиторій у проекті |
| `-y`, `--default` | Створення нового t3-додатку з дефолтними параметрами |
| `--noInstall` | Генерація проекту без встановлення залежностей |
## Експериментальне використання
Для нашого CI ми маємо деякі експериментальні прапори, які дають змогу створювати будь-який додаток без будь-яких запитів. Якщо це стосується вашого випадку, ви можете використовувати ці прапори. Зверніть увагу, що ці прапори є експериментальними і можуть змінитися в майбутньому без зміни версії.
| Опції/Флаги | Опис |
| ------------ | ----------------------------------------------- |
| `--CI` | Повідомлення CLI, що ви перебуваєте в режимі CI |
| `--trpc` | Додавання tRPC у проєкт |
| `--prisma` | Додавання Prisma у проєкт |
| `--nextAuth` | Додавання NextAuth у проєкт |
| `--tailwind` | Додавання Tailwind CSS у проєкт |
Якщо ви не вказуєте прапор `CI`, то інші прапори не мають ефекту.
Вам не потрібно явно відмовлятися від пакетів, які вам не потрібні. Однак, якщо ви віддаєте перевагу бути точним, ви можете передати `false`, наприклад `--nextAuth false`.
### Приклад
Наступний приклад створить додаток T3 з tRPC і Tailwind CSS.
```bash
pnpm dlx create-t3-app@latest --CI --trpc --tailwind
```
================================================
FILE: www/src/pages/uk/introduction.md
================================================
---
title: Вступ
description: Вступ в T3 стек
layout: ../../layouts/docs.astro
lang: uk
---
## T3 Stack
_"T3 Stack"_ - це стек веб-розробки, створений [Theo](https://twitter.com/t3dotgg), з упором на простоту, модульність і full-stack типобезпека.
Основні частини - [**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/) - чудові доповнення.
Ви могли помітити, що тут... багато частин. Це зроблено наміренно. Змінюйте частини залежно від ваших потреб - цей стек є модульним за своєю суттю :)
## І... що таке create-t3-app? Шаблон?
Щось типу? `create-t3-app` - це CLI, створений досвідченими розробниками T3 стека, щоб спростити налаштування модульного додатка T3 стека. Це означає, що кожна частина є необов'язковою, і "шаблон" генерується на основі ваших конкретних потреб.
Після безлічі проєктів і багатьох років із цією технологією у нас є безліч думок та інсайтів. Ми постаралися зафіксувати їх у цьому CLI.
Це **НЕ** всеосяжний шаблон. Ми **очікуємо**, що ви будете використовувати свої власні бібліотеки, які вирішують потреби **ВАШОГО** додатка. Хоча ми не хочемо призначати рішення для більш конкретних проблем, таких як управління станом і деплоймент, ми [маємо деякі рекомендації, перераховані тут](/uk/other-recs).
## Аксіоми T3
Будемо чесними - це _суб'єктивний проєкт_. Ми поділилися кількома основними переконаннями навколо створення і розглядаємо їх як основу для наших рішень.
### Вирішуйте проблеми
Легко потрапити в пастку "додавання всього" - ми явно не хочемо цього робити. Усе, що додається в `create-t3-app`, повинно вирішувати конкретну проблему, яка існує в основних технологіях, включених до нього. Це означає, що ми не додамо бібліотеки менеджменту стану (`zustand`, `redux`), але ми додамо NextAuth.js та інтегруємо Prisma і tRPC для вас.
### Оновлюйтесь з відповідальністю
Ми любимо технологічні новинки. Швидкість і, будемо чесними, приколів від нових фіговін, дійсно круті. Ми вважаємо важливим використовувати їх відповідально, використовуючи більш ризиковані технології в менш ризикованих частинах. Це означає, що ми не будемо ⛔️ робити ставку на ризиковану нову технологію бази даних (SQL - це здорово!). Але ми із задоволенням ✅ зробимо ставку на tRPC, оскільки це просто функції, які легко замінити.
### Типобезпека не є опціональною
Зазначена мета Create T3 App - це надати найшвидший спосіб розпочати новий повнофункціональний, **типобезпечний** веб-додаток. Ми серйозно ставимося до типобезпеки в цих частинах, оскільки вона підвищує нашу продуктивність і допомагає нам створювати менше багів. Будь-яке рішення, яке знижує типобезпеку Create T3 App, це рішення, яке повинно бути прийнято в іншому проекті.
================================================
FILE: www/src/pages/uk/other-recs.md
================================================
---
title: Додаткові рекомендації
description: Бібліотеки та сервіси, які ми рекомендуємо для багатьох проектів
layout: ../../layouts/docs.astro
lang: uk
---
Ми розуміємо, що бібліотеки, включені до `create-t3-app`, не вирішують кожну проблему. Хоча ми рекомендуємо розпочати свій проект з того, що ми надаємо, настане час, коли вам потрібно буде встановити інші пакети. Тільки ви можете знати, чого потребує ваш проект, але ось деякі рішення, які ми часто рекомендуємо.
Це рекомендації окремих учасників Create T3 App і не повинні розглядатись як "офіційні" рекомендації команди Create T3 App або T3-OSS. _**Будь ласка, проведіть власне дослідження, особливо перед тим, як прив'язуватись до платних сервісів**_.
## Управління станом
_**Примітка редактора**_: Бібліотеки керування станом можуть бути відмінними, але часто не потрібні. tRPC's хуки React Query повинні впоратися із вашим серверним станом. Для клієнтського стану почніть з `useState` React, і зверніться до одного з цих варіантів, коли вам буде потрібно більше.
### Zustand
**Для того, щоб більше ніколи не використовувати Redux**
"Сучасний простий Redux", який ви не знали, що вам потрібен. [Poimandres](https://github.com/pmndrs) завжди можна довіряти. Ви можете створювати все, від відеодзвінків до ігор та серверів із цією маленькою бібліотекою.
- [Головна Zustand](https://zustand-demo.pmnd.rs/)
- [Zustand GitHub](https://github.com/pmndrs/zustand)
### Jotai
**Для того, щоб більше ніколи не використовувати Context**
Jotai важко перевершити в підході Atomic. Також від [Poimandres](https://github.com/pmndrs), Jotai дозволяє визначати сінгелтони, які здаються глобальними useState. Відмінний варіант для станів, які не вимагають стейт машини прямо зараз.
- [Головна Jotai](https://jotai.org/)
- [Jotai GitHub](https://github.com/pmndrs/jotai)
## Бібліотеки компонентів
Більшість додатків потребують однакову низку компонентів: перемикачі, меню, модальні вікна і т.д. Ці бібліотеки надають відмінні, доступні компоненти, які ви можете використовувати та налаштовувати на свій розсуд.
### Бібліотеки компонентів без стилів
Також відомі як headless бібліотеки, вони надають відмінні, нестилізовані та доступні компоненти, які ви можете налаштувати на свій розсуд. Ось кілька рекомендацій.
- [Radix UI](https://www.radix-ui.com/) надає потужний набір зручних і доступних примітивів, які ви можете стилізувати за допомогою звичайного CSS або Tailwind CSS.
- [Headless UI](https://headlessui.com/) від команди Tailwind CSS також надає нестилізовані, доступні компоненти, які бездоганно інтегруються з Tailwind CSS.
- [React Aria](https://react-spectrum.adobe.com/react-aria/) надає доступні примітивні налаштування UI для вашої системи дизайну. Їхній компонент вибору дати - це найвищий рівень.
### Бібліотеки компонентів зі стилями
**Коли вам просто потрібно, щоб ваш додаток виглядав непогано**
Іноді ви створюєте проект, де вам просто потрібно, щоб інтерфейс користувача виглядав від початку. Для адміністративних панелей управління та інших подібних проектів будь-яка з цих бібліотек компонентів упорається з цим завданням.
- [Chakra UI](https://chakra-ui.com)
- [Mantine](https://mantine.dev)
- [@shadcn/ui](https://ui.shadcn.com/)
### Class Variance Authority
**Для створення бібліотек інтерфейсу користувача**
Декларативно створюйте бібліотеку інтерфейсу користувача з різними кольоровими, розмірними і т.д. варіантами. Коли ваш проект досягає масштабу, де вам потрібен стандартизований набір компонентів інтерфейсу користувача з кількома варіантами з використанням Tailwind CSS, CVA - відмінний інструмент.
- [Class Variance Authority GitHub](https://github.com/joe-bell/cva)
## Анімації
Наші рекомендації для створення анімацій у вашому додатку.
### AutoAnimate
**Для анімацій з одним рядком коду**
Більшість бібліотек анімації намагаються задовольнити кожен можливий випадок використання і стають громіздкими. AutoAnimate – це інструмент без конфігурації, який дасть вам значне покращення UX без додаткових зусиль розробника.
- [Головна AutoAnimate](https://auto-animate.formkit.com/)
- [AutoAnimate GitHub](https://github.com/formkit/auto-animate)
- [Компонент для AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
### Framer Motion
**Для складних анімацій із декларативним кодом**
Framer Motion надає простий, декларативний синтаксис і дозволяє писати менше коду для створення всього: від складних анімацій і навіть до жестів.
- [Головна Framer Motion](https://framer.com/motion)
- [Документація Framer Motion](https://www.framer.com/docs/)
## Деплоймент, інфраструктура, бази даних і CI
### Vercel
**Для хостинга вашого додатка**
Vercel позбавив нас болю при деплойменті веб-додатків, зробивши його простою інтеграцією з GitHub, яку можна встановити і забути. Ми без проблем масштабувалися до сотень тисяч користувачів. Він працює на AWS, але має набагато кращий інтерфейс :)
- [Головна Vercel](https://vercel.com/)
- [Гайд із деплою T3 додатка на Vercel](/uk/deployment/vercel)
### PlanetScale
**Для баз даних без занепокоєння**
PlanetScale - найкраща serverless платформа для баз даних, яку ми використовували. Неймовірна масштабованість, чудовий DX і фантастична ціна. Якщо ви використовуєте SQL (і, сподіваюся, Prisma), це важко перевершити.
- [Головна PlanetScale](https://planetscale.com/)
### Railway
**Для розміщення вашої інфраструктури**
"Сучасний Heroku". Найпростіший спосіб запустити реальний сервер. Якщо вам не вистачає функціоналу Vercel і PlanetScale, то Railway, ймовірно, вам підійде. Вкажіть його на репозиторій GitHub і готово.
- [Головна Railway](https://railway.app/)
### Upstash
**Для serverless Redis**
Ми любимо Prisma і PlanetScale, але деякі проєкти вимагають більш продуктивного рішення. Upstash дає вам змогу отримати in-memory продуктивність Redis у вашому безсерверному проєкті, не переймаючись самостійним управлінням інфраструктурою та масштабуванням.
- [Головна Upstash](https://upstash.com/)
### Pusher
**Для безсерверних WebSocket-ів**
Якщо WebSocket є основним фокусом вашого проекту, ви можете розглянути більш традиційний бекенд, такий як [Fastify](https://www.fastify.io/) (який [також працює з tRPC!](https://trpc.io/docs/v10/fastify)). Але для швидкого додавання WebSocket у T3 App, Pusher - чудовий вибір.
- [Головна Pusher](https://pusher.com/)
### Soketi
Soketi - це самодостатня, проста і швидка альтернатива Pusher. Він повністю сумісний з Pusher SDK, який ви можете використовувати для підключення до сервера. Soketi serverless також перебуває в бета-версії.
- [Головна Soketi](https://soketi.app)
- [Soketi GitHub](https://github.com/soketi/soketi)
## Аналітика
Користувацькі дані дуже цінні, коли ви створюєте додаток. Ось кілька рекомендованих провайдерів аналітики.
### Plausible
Потрібна аналітика? Plausible - один із найшвидших способів її отримати. Супер мінімалістичний. У нього навіть є [простий плагін для Next.js](https://plausible.io/docs/proxy/guides/nextjs).
- [Головна Plausible](https://plausible.io/)
### Umami
Umami - це самодостатня, проста, швидка і конфіденційна альтернатива Google Analytics. Ви можете легко задеплоїти його на Vercel, Railway і т.д. з PlanetScale як базою даних.
- [Головна Umami](https://umami.is/)
- [Umami GitHub](https://github.com/umami-software/umami)
- [Umami Cloud](https://cloud.umami.is/)
## Інше
### Next Bundle Analyzer
Буває складно визначити, що буде включено до збірки вихідних даних для вашого додатка. Next Bundle Analyzer - це простий спосіб візуалізувати й аналізувати JavaScript-бандли, які генеруються.
- [@next/bundle-analyzer на npm](https://www.npmjs.com/package/@next/bundle-analyzer)
================================================
FILE: www/src/pages/uk/t3-collection.mdx
================================================
---
title: T3 колекція
description: Круті open source проекти та компанії, що використовують T3 стек
layout: ../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../components/docs/callout.tsx";
import CompanyList from "../../components/docs/companyList.tsx";
import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
Зробили проект, що використовує T3 стек і хочете поділитися ним? Додайте його до списку!
## Open Source програми зроблені з використанням T3 стека
## Компанії використовують T3 стек
Нам би дуже хотілося дізнатися про компанії, які використовують T3 стек для своїх додатків. Ваша компанія використовує стек T3 і ви хочете поділитися цим? Додайте її до списку!
Є крутий проект, що використовує T3 стек? Зробіть [pull
request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)
та додайте його до списку!
================================================
FILE: www/src/pages/uk/usage/drizzle.mdx
================================================
---
title: Drizzle
description: Використання Drizzle
layout: ../../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Опція `drizzle` є новим додатком и жодні документи ще не були написані. Ми
будемо раді вашим внескам!
================================================
FILE: www/src/pages/uk/usage/env-variables.mdx
================================================
---
title: Змінні середовища
description: Початок роботи з Create T3 App
layout: ../../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Create T3 App використовує власний пакет [@t3-oss/env-nextjs](https://env.t3.gg) разом із [Zod](https://github.com/colinhacks/zod) для валідації змінних середовища під час виконання _та_ під час збирання, надаючи просту логіку у файлі `src/env.js`:
## env.js
_TLDR; Якщо ви хочете додати нову змінну середовища, вам слід додати валідатор до `src/env.js`, а потім пару ключ-значення в `.env`._
```ts:env.js
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
NODE_ENV: z.enum(["development", "test", "production"]),
},
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
},
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
},
});
```
T3 Env використовує `createEnv`, який відповідає за створення схеми і буде включати головну логіку валідації для клієнтських і серверних змінних середовища.
Для отримання додаткової інформації про те, як `createEnv` працює зсередини,
подивіться документацію [T3 Env](https://env.t3.gg/docs/introduction) (EN)
## Використання змінних середовища
Коли ви хочете використовувати змінні середовища, ви можете імпортувати їх із `env.js` і використовувати їх так, як ви зазвичай використовували б. Якщо ви імпортуєте цей файл на стороні клієнта і спробуєте отримати серверну змінну, ви отримаєте помилку виконання:
```ts:pages/api/hello.ts
import { env } from "../../env.js";
// `env` is fully typesafe and provides autocompletion
const dbUrl = env.DATABASE_URL;
```
```ts:pages/index.tsx
import { env } from "../env.js";
// ❌ This will throw a runtime error
const dbUrl = env.DATABASE_URL;
// ✅ This is fine
const wsKey = env.NEXT_PUBLIC_WS_KEY;
```
## .env.example
Через те, що файл `.env` за замовчуванням не додається до системи контролю версій, ми також додали файл `.env.example`, в якому ви можете за бажанням зберегти копію вашого файлу `.env` з видаленими secrets. Це необов'язково, але ми рекомендуємо тримати приклад в актуальному стані, щоб зробити процес налаштування середовища для нових учасників проекту якомога простішим.
Деякі фреймворки та інструменти збірки, такі як Next.js, пропонують зберігати secrets у файлі `.env.local` і коммітити файли `.env` у ваш проект. Це не рекомендується, оскільки це може полегшити випадковий комміт secrets у ваш проект. Натомість ми рекомендуємо зберігати secrets в `.env`, тримати ваш файл `.env` в `.gitignore` і коммітити лише файли `.env.example` у ваш проект.
## Додавання змінних середовища
Для того, щоб переконатися, що ваша збірка ніколи не завершиться без змінних середовища, які проєкт вимагає, вам потрібно додати нові змінні середовища в **двох** місцях:
📄 `.env`: Введіть змінну середовища, як зазвичай робите у файлі `.env`, тобто `KEY=VALUE`
📄 `env.js`: Додайте відповідну логіку валідації для змінних середовища, визначивши для кожної з них Zod схему всередині `createEnv`, наприклад `KEY: z.string()`. Крім цього, переконайтеся в тому, що ви деструктурували їх в опції `runtimeEnv`, наприклад `KEY: process.env.KEY`.
Навіщо потрібно деструктурувати змінні середовища всередині `runtimeEnv`? Це
пов'язано з тим, як Next.js збирає змінні середовища в деяких рантаймах.
Деструктуруючи їх вручну, ми гарантуємо, що ці змінні не будуть прибрані з
фінальної збірки.
Опціонально, ви також можете оновлювати файл `.env.example`:
📄 `.env.example`: Введіть вашу змінну середовища, але переконайтеся, що не включаєте значення, якщо воно є секретним, тобто `KEY=VALUE` або `KEY=`.
### Приклад
_Я хочу додати мій Twitter API токен як змінну середовища на стороні сервера_
1. Додайте змінну середовища в `.env`:
```
TWITTER_API_TOKEN=1234567890
```
2. Додайте змінну середовища в `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
TWITTER_API_TOKEN: z.string(),
},
// ...
runtimeEnv: {
// ...
TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
},
});
```
3. _Опціонально:_ Додайте змінну середовища в `.env.example`, але не включайте токен в `runtimeEnv`.
```
TWITTER_API_TOKEN=
```
## Type Coercion
Усі змінні які ви додаєте до `.env` будуть импортовані як рядки, навіть якщо їх значення має представляти інший тип. Якщо ви хочете використовувати ваші змінні середовища як інший тип під час рантайму, ви можете використовувати `coerce` з Zod для конвертації рядків в тип, який ви хочете. Це викине помилку, якщо конвертація не вдасться.
Додайте змінну до вашого `.env`:
```
SOME_NUMBER=123
SOME_BOOLEAN=true
```
Потім, провалідуйте їх в `env.js`:
```ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
SOME_NUMBER: z.coerce.number(),
SOME_BOOLEAN: z.coerce.boolean(),
},
// ...
runtimeEnv: {
SOME_NUMBER: process.env.SOME_NUMBER,
SOME_BOOLEAN: process.env.SOME_BOOLEAN,
},
});
```
================================================
FILE: www/src/pages/uk/usage/first-steps.md
================================================
---
title: Перші кроки
description: Початок роботи з вашим новим T3 App
layout: ../../../layouts/docs.astro
lang: uk
---
Ви щойно створили новий додаток T3 і готові до роботи. Ось мінімум для запуску вашої програми.
## База даних
### MySQL, PostgreSQL
Якщо ви обираєте MySQL або PostgreSQL як свою базу даних, ваше T3 додаток буде починатись з `start-database.sh` bash-скриптом, який може створити контейнер Docker з базою даних для локальної розробки. Якщо у вас вже є база даних, ви можете видалити цей файл і вказати свої облікові дані для бази даних в `.env`. На macOS ви також можете використовувати [DBngin](https://dbngin.com/), якщо ви не хочете використовувати Docker.
### Prisma
Якщо ваш додаток включає Prisma, переконайтеся, що ви запустили `npx prisma db push` з кореневої директорії вашої програми. Ця команда синхронізує схему Prisma з вашою базою даних і генерує типи TypeScript для Prisma Client на основі вашої схеми. Зверніть увагу, що вам потрібно [перезапустити сервер TypeScript](https://tinytip.co/tips/vscode-restart-ts/) після цього, щоб він міг виявити згенеровані типи.
### Drizzle
Якщо ваш додаток включає в себе Drizzle, перевірте `.env` файл для інструкцій щодо побудови вашої змінної середовища `DATABASE_URL`. Як тільки ваш файл середовища готовий, запустіть `pnpm db:push` (або еквівалент для інших менеджерів пакетів), щоб відправити вашу схему.
## Аутентифікація
Якщо ваш додаток включає NextAuth.js, ми починаємо з `DiscordProvider`. Це один з найпростіших провайдерів, пропонований NextAuth.js, однак він все ще вимагає певного початкового налаштування з вашого боку.
Звичайно, якщо ви віддаєте перевагу використанню іншого провайдера автентифікації, ви також можете використати один із [багатьох провайдерів](https://next-auth.js.org/providers/), які пропонує NextAuth.js.
1. Вам потрібен обліковий запис Discord, тому зареєструйтеся, якщо ще не зареєструвалися.
2. Перейдіть на https://discord.com/developers/applications і натисніть "New Application" у правому верхньому куті. Дайте вашому додатку ім'я та погодьтеся з Умовами використання.
3. Коли ви створите додаток, перейдіть до "Settings → OAuth2 → General".
4. Скопіюйте "Client ID" і додайте його у ваш `.env` як `AUTH_DISCORD_ID`.
5. Натисніть "Reset Secret", скопіюйте новий secret і додайте його у ваш `.env` як `AUTH_DISCORD_SECRET`.
6. Натисніть "Add Redirect" і введіть `http://localhost:3000/api/auth/callback/discord`.
- Для деплойменту в продакшені дотримуйтесь попередніх кроків для створення іншого додатка Discord, але цього разу замініть `http://localhost:3000` на URL, на який ви деплоїте.
7. Збережіть зміни.
Тепер у вас має бути можливість увійти в систему.
## Сетап едітора
Наступні розширення рекомендуються для оптимального досвіду розробки. Нижче наведені посилання на підтримку плагінів для редактора.
- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)
- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)
- [Prettier Extension](https://prettier.io/docs/en/editors.html)
## Наступні кроки
- Якщо ваш додаток включає tRPC, ознайомтеся з `src/pages/index.tsx` і `src/server/trpc/router/post.ts`, щоб дізнатися, як працюють запити tRPC.
- Подивіться на документацію `create-t3-app`, а також на документацію пакетів, які включає ваш додаток.
- Приєднуйтесь до нашого [Discord](https://t3.gg/discord) і поставте зірку на [GitHub](https://github.com/t3-oss/create-t3-app)! :)
================================================
FILE: www/src/pages/uk/usage/index.astro
================================================
---
import IndexPage from "../../../components/docs/indexPage.astro";
import { SIDEBAR, type Frontmatter } from "../../../config";
import { getLanguageFromURL } from "../../../languages";
import Layout from "../../../layouts/docs.astro";
const frontmatter: Frontmatter = {
title: "Використання",
layout: "docs",
description: "Навчіться використовувати різні технології з T3 Stack.",
};
const lang = getLanguageFromURL(Astro.url.pathname);
const sidebarEntries = SIDEBAR[lang]["Usage"]!;
const files = await Astro.glob("./*.{md,mdx,astro}");
---
================================================
FILE: www/src/pages/uk/usage/next-auth.mdx
================================================
---
title: NextAuth.js
description: Використання NextAuth.js
layout: ../../../layouts/docs.astro
lang: uk
isMdx: true
---
import Callout from "../../../components/docs/callout.tsx";
Коли ви хочете мати систему автентифікації у вашому додатку Next.js, NextAuth.js - чудове рішення, щоб не морочитися з реалізацією складної безпеки самостійно. Він має великий список провайдерів для швидкого додавання аутентифікації OAuth і надає адаптери для багатьох баз даних і ORM.
## Провайдер контексту
У точці входу вашого додатка ви побачите, що ваш додаток загорнутий у [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
```tsx:pages/_app.tsx
>
```
Цей провайдер контексту дає змогу вашому застосунку отримати доступ до даних сесії з будь-якого місця вашого застосунку, не передаючи їх як пропси:
```tsx:pages/users/[id].tsx
import { useSession } from "next-auth/react";
const User = () => {
const { data: session } = useSession();
if (!session) {
// Handle unauthenticated state, e.g. render a SignIn component
return ;
}
return
Welcome {session.user.name}!
;
};
```
## Отримання сесії на сервері
Іноді вам може знадобитися запросити сесію на сервері. Щоб зробити це, попередньо отримайте сесію за допомогою функції-помічника `getServerAuthSession`, яку надає `create-t3-app`, і передайте її на клієнт за допомогою `getServerSideProps`:
```tsx:pages/users/[id].tsx
import { getServerAuthSession } from "../server/auth";
import { type GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerAuthSession(ctx);
return {
props: { session },
};
};
const User = () => {
const { data: session } = useSession();
// NOTE: `session` wont have a loading state since it's already prefetched on the server
...
}
```
## Включення `user.id` у сесію
Create T3 App налаштований для використання [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) у конфігурації NextAuth.js для включення ID користувача в об'єкт`session`.
```ts:pages/api/auth/[...nextauth].ts
callbacks: {
session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
```
Це пов'язано з файлом оголошення типів, щоб переконатися, що `user.id` типізовано під час доступу до об'єкта `session`. Детальніше про [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) у документації NextAuth.js.
```ts:types/next-auth.d.ts
import { DefaultSession } from "next-auth";
declare module "next-auth" {
інтерфейс Session {
user? {
id: string;
} & DefaultSession["user"];
}
}
```
Такий самий шаблон може бути використаний для додавання будь-яких інших даних в об'єкт `session`, наприклад, поля `role`, але **ним не слід зловживати для зберігання конфіденційних даних** на клієнті.
## Використання з tRPC
При використанні NextAuth.js з tRPC ви можете повторно створити використовувані, захищені процедури за допомогою [middleware](https://trpc.io/docs/v10/middlewares). Це дозволяє вам створювати процедури, які можуть бути доступні тільки автентифікованим користувачам. `create-t3-app` налаштовує все це для вас, дозволяючи вам легко отримувати доступ до сесії об’єкта в аутентифікованих процедурах.
Це робиться в два кроки:
1. Викликайте сесію із заголовків запиту за допомогою функції [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Перевага використання `getServerSession` замість звичайного `getSession` полягає в тому, що це серверна функція і вона не викликає непотрібних викликів fetch. `create-t3-app` створює допоміжну функцію, яка абстрагує це конкретне API щоб вам не треба було імпортувати обидва ваших NextAuth.js варіанти так як і `getServerSession` функцію кожного разу коли вам треба отримати доступ до сесії.
```ts:server/auth.ts
export const getServerAuthSession = async (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return await getServerSession(ctx.req, ctx.res, authOptions);
};
```
Використовуючи цю допоміжну функцію, ми можемо отримати сесію та передати її в контексті tRPC:
```ts:server/api/trpc.ts
import { getServerAuthSession } from "../auth";
export const createContext = async (opts: CreateNextContextOptions) => {
const { req, res } = opts;
const session = await getServerAuthSession({ req, res });
return await createContextInner({
session,
});
};
```
2. Створіть tRPC middleware, яке перевіряє, аутентифіковано чи користувач. Потім ми використовуємо middleware в `protectedProcedure`. Будь-який виклик процедур повинен бути автентифікований, інакше буде сгенерована помилка, яку можна правильно опрацювати на стороні клієнта.
```ts:server/api/trpc.ts
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
})
```
Об'єкт сесії - це легке, мінімальне представлення користувача і містить лише кілька полів. При використанні `protectedProcedures` у вас є доступ до ідентифікатора користувача, який можна використовувати для отримання більшої кількості даних з бази даних.
```ts:server/api/routers/user.ts
const userRouter = router({
me: protectedProcedure.query(async ({ ctx }) => {
const user = await prisma.user.findUnique({
where: {
id: ctx.session.user.id,
},
});
return user;
}),
});
```
## Використання з Prisma
Щоб змусити 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/). Зверніть увагу, що деякі провайдери вимагають додаткових полів для додавання в певні моделі. Ми рекомендуємо вам прочитати документацію для провайдера, який ви хочете використовувати, щоб переконатися, що у вас є всі необхідні поля.
### Додавання нових полів у ваші моделі
Коли ви додаєте нові поля до будь-якої з моделей `User`, `Account`, `Session` або `VerificationToken` (у більшості випадків вам потрібно лише змінити модель `User`), вам потрібно мати на увазі, що [адаптер Prisma](https://next-auth.js.org/adapters/prisma) автоматично створює поля в цих моделях при реєстрації нових користувачів та вході до системи. Тому, додаючи нові поля до цих моделей, ви повинні надати значення за замовчуванням для них, оскільки адаптер не знає про них.
Якщо, наприклад, ви хочете додати `role` у модель `User`, вам потрібно буде надати значення за замовчуванням для поля `role`. Це робиться шляхом додавання значення `@default` до поля `role` у моделі `User`:
```diff:prisma/schema.prisma
+ enum Role {
+ USER
+ ADMIN
+ }
model User {
...
+ role Role @default(USER)
}
```
## Використання з Next.js middleware
Використання NextAuth.js з Next.js middleware [вимагає використання стратегії сеансу JWT](https://next-auth.js.org/configuration/nextjs#caveats) для автентифікації. Це пов'язано з тим, що middleware може отримати доступ до сесійного cookie тільки в тому випадку, якщо це JWT. За замовчуванням, create-t3-app налаштований на використання **default** стратегії бази даних, у поєднанні з Prisma як адаптера бази даних.
Використання сесій баз даних - рекомендований підхід, й вам варто почитати про
JWT перед тим як переходити до стратегії JWT сесії, щоб уникнути будь-яких
проблем з безпекою.
Після переходу до стратегії JWT сесії, переконайтеся, що ви оновили `session` колбек в `src/server/auth.ts`.
Об'єкт `user` буде `undefined`. Замість цього, витягніть ID користувача з об'єкту `token`.
Наприклад:
```diff:server/auth.ts
export const authOptions: NextAuthOptions = {
+ session: {
+ strategy: "jwt",
+ },
callbacks: {
- session: ({ session, user }) => ({
+ session: ({ session, token }) => ({
...session,
user: {
...session.user,
- id: user.id,
+ id: token.sub,
},
}),
},
}
```
## Налаштовуємо DiscordProvider за замовчуванням
1. Перейдіть до розділу Applications у [Discord Developer Portal](https://discord.com/developers/applications) і натисніть "New Application"
2. У меню налаштувань перейдіть до "OAuth2 => General"
- Скопіюйте Client ID і вставте його в `AUTH_DISCORD_ID` у `.env`.
- Біля Client Secret натисніть "Reset Secret" і скопіюйте цей рядок у `AUTH_DISCORD_SECRET` у `.env`. Будьте обережними, оскільки ви більше не зможете побачити цей secret, і скидання його призведе до того, що існуючий протермінується.
- Натисніть "Add Redirect" і вставте `/api/auth/callback/discord` (приклад для локальної розробки: http://localhost:3000/api/auth/callback/discord)
- Збережіть зміни
- Можливо, але не рекомендується, використовувати один і той же додаток Discord для розробки та продакшену. Ви також можете розглянути [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) під час розробки.
## Корисні ресурси
| Ресурс | Посилання |
| --------------------------------- | --------------------------------------- |
| Документація NextAuth.js | https://next-auth.js.org/ |
| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth |
| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth |
================================================
FILE: www/src/pages/uk/usage/next-js.md
================================================
---
title: Next.js
description: Використання Next.js
layout: ../../../layouts/docs.astro
lang: uk
---
Next.js це бекенд фреймворк для ваших React додатків.
Подивіться [виступ Theo на Next.js Conf](https://www.youtube.com/watch?v=W4UhNo3HAMw) щоб отримати більш детальне розуміння того, що таке Next.js і як він працює.
## Чому я повинен це використовувати?
Ми любимо React. Він зробив розробку UI доступною у тому вигляді, в якому ми ніколи не могли собі уявити. Він також може вести розробників тернистими шляхами. Next.js пропонує злегка суб'єктивний, більш оптимізований підхід до створення додатків з використанням React. Від маршрутизації до визначення API до візуалізації зображень ми довіряємо Next.js, щоб вести розробників до правильних рішень.
Поєднуючи Next.js з [Vercel](https://vercel.com/), ви можете розробляти та деплоїти веб-програми легше, ніж будь-коли. Їх надзвичайно щедрий безкоштовний тариф та супер інтуїтивний інтерфейс надають рішення в один клік для деплойменту вашого сайту (Ми ❤️ Vercel)
## Get Static/Server Props
Ключові особливості 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`, коли дані динамічні та можуть бути отримані поступово.
Якщо ви все одно хочете використовувати цю функцію, перегляньте ці посилання: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) та [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers)
## Корисні ресурси
| Ресурс | Посилання |
| ------------------------- | ---------------------------------- |
| Next.js Документація | https://nextjs.org/docs |
| Next.js GitHub | https://github.com/vercel/next.js |
| Next.js Блог | https://nextjs.org/blog |
| Next.js Discord | https://nextjs.org/discord |
| Next.js Twitter | https://twitter.com/nextjs |
| Vercel/Next.js на YouTube | https://www.youtube.com/c/VercelHQ |
================================================
FILE: www/src/pages/uk/usage/prisma.md
================================================
---
title: Prisma
description: Використання Prisma
layout: ../../../layouts/docs.astro
lang: uk
---
Prisma це ORM для TypeScript, який дозволяє визначати схему та моделі бази даних у файлі `schema.prisma`, а потім генерувати клієнт, який забезпечує типобезпеку та може використовуватись для взаємодії з базою даних з вашого бекенда.
## Prisma Client
Розташований в `/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) за замовчуванням і рекомендуємо використовувати його замість окремого імпорту у кожному файлі.
## Схема
Ви знайдете файл схеми Prisma в `/prisma/schema.prisma`. Цей файл використовується для визначення схеми та моделей баз даних, а також для генерації Prisma Client.
### З NextAuth.js
Коли ви вибираєте NextAuth.js у поєднанні з Prisma, файл схеми генерується і налаштовується для вас з рекомендованими значеннями для моделей `User`, `Session`, `Account` та `VerificationToken`, згідно з [документацією NextAuth.js](https://next-auth.js.org/adapters/prisma).
## База даних за замовчуванням
База даних за замовчуванням - це база даних SQLite, яка відмінно підходить для розробки та швидкого створення proof-of-concept, але не рекомендується для використання у продакшені. Ви можете змінити базу даних, використовуючи 'provider' в блоці 'datasource' на 'postgresql' або 'mysql', а потім оновити рядок підключення до змінних середовища, щоб вказати на вашу базу даних.
## Заповнення (seeding) бази даних
[Заповнення (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` або інші раннери також працюватимуть.
```jsonc:package.json
{
"scripts": {
"db-seed": "NODE_ENV=development prisma db seed"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
```
```ts:prisma/seed.ts
import { db } from "../src/server/db";
async function main() {
const id = "cl9ebqhxk00003b600tymydho";
await db.example.upsert({
where: {
id,
},
create: {
id,
},
update: {},
});
}
main()
.then(async () => {
await db.$disconnect();
})
.catch(async (e) => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
```
Потім, просто запустіть `pnpm db-seed` (або `npm`/`yarn`), щоб заповнити вашу базу даних.
## Корисні ресурси
| Ресурс | Посилання |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Документація Prisma | https://www.prisma.io/ |
| Prisma GitHub | https://github.com/prisma/ |
| Prisma Migrate Playground | https://playground.prisma.io/guides |
| NextAuth.JS Адаптер для Prisma | https://next-auth.js.org/adapters/ |
| Гайд з підключення PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
================================================
FILE: www/src/pages/uk/usage/tailwind.md
================================================
---
title: Tailwind CSS
description: Використання Tailwind CSS
layout: ../../../layouts/docs.astro
lang: uk
---
## Що таке Tailwind CSS?
Tailwind CSS - це невеликий [utility first](https://tailwindcss.com/docs/utility-first) CSS фреймворк для створення власного дизайну, без перемикання контексту, який потрібний для звичайного CSS. Це чисто CSS фреймворк і він не надає ніяких попередньо зібраних компонентів або логіки, і надає [принципово інший набір переваг](https://www.youtube.com/watch?v=CQuTF-bkOgc) у порівнянні з бібліотекою компонентів, такою як наприклад Material UI.
Він робить CSS неймовірно легким і швидким для написання, як показано в наступному прикладі:
Старий CSS:
1. Напишіть CSS, часто в окремому файлі
```css
.my-class {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
border: 1px solid #e2e8f0;
border-radius: 0.25rem;
padding: 1rem;
}
```
2. Імпортуйте CSS у ваш компонент
```jsx
import "./my-class.css";
```
3. Додайте клас у ваш HTML
```html
...
```
Еквівалент у Tailwind:
1. Просто напишіть класи у вашому HTML
```html
...
```
Використовуючи разом із React компонентами, він є надзвичайно потужним для швидкого створення UI.
Tailwind CSS містить вбудовану красиву систему дизайну, яка поставляється від початку з ретельно вибраною палітрою кольорів, розмірами для стилів, таких як ширина/висота і відступи для єдиного дизайну, а також точками переривання для створення адаптивних макетів. Ця система дизайну може бути налаштована та розширена для створення точного набору стилів, які потрібні вашому проекту.
Tru Narla краще відома як [mewtru](https://twitter.com/trunarla) дала приголомшливу лекцію про [створення системи дизайну з використанням Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).
## Використання
Переконайтеся, що у вас є плагіни редактора для Tailwind, щоб поліпшити ваш досвід написання Tailwind.
### Розширення та плагіни
- [Розширення для VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
### Форматування
Класи 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 ми встановимо та налаштуємо це для вас.
### Додавання класів в залежності від умов
Додавання класів в залежності від умов з використанням тернарних операторів може стати дуже безладним і важким для читання. Ці пакети допомагають організувати ваші класи, використовуючи деяку логіку з умовами.
- [clsx](https://github.com/lukeed/clsx)
- [classnames](https://github.com/JedWatson/classnames)
## Корисні ресурси
| Ресурс | Посилання |
| ----------------------------- | -------------------------------------------------------- |
| Документація Tailwind | https://tailwindcss.com/docs/editor-setup/ |
| Шпаргалка по Tailwind | https://nerdcave.com/tailwind-cheat-sheet/ |
| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ |
| Сервер Tailwind в Discord | https://tailwindcss.com/discord/ |
| Канал TailwindLabs на Youtube | https://www.youtube.com/tailwindlabs/ |
| Tailwind Playground | https://play.tailwindcss.com/ |
================================================
FILE: www/src/pages/uk/usage/trpc.md
================================================
---
title: tRPC
description: Використання tRPC
layout: ../../../layouts/docs.astro
lang: uk
---
tRPC дозволяє нам писати типобезпечні API від кінця до кінця (end-to-end) без будь-якої генерації коду чи подовження рантайму. Він використовує чудовий висновок TypeScript для виведення визначень типів вашого API-маршрутизатора і дозволяє викликати ваші API-процедури з інтерфейсу з повною безпекою типів і автоматичним завершенням. Використовуючи tRPC, ваш фронтенд і бекенд почуваються ближче один до одного, ніж будь-коли, забезпечуючи винятковий досвід розробника.
"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."
tRPC контриб'ютор [trashh_dev](https://twitter.com/trashh_dev) [виступив на Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) з розповіддю про tRPC. Ми рекомендуємо вам подивитися, якщо ви ще не зробили це.
З tRPC ви пишете функції TypeScript на бекенді, а потім викликаєте їх із фронтенду. Проста процедура tRPC може виглядати так:
```ts:server/api/routers/user.ts
const userRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.prisma.user.findFirst({
where: {
id: input,
},
});
}),
});
```
Це процедура tRPC (еквівалент route handler-а у традиційному бекенді), яка спочатку перевіряє вхідні дані за допомогою Zod (який є тією самою бібліотекою перевірки, яку ми використовуємо для [змінних середовища](./env-variables)) – у цьому випадку ми переконуємось , що вхідні дані є рядком. Якщо вхідні дані не є рядком, він надішле інформативну помилку.
Після вхідних даних ми застосовуємо функцію, яка може бути або [запитом](https://trpc.io/docs/v10/react-queries), [мутацією](https://trpc.io/docs/v10/react-mutations) або [підпискою](https://trpc.io/docs/v10/subscriptions). У нашому прикладі resolver викликає нашу базу даних за допомогою клієнта [prisma](./prisma) і повертає користувача, у якого `id` збігається з тим, що ми передали.
Ви визначаєте свої процедури в `routers` які є колекцією пов'язаних процедур із спільним ім'ям. У вас може бути один роутер для користувачів, один для постів і ще один для повідомлень. Ці роутери потім можна об'єднати в єдиний централізований `appRouter`:
```ts:server/api/root.ts
const appRouter = createTRPCRouter({
users: userRouter,
posts: postRouter,
messages: messageRouter,
});
export type AppRouter = typeof appRouter;
```
Зверніть увагу, що нам потрібно експортувати тільки типи наших роутерів, що означає, що ми ніколи не імпортуємо серверний код на клієнта.
Тепер давайте викличемо процедуру на нашому фронтенді. tRPC надає обгортку для `@tanstack/react-query`, яка дозволяє використовувати всі можливості хуків (hooks), які він надає, але з додатковою перевагою того, що ваші виклики API типізовані та інферовані (inferred). Ми можемо викликати наші процедури з фронтенду так:
```tsx:pages/users/[id].tsx
import { useRouter } from "next/router";
import { api } from "../../utils/api";
const UserPage = () => {
const { query } = useRouter();
const userQuery = api.users.getById.useQuery(query.id);
return (
{userQuery.data?.name}
);
};
```
Ви відразу помітите, наскільки хороші автодоповнення та типобезпека. Як тільки ви почнете писати `api.`, ваші роутери з'являться в автодоповненні, і коли ви оберете роутер, його процедури також з'являться. Ви також отримаєте помилку TypeScript, якщо ваше введення не відповідає валідатору, який ви визначили на бекенді.
## Обробка помилок
По дефолту, `create-t3-app` створює [error formatter](https://trpc.io/docs/error-formatting) який дозволяє вам виводити ваші Zod помилки якщо ви отримуєте помилки валідації на бекенді.
Приклад використання:
```tsx
function MyComponent() {
const { mutate, error } = api.post.create.useMutation();
return (
);
}
```
## Файли
tRPC вимагає багато шаблонного коду, який `create-t3-app` налаштовує для вас. Давайте розглянемо файли, що генеруються:
### 📄 `pages/api/trpc/[trpc].ts`
Цей файл є точкою входу для вашого 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.
### 📄 `server/api/trpc.ts`
Цей файл поділено на дві частини: створення контексту та ініціалізація tRPC.
1. Ми визначаємо контекст, який передається вашим tRPC процедурам. Контекст - це дані, до яких у вас є доступ у всіх ваших процедурах tRPC, і це відмінне місце, щоб помістити речі, такі як з'єднання з базою даних, інформація про аутентифікацію і т.д. У create-t3-app ми використовуємо дві функції, щоб увімкнути використання підмножини контексту, коли ми не маємо доступу до об'єкта запиту.
- `createInnerTRPCContext`: Це те місце, де ви визначаєте контекст, який не залежить від запиту, наприклад, ваше з'єднання з базою даних. Ви можете використовувати цю функцію для [інтеграційного тестування](#sample-integration-test) або [ssg-помічників](https://trpc.io/docs/v10/ssg-helpers), де у вас немає об'єкта запиту.
- `createTRPCContext`: Тут ви визначаєте контекст, який залежить від запиту: наприклад, сесія користувача. Ви запитуєте сесію за допомогою об'єкта `opts.req`, а потім передаєте сесію у функцію `createInnerTRPCContext` для створення остаточного контексту.
2. Ми ініціалізуємо tRPC і визначаємо повторно використовані [процедури](https://trpc.io/docs/v10/procedures) та [посередники](https://trpc.io/docs/v10/middlewares). За угодою, ви не повинні експортувати весь об'єкт `t`, а натомість створювати повторно використовувані процедури та посередники та експортувати їх.
Ви помітите, що ми використовуємо `superjson` як [перетворювач даних](https://trpc.io/docs/v10/data-transformers). Це дозволяє зберігати типи даних, коли вони досягають клієнта, тому якщо ви, наприклад, відправляєте об'єкт `Date`, клієнт поверне `Date`, а не рядок, що є нагодою для більшості API.
### 📄 `server/api/routers/*.ts`
Це те місце, де ви визначаєте маршрути та процедури вашого API. Ви [створюєте окремі маршрутизатори](https://trpc.io/docs/v10/router) для пов'язаних процедур.
### 📄 `server/api/root.ts`
Тут ми [об'єднуємо](https://trpc.io/docs/v10/merging-routers) всі під-маршрутизатори, визначені в `routers/**` в єдиний додатковий маршрутизатор.
### 📄 `utils/api.ts`
Це точка входу для tRPC на фронтенді. Тут ви імпортуєте **визначення типів** маршрутизатора та створюєте клієнт tRPC разом із хуками react-query. Оскільки ми включили `superjson` як перетворювач даних на бекенді, нам також потрібно включити його на фронтенді. Це тому що серіалізовані дані з бэкенда десеріалізуються на фронтенді.
Тут ви визначите свої 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), що виводить корисні журнали запитів під час розробки.
Зрештою, ми експортуємо [допоміжний тип](https://trpc.io/docs/v10/infer-types#additional-dx-helper-type), який ви можете використовувати для виведення типів на фронтенді.
Create T3 App контриб’ютор [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) зробив [відео про потоки даних у tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Це відео рекомендовано якщо ви використовували tRPC, але все ще відчуваєте, що трохи не розумієте як воно працює.
## Як я можу викликати свій API ззовні?
У звичайних API, ви можете викликати ваші кінцеві точки (endpoints) використовуючи будь-який HTTP клієнт, як `curl`, `Postman`, `fetch` або прямо з вашого браузера. З tRPC, це працює трохи інакше. Якщо ви хочете викликати ваші процедури без клієнта tRPC, є два рекомендовані способи зробити це:
### Розкрийте одну процедуру зовні
Якщо ви бажаєте розкрити вашу процедуру зовні, вам варто шукати [server side calls](https://trpc.io/docs/v10/server-side-calls). Це дозволить вам створити звичайну кінцеву точку (endpoint) API Next.js, але перевикористовувати частину резолвера вашої процедури tRPC.
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { appRouter, createCaller } from "../../../server/api/root";
import { createTRPCContext } from "../../../server/api/trpc";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
// Create context and caller
const ctx = await createTRPCContext({ req, res });
const caller = createCaller(ctx);
try {
const { id } = req.query;
const user = await caller.user.getById(id);
res.status(200).json(user);
} catch (cause) {
if (cause instanceof TRPCError) {
// An error from tRPC occurred
const httpCode = getHTTPStatusCodeFromError(cause);
return res.status(httpCode).json(cause);
}
// Another error occurred
console.error(cause);
res.status(500).json({ message: "Internal server error" });
}
};
export default userByIdHandler;
```
### Розкрийте кожну процедуру зовнішньо
Якщо ви хочете розкрити будь-яку процедуру ззовні, познайомтеся з плагіном спільноти [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Надаючи додаткові метаданні вашим процедурам, ви можете створити відповідний REST API з вашого маршрутизатора tRPC.
### Це всього лише HTTP-запити
tRPC взаємодіє через HTTP, тому також можна викликати ваші процедури tRPC за допомогою "звичайних" HTTP-запитів. Однак синтаксис може бути неприйнятним із-за [протоколу RPC](https://trpc.io/docs/v10/rpc), який використовує tRPC. Якщо вам цікаво, ви можете перевірити, як виглядають запити та відповіді tRPC у вашій network вкладці веб-браузера, але ми рекомендуємо робити це лише в якості навчальної вправи і притримуватися одного з рішень, описаних вище.
## Порівняння з кінцевою точкою (enpoint) Next.js API
Давайте порівняємо кінцеву точку Next.js API з процедурою tRPC. Припустимо, ми хочемо отримати об'єкт користувача з нашої бази даних і повернути його на фронтенд. Ми могли б написати кінцеву точку Next.js API таким чином:
```ts:pages/api/users/[id].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { prisma } from "../../../server/db";
const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const { id } = req.query;
if (!id || typeof id !== "string") {
return res.status(400).json({ error: "Invalid id" });
}
const examples = await prisma.example.findFirst({
where: {
id,
},
});
res.status(200).json(examples);
};
export default userByIdHandler;
```
```ts:pages/users/[id].tsx
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
const UserPage = () => {
const router = useRouter();
const { id } = router.query;
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/user/${id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [id]);
};
```
Порівняйте це з прикладом tRPC вище і ви побачите деякі переваги tRPC:
- Замість того, щоб вказувати URL для кожного маршруту, який може стати незручним для дебагінгу, якщо ви перемістите щось, ваш весь маршрутизатор - це об'єкт з автозаповненням.
- Вам не потрібно перевіряти, який метод HTTP був використаний.
- Вам не потрібно перевіряти, що запит або тіло запиту містять правильні дані у процедурі, тому що Zod подбає про це.
- Замість створення відповіді, ви можете викидати помилки та повертати значення або об'єкт, як у будь-якій іншій функції TypeScript.
- Викликаючи процедуру на фронтенді, ви отримуєте автозаповнення та перевірку типів.
## Корисні сніпети
Тут наведені деякі сніпети, які можуть стати в нагоді.
### Включення CORS
Якщо вам потрібно використовувати ваш API з іншого домену, наприклад в монорепозиторії, який включає додаток React Native, вам може знадобитися включити CORS:
```ts:pages/api/trpc/[trpc].ts
import { type NextApiRequest, type NextApiResponse } from "next";
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";
import cors from "nextjs-cors";
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// Enable cors
await cors(req, res);
// Create and call the tRPC handler
return createNextApiHandler({
router: appRouter,
createContext: createTRPCContext,
})(req, res);
};
export default handler;
```
### Оптимістичні оновлення
Оптимістичне оновлення - це коли ми оновлюємо інтерфейс користувача до того, як API-запит завершиться. Це надає користувачеві кращий досвід, тому що він не повинен чекати завершення API-запиту, перш ніж інтерфейс користувача відобразить результат його дії. Однак програми, які цінують коректність даних, повинні уникати оптимістичних оновлень, оскільки вони не є «вірним» уявленням стану бекенда. Ви можете прочитати більше у [документації React Query](https://tanstack.com/query/v4/docs/guides/optimistic-updates).
```tsx
const MyComponent = () => {
const listPostQuery = api.post.list.useQuery();
const utils = api.useContext();
const postCreate = api.post.create.useMutation({
async onMutate(newPost) {
// Cancel outgoing fetches (so they don't overwrite our optimistic update)
await utils.post.list.cancel();
// Get the data from the queryCache
const prevData = utils.post.list.getData();
// Optimistically update the data with our new post
utils.post.list.setData(undefined, (old) => [...old, newPost]);
// Return the previous data so we can revert if something goes wrong
return { prevData };
},
onError(err, newPost, ctx) {
// If the mutation fails, use the context-value from onMutate
utils.post.list.setData(undefined, ctx.prevData);
},
onSettled() {
// Sync with server once mutation has settled
utils.post.list.invalidate();
},
});
};
```
### Простий Інтеграційний Тест
Тут приведено простий інтеграційний тест, який використовує [Vitest](https://vitest.dev), щоб перевірити, що ваш маршрутизатор tRPC працює належним чином, парсер вхідних даних виводить правильний тип і дані, що повертаються, відповідають очікуваному результату.
```ts
import { type inferProcedureInput } from "@trpc/server";
import { expect, test } from "vitest";
import { appRouter, type AppRouter } from "~/server/api/root";
import { createInnerTRPCContext } from "~/server/api/trpc";
test("example router", async () => {
const ctx = await createInnerTRPCContext({ session: null });
const caller = appRouter.createCaller(ctx);
type Input = inferProcedureInput;
const input: Input = {
text: "test",
};
const example = await caller.example.hello(input);
expect(example).toMatchObject({ greeting: "Hello test" });
});
```
Якшо ваша процедура захищена, ви можете передати замоканий об'єкт `session` при створенні контексту:
```ts
test("protected example router", async () => {
const ctx = await createInnerTRPCContext({
session: {
user: { id: "123", name: "John Doe" },
expires: "1",
},
});
const caller = appRouter.createCaller(ctx);
// ...
});
```
## Корисні ресурси
| Ресурс | Посилання |
| ------------------------------------ | ------------------------------------------------------- |
| Документація tRPC | https://www.trpc.io |
| Декілька прикладів використання tRPC | https://github.com/trpc/trpc/tree/next/examples |
| Документація React Query | https://tanstack.com/query/v4/docs/adapters/react-query |
================================================
FILE: www/src/pages/uk/usage/typescript.md
================================================
---
title: TypeScript
description: Використання TypeScript
layout: ../../../layouts/docs.astro
lang: uk
---
Незважаючи на те новачок ви або досвідчений розробник, ми вважаємо, що TypeScript - це маст-хев. Спочатку він може виглядати гнітюче, але, як і багато інших інструментів, багато розробників не повертаються назад після того, як почали його використовувати.
Він надає зворотний зв'язок в режимі реального часу при написанні коду, визначаючи очікувані типи даних, і надає корисні підказки в редакторі коду або кричить червоними хвилястими лініями, якщо ви намагаєтеся отримати доступ до властивості, якої не існує, або намагаєтеся передати значення неправильного типу, яке в іншому випадку довелося б налагоджувати далі по лінії.
Це інструмент, який, мабуть, забезпечує найбільшу продуктивність розробникам; він надає документацію для коду, який ви пишете або використовуєте безпосередньо у вашому редакторі та має миттєвий зворотний зв'язок, коли ви неминуче робите помилки, що абсолютно безцінно.
## Виведення типів (Type Inference)
Поки багато нових розробників на TypeScript стурбовані написанням TypeScript, багато з його переваг насправді не вимагають від вас зміни вашого коду взагалі, зокрема виведення типів. Висновок типів означає, що якщо щось типізовано, цей тип слідуватиме за ним протягом потоку програми без необхідності повторного оголошення в інших місцях. Це означає, що, наприклад, після того, як ви визначили типи аргументів, які приймає функція, решта функції зазвичай буде безпечною щодо типів без необхідності введення будь-якого додаткового коду, специфічного для TypeScript. Розробники бібліотек витрачають величезну кількість часу на підтримку типів для своїх бібліотек, що означає, що ми, як розробники додатків, можемо отримати вигоду від виведення типів та вбудованої документації у вашому редакторі коду, який ці типи надають.
Перегляньте відео Theo про те, що [ви, можливо, використовуєте TypeScript неправильно](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
## Потужні застосування виведення типів
### Zod
[Zod](https://github.com/colinhacks/zod) - це бібліотека перевірки схем, побудована поверх TypeScript. Напишіть схему, яка є єдиним джерелом істини для ваших даних, і Zod гарантує, що ваші дані будуть дійсними у всьому додатку, навіть поза межами мережі та зовнішніх API.
### Tanstack Query
[Tanstack Query](https://tanstack.com/query/v4/) надає вам декларативні, завжди актуальні автоматично керовані запити та мутації, які безпосередньо покращують як Developer, так і User Experience.
## Корисні ресурси
| Ресурс | Посилання |
| ---------------------------------------------------------------- | ----------------------------------------------------------------- |
| Посібник з TypeScript | https://www.typescriptlang.org/docs/handbook/ |
| Гайд по TypeScript для новачків | https://github.com/total-typescript/beginners-typescript-tutorial |
| Type Challenges | https://github.com/type-challenges/type-challenges |
| Канал Родні Маллена зі світу TypeScript (Matt Pocock) на YouTube | https://www.youtube.com/c/MattPocockUk/videos |
================================================
FILE: www/src/pages/uk/why.md
================================================
---
title: Чому CT3A?
description: Чому вам слід вибрати Create T3 App для наступного проекту?
layout: ../../layouts/docs.astro
lang: uk
---
Ми почали Create T3 App, тому що [Theo](https://twitter.com/t3dotgg) відмовився робити шаблон своїх улюблених технологій. Натхненний create-next-app, [Astro's CLI](https://astro.build) та загальною любов'ю до типобезпеки, команда Create T3 App працювала, щоб створити кращу можливу відправну точку для нових проектів T3 Stack.
Якщо ви зацікавлені у використанні Next.js у типобезпечному варіанті, це те, з чого потрібно почати. Якщо ви цікавитеся будь-якими з конкретних технологічних рішень, які ми зробили, читайте далі :)
## Чому TypeScript?
JavaScript складний. Навіщо додавати ще більше правил?
Ми цілком впевнені, що досвід TypeScript дозволяє вам бути кращим розробником. Він надає зворотний зв'язок під час написання коду, визначаючи очікувані типи даних, і, або допомгає корисним автозаповненням у вашому редакторі, або кричить на вас червоними хвилястими лініями, якщо ви намагаєтеся отримати доступ до властивості, якої не існує, або намагаєтеся передати значення неправильного типу, що в іншому випадку довелося б налагоджувати в подальшому. Незалежно від того, новачок ви у веб-розробці або досвідчений професіонал, "суворість" TypeScript забезпечує менш дратівливий, більш послідовний досвід, ніж ванільний JS.
Типобезпека робить вас швидше. Якщо ви ще не переконані, ви [можете використовувати TypeScript неправильно...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
## Чому Next.js?
Ми любимо React. Він зробив розробку UI доступною у тому вигляді, в якому ми ніколи не могли собі уявити. Він також може вести розробників тернистими шляхами.
Next.js пропонує злегка суб'єктивний, більш оптимізований підхід до створення додатків з використанням React. Від маршрутизації до визначення API до візуалізації зображень ми довіряємо Next.js, щоб вести розробників до правильних рішень.
## Чому tRPC/Prisma/Tailwind/и т.д.?
Хоча ми віримо, що все має бути якнайлегше, ми знаходимо, що ці частини використовуються в кожному проекті, складнішому ніж "лендінг" (напр. проєкти зі складнішими технологіями і логікою). `create-t3-app` виконує чудову роботу, дозволяючи вам вибрати ті частини, які вам потрібні.
### tRPC
tRPC надає всі переваги GraphQL, такі як гладка та безперервна розробка клієнта проти типобезпечного сервера без будь-якого бойлерплейту. Це розумний аб'юз TypeScript, яке забезпечує неймовірний досвід розробки.
### Prisma
Prisma для SQL це те й що TypeScript для JS. Вона створила досвід розробки, якого раніше не було. Створюючи типи з схеми користувача, сумісної з [кількома базами даних](https://www.prisma.io/docs/concepts/database-connectors), Prisma гарантує безпеку типів від початку до кінця від вашої бази даних до вашої програми.
Prisma надає цілий [набір інструментів](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 для вашої бази даних, який дозволяє швидко читати та маніпулювати даними без необхідності писати код.
### Tailwind CSS
Tailwind відчувається як "CSS у режимі дзен".
Завдяки наданню будівельних блоків у вигляді гарних кольорів за замовчуванням, відступів та інших примітивних налаштувань Tailwind дозволяє легко створювати додаток із гарним зовнішнім виглядом. І на відміну від бібліотек компонентів, він не обмежує вас, коли ви хочете вивести свою програму на наступний рівень і створити щось красиве та унікальне.
До того ж, завдяки інлайновому підходу, Tailwind спонукає вас стилізувати без занепокоєння про назву класів, організацію файлів або будь-яку іншу проблему, не пов'язану з вирішенням завдання.
### NextAuth.js
Коли ви хочете додати систему аутентифікації у вашу програму NextJS, NextAuth.js - відмінне рішення, щоб не морочитися з реалізацією складної системи безпеки. Вона має великий список провайдерів для швидкого додавання аутентифікації через OAuth і надає адаптери для багатьох баз даних та ORM.
================================================
FILE: www/src/pages/zh-hans/deployment/docker.md
================================================
---
title: Docker
description: 使用 Docker 部署
layout: ../../../layouts/docs.astro
lang: zh-hans
---
你可以将这个 stack 容器化,将它作为一个单独容器使用 Docker 来部署,或者作为一系列容器的部分,使用 docker-compose 来部署。参看基于本文档的示例仓库 [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker)。
## Docker 项目配置
请注意 Next.js 会针对编译时客户端的环境变量(在客户端,名称前缀含有 `NEXT_PUBLIC`) 和运行时环境的服务器端变量有不同的处理过程。在本次演示中我们将使用两个环境变量,请注意它们在 `Dockerfile` 文件中的位置、命令行参数以及文件 `docker-compose.yml`:
- `DATABASE_URL` (被用于服务器端)
- `NEXT_PUBLIC_CLIENTVAR` (被用于客户端)
### 1. Next 的配置
在你的 [`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):
```diff
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
```
### 2. 创建 dockerignore 文件
点击这里并将下方内容添加到 .dockerignore 里: