├── .gitignore
├── README.md
├── components
├── Navbar.tsx
└── SwapInput.tsx
├── const
└── details.ts
├── next.config.js
├── package.json
├── pages
├── _app.tsx
├── _document.tsx
├── api
│ └── hello.ts
└── index.tsx
├── public
├── favicon.ico
├── next.svg
├── thirteen.svg
├── token.png
└── vercel.svg
├── styles
├── Home.module.css
└── globals.css
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!Important]
2 | > This repository is referencing the `mumbai` chain.
3 | >
4 | > `Mumbai` [is deprecated since 08/04/2024](https://blog.thirdweb.com/deprecation-of-mumbai-testnet/), meaning the code in this repository will no longer work out of the box.
5 | >
6 | > You can still use this repository, however you will have to switch any references to `mumbai` to another chain.
7 |
8 | # DEX app
9 |
10 | Create your own DEX for your ERC-20 token. Find the related contracts in the [dex-contracts repository](https://github.com/thirdweb-example/dex-contracts).
11 |
12 | ## Installation
13 |
14 | After cloning this repository, install the dependencies using the following command:
15 |
16 | ```bash
17 | # npm
18 | npm install
19 |
20 | # yarn
21 | yarn install
22 | ```
23 |
24 | ## Adding details
25 |
26 | Make sure you deploy the contracts specified in the dex-contracts repository and add the contract details in the `const/details.ts` file.
27 |
28 | ## Running the app
29 |
30 | Use the following command to start the development server:
31 |
32 | ```bash
33 | # npm
34 | npm run dev
35 |
36 | # yarn
37 | yarn dev
38 | ```
39 |
40 | ## Conclusion
41 |
42 | If you need any support, feel free to join our [Discord server](https://discord.gg/thirdweb) and ask us. If you have any feedback related to thirdweb, please leave it on our [feedback board](https://feedback.thirdweb.com).
43 |
--------------------------------------------------------------------------------
/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, Text } from "@chakra-ui/react";
2 | import { ConnectWallet } from "@thirdweb-dev/react";
3 | import React from "react";
4 |
5 | export default function Navbar() {
6 | return (
7 |
8 |
17 |
18 | Token DEX
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/components/SwapInput.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Button, HStack, Image, Input } from "@chakra-ui/react";
2 | import { resolveIpfsUri } from "@thirdweb-dev/react";
3 | import React from "react";
4 |
5 | type Props = {
6 | type: "native" | "token";
7 | tokenImage?: string;
8 | current: string;
9 | setValue: (value: string) => void;
10 | max?: string;
11 | value: string;
12 | };
13 |
14 | export default function SwapInput({
15 | type,
16 | tokenImage,
17 | setValue,
18 | value,
19 | current,
20 | max,
21 | }: Props) {
22 | return (
23 |
24 |
25 | setValue(e.target.value)}
31 | outline="none"
32 | py="10"
33 | isDisabled={current !== type}
34 | border="none"
35 | fontFamily="monospace"
36 | _focus={{ boxShadow: "none" }}
37 | />
38 | {current === type && (
39 |
40 | )}
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/const/details.ts:
--------------------------------------------------------------------------------
1 | import { Chain, Mumbai } from "@thirdweb-dev/chains";
2 |
3 | export const TOKEN_ADDRESS: string =
4 | "0x9b84D0E4fc807CB664aFdBF9E7096bed3a7aB18A";
5 | export const DEX_ADDRESS: string = "0x92c85c31c74F482AB30D94D7e5c63fe9BD53883B";
6 | export const ACTIVE_CHAIN: Chain = Mumbai;
7 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | }
5 |
6 | module.exports = nextConfig
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@chakra-ui/react": "^2.5.5",
13 | "@emotion/react": "^11.10.6",
14 | "@emotion/styled": "^11.10.6",
15 | "@thirdweb-dev/chains": "^0.1.11",
16 | "@thirdweb-dev/react": "^3.11.7",
17 | "@thirdweb-dev/sdk": "^3.10.10",
18 | "@types/node": "18.15.11",
19 | "@types/react": "18.0.35",
20 | "@types/react-dom": "18.0.11",
21 | "ethers": "5",
22 | "framer-motion": "^10.12.2",
23 | "next": "13.3.0",
24 | "react": "18.2.0",
25 | "react-dom": "18.2.0",
26 | "typescript": "5.0.4"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import { ACTIVE_CHAIN } from "@/const/details";
2 | import "@/styles/globals.css";
3 | import { ChakraProvider } from "@chakra-ui/react";
4 | import { ThirdwebProvider } from "@thirdweb-dev/react";
5 | import type { AppProps } from "next/app";
6 |
7 | export default function App({ Component, pageProps }: AppProps) {
8 | return (
9 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from 'next/document'
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/pages/api/hello.ts:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 | import type { NextApiRequest, NextApiResponse } from 'next'
3 |
4 | type Data = {
5 | name: string
6 | }
7 |
8 | export default function handler(
9 | req: NextApiRequest,
10 | res: NextApiResponse
11 | ) {
12 | res.status(200).json({ name: 'John Doe' })
13 | }
14 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import Head from "next/head";
2 | import { Inter } from "next/font/google";
3 | import Navbar from "@/components/Navbar";
4 | import {
5 | Box,
6 | Button,
7 | Flex,
8 | HStack,
9 | Image,
10 | Input,
11 | Spinner,
12 | useToast,
13 | } from "@chakra-ui/react";
14 | import { ACTIVE_CHAIN, DEX_ADDRESS, TOKEN_ADDRESS } from "@/const/details";
15 | import {
16 | ConnectWallet,
17 | resolveIpfsUri,
18 | toEther,
19 | toWei,
20 | useAddress,
21 | useBalance,
22 | useContract,
23 | useContractMetadata,
24 | useContractRead,
25 | useContractWrite,
26 | useNetworkMismatch,
27 | useSDK,
28 | useSwitchChain,
29 | useTokenBalance,
30 | } from "@thirdweb-dev/react";
31 | import { useEffect, useState } from "react";
32 | import SwapInput from "@/components/SwapInput";
33 |
34 | const inter = Inter({ subsets: ["latin"] });
35 |
36 | export default function Home() {
37 | const toast = useToast();
38 | const address = useAddress();
39 | const { contract: tokenContract } = useContract(TOKEN_ADDRESS, "token");
40 | const { contract: dexContract } = useContract(DEX_ADDRESS, "custom");
41 | const { data: symbol } = useContractRead(tokenContract, "symbol");
42 | const { data: tokenMetadata } = useContractMetadata(tokenContract);
43 | const { data: tokenBalance } = useTokenBalance(tokenContract, address);
44 | const { data: nativeBalance } = useBalance();
45 | const { data: contractTokenBalance } = useTokenBalance(
46 | tokenContract,
47 | DEX_ADDRESS
48 | );
49 |
50 | const isMismatched = useNetworkMismatch();
51 | const switchChain = useSwitchChain();
52 |
53 | const sdk = useSDK();
54 | const [contractBalance, setContractBalance] = useState("0");
55 |
56 | const [nativeValue, setNativeValue] = useState("0");
57 | const [tokenValue, setTokenValue] = useState("0");
58 | const [currentFrom, setCurrentFrom] = useState("native");
59 | const [loading, setLoading] = useState(false);
60 |
61 | const { mutateAsync: swapNativeToToken } = useContractWrite(
62 | dexContract,
63 | "swapEthTotoken"
64 | );
65 | const { mutateAsync: swapTokenToNative } = useContractWrite(
66 | dexContract,
67 | "swapTokenToEth"
68 | );
69 | const { mutateAsync: approveTokenSpending } = useContractWrite(
70 | tokenContract,
71 | "approve"
72 | );
73 |
74 | const { data: amountToGet } = useContractRead(
75 | dexContract,
76 | "getAmountOfTokens",
77 | currentFrom === "native"
78 | ? [
79 | toWei(nativeValue || "0"),
80 | toWei(contractBalance || "0"),
81 | contractTokenBalance?.value,
82 | ]
83 | : [
84 | toWei(tokenValue || "0"),
85 | contractTokenBalance?.value,
86 | toWei(contractBalance || "0"),
87 | ]
88 | );
89 |
90 | const fetchContractBalance = async () => {
91 | try {
92 | const balance = await sdk?.getBalance(DEX_ADDRESS);
93 | setContractBalance(balance?.displayValue || "0");
94 | } catch (err) {
95 | console.error(err);
96 | }
97 | };
98 |
99 | const executeSwap = async () => {
100 | setLoading(true);
101 | if (isMismatched) {
102 | switchChain(ACTIVE_CHAIN.chainId);
103 | setLoading(false);
104 | return;
105 | }
106 | try {
107 | if (currentFrom === "native") {
108 | await swapNativeToToken({ overrides: { value: toWei(nativeValue) } });
109 | toast({
110 | status: "success",
111 | title: "Swap Successful",
112 | description: `You have successfully swapped your ${
113 | ACTIVE_CHAIN.nativeCurrency.symbol
114 | } to ${symbol || "tokens"}.`,
115 | });
116 | } else {
117 | // Approve token spending
118 | await approveTokenSpending({ args: [DEX_ADDRESS, toWei(tokenValue)] });
119 | // Swap!
120 | await swapTokenToNative({ args: [toWei(tokenValue)] });
121 | toast({
122 | status: "success",
123 | title: "Swap Successful",
124 | description: `You have successfully swapped your ${
125 | symbol || "tokens"
126 | } to ${ACTIVE_CHAIN.nativeCurrency.symbol}.`,
127 | });
128 | }
129 | setLoading(false);
130 | } catch (err) {
131 | console.error(err);
132 | toast({
133 | status: "error",
134 | title: "Swap Failed",
135 | description:
136 | "There was an error performing the swap. Please try again.",
137 | });
138 | setLoading(false);
139 | }
140 | };
141 |
142 | useEffect(() => {
143 | fetchContractBalance();
144 | setInterval(fetchContractBalance, 10000);
145 | }, []);
146 |
147 | useEffect(() => {
148 | if (!amountToGet) return;
149 | if (currentFrom === "native") {
150 | setTokenValue(toEther(amountToGet));
151 | } else {
152 | setNativeValue(toEther(amountToGet));
153 | }
154 | }, [amountToGet]);
155 |
156 | return (
157 | <>
158 |
159 | Decentralised Exchange
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
179 |
183 |
191 |
192 |
203 |
204 |
212 |
213 |
214 | {address ? (
215 |
225 | ) : (
226 |
230 | )}
231 |
232 | >
233 | );
234 | }
235 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thirdweb-example/dex-app/a5ef43eba5536cd8b1d4f77edd5b7d5c5a15f4e6/public/favicon.ico
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thirdweb-example/dex-app/a5ef43eba5536cd8b1d4f77edd5b7d5c5a15f4e6/public/token.png
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .main {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: space-between;
5 | align-items: center;
6 | padding: 6rem;
7 | min-height: 100vh;
8 | }
9 |
10 | .description {
11 | display: inherit;
12 | justify-content: inherit;
13 | align-items: inherit;
14 | font-size: 0.85rem;
15 | max-width: var(--max-width);
16 | width: 100%;
17 | z-index: 2;
18 | font-family: var(--font-mono);
19 | }
20 |
21 | .description a {
22 | display: flex;
23 | justify-content: center;
24 | align-items: center;
25 | gap: 0.5rem;
26 | }
27 |
28 | .description p {
29 | position: relative;
30 | margin: 0;
31 | padding: 1rem;
32 | background-color: rgba(var(--callout-rgb), 0.5);
33 | border: 1px solid rgba(var(--callout-border-rgb), 0.3);
34 | border-radius: var(--border-radius);
35 | }
36 |
37 | .code {
38 | font-weight: 700;
39 | font-family: var(--font-mono);
40 | }
41 |
42 | .grid {
43 | display: grid;
44 | grid-template-columns: repeat(4, minmax(25%, auto));
45 | width: var(--max-width);
46 | max-width: 100%;
47 | }
48 |
49 | .card {
50 | padding: 1rem 1.2rem;
51 | border-radius: var(--border-radius);
52 | background: rgba(var(--card-rgb), 0);
53 | border: 1px solid rgba(var(--card-border-rgb), 0);
54 | transition: background 200ms, border 200ms;
55 | }
56 |
57 | .card span {
58 | display: inline-block;
59 | transition: transform 200ms;
60 | }
61 |
62 | .card h2 {
63 | font-weight: 600;
64 | margin-bottom: 0.7rem;
65 | }
66 |
67 | .card p {
68 | margin: 0;
69 | opacity: 0.6;
70 | font-size: 0.9rem;
71 | line-height: 1.5;
72 | max-width: 30ch;
73 | }
74 |
75 | .center {
76 | display: flex;
77 | justify-content: center;
78 | align-items: center;
79 | position: relative;
80 | padding: 4rem 0;
81 | }
82 |
83 | .center::before {
84 | background: var(--secondary-glow);
85 | border-radius: 50%;
86 | width: 480px;
87 | height: 360px;
88 | margin-left: -400px;
89 | }
90 |
91 | .center::after {
92 | background: var(--primary-glow);
93 | width: 240px;
94 | height: 180px;
95 | z-index: -1;
96 | }
97 |
98 | .center::before,
99 | .center::after {
100 | content: '';
101 | left: 50%;
102 | position: absolute;
103 | filter: blur(45px);
104 | transform: translateZ(0);
105 | }
106 |
107 | .logo,
108 | .thirteen {
109 | position: relative;
110 | }
111 |
112 | .thirteen {
113 | display: flex;
114 | justify-content: center;
115 | align-items: center;
116 | width: 75px;
117 | height: 75px;
118 | padding: 25px 10px;
119 | margin-left: 16px;
120 | transform: translateZ(0);
121 | border-radius: var(--border-radius);
122 | overflow: hidden;
123 | box-shadow: 0px 2px 8px -1px #0000001a;
124 | }
125 |
126 | .thirteen::before,
127 | .thirteen::after {
128 | content: '';
129 | position: absolute;
130 | z-index: -1;
131 | }
132 |
133 | /* Conic Gradient Animation */
134 | .thirteen::before {
135 | animation: 6s rotate linear infinite;
136 | width: 200%;
137 | height: 200%;
138 | background: var(--tile-border);
139 | }
140 |
141 | /* Inner Square */
142 | .thirteen::after {
143 | inset: 0;
144 | padding: 1px;
145 | border-radius: var(--border-radius);
146 | background: linear-gradient(
147 | to bottom right,
148 | rgba(var(--tile-start-rgb), 1),
149 | rgba(var(--tile-end-rgb), 1)
150 | );
151 | background-clip: content-box;
152 | }
153 |
154 | /* Enable hover only on non-touch devices */
155 | @media (hover: hover) and (pointer: fine) {
156 | .card:hover {
157 | background: rgba(var(--card-rgb), 0.1);
158 | border: 1px solid rgba(var(--card-border-rgb), 0.15);
159 | }
160 |
161 | .card:hover span {
162 | transform: translateX(4px);
163 | }
164 | }
165 |
166 | @media (prefers-reduced-motion) {
167 | .thirteen::before {
168 | animation: none;
169 | }
170 |
171 | .card:hover span {
172 | transform: none;
173 | }
174 | }
175 |
176 | /* Mobile */
177 | @media (max-width: 700px) {
178 | .content {
179 | padding: 4rem;
180 | }
181 |
182 | .grid {
183 | grid-template-columns: 1fr;
184 | margin-bottom: 120px;
185 | max-width: 320px;
186 | text-align: center;
187 | }
188 |
189 | .card {
190 | padding: 1rem 2.5rem;
191 | }
192 |
193 | .card h2 {
194 | margin-bottom: 0.5rem;
195 | }
196 |
197 | .center {
198 | padding: 8rem 0 6rem;
199 | }
200 |
201 | .center::before {
202 | transform: none;
203 | height: 300px;
204 | }
205 |
206 | .description {
207 | font-size: 0.8rem;
208 | }
209 |
210 | .description a {
211 | padding: 1rem;
212 | }
213 |
214 | .description p,
215 | .description div {
216 | display: flex;
217 | justify-content: center;
218 | position: fixed;
219 | width: 100%;
220 | }
221 |
222 | .description p {
223 | align-items: center;
224 | inset: 0 0 auto;
225 | padding: 2rem 1rem 1.4rem;
226 | border-radius: 0;
227 | border: none;
228 | border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
229 | background: linear-gradient(
230 | to bottom,
231 | rgba(var(--background-start-rgb), 1),
232 | rgba(var(--callout-rgb), 0.5)
233 | );
234 | background-clip: padding-box;
235 | backdrop-filter: blur(24px);
236 | }
237 |
238 | .description div {
239 | align-items: flex-end;
240 | pointer-events: none;
241 | inset: auto 0 0;
242 | padding: 2rem;
243 | height: 200px;
244 | background: linear-gradient(
245 | to bottom,
246 | transparent 0%,
247 | rgb(var(--background-end-rgb)) 40%
248 | );
249 | z-index: 1;
250 | }
251 | }
252 |
253 | /* Tablet and Smaller Desktop */
254 | @media (min-width: 701px) and (max-width: 1120px) {
255 | .grid {
256 | grid-template-columns: repeat(2, 50%);
257 | }
258 | }
259 |
260 | @media (prefers-color-scheme: dark) {
261 | .vercelLogo {
262 | filter: invert(1);
263 | }
264 |
265 | .logo,
266 | .thirteen img {
267 | filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
268 | }
269 | }
270 |
271 | @keyframes rotate {
272 | from {
273 | transform: rotate(360deg);
274 | }
275 | to {
276 | transform: rotate(0deg);
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --max-width: 1100px;
3 | --border-radius: 12px;
4 | --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
5 | 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
6 | 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
7 |
8 | --foreground-rgb: 0, 0, 0;
9 | --background-start-rgb: 214, 219, 220;
10 | --background-end-rgb: 255, 255, 255;
11 |
12 | --primary-glow: conic-gradient(
13 | from 180deg at 50% 50%,
14 | #16abff33 0deg,
15 | #0885ff33 55deg,
16 | #54d6ff33 120deg,
17 | #0071ff33 160deg,
18 | transparent 360deg
19 | );
20 | --secondary-glow: radial-gradient(
21 | rgba(255, 255, 255, 1),
22 | rgba(255, 255, 255, 0)
23 | );
24 |
25 | --tile-start-rgb: 239, 245, 249;
26 | --tile-end-rgb: 228, 232, 233;
27 | --tile-border: conic-gradient(
28 | #00000080,
29 | #00000040,
30 | #00000030,
31 | #00000020,
32 | #00000010,
33 | #00000010,
34 | #00000080
35 | );
36 |
37 | --callout-rgb: 238, 240, 241;
38 | --callout-border-rgb: 172, 175, 176;
39 | --card-rgb: 180, 185, 188;
40 | --card-border-rgb: 131, 134, 135;
41 | }
42 |
43 | @media (prefers-color-scheme: dark) {
44 | :root {
45 | --foreground-rgb: 255, 255, 255;
46 | --background-start-rgb: 0, 0, 0;
47 | --background-end-rgb: 0, 0, 0;
48 |
49 | --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
50 | --secondary-glow: linear-gradient(
51 | to bottom right,
52 | rgba(1, 65, 255, 0),
53 | rgba(1, 65, 255, 0),
54 | rgba(1, 65, 255, 0.3)
55 | );
56 |
57 | --tile-start-rgb: 2, 13, 46;
58 | --tile-end-rgb: 2, 5, 19;
59 | --tile-border: conic-gradient(
60 | #ffffff80,
61 | #ffffff40,
62 | #ffffff30,
63 | #ffffff20,
64 | #ffffff10,
65 | #ffffff10,
66 | #ffffff80
67 | );
68 |
69 | --callout-rgb: 20, 20, 20;
70 | --callout-border-rgb: 108, 108, 108;
71 | --card-rgb: 100, 100, 100;
72 | --card-border-rgb: 200, 200, 200;
73 | }
74 | }
75 |
76 | * {
77 | box-sizing: border-box;
78 | padding: 0;
79 | margin: 0;
80 | }
81 |
82 | html,
83 | body {
84 | max-width: 100vw;
85 | overflow-x: hidden;
86 | }
87 |
88 | body {
89 | color: rgb(var(--foreground-rgb));
90 | background: linear-gradient(
91 | to bottom,
92 | transparent,
93 | rgb(var(--background-end-rgb))
94 | )
95 | rgb(var(--background-start-rgb));
96 | }
97 |
98 | a {
99 | color: inherit;
100 | text-decoration: none;
101 | }
102 |
103 | @media (prefers-color-scheme: dark) {
104 | html {
105 | color-scheme: dark;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "paths": {
18 | "@/*": ["./*"]
19 | }
20 | },
21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
22 | "exclude": ["node_modules"]
23 | }
24 |
--------------------------------------------------------------------------------