add some scaffolding to name-generator
parent
e40a7aea4d
commit
aa35f43191
|
@ -32,3 +32,6 @@ yarn-error.log*
|
||||||
# turbo
|
# turbo
|
||||||
.turbo
|
.turbo
|
||||||
.direnv
|
.direnv
|
||||||
|
|
||||||
|
# I just clone create-t3-turbo and copy the apps and packages, so pls ignore it
|
||||||
|
create-t3-turbo
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Expo doesn't play nice with pnpm by default.
|
||||||
|
# The symbolic links of pnpm break the rules of Expo monorepos.
|
||||||
|
# @link https://docs.expo.dev/guides/monorepos/#common-issues
|
||||||
|
node-linker=hoisted
|
||||||
|
|
||||||
|
# In order to cache Prisma correctly
|
||||||
|
public-hoist-pattern[]=*prisma*
|
||||||
|
|
||||||
|
# FIXME: @prisma/client is required by the @acme/auth,
|
||||||
|
# but we don't want it installed there since it's already
|
||||||
|
# installed in the @acme/db package
|
||||||
|
strict-peer-dependencies=false
|
|
@ -0,0 +1,12 @@
|
||||||
|
/** @type {import("prettier").Config} */
|
||||||
|
module.exports = {
|
||||||
|
arrowParens: "always",
|
||||||
|
printWidth: 80,
|
||||||
|
singleQuote: false,
|
||||||
|
jsxSingleQuote: false,
|
||||||
|
semi: true,
|
||||||
|
trailingComma: "all",
|
||||||
|
tabWidth: 2,
|
||||||
|
plugins: [require.resolve("prettier-plugin-tailwindcss")],
|
||||||
|
tailwindConfig: "./packages/config/tailwind",
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
/** @type {import("eslint").Linter.Config} */
|
||||||
|
module.exports = {
|
||||||
|
extends: ["../../.eslintrc.cjs", "next"],
|
||||||
|
};
|
|
@ -0,0 +1,131 @@
|
||||||
|
# Create T3 App
|
||||||
|
|
||||||
|
This is an app bootstrapped according to the [init.tips](https://init.tips) stack, also known as the T3-Stack.
|
||||||
|
|
||||||
|
## Why are there `.js` files in here?
|
||||||
|
|
||||||
|
As per [T3-Axiom #3](https://github.com/t3-oss/create-t3-app/tree/next#3-typesafety-isnt-optional), we believe take 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 its 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 `@ts-check` comment at the top.
|
||||||
|
|
||||||
|
## 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 the most basic configuration and then move on to more advanced configuration.
|
||||||
|
|
||||||
|
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-Auth.js](https://next-auth.js.org)
|
||||||
|
- [Prisma](https://prisma.io)
|
||||||
|
- [TailwindCSS](https://tailwindcss.com)
|
||||||
|
- [tRPC](https://trpc.io) (using @next version? [see v10 docs here](https://alpha.trpc.io))
|
||||||
|
|
||||||
|
## How do I deploy this?
|
||||||
|
|
||||||
|
### Vercel
|
||||||
|
|
||||||
|
We recommend deploying to [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). It makes it super easy to deploy NextJs apps.
|
||||||
|
|
||||||
|
- Push your code to a GitHub repository.
|
||||||
|
- Go to [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) and sign up with GitHub.
|
||||||
|
- Create a Project and import the repository you pushed your code to.
|
||||||
|
- Add your environment variables.
|
||||||
|
- Click **Deploy**
|
||||||
|
- Now whenever you push a change to your repository, Vercel will automatically redeploy your website!
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
You can also dockerize this stack and deploy a container.
|
||||||
|
|
||||||
|
1. In your [next.config.mjs](./next.config.mjs), add the `output: "standalone"` option to your config.
|
||||||
|
2. Create a `.dockerignore` file with the following contents:
|
||||||
|
<details>
|
||||||
|
<summary>.dockerignore</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
README.md
|
||||||
|
.next
|
||||||
|
.git
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
3. Create a `Dockerfile` with the following contents:
|
||||||
|
<details>
|
||||||
|
<summary>Dockerfile</summary>
|
||||||
|
|
||||||
|
```Dockerfile
|
||||||
|
# Install dependencies only when needed
|
||||||
|
FROM node:16-alpine AS deps
|
||||||
|
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
# Rebuild the source code only when needed
|
||||||
|
FROM node:16-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Next.js collects completely anonymous telemetry data about general usage.
|
||||||
|
# Learn more here: https://nextjs.org/telemetry
|
||||||
|
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||||
|
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||||
|
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# If using npm comment out above and use below instead
|
||||||
|
# RUN npm run build
|
||||||
|
|
||||||
|
# Production image, copy all the files and run next
|
||||||
|
FROM node:16-alpine AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV production
|
||||||
|
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||||
|
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
# You only need to copy next.config.js if you are NOT using the default configuration
|
||||||
|
# COPY --from=builder /app/next.config.js ./
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder /app/package.json ./package.json
|
||||||
|
|
||||||
|
# Automatically leverage output traces to reduce image size
|
||||||
|
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||||
|
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"]
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
4. You can now build an image to deploy yourself, or use a PaaS such as [Railway's](https://railway.app) automated [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles) to deploy your app.
|
||||||
|
|
||||||
|
## Useful resources
|
||||||
|
|
||||||
|
Here are some resources that we commonly refer to:
|
||||||
|
|
||||||
|
- [Protecting routes with Next-Auth.js](https://next-auth.js.org/configuration/nextjs#unstable_getserversession)
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
@ -0,0 +1,22 @@
|
||||||
|
// @ts-check
|
||||||
|
/**
|
||||||
|
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
|
||||||
|
* This is especially useful for Docker builds.
|
||||||
|
*/
|
||||||
|
!process.env.SKIP_ENV_VALIDATION && (await import("./src/env/server.mjs"));
|
||||||
|
|
||||||
|
/** @type {import("next").NextConfig} */
|
||||||
|
const config = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
swcMinify: true,
|
||||||
|
experimental: {
|
||||||
|
// Enables hot-reload and easy integration for local packages
|
||||||
|
transpilePackages: ["@acme/api", "@acme/auth", "@acme/db"],
|
||||||
|
},
|
||||||
|
// We already do linting on GH actions
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: !!process.env.CI,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "@acme/name-generator",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"clean": "rm -rf .next .turbo node_modules",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"type-check": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@acme/api": "*",
|
||||||
|
"@acme/auth": "*",
|
||||||
|
"@acme/db": "*",
|
||||||
|
"@acme/tailwind-config": "*",
|
||||||
|
"@tanstack/react-query": "^4.16.1",
|
||||||
|
"@trpc/client": "^10.1.0",
|
||||||
|
"@trpc/next": "^10.1.0",
|
||||||
|
"@trpc/react-query": "^10.1.0",
|
||||||
|
"@trpc/server": "^10.1.0",
|
||||||
|
"next": "^13.0.5",
|
||||||
|
"next-auth": "^4.17.0",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"zod": "^3.18.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.0.0",
|
||||||
|
"@types/react": "^18.0.25",
|
||||||
|
"@types/react-dom": "^18.0.9",
|
||||||
|
"autoprefixer": "^10.4.13",
|
||||||
|
"eslint": "^8.28.0",
|
||||||
|
"eslint-config-next": "13.0.4",
|
||||||
|
"postcss": "^8.4.19",
|
||||||
|
"tailwindcss": "^3.2.4",
|
||||||
|
"typescript": "^4.9.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
module.exports = require("@acme/tailwind-config/postcss");
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,33 @@
|
||||||
|
// @ts-check
|
||||||
|
import { clientEnv, clientSchema } from "./schema.mjs";
|
||||||
|
|
||||||
|
const _clientEnv = clientSchema.safeParse(clientEnv);
|
||||||
|
|
||||||
|
export const formatErrors = (
|
||||||
|
/** @type {import('zod').ZodFormattedError<Map<string,string>,string>} */
|
||||||
|
errors,
|
||||||
|
) =>
|
||||||
|
Object.entries(errors)
|
||||||
|
.map(([name, value]) => {
|
||||||
|
if (value && "_errors" in value)
|
||||||
|
return `${name}: ${value._errors.join(", ")}\n`;
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (!_clientEnv.success) {
|
||||||
|
console.error(
|
||||||
|
"❌ Invalid environment variables:\n",
|
||||||
|
...formatErrors(_clientEnv.error.format()),
|
||||||
|
);
|
||||||
|
throw new Error("Invalid environment variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key of Object.keys(_clientEnv.data)) {
|
||||||
|
if (!key.startsWith("NEXT_PUBLIC_")) {
|
||||||
|
console.warn("❌ Invalid public environment variable name:", key);
|
||||||
|
|
||||||
|
throw new Error("Invalid public environment variable name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env = _clientEnv.data;
|
|
@ -0,0 +1,29 @@
|
||||||
|
// @ts-check
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify your server-side environment variables schema here.
|
||||||
|
* This way you can ensure the app isn't built with invalid env vars.
|
||||||
|
*/
|
||||||
|
export const serverSchema = z.object({
|
||||||
|
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_`.
|
||||||
|
*/
|
||||||
|
export const clientSchema = z.object({
|
||||||
|
// NEXT_PUBLIC_BAR: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can't destruct `process.env` as a regular object, so you have to do
|
||||||
|
* it manually here. This is because Next.js evaluates this at build time,
|
||||||
|
* and only used environment variables are included in the build.
|
||||||
|
* @type {{ [k in keyof z.infer<typeof clientSchema>]: z.infer<typeof clientSchema>[k] | undefined }}
|
||||||
|
*/
|
||||||
|
export const clientEnv = {
|
||||||
|
// NEXT_PUBLIC_BAR: process.env.NEXT_PUBLIC_BAR,
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
// @ts-check
|
||||||
|
/**
|
||||||
|
* This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars.
|
||||||
|
* It has to be a `.mjs`-file to be imported there.
|
||||||
|
*/
|
||||||
|
import { serverSchema } from "./schema.mjs";
|
||||||
|
import { env as clientEnv, formatErrors } from "./client.mjs";
|
||||||
|
|
||||||
|
const _serverEnv = serverSchema.safeParse(process.env);
|
||||||
|
|
||||||
|
if (!_serverEnv.success) {
|
||||||
|
console.error(
|
||||||
|
"❌ Invalid environment variables:\n",
|
||||||
|
...formatErrors(_serverEnv.error.format()),
|
||||||
|
);
|
||||||
|
throw new Error("Invalid environment variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key of Object.keys(_serverEnv.data)) {
|
||||||
|
if (key.startsWith("NEXT_PUBLIC_")) {
|
||||||
|
console.warn("❌ You are exposing a server-side env-variable:", key);
|
||||||
|
|
||||||
|
throw new Error("You are exposing a server-side env-variable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env = { ..._serverEnv.data, ...clientEnv };
|
|
@ -0,0 +1,20 @@
|
||||||
|
// src/pages/_app.tsx
|
||||||
|
import "../styles/globals.css";
|
||||||
|
import { SessionProvider } from "next-auth/react";
|
||||||
|
import type { Session } from "next-auth";
|
||||||
|
import type { AppType } from "next/app";
|
||||||
|
|
||||||
|
import { trpc } from "../utils/trpc";
|
||||||
|
|
||||||
|
const MyApp: AppType<{ session: Session | null }> = ({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default trpc.withTRPC(MyApp);
|
|
@ -0,0 +1,5 @@
|
||||||
|
import NextAuth from "next-auth";
|
||||||
|
|
||||||
|
import { authOptions } from "@acme/auth";
|
||||||
|
|
||||||
|
export default NextAuth(authOptions);
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { appRouter, createContext } from "@acme/api";
|
||||||
|
import { createNextApiHandler } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
|
// export API handler
|
||||||
|
export default createNextApiHandler({
|
||||||
|
router: appRouter,
|
||||||
|
createContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
// If you need to enable cors, you can do so like this:
|
||||||
|
// const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
// // Enable cors
|
||||||
|
// await cors(req, res);
|
||||||
|
|
||||||
|
// // Let the tRPC handler do its magic
|
||||||
|
// return createNextApiHandler({
|
||||||
|
// router: appRouter,
|
||||||
|
// createContext,
|
||||||
|
// })(req, res);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default handler;
|
|
@ -0,0 +1,81 @@
|
||||||
|
import type { NextPage } from "next";
|
||||||
|
import Head from "next/head";
|
||||||
|
import { signIn, signOut } from "next-auth/react";
|
||||||
|
import { trpc } from "../utils/trpc";
|
||||||
|
import type { inferProcedureOutput } from "@trpc/server";
|
||||||
|
import type { AppRouter } from "@acme/api";
|
||||||
|
|
||||||
|
const PostCard: React.FC<{
|
||||||
|
post: inferProcedureOutput<AppRouter["post"]["all"]>[number];
|
||||||
|
}> = ({ post }) => {
|
||||||
|
return (
|
||||||
|
<div className="max-w-2xl rounded-lg border-2 border-gray-500 p-4 transition-all hover:scale-[101%]">
|
||||||
|
<h2 className="text-2xl font-bold text-[hsl(280,100%,70%)]">
|
||||||
|
{post.title}
|
||||||
|
</h2>
|
||||||
|
<p>{post.content}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Home: NextPage = () => {
|
||||||
|
const postQuery = trpc.post.all.useQuery();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create T3 App</title>
|
||||||
|
<meta name="description" content="Generated by create-t3-app" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
</Head>
|
||||||
|
<main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
|
||||||
|
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-8">
|
||||||
|
<h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">
|
||||||
|
Create <span className="text-[hsl(280,100%,70%)]">T3</span> Turbo
|
||||||
|
</h1>
|
||||||
|
<AuthShowcase />
|
||||||
|
|
||||||
|
<div className="flex h-[60vh] justify-center overflow-y-scroll px-4 text-2xl">
|
||||||
|
{postQuery.data ? (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
{postQuery.data?.map((p) => {
|
||||||
|
return <PostCard key={p.id} post={p} />;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<p>Loading..</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
|
|
||||||
|
const AuthShowcase: React.FC = () => {
|
||||||
|
const { data: session } = trpc.auth.getSession.useQuery();
|
||||||
|
|
||||||
|
const { data: secretMessage } = trpc.auth.getSecretMessage.useQuery(
|
||||||
|
undefined, // no input
|
||||||
|
{ enabled: !!session?.user },
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center gap-4">
|
||||||
|
{session?.user && (
|
||||||
|
<p className="text-center text-2xl text-white">
|
||||||
|
{session && <span>Logged in as {session?.user?.name}</span>}
|
||||||
|
{secretMessage && <span> - {secretMessage}</span>}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className="rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20"
|
||||||
|
onClick={session ? () => signOut() : () => signIn()}
|
||||||
|
>
|
||||||
|
{session ? "Sign out" : "Sign in"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
|
@ -0,0 +1,44 @@
|
||||||
|
// src/utils/trpc.ts
|
||||||
|
import { createTRPCNext } from "@trpc/next";
|
||||||
|
import { httpBatchLink, loggerLink } from "@trpc/client";
|
||||||
|
import { inferRouterInputs, inferRouterOutputs } from "@trpc/server";
|
||||||
|
import type { AppRouter } from "@acme/api";
|
||||||
|
import { transformer } from "@acme/api/transformer";
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
export const trpc = createTRPCNext<AppRouter>({
|
||||||
|
config() {
|
||||||
|
return {
|
||||||
|
transformer,
|
||||||
|
links: [
|
||||||
|
loggerLink({
|
||||||
|
enabled: (opts) =>
|
||||||
|
process.env.NODE_ENV === "development" ||
|
||||||
|
(opts.direction === "down" && opts.result instanceof Error),
|
||||||
|
}),
|
||||||
|
httpBatchLink({
|
||||||
|
url: `${getBaseUrl()}/api/trpc`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inference helpers for input types
|
||||||
|
* @example type HelloInput = RouterInputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterInputs = inferRouterInputs<AppRouter>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inference helpers for output types
|
||||||
|
* @example type HelloOutput = RouterOutputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterOutputs = inferRouterOutputs<AppRouter>;
|
|
@ -0,0 +1,4 @@
|
||||||
|
/** @type {import("tailwindcss").Config} */
|
||||||
|
module.exports = {
|
||||||
|
presets: [require("@acme/tailwind-config")],
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"exclude": [],
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"node_modules/@acme/auth/next-auth.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.cjs",
|
||||||
|
"**/*.mjs"
|
||||||
|
]
|
||||||
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
nativeBuildInputs = [ pkgs.bashInteractive ];
|
nativeBuildInputs = [ pkgs.bashInteractive ];
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
pkgs.nodejs-18_x
|
pkgs.nodejs-18_x
|
||||||
|
# pkgs.prettierd # not available?
|
||||||
pkgs.nodePackages.pnpm
|
pkgs.nodePackages.pnpm
|
||||||
pkgs.nodePackages.prisma
|
pkgs.nodePackages.prisma
|
||||||
pkgs.prisma-engines
|
pkgs.prisma-engines
|
||||||
|
|
23
package.json
23
package.json
|
@ -7,10 +7,15 @@
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo run build",
|
"build": "turbo build",
|
||||||
"dev": "turbo run dev --parallel",
|
"clean": "rm -rf node_modules",
|
||||||
"lint": "turbo run lint",
|
"clean:workspaces": "turbo clean",
|
||||||
"format": "prettier --write \"**/*.{ts,tsx,md}\""
|
"db-generate": "turbo db-generate",
|
||||||
|
"db-push": "turbo db-push",
|
||||||
|
"dev": "turbo dev --parallel",
|
||||||
|
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||||
|
"lint": "turbo lint && manypkg check",
|
||||||
|
"type-check": "turbo type-check"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint-config-custom": "workspace:*",
|
"eslint-config-custom": "workspace:*",
|
||||||
|
@ -20,6 +25,14 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {
|
||||||
|
"@manypkg/cli": "^0.19.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
||||||
|
"@typescript-eslint/parser": "^5.43.0",
|
||||||
|
"eslint": "^8.28.0",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.1.13",
|
||||||
|
"typescript": "^4.9.3"
|
||||||
|
},
|
||||||
"packageManager": "pnpm@7.14.0"
|
"packageManager": "pnpm@7.14.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{ts,tsx}", "./src/_app.tsx"],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "@acme/tailwind-config",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"postcss.js"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^10.4.13",
|
||||||
|
"postcss": "^8.4.19",
|
||||||
|
"tailwindcss": "^3.2.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
42
turbo.json
42
turbo.json
|
@ -2,25 +2,56 @@
|
||||||
"$schema": "https://turbo.build/schema.json",
|
"$schema": "https://turbo.build/schema.json",
|
||||||
"pipeline": {
|
"pipeline": {
|
||||||
"build": {
|
"build": {
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": [
|
||||||
"outputs": ["dist/**", ".next/**"]
|
"^build",
|
||||||
|
"^db-generate"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"dist/**",
|
||||||
|
".next/**",
|
||||||
|
".expo/**"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"outputs": []
|
"outputs": []
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^db-generate"
|
||||||
|
],
|
||||||
"cache": false
|
"cache": false
|
||||||
},
|
},
|
||||||
"dev:local_infra": {
|
"dev:local_infra": {
|
||||||
"cache": false
|
"cache": false
|
||||||
},
|
},
|
||||||
"db:migrate": {
|
"db-generate": {
|
||||||
|
"inputs": [
|
||||||
|
"prisma/schema.prisma"
|
||||||
|
],
|
||||||
|
"cache": false
|
||||||
|
},
|
||||||
|
"db-push": {
|
||||||
|
"inputs": [
|
||||||
|
"prisma/schema.prisma"
|
||||||
|
],
|
||||||
"cache": false
|
"cache": false
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"cache": false
|
"cache": false
|
||||||
},
|
},
|
||||||
|
"type-check": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^db-generate"
|
||||||
|
],
|
||||||
|
"cache": false
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"cache": false
|
||||||
|
},
|
||||||
|
"//#clean": {
|
||||||
|
"cache": false
|
||||||
|
},
|
||||||
"about-me#build": {
|
"about-me#build": {
|
||||||
"dependsOn": [
|
"dependsOn": [
|
||||||
"^build"
|
"^build"
|
||||||
|
@ -32,7 +63,10 @@
|
||||||
"NODE_ENV",
|
"NODE_ENV",
|
||||||
"DATABASE_URL"
|
"DATABASE_URL"
|
||||||
],
|
],
|
||||||
"outputs": ["dist/**", ".next/**"]
|
"outputs": [
|
||||||
|
"dist/**",
|
||||||
|
".next/**"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue