mirror of
https://github.com/Xevion/100prisoners.git
synced 2025-12-06 01:14:17 -06:00
Project init
This commit is contained in:
11
.env.example
Normal file
11
.env.example
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Since .env is gitignored, you can use .env.example to build a new `.env` file when you clone the repo.
|
||||||
|
# Keep this file up-to-date when you add new variables to `.env`.
|
||||||
|
|
||||||
|
# This file will be committed to version control, so make sure not to have any secrets in it.
|
||||||
|
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
|
||||||
|
|
||||||
|
# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly
|
||||||
|
|
||||||
|
# Example:
|
||||||
|
# SERVERVAR=foo
|
||||||
|
# NEXT_PUBLIC_CLIENTVAR=bar
|
||||||
11
.eslintrc.json
Normal file
11
.eslintrc.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"extends": ["next/core-web-vitals", "plugin:@typescript-eslint/recommended"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/consistent-type-imports": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# database
|
||||||
|
/prisma/db.sqlite
|
||||||
|
/prisma/db.sqlite-journal
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
28
README.md
Normal file
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Create T3 App
|
||||||
|
|
||||||
|
This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `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)
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources:
|
||||||
|
|
||||||
|
- [Documentation](https://create.t3.gg/)
|
||||||
|
- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials
|
||||||
|
|
||||||
|
You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## How do I deploy this?
|
||||||
|
|
||||||
|
Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.
|
||||||
17
next.config.mjs
Normal file
17
next.config.mjs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// @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,
|
||||||
|
i18n: {
|
||||||
|
locales: ["en"],
|
||||||
|
defaultLocale: "en",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default config;
|
||||||
44
package.json
Normal file
44
package.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "100prisoners",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "next build",
|
||||||
|
"dev": "next dev",
|
||||||
|
"lint": "next lint",
|
||||||
|
"start": "next start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/react-query": "^4.16.0",
|
||||||
|
"@trpc/client": "^10.0.0",
|
||||||
|
"@trpc/next": "^10.0.0",
|
||||||
|
"@trpc/react-query": "^10.0.0",
|
||||||
|
"@trpc/server": "^10.0.0",
|
||||||
|
"@types/chance": "^1.1.3",
|
||||||
|
"chance": "^1.1.9",
|
||||||
|
"next": "13.0.2",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"sass": "^1.57.0",
|
||||||
|
"superjson": "1.9.1",
|
||||||
|
"zod": "^3.18.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.0.0",
|
||||||
|
"@types/react": "^18.0.14",
|
||||||
|
"@types/react-dom": "^18.0.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||||
|
"@typescript-eslint/parser": "^5.33.0",
|
||||||
|
"autoprefixer": "^10.4.7",
|
||||||
|
"eslint": "^8.26.0",
|
||||||
|
"eslint-config-next": "13.0.2",
|
||||||
|
"postcss": "^8.4.14",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.1.13",
|
||||||
|
"tailwindcss": "^3.2.0",
|
||||||
|
"typescript": "^4.8.4"
|
||||||
|
},
|
||||||
|
"ct3aMetadata": {
|
||||||
|
"initVersion": "6.11.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.cjs
Normal file
6
postcss.config.cjs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
4
prettier.config.cjs
Normal file
4
prettier.config.cjs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/** @type {import("prettier").Config} */
|
||||||
|
module.exports = {
|
||||||
|
plugins: [require.resolve("prettier-plugin-tailwindcss")],
|
||||||
|
};
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
35
src/env/client.mjs
vendored
Normal file
35
src/env/client.mjs
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// @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}. It must begin with 'NEXT_PUBLIC_'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new Error("Invalid public environment variable name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env = _clientEnv.data;
|
||||||
29
src/env/schema.mjs
vendored
Normal file
29
src/env/schema.mjs
vendored
Normal file
@@ -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_CLIENTVAR: 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_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
|
||||||
|
};
|
||||||
27
src/env/server.mjs
vendored
Normal file
27
src/env/server.mjs
vendored
Normal file
@@ -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 };
|
||||||
11
src/pages/_app.tsx
Normal file
11
src/pages/_app.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { type AppType } from "next/app";
|
||||||
|
|
||||||
|
import { trpc } from "../utils/trpc";
|
||||||
|
|
||||||
|
import "../styles/globals.scss";
|
||||||
|
|
||||||
|
const MyApp: AppType = ({ Component, pageProps }) => {
|
||||||
|
return <Component {...pageProps} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default trpc.withTRPC(MyApp);
|
||||||
17
src/pages/api/trpc/[trpc].ts
Normal file
17
src/pages/api/trpc/[trpc].ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { createNextApiHandler } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
|
import { env } from "../../../env/server.mjs";
|
||||||
|
import { createContext } from "../../../server/trpc/context";
|
||||||
|
import { appRouter } from "../../../server/trpc/router/_app";
|
||||||
|
|
||||||
|
// export API handler
|
||||||
|
export default createNextApiHandler({
|
||||||
|
router: appRouter,
|
||||||
|
createContext,
|
||||||
|
onError:
|
||||||
|
env.NODE_ENV === "development"
|
||||||
|
? ({ path, error }) => {
|
||||||
|
console.error(`❌ tRPC failed on ${path}: ${error}`);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
53
src/pages/index.tsx
Normal file
53
src/pages/index.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {type NextPage} from "next";
|
||||||
|
import Head from "next/head";
|
||||||
|
import BoxGraphic from "../components/BoxGraphic";
|
||||||
|
import Chance from "chance";
|
||||||
|
import {range} from "../utils/helpers";
|
||||||
|
|
||||||
|
const chance = new Chance();
|
||||||
|
|
||||||
|
const Home: NextPage = () => {
|
||||||
|
const sources = range(0, 100);
|
||||||
|
const destinations = chance.shuffle(sources);
|
||||||
|
const boxes = sources.map((e, i) => [e, destinations[i]])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>100prisoners.com</title>
|
||||||
|
<link rel="icon" href="/favicon.ico"/>
|
||||||
|
</Head>
|
||||||
|
<main className="flex min-h-screen flex-col items-center bg-white">
|
||||||
|
<div className="mt-8 px-3 w-[50rem] space-y-3">
|
||||||
|
<h1 className="text-4xl mb-2">100Prisoners.com</h1>
|
||||||
|
<div>
|
||||||
|
This website is dedicated to exploring the intriguing 100 prisoners problem, a mathematical
|
||||||
|
challenge that seems astronomically impossible at first, yet can leverage mathematics to raise
|
||||||
|
the chances one hundred octillion.
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
This thought experiment presents a scenario in which a group of 100 prisoners are tasked with
|
||||||
|
finding their own numbered slip among a collection of 100 boxes, each containing a random
|
||||||
|
permutation of the numbers 1 through 100. The prisoners are allowed to open 50 boxes each in an
|
||||||
|
attempt to find their own number, and all of the prisoners must be successful in order to be set
|
||||||
|
free. This problem raises questions about strategy and probability in search of a solution.
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-10 w-full space-y-2">
|
||||||
|
{boxes.map(([source, destination]) =>
|
||||||
|
<div className="col-span-1 px-2">
|
||||||
|
<div key={source} className="box aspect-square relative">
|
||||||
|
<span className="absolute left-6 top-8 cursor-pointer">{destination}</span>
|
||||||
|
<BoxGraphic className="transition-all cursor-pointer relative z-30">
|
||||||
|
{source + 1}
|
||||||
|
</BoxGraphic>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
26
src/server/trpc/context.ts
Normal file
26
src/server/trpc/context.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { type inferAsyncReturnType } from "@trpc/server";
|
||||||
|
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace this with an object if you want to pass things to createContextInner
|
||||||
|
*/
|
||||||
|
type CreateContextOptions = Record<string, never>;
|
||||||
|
|
||||||
|
/** Use this helper for:
|
||||||
|
* - testing, so we dont 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#-servertrpccontextts
|
||||||
|
**/
|
||||||
|
export const createContextInner = async (opts: CreateContextOptions) => {
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the actual context you'll use in your router
|
||||||
|
* @link https://trpc.io/docs/context
|
||||||
|
**/
|
||||||
|
export const createContext = async (opts: CreateNextContextOptions) => {
|
||||||
|
return await createContextInner({});
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Context = inferAsyncReturnType<typeof createContext>;
|
||||||
9
src/server/trpc/router/_app.ts
Normal file
9
src/server/trpc/router/_app.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { router } from "../trpc";
|
||||||
|
import { exampleRouter } from "./example";
|
||||||
|
|
||||||
|
export const appRouter = router({
|
||||||
|
example: exampleRouter,
|
||||||
|
});
|
||||||
|
|
||||||
|
// export type definition of API
|
||||||
|
export type AppRouter = typeof appRouter;
|
||||||
13
src/server/trpc/router/example.ts
Normal file
13
src/server/trpc/router/example.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { router, publicProcedure } from "../trpc";
|
||||||
|
|
||||||
|
export const exampleRouter = router({
|
||||||
|
hello: publicProcedure
|
||||||
|
.input(z.object({ text: z.string().nullish() }).nullish())
|
||||||
|
.query(({ input }) => {
|
||||||
|
return {
|
||||||
|
greeting: `Hello ${input?.text ?? "world"}`,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
15
src/server/trpc/trpc.ts
Normal file
15
src/server/trpc/trpc.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { initTRPC } from "@trpc/server";
|
||||||
|
import superjson from "superjson";
|
||||||
|
|
||||||
|
import { type Context } from "./context";
|
||||||
|
|
||||||
|
const t = initTRPC.context<Context>().create({
|
||||||
|
transformer: superjson,
|
||||||
|
errorFormatter({ shape }) {
|
||||||
|
return shape;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const router = t.router;
|
||||||
|
|
||||||
|
export const publicProcedure = t.procedure;
|
||||||
2
src/utils/helpers.ts
Normal file
2
src/utils/helpers.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const range = (start: number, stop: number, step = 1) =>
|
||||||
|
Array.from({length: (stop - start) / step + 1}, (_, i) => start + i * step);
|
||||||
42
src/utils/trpc.ts
Normal file
42
src/utils/trpc.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
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/trpc/router/_app";
|
||||||
|
|
||||||
|
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: superjson,
|
||||||
|
links: [
|
||||||
|
loggerLink({
|
||||||
|
enabled: (opts) =>
|
||||||
|
process.env.NODE_ENV === "development" ||
|
||||||
|
(opts.direction === "down" && opts.result instanceof Error),
|
||||||
|
}),
|
||||||
|
httpBatchLink({
|
||||||
|
url: `${getBaseUrl()}/api/trpc`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inference helper for inputs
|
||||||
|
* @example type HelloInput = RouterInputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterInputs = inferRouterInputs<AppRouter>;
|
||||||
|
/**
|
||||||
|
* Inference helper for outputs
|
||||||
|
* @example type HelloOutput = RouterOutputs['example']['hello']
|
||||||
|
**/
|
||||||
|
export type RouterOutputs = inferRouterOutputs<AppRouter>;
|
||||||
12
tailwind.config.cjs
Normal file
12
tailwind.config.cjs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{js,ts,jsx,tsx}"],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
playfair: ["\"Playfair Display\"", "serif"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
21
tsconfig.json
Normal file
21
tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"noUncheckedIndexedAccess": true
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.mjs"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user