···3344# This file will be committed to version control, so make sure not to have any secrets in it.
55# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
66-77-# We use dotenv to load Prisma from Next.js' .env file
88-# @see https://www.prisma.io/docs/reference/database-reference/connection-urls
99-DATABASE_URL=file:./db.sqlite
1010-1111-# @see https://next-auth.js.org/configuration/options#nextauth_url
1212-NEXTAUTH_URL=http://localhost:3000
1313-1414-# You can generate the secret via 'openssl rand -base64 32' on Unix
1515-# @see https://next-auth.js.org/configuration/options#secret
1616-NEXTAUTH_SECRET=supersecret
1717-1818-# Preconfigured Discord OAuth provider, works out-of-the-box
1919-# @see https://next-auth.js.org/providers/discord
2020-DISCORD_CLIENT_ID=
2121-DISCORD_CLIENT_SECRET=
+1-1
.eslintrc.js
···11/** @type {import("eslint").Linter.Config} */
22const config = {
33 root: true,
44- extends: ["@acme/eslint-config"], // uses the config in `packages/config/eslint`
44+ extends: ["@graysky/eslint-config"], // uses the config in `packages/config/eslint`
55 parser: "@typescript-eslint/parser",
66 parserOptions: {
77 ecmaVersion: "latest",
-5
.github/workflows/ci.yml
···4747 - name: Install deps (with cache)
4848 run: pnpm install
49495050- # Normally, this would be done as part of the turbo pipeline - however since the Expo app doesn't depend on `@acme/db` it doesn't care.
5151- # TODO: Free for all to find a better solution here.
5252- - name: Generate Prisma Client
5353- run: pnpm turbo db:generate
5454-5550 - name: Build, lint and type-check
5651 run: pnpm turbo build lint type-check
5752 env:
···33# @link https://docs.expo.dev/guides/monorepos/#common-issues
44node-linker=hoisted
5566-# In order to cache Prisma correctly
77-public-hoist-pattern[]=*prisma*
88-99-# FIXME: @prisma/client is required by the @acme/auth,
1010-# but we don't want it installed there since it's already
1111-# installed in the @acme/db package
1212-strict-peer-dependencies=false
1313-146# Prevent pnpm from adding the "workspace:"" prefix to local
157# packages as it casues issues with manypkg
168# @link https://pnpm.io/npmrc#prefer-workspace-packages
···55## Installation
6677There are two ways of initializing an app using `create-t3-turbo` starter. You can either use this repository as a template or use Turbo's CLI to init your project:
88+89```bash
910npx create-turbo@latest -e https://github.com/t3-oss/create-t3-turbo
1011```
···55import { createTRPCReact } from "@trpc/react-query";
66import superjson from "superjson";
7788-import { type AppRouter } from "@acme/api";
88+import { type AppRouter } from "@graysky/api";
991010/**
1111 * A set of typesafe hooks for consuming your API.
1212 */
1313export const api = createTRPCReact<AppRouter>();
1414-export { type RouterInputs, type RouterOutputs } from "@acme/api";
1414+export { type RouterInputs, type RouterOutputs } from "@graysky/api";
15151616/**
1717 * Extend this function when going to production by
+4
apps/expo/src/utils/cx.ts
···11+import clsx, { type ClassValue } from "clsx";
22+import { twMerge } from "tailwind-merge";
33+44+export const cx = (...values: ClassValue[]) => twMerge(clsx(...values));
+1-1
apps/expo/tailwind.config.js
···2233// import { type Config } from "tailwindcss";
4455-// import baseConfig from "@acme/tailwind-config";
55+// import baseConfig from "@graysky/tailwind-config";
6677// export default {
88// presets: [baseConfig],
+1-1
apps/nextjs/next.config.mjs
···88const config = {
99 reactStrictMode: true,
1010 /** Enables hot reloading for local packages without a build step */
1111- transpilePackages: ["@acme/api", "@acme/auth", "@acme/db"],
1111+ transpilePackages: ["@graysky/api"],
1212 /** We already do linting and typechecking as separate tasks in CI */
1313 eslint: { ignoreDuringBuilds: !!process.env.CI },
1414 typescript: { ignoreBuildErrors: !!process.env.CI },
···22import { createTRPCNext } from "@trpc/next";
33import superjson from "superjson";
4455-import type { AppRouter } from "@acme/api";
55+import type { AppRouter } from "@graysky/api";
6677const getBaseUrl = () => {
88 if (typeof window !== "undefined") return ""; // browser should use relative url
···3030 ssr: false,
3131});
32323333-export { type RouterInputs, type RouterOutputs } from "@acme/api";
3333+export { type RouterInputs, type RouterOutputs } from "@graysky/api";
+1-1
apps/nextjs/tailwind.config.ts
···11import type { Config } from "tailwindcss";
2233-import baseConfig from "@acme/tailwind-config";
33+import baseConfig from "@graysky/tailwind-config";
4455export default {
66 content: ["./src/**/*.tsx"],
···66 * tl;dr - this is where all the tRPC server stuff is created and plugged in.
77 * The pieces you will need to use are documented accordingly near the end
88 */
99-import { TRPCError, initTRPC } from "@trpc/server";
99+import { initTRPC } from "@trpc/server";
1010import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
1111import superjson from "superjson";
1212import { ZodError } from "zod";
1313-1414-import { getServerSession, type Session } from "@acme/auth";
1515-import { prisma } from "@acme/db";
16131714/**
1815 * 1. CONTEXT
···2320 * processing a request
2421 *
2522 */
2626-type CreateContextOptions = {
2727- session: Session | null;
2828-};
2323+type CreateContextOptions = Record<string, never>;
29243025/**
3126 * This helper generates the "internals" for a tRPC context. If you need to use
···3732 * @see https://create.t3.gg/en/usage/trpc#-servertrpccontextts
3833 */
3934const createInnerTRPCContext = (opts: CreateContextOptions) => {
4040- return {
4141- session: opts.session,
4242- prisma,
4343- };
3535+ return {};
4436};
45374638/**
···5244 const { req, res } = opts;
53455446 // Get the session from the server using the unstable_getServerSession wrapper function
5555- const session = await getServerSession({ req, res });
56475757- return createInnerTRPCContext({
5858- session,
5959- });
4848+ return createInnerTRPCContext({});
6049};
61506251/**
···10089 * can still access user session data if they are logged in
10190 */
10291export const publicProcedure = t.procedure;
103103-104104-/**
105105- * Reusable middleware that enforces users are logged in before running the
106106- * procedure
107107- */
108108-const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
109109- if (!ctx.session?.user) {
110110- throw new TRPCError({ code: "UNAUTHORIZED" });
111111- }
112112- return next({
113113- ctx: {
114114- // infers the `session` as non-nullable
115115- session: { ...ctx.session, user: ctx.session.user },
116116- },
117117- });
118118-});
119119-120120-/**
121121- * Protected (authed) procedure
122122- *
123123- * If you want a query or mutation to ONLY be accessible to logged in users, use
124124- * this. It verifies the session is valid and guarantees ctx.session.user is not
125125- * null
126126- *
127127- * @see https://trpc.io/docs/procedures
128128- */
129129-export const protectedProcedure = t.procedure.use(enforceUserIsAuthed);
-3
packages/auth/index.ts
···11-export { authOptions } from "./src/auth-options";
22-export { getServerSession } from "./src/get-session";
33-export type { Session } from "next-auth";
···11-import { PrismaAdapter } from "@next-auth/prisma-adapter";
22-import { type DefaultSession, type NextAuthOptions } from "next-auth";
33-import DiscordProvider from "next-auth/providers/discord";
44-55-import { prisma } from "@acme/db";
66-77-/**
88- * Module augmentation for `next-auth` types
99- * Allows us to add custom properties to the `session` object
1010- * and keep type safety
1111- * @see https://next-auth.js.org/getting-started/typescript#module-augmentation
1212- **/
1313-declare module "next-auth" {
1414- interface Session extends DefaultSession {
1515- user: {
1616- id: string;
1717- // ...other properties
1818- // role: UserRole;
1919- } & DefaultSession["user"];
2020- }
2121-2222- // interface User {
2323- // // ...other properties
2424- // // role: UserRole;
2525- // }
2626-}
2727-2828-/**
2929- * Options for NextAuth.js used to configure
3030- * adapters, providers, callbacks, etc.
3131- * @see https://next-auth.js.org/configuration/options
3232- **/
3333-export const authOptions: NextAuthOptions = {
3434- callbacks: {
3535- session({ session, user }) {
3636- if (session.user) {
3737- session.user.id = user.id;
3838- // session.user.role = user.role; <-- put other properties on the session here
3939- }
4040- return session;
4141- },
4242- },
4343- adapter: PrismaAdapter(prisma),
4444- providers: [
4545- DiscordProvider({
4646- clientId: process.env.DISCORD_CLIENT_ID as string,
4747- clientSecret: process.env.DISCORD_CLIENT_SECRET as string,
4848- }),
4949- /**
5050- * ...add more providers here
5151- *
5252- * Most other providers require a bit more work than the Discord provider.
5353- * For example, the GitHub provider requires you to add the
5454- * `refresh_token_expires_in` field to the Account model. Refer to the
5555- * NextAuth.js docs for the provider you want to use. Example:
5656- * @see https://next-auth.js.org/providers/github
5757- **/
5858- ],
5959-};