@upstash/ratelimit 0.4.3 → 0.4.5-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.github/actions/redis/action.yaml +58 -0
  2. package/.github/img/dashboard.png +0 -0
  3. package/.github/workflows/release.yml +46 -0
  4. package/.github/workflows/stale.yaml +31 -0
  5. package/.github/workflows/tests.yaml +79 -0
  6. package/README.md +10 -3
  7. package/biome.json +37 -0
  8. package/bun.lockb +0 -0
  9. package/cmd/set-version.js +14 -0
  10. package/examples/cloudflare-workers/package.json +18 -0
  11. package/examples/cloudflare-workers/src/index.ts +35 -0
  12. package/examples/cloudflare-workers/tsconfig.json +105 -0
  13. package/examples/cloudflare-workers/wrangler.toml +3 -0
  14. package/examples/nextjs/LICENSE +21 -0
  15. package/examples/nextjs/README.md +17 -0
  16. package/examples/nextjs/components/Breadcrumb.tsx +67 -0
  17. package/examples/nextjs/components/Header.tsx +18 -0
  18. package/examples/nextjs/components/ReadBlogPost.tsx +9 -0
  19. package/examples/nextjs/components/StarButton.tsx +27 -0
  20. package/examples/nextjs/middleware.ts +35 -0
  21. package/examples/nextjs/next-env.d.ts +5 -0
  22. package/examples/nextjs/package.json +27 -0
  23. package/examples/nextjs/pages/_app.tsx +47 -0
  24. package/examples/nextjs/pages/api/blocked.ts +6 -0
  25. package/examples/nextjs/pages/api/hello.ts +5 -0
  26. package/examples/nextjs/pages/index.tsx +62 -0
  27. package/examples/nextjs/postcss.config.js +6 -0
  28. package/examples/nextjs/public/favicon.ico +0 -0
  29. package/examples/nextjs/public/github.svg +11 -0
  30. package/examples/nextjs/public/upstash.svg +27 -0
  31. package/examples/nextjs/styles/globals.css +76 -0
  32. package/examples/nextjs/tailwind.config.js +19 -0
  33. package/examples/nextjs/tsconfig.json +21 -0
  34. package/examples/nextjs13/README.md +38 -0
  35. package/examples/nextjs13/app/favicon.ico +0 -0
  36. package/examples/nextjs13/app/globals.css +107 -0
  37. package/examples/nextjs13/app/layout.tsx +18 -0
  38. package/examples/nextjs13/app/page.module.css +271 -0
  39. package/examples/nextjs13/app/route.tsx +14 -0
  40. package/examples/nextjs13/next.config.js +8 -0
  41. package/examples/nextjs13/package.json +22 -0
  42. package/examples/nextjs13/public/next.svg +1 -0
  43. package/examples/nextjs13/public/thirteen.svg +1 -0
  44. package/examples/nextjs13/public/vercel.svg +1 -0
  45. package/examples/nextjs13/tsconfig.json +28 -0
  46. package/examples/remix/.env.example +2 -0
  47. package/examples/remix/.eslintrc.js +4 -0
  48. package/examples/remix/README.md +59 -0
  49. package/examples/remix/app/root.tsx +25 -0
  50. package/examples/remix/app/routes/index.tsx +47 -0
  51. package/examples/remix/package.json +32 -0
  52. package/examples/remix/public/favicon.ico +0 -0
  53. package/examples/remix/remix.config.js +12 -0
  54. package/examples/remix/remix.env.d.ts +2 -0
  55. package/examples/remix/server.js +4 -0
  56. package/examples/remix/tsconfig.json +22 -0
  57. package/examples/with-vercel-kv/README.md +51 -0
  58. package/examples/with-vercel-kv/app/favicon.ico +0 -0
  59. package/examples/with-vercel-kv/app/globals.css +27 -0
  60. package/examples/with-vercel-kv/app/layout.tsx +21 -0
  61. package/examples/with-vercel-kv/app/page.tsx +71 -0
  62. package/examples/with-vercel-kv/next.config.js +8 -0
  63. package/examples/with-vercel-kv/package.json +25 -0
  64. package/examples/with-vercel-kv/postcss.config.js +6 -0
  65. package/examples/with-vercel-kv/public/next.svg +1 -0
  66. package/examples/with-vercel-kv/public/vercel.svg +1 -0
  67. package/examples/with-vercel-kv/tailwind.config.js +17 -0
  68. package/examples/with-vercel-kv/tsconfig.json +28 -0
  69. package/package.json +12 -33
  70. package/src/analytics.test.ts +23 -0
  71. package/src/analytics.ts +92 -0
  72. package/src/blockUntilReady.test.ts +56 -0
  73. package/src/cache.test.ts +41 -0
  74. package/src/cache.ts +43 -0
  75. package/src/duration.test.ts +23 -0
  76. package/src/duration.ts +30 -0
  77. package/src/index.ts +17 -0
  78. package/src/multi.ts +365 -0
  79. package/src/ratelimit.test.ts +155 -0
  80. package/src/ratelimit.ts +238 -0
  81. package/src/single.ts +487 -0
  82. package/src/test_utils.ts +65 -0
  83. package/src/tools/seed.ts +37 -0
  84. package/src/types.ts +78 -0
  85. package/src/version.ts +1 -0
  86. package/tsconfig.json +103 -0
  87. package/tsup.config.js +11 -0
  88. package/turbo.json +16 -0
  89. package/dist/index.d.ts +0 -558
  90. package/dist/index.js +0 -828
  91. package/dist/index.js.map +0 -1
  92. package/dist/index.mjs +0 -799
  93. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,35 @@
1
+ import { Ratelimit } from "@upstash/ratelimit";
2
+ import { Redis } from "@upstash/redis";
3
+ import { type NextFetchEvent, type NextRequest, NextResponse } from "next/server";
4
+
5
+ const ratelimit = new Ratelimit({
6
+ redis: Redis.fromEnv(),
7
+ limiter: Ratelimit.cachedFixedWindow(10, "10s"),
8
+ ephemeralCache: new Map(),
9
+ analytics: true,
10
+ });
11
+
12
+ export default async function middleware(
13
+ request: NextRequest,
14
+ event: NextFetchEvent,
15
+ ): Promise<Response | undefined> {
16
+ const ip = request.ip ?? "127.0.0.1";
17
+
18
+ const { success, pending, limit, reset, remaining } = await ratelimit.limit(
19
+ `ratelimit_middleware_${ip}`,
20
+ );
21
+ event.waitUntil(pending);
22
+
23
+ const res = success
24
+ ? NextResponse.next()
25
+ : NextResponse.redirect(new URL("/api/blocked", request.url));
26
+
27
+ res.headers.set("X-RateLimit-Limit", limit.toString());
28
+ res.headers.set("X-RateLimit-Remaining", remaining.toString());
29
+ res.headers.set("X-RateLimit-Reset", reset.toString());
30
+ return res;
31
+ }
32
+
33
+ export const config = {
34
+ matcher: "/api/hello",
35
+ };
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "upstash-ratelimit-nextjs",
3
+ "private": true,
4
+ "scripts": {
5
+ "dev": "next dev",
6
+ "build": "next build",
7
+ "start": "next start"
8
+ },
9
+ "dependencies": {
10
+ "@upstash/ratelimit": "workspace:*",
11
+ "@upstash/redis": "^1.20.6",
12
+ "next": "^13.4.1",
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "@tailwindcss/forms": "^0.5.3",
18
+ "@types/node": "^20.1.2",
19
+ "@types/react": "^18.2.6",
20
+ "autoprefixer": "^10.4.14",
21
+ "postcss": "^8.4.23",
22
+ "prettier": "^2.8.8",
23
+ "prettier-plugin-tailwindcss": "^0.2.8",
24
+ "tailwindcss": "^3.3.2",
25
+ "typescript": "^5.0.4"
26
+ }
27
+ }
@@ -0,0 +1,47 @@
1
+ import "styles/globals.css";
2
+
3
+ import Header from "components/Header";
4
+ import ReadBlogPost from "components/ReadBlogPost";
5
+ import type { AppProps } from "next/app";
6
+ import Head from "next/head";
7
+ import React from "react";
8
+
9
+ function MyApp({ Component, pageProps }: AppProps) {
10
+ return (
11
+ <>
12
+ <Head>
13
+ <title>Create Next App</title>
14
+ <link rel="icon" href="/favicon.ico" />
15
+ </Head>
16
+
17
+ <Header
18
+ breadcrumbOptions={{
19
+ data: [
20
+ {
21
+ name: "ratelimit",
22
+ url: "https://github.com/upstash/ratelimit",
23
+ },
24
+ ],
25
+ }}
26
+ />
27
+
28
+ {/*<ReadBlogPost>
29
+ This is a sample project for the blogpost{" "}
30
+ <a
31
+ className="text-primary-600"
32
+ target="_blank"
33
+ rel="noopener noreferrer"
34
+ href="https://blog.upstash.com/nextjs-caching-with-redis"
35
+ >
36
+ Example Post
37
+ </a>
38
+ </ReadBlogPost>*/}
39
+
40
+ <div className="w-full max-w-3xl px-6 mx-auto py-14">
41
+ <Component {...pageProps} />
42
+ </div>
43
+ </>
44
+ );
45
+ }
46
+
47
+ export default MyApp;
@@ -0,0 +1,6 @@
1
+ import type { NextApiRequest, NextApiResponse } from "next";
2
+
3
+ export default function handler(_req: NextApiRequest, res: NextApiResponse) {
4
+ res.status(429);
5
+ return res.end();
6
+ }
@@ -0,0 +1,5 @@
1
+ import type { NextApiRequest, NextApiResponse } from "next";
2
+
3
+ export default function handler(_req: NextApiRequest, res: NextApiResponse) {
4
+ return res.json({ hello: "world" });
5
+ }
@@ -0,0 +1,62 @@
1
+ import type { NextPage } from "next";
2
+ import { useRouter } from "next/router";
3
+ import { useEffect, useState } from "react";
4
+
5
+ const Home: NextPage = () => {
6
+ const [response, setResponse] = useState<Record<string, unknown> | null>(null);
7
+
8
+ const router = useRouter();
9
+ useEffect(() => {}, []);
10
+
11
+ const generate = async () => {
12
+ const res = await fetch("/api/hello");
13
+
14
+ if (res.ok) {
15
+ setResponse({
16
+ status: res.status,
17
+ body: await res.json(),
18
+ headers: {
19
+ "X-RateLimit-Limit": res.headers.get("X-RateLimit-Limit"),
20
+ "X-RateLimit-Remaining": res.headers.get("X-RateLimit-Remaining"),
21
+ "X-RateLimit-Reset": res.headers.get("X-RateLimit-Reset"),
22
+ },
23
+ });
24
+ } else {
25
+ setResponse(null);
26
+
27
+ alert("Ratelimit reached, try again later");
28
+ }
29
+ };
30
+ return (
31
+ <>
32
+ <main>
33
+ <header>
34
+ <h1 className="text-4xl font-bold">
35
+ Welcome to <span className="text-primary-500">@upstash/ratelimit</span>
36
+ </h1>
37
+
38
+ <p className="mt-4">
39
+ This is an example of how to ratelimit your nextjs app at the edge using Vercel Edge and
40
+ Upstash Redis
41
+ </p>
42
+
43
+ <p className="mt-4">
44
+ Click the button below to make a request, that will be ratelimited by your IP.
45
+ </p>
46
+ </header>
47
+
48
+ <hr className="my-10" />
49
+
50
+ <div className="grid grid-cols-1 gap-6">
51
+ <div className="flex justify-center">
52
+ <button onClick={generate}>Make a request</button>
53
+ </div>
54
+
55
+ {response ? <pre>{JSON.stringify(response, null, 2)}</pre> : null}
56
+ </div>
57
+ </main>
58
+ </>
59
+ );
60
+ };
61
+
62
+ export default Home;
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -0,0 +1,11 @@
1
+ <svg
2
+ width="32"
3
+ height="32"
4
+ viewBox="0 0 16 16"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ >
7
+ <path
8
+ fill-rule="evenodd"
9
+ d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
10
+ />
11
+ </svg>
@@ -0,0 +1,27 @@
1
+ <svg width="90" height="26" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#a)">
3
+ <path
4
+ d="M.023 22.749c4.303 4.302 11.278 4.302 15.58 0 4.303-4.303 4.303-11.278 0-15.58l-1.947 1.947A8.263 8.263 0 1 1 1.97 20.801L.023 22.75Z"
5
+ fill="#00C98D"/>
6
+ <path d="M3.918 18.854a5.509 5.509 0 0 0 7.79-7.79L9.761 13.01a2.754 2.754 0 1 1-3.895 3.895l-1.948 1.948Z"
7
+ fill="#00C98D"/>
8
+ <path
9
+ d="M19.498 3.273c-4.302-4.302-11.277-4.302-15.58 0-4.302 4.302-4.302 11.278 0 15.58l1.948-1.947A8.263 8.263 0 0 1 17.55 5.22l1.947-1.948Z"
10
+ fill="#00C98D"/>
11
+ <path d="M15.603 7.168a5.508 5.508 0 0 0-7.79 7.79l1.948-1.947a2.754 2.754 0 0 1 3.895-3.895l1.947-1.948Z"
12
+ fill="#00C98D"/>
13
+ <path
14
+ d="M19.498 3.273c-4.302-4.302-11.277-4.302-15.58 0-4.302 4.302-4.302 11.278 0 15.58l1.948-1.947A8.263 8.263 0 0 1 17.55 5.22l1.947-1.948Z"
15
+ fill="#fff" fill-opacity=".4"/>
16
+ <path d="M15.603 7.168a5.508 5.508 0 0 0-7.79 7.79l1.948-1.947a2.754 2.754 0 0 1 3.895-3.895l1.947-1.948Z"
17
+ fill="#fff" fill-opacity=".4"/>
18
+ </g>
19
+ <path
20
+ d="M32.396 14.523V9.3h2.124v9.014h-2.06V16.71h-.094a2.711 2.711 0 0 1-1.003 1.239c-.462.32-1.031.48-1.708.48-.59 0-1.113-.13-1.567-.392a2.733 2.733 0 0 1-1.056-1.156c-.254-.509-.381-1.123-.381-1.843v-5.74h2.124v5.411c0 .571.156 1.025.47 1.362.312.336.723.504 1.232.504.313 0 .616-.076.91-.228a1.85 1.85 0 0 0 .721-.681c.192-.305.288-.687.288-1.144Zm3.978 7.17V9.3h2.09v1.49h.122c.11-.219.264-.452.464-.698.2-.25.47-.464.81-.64.34-.18.775-.27 1.303-.27.696 0 1.324.178 1.883.534.564.352 1.01.875 1.338 1.567.333.689.5 1.534.5 2.535 0 .99-.163 1.831-.488 2.524-.325.692-.767 1.22-1.326 1.584a3.41 3.41 0 0 1-1.901.546c-.517 0-.945-.086-1.286-.258a2.615 2.615 0 0 1-.821-.622 4.028 4.028 0 0 1-.476-.699h-.088v4.8h-2.124Zm2.083-7.886c0 .582.082 1.093.247 1.531.168.438.409.78.722 1.027.316.243.7.364 1.15.364.47 0 .862-.125 1.18-.376.316-.254.555-.6.715-1.038.165-.442.247-.945.247-1.508 0-.56-.08-1.057-.24-1.491-.161-.434-.4-.775-.717-1.021-.317-.246-.712-.37-1.185-.37-.454 0-.84.12-1.156.358-.317.239-.558.573-.722 1.004-.16.43-.24.937-.24 1.52Zm15.039-2.125-1.937.211a1.555 1.555 0 0 0-.287-.551 1.426 1.426 0 0 0-.54-.417c-.227-.105-.505-.158-.833-.158-.442 0-.814.096-1.115.287-.298.192-.444.44-.44.746a.78.78 0 0 0 .287.64c.2.164.528.299.986.404l1.538.329c.852.184 1.486.475 1.9.874.42.4.63.921.635 1.567a2.451 2.451 0 0 1-.5 1.502c-.324.43-.776.767-1.355 1.01-.579.242-1.244.363-1.995.363-1.103 0-1.991-.23-2.664-.692-.673-.466-1.074-1.113-1.203-1.942l2.071-.2c.094.407.294.714.599.921.305.208.702.311 1.191.311.505 0 .91-.103 1.215-.31.309-.208.464-.464.464-.77a.8.8 0 0 0-.3-.639c-.195-.168-.5-.297-.915-.387l-1.538-.323c-.864-.18-1.504-.483-1.919-.91-.414-.43-.62-.974-.616-1.631-.004-.556.147-1.037.452-1.444.31-.41.737-.727 1.285-.95.552-.227 1.188-.34 1.907-.34 1.057 0 1.888.224 2.494.674.61.45.988 1.058 1.133 1.825ZM59.612 9.3v1.643H54.43V9.3h5.182Zm-3.903-2.16h2.125v8.462c0 .286.043.505.129.658.09.148.207.25.352.305.145.054.305.082.481.082.133 0 .255-.01.364-.03.114-.019.2-.037.258-.052l.358 1.66a4.76 4.76 0 0 1-.487.13 3.991 3.991 0 0 1-.763.082 3.463 3.463 0 0 1-1.438-.24 2.237 2.237 0 0 1-1.015-.834c-.246-.376-.367-.845-.364-1.409V7.14Zm7.943 11.355a3.76 3.76 0 0 1-1.544-.305 2.519 2.519 0 0 1-1.08-.915c-.261-.403-.392-.9-.392-1.49 0-.51.093-.93.281-1.262a2.18 2.18 0 0 1 .769-.799c.325-.2.69-.35 1.097-.451.411-.106.836-.182 1.274-.23.528-.054.956-.103 1.285-.146.329-.047.567-.117.716-.211.152-.098.229-.249.229-.452v-.035c0-.442-.131-.785-.393-1.027-.263-.243-.64-.364-1.133-.364-.52 0-.933.113-1.238.34-.302.227-.505.495-.61.804l-1.984-.281a3.166 3.166 0 0 1 .775-1.374c.36-.371.8-.65 1.32-.833a5.05 5.05 0 0 1 1.725-.282c.434 0 .867.051 1.297.153.43.102.824.27 1.18.505.356.23.641.545.856.944.22.4.33.898.33 1.497v6.033h-2.043v-1.239h-.07c-.13.25-.312.485-.546.704-.231.216-.522.39-.875.523-.348.129-.757.193-1.226.193Zm.552-1.56c.426 0 .796-.085 1.109-.253.313-.172.553-.399.721-.68.173-.282.259-.59.259-.922v-1.062a.997.997 0 0 1-.34.152 4.827 4.827 0 0 1-.529.124c-.196.035-.39.066-.58.093l-.5.071c-.317.043-.6.113-.85.211-.251.098-.449.235-.593.411-.145.172-.217.395-.217.669 0 .391.142.687.428.886.286.2.65.3 1.092.3Zm13.137-5.253-1.937.211a1.557 1.557 0 0 0-.287-.551 1.428 1.428 0 0 0-.54-.417c-.227-.105-.505-.158-.833-.158-.442 0-.814.096-1.115.287-.298.192-.445.44-.44.746a.78.78 0 0 0 .287.64c.2.164.528.299.986.404l1.537.329c.853.184 1.487.475 1.902.874.418.4.63.921.633 1.567a2.451 2.451 0 0 1-.498 1.502c-.325.43-.777.767-1.356 1.01-.579.242-1.244.363-1.995.363-1.103 0-1.991-.23-2.664-.692-.673-.466-1.074-1.113-1.203-1.942l2.071-.2c.094.407.294.714.599.921.305.208.702.311 1.191.311.505 0 .91-.103 1.215-.31.309-.208.463-.464.463-.77a.8.8 0 0 0-.299-.639c-.196-.168-.5-.297-.915-.387l-1.538-.323c-.865-.18-1.504-.483-1.919-.91-.415-.43-.62-.974-.616-1.631-.004-.556.147-1.037.452-1.444.309-.41.737-.727 1.285-.95.552-.227 1.187-.34 1.907-.34 1.056 0 1.888.224 2.494.674.61.45.988 1.058 1.133 1.825Zm3.74 1.35v5.282h-2.125V6.295h2.077v4.536h.106c.211-.508.538-.91.98-1.203.446-.297 1.013-.446 1.702-.446.626 0 1.171.131 1.637.393.465.263.825.646 1.08 1.15.258.505.387 1.122.387 1.85v5.739H84.8v-5.411c0-.607-.157-1.078-.47-1.414-.309-.34-.743-.511-1.303-.511-.375 0-.712.082-1.009.247-.293.16-.524.393-.693.698-.164.305-.246.675-.246 1.109Z"
21
+ fill="#050505"/>
22
+ <defs>
23
+ <clipPath id="a">
24
+ <path fill="#fff" d="M0 0h19.5v26H0z"/>
25
+ </clipPath>
26
+ </defs>
27
+ </svg>
@@ -0,0 +1,76 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ body {
7
+ @apply antialiased text-gray-900;
8
+ }
9
+
10
+ a {
11
+ @apply transition;
12
+ }
13
+
14
+ pre {
15
+ @apply bg-gray-800 text-gray-50 p-6 rounded-lg text-sm;
16
+ }
17
+ }
18
+
19
+ @layer components {
20
+ button {
21
+ @apply flex
22
+ items-center
23
+ px-4
24
+ py-2
25
+ font-semibold
26
+ rounded
27
+ bg-emerald-500
28
+ text-white
29
+ hover:bg-emerald-600
30
+ focus:outline-none
31
+ focus:ring-2
32
+ focus:ring-primary-200
33
+ focus:ring-offset-2;
34
+ }
35
+
36
+ [type="text"],
37
+ [type="email"],
38
+ [type="url"],
39
+ [type="password"],
40
+ [type="number"],
41
+ [type="date"],
42
+ [type="datetime-local"],
43
+ [type="month"],
44
+ [type="search"],
45
+ [type="tel"],
46
+ [type="time"],
47
+ [type="week"],
48
+ textarea,
49
+ select {
50
+ @apply rounded
51
+ shadow-sm
52
+ border-gray-300
53
+ focus:ring
54
+ focus:ring-primary-200
55
+ focus:ring-opacity-50
56
+ focus:border-primary-300;
57
+ }
58
+
59
+ [type="checkbox"],
60
+ [type="radio"] {
61
+ @apply w-5
62
+ h-5
63
+ text-primary-500
64
+ border-gray-300
65
+ focus:ring
66
+ focus:ring-offset-0
67
+ focus:ring-primary-200
68
+ focus:ring-opacity-50
69
+ focus:border-primary-300;
70
+ }
71
+
72
+ [type="checkbox"] {
73
+ @apply rounded
74
+ shadow-sm;
75
+ }
76
+ }
@@ -0,0 +1,19 @@
1
+ const colors = require("tailwindcss/colors");
2
+
3
+ module.exports = {
4
+ content: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
5
+ theme: {
6
+ extend: {
7
+ colors: {
8
+ gray: colors.zinc,
9
+ primary: colors.emerald,
10
+ },
11
+ },
12
+ },
13
+ plugins: [
14
+ require("@tailwindcss/forms")({
15
+ strategy: "base", // only generate global styles
16
+ // strategy: "class", // only generate classes
17
+ }),
18
+ ],
19
+ };
@@ -0,0 +1,21 @@
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
+ "baseUrl": "."
18
+ },
19
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20
+ "exclude": ["node_modules"]
21
+ }
@@ -0,0 +1,38 @@
1
+ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2
+
3
+ ## Getting Started
4
+
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ ```
14
+
15
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16
+
17
+ You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
18
+
19
+ [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
20
+
21
+ The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
22
+
23
+ This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
24
+
25
+ ## Learn More
26
+
27
+ To learn more about Next.js, take a look at the following resources:
28
+
29
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
30
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
31
+
32
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
33
+
34
+ ## Deploy on Vercel
35
+
36
+ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
37
+
38
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
@@ -0,0 +1,107 @@
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
+ }
@@ -0,0 +1,18 @@
1
+ import "./globals.css";
2
+
3
+ export const metadata = {
4
+ title: "Create Next App",
5
+ description: "Generated by create next app",
6
+ };
7
+
8
+ export default function RootLayout({
9
+ children,
10
+ }: {
11
+ children: React.ReactNode;
12
+ }) {
13
+ return (
14
+ <html lang="en">
15
+ <body>{children}</body>
16
+ </html>
17
+ );
18
+ }