├── .gitignore ├── app-search-turborepo ├── .eslintrc.js ├── .gitignore ├── .npmrc ├── .vscode │ └── settings.json ├── README.md ├── apps │ └── app-search │ │ ├── .eslintrc.js │ │ ├── README.md │ │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── users │ │ │ └── page.tsx │ │ ├── next-env.d.ts │ │ ├── next.config.js │ │ ├── package.json │ │ ├── postcss.config.js │ │ ├── public │ │ ├── circles.svg │ │ ├── next.svg │ │ ├── turborepo.svg │ │ └── vercel.svg │ │ ├── tailwind.config.js │ │ └── tsconfig.json ├── package.json ├── packages │ ├── eslint-config │ │ ├── README.md │ │ ├── library.js │ │ ├── next.js │ │ ├── package.json │ │ └── react-internal.js │ ├── typescript-config │ │ ├── base.json │ │ ├── nextjs.json │ │ ├── package.json │ │ └── react-library.json │ └── ui │ │ ├── .eslintrc.js │ │ ├── package.json │ │ ├── src │ │ ├── Comments.tsx │ │ ├── SearchableComments.tsx │ │ ├── Users.tsx │ │ └── types.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lint.json │ │ └── turbo │ │ └── generators │ │ ├── config.ts │ │ └── templates │ │ └── component.hbs ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── tsconfig.json └── turbo.json ├── app-search ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public │ ├── next.svg │ └── vercel.svg ├── src │ ├── app │ │ ├── components │ │ │ ├── Comments.tsx │ │ │ ├── SearchableComments.tsx │ │ │ └── Users.tsx │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── users │ │ │ └── page.tsx │ └── types.ts ├── tailwind.config.ts └── tsconfig.json ├── app-simple ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public │ ├── next.svg │ └── vercel.svg ├── src │ ├── app │ │ ├── components │ │ │ ├── Comments.tsx │ │ │ └── Users.tsx │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── users │ │ │ └── page.tsx │ └── types.ts ├── tailwind.config.ts └── tsconfig.json ├── app-suspense ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public │ ├── next.svg │ └── vercel.svg ├── src │ ├── app │ │ ├── components │ │ │ ├── Comments.tsx │ │ │ └── Users.tsx │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── users │ │ │ └── page.tsx │ └── constants.ts ├── tailwind.config.ts └── tsconfig.json ├── pages-search ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public │ ├── favicon.ico │ ├── next.svg │ └── vercel.svg ├── src │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── api │ │ │ └── comment-search.ts │ │ ├── components │ │ │ ├── Comments.tsx │ │ │ └── Users.tsx │ │ ├── index.tsx │ │ └── users.tsx │ ├── styles │ │ └── globals.css │ └── types.ts ├── tailwind.config.ts └── tsconfig.json ├── pages-simple ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public │ ├── favicon.ico │ ├── next.svg │ └── vercel.svg ├── src │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── api │ │ │ └── hello.ts │ │ ├── components │ │ │ ├── Comments.tsx │ │ │ └── Users.tsx │ │ ├── index.tsx │ │ └── users.tsx │ ├── styles │ │ └── globals.css │ └── types.ts ├── tailwind.config.ts └── tsconfig.json └── pages-suspense ├── .eslintrc.json ├── .gitignore ├── README.md ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── favicon.ico ├── next.svg └── vercel.svg ├── src ├── constants.ts ├── getCommentsServer.ts ├── getUsersServer.ts ├── pages │ ├── _app.tsx │ ├── _document.tsx │ ├── api │ │ ├── comments.ts │ │ └── users.ts │ ├── components │ │ ├── Comments.tsx │ │ └── Users.tsx │ ├── index.tsx │ └── users.tsx ├── styles │ └── globals.css └── types.ts ├── tailwind.config.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /app-search-turborepo/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ["apps/**", "packages/**"], 5 | extends: ["@repo/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /app-search-turborepo/.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 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | 30 | 31 | # Debug 32 | npm-debug.log* 33 | yarn-debug.log* 34 | yarn-error.log* 35 | 36 | # Misc 37 | .DS_Store 38 | *.pem 39 | -------------------------------------------------------------------------------- /app-search-turborepo/.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/app-search-turborepo/.npmrc -------------------------------------------------------------------------------- /app-search-turborepo/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.workingDirectories": [ 3 | { 4 | "mode": "auto" 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /app-search-turborepo/README.md: -------------------------------------------------------------------------------- 1 | # Turborepo starter 2 | 3 | This is an official starter Turborepo. 4 | 5 | ## Using this example 6 | 7 | Run the following command: 8 | 9 | ```sh 10 | npx create-turbo@latest 11 | ``` 12 | 13 | ## What's inside? 14 | 15 | This Turborepo includes the following packages/apps: 16 | 17 | ### Apps and Packages 18 | 19 | - `docs`: a [Next.js](https://nextjs.org/) app 20 | - `web`: another [Next.js](https://nextjs.org/) app 21 | - `@repo/ui`: a stub React component library shared by both `web` and `docs` applications 22 | - `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) 23 | - `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo 24 | 25 | Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). 26 | 27 | ### Utilities 28 | 29 | This Turborepo has some additional tools already setup for you: 30 | 31 | - [TypeScript](https://www.typescriptlang.org/) for static type checking 32 | - [ESLint](https://eslint.org/) for code linting 33 | - [Prettier](https://prettier.io) for code formatting 34 | 35 | ### Build 36 | 37 | To build all apps and packages, run the following command: 38 | 39 | ``` 40 | cd my-turborepo 41 | pnpm build 42 | ``` 43 | 44 | ### Develop 45 | 46 | To develop all apps and packages, run the following command: 47 | 48 | ``` 49 | cd my-turborepo 50 | pnpm dev 51 | ``` 52 | 53 | ### Remote Caching 54 | 55 | Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. 56 | 57 | By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands: 58 | 59 | ``` 60 | cd my-turborepo 61 | npx turbo login 62 | ``` 63 | 64 | This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). 65 | 66 | Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: 67 | 68 | ``` 69 | npx turbo link 70 | ``` 71 | 72 | ## Useful Links 73 | 74 | Learn more about the power of Turborepo: 75 | 76 | - [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) 77 | - [Caching](https://turbo.build/repo/docs/core-concepts/caching) 78 | - [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) 79 | - [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) 80 | - [Configuration Options](https://turbo.build/repo/docs/reference/configuration) 81 | - [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) 82 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ["@repo/eslint-config/next.js"], 5 | parser: "@typescript-eslint/parser", 6 | parserOptions: { 7 | project: true, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/README.md: -------------------------------------------------------------------------------- 1 | ## Getting Started 2 | 3 | First, run the development server: 4 | 5 | ```bash 6 | yarn dev 7 | ``` 8 | 9 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 10 | 11 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 12 | 13 | To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). 14 | 15 | ## Learn More 16 | 17 | To learn more about Next.js, take a look at the following resources: 18 | 19 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 20 | - [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. 21 | 22 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 23 | 24 | ## Deploy on Vercel 25 | 26 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. 27 | 28 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 29 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/app-search-turborepo/apps/app-search/app/favicon.ico -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | import type { Metadata } from "next"; 3 | import { Inter } from "next/font/google"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Turborepo", 9 | description: "Generated by create turbo", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: { 15 | children: React.ReactNode; 16 | }): JSX.Element { 17 | return ( 18 | 19 | {children} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "@repo/ui/Comments"; 2 | 3 | export default function Page() { 4 | return ( 5 |
6 |

Home Page

7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/app/users/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "@repo/ui/Comments"; 2 | import Users from "@repo/ui/Users"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |

Users Page

8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | transpilePackages: ["@repo/ui"], 4 | }; 5 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-search", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "eslint . --max-warnings 0" 10 | }, 11 | "dependencies": { 12 | "@repo/ui": "workspace:*", 13 | "next": "^14.0.4", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@next/eslint-plugin-next": "^14.0.4", 19 | "@repo/eslint-config": "workspace:*", 20 | "@repo/typescript-config": "workspace:*", 21 | "@tailwindcss/container-queries": "^0.1.1", 22 | "@tailwindcss/typography": "^0.5.10", 23 | "@types/eslint": "^8.56.1", 24 | "@types/node": "^20.10.6", 25 | "@types/react": "^18.2.46", 26 | "@types/react-dom": "^18.2.18", 27 | "autoprefixer": "^10.4.17", 28 | "eslint": "^8.56.0", 29 | "postcss": "^8.4.33", 30 | "tailwindcss": "^3.4.1", 31 | "typescript": "^5.3.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/public/circles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/public/turborepo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 5 | "../../packages/ui/**/*.{js,ts,jsx,tsx,mdx}", 6 | ], 7 | theme: { 8 | extend: { 9 | backgroundImage: { 10 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 11 | "gradient-conic": 12 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 13 | }, 14 | }, 15 | }, 16 | plugins: [require("@tailwindcss/typography")], 17 | }; 18 | -------------------------------------------------------------------------------- /app-search-turborepo/apps/app-search/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "plugins": [ 5 | { 6 | "name": "next" 7 | } 8 | ] 9 | }, 10 | "include": [ 11 | "next-env.d.ts", 12 | "next.config.js", 13 | "**/*.ts", 14 | "**/*.tsx", 15 | ".next/types/**/*.ts" 16 | ], 17 | "exclude": ["node_modules"] 18 | } 19 | -------------------------------------------------------------------------------- /app-search-turborepo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-search-turborepo", 3 | "private": true, 4 | "scripts": { 5 | "build": "turbo build", 6 | "dev": "turbo dev", 7 | "lint": "turbo lint", 8 | "format": "prettier --write \"**/*.{ts,tsx,md}\"" 9 | }, 10 | "devDependencies": { 11 | "@repo/eslint-config": "workspace:*", 12 | "@repo/typescript-config": "workspace:*", 13 | "prettier": "^3.1.1", 14 | "turbo": "latest" 15 | }, 16 | "packageManager": "pnpm@8.9.0", 17 | "engines": { 18 | "node": ">=18" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@turbo/eslint-config` 2 | 3 | Collection of internal eslint configurations. 4 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/eslint-config/library.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /** @type {import("eslint").Linter.Config} */ 6 | module.exports = { 7 | extends: ["eslint:recommended", "prettier", "eslint-config-turbo"], 8 | plugins: ["only-warn"], 9 | globals: { 10 | React: true, 11 | JSX: true, 12 | }, 13 | env: { 14 | node: true, 15 | }, 16 | settings: { 17 | "import/resolver": { 18 | typescript: { 19 | project, 20 | }, 21 | }, 22 | }, 23 | ignorePatterns: [ 24 | // Ignore dotfiles 25 | ".*.js", 26 | "node_modules/", 27 | "dist/", 28 | ], 29 | overrides: [ 30 | { 31 | files: ["*.js?(x)", "*.ts?(x)"], 32 | }, 33 | ], 34 | }; 35 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/eslint-config/next.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /** @type {import("eslint").Linter.Config} */ 6 | module.exports = { 7 | extends: [ 8 | "eslint:recommended", 9 | "prettier", 10 | require.resolve("@vercel/style-guide/eslint/next"), 11 | "eslint-config-turbo", 12 | ], 13 | globals: { 14 | React: true, 15 | JSX: true, 16 | }, 17 | env: { 18 | node: true, 19 | browser: true, 20 | }, 21 | plugins: ["only-warn"], 22 | settings: { 23 | "import/resolver": { 24 | typescript: { 25 | project, 26 | }, 27 | }, 28 | }, 29 | ignorePatterns: [ 30 | // Ignore dotfiles 31 | ".*.js", 32 | "node_modules/", 33 | ], 34 | overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }], 35 | }; 36 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/eslint-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "files": [ 6 | "library.js", 7 | "next.js", 8 | "react-internal.js" 9 | ], 10 | "devDependencies": { 11 | "@vercel/style-guide": "^5.1.0", 12 | "eslint-config-turbo": "^1.11.3", 13 | "eslint-config-prettier": "^9.1.0", 14 | "eslint-plugin-only-warn": "^1.1.0", 15 | "@typescript-eslint/parser": "^6.17.0", 16 | "@typescript-eslint/eslint-plugin": "^6.17.0", 17 | "typescript": "^5.3.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/eslint-config/react-internal.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("node:path"); 2 | 3 | const project = resolve(process.cwd(), "tsconfig.json"); 4 | 5 | /* 6 | * This is a custom ESLint configuration for use with 7 | * internal (bundled by their consumer) libraries 8 | * that utilize React. 9 | * 10 | * This config extends the Vercel Engineering Style Guide. 11 | * For more information, see https://github.com/vercel/style-guide 12 | * 13 | */ 14 | 15 | /** @type {import("eslint").Linter.Config} */ 16 | module.exports = { 17 | extends: ["eslint:recommended", "prettier", "eslint-config-turbo"], 18 | plugins: ["only-warn"], 19 | globals: { 20 | React: true, 21 | JSX: true, 22 | }, 23 | env: { 24 | browser: true, 25 | }, 26 | settings: { 27 | "import/resolver": { 28 | typescript: { 29 | project, 30 | }, 31 | }, 32 | }, 33 | ignorePatterns: [ 34 | // Ignore dotfiles 35 | ".*.js", 36 | "node_modules/", 37 | "dist/", 38 | ], 39 | overrides: [ 40 | // Force ESLint to detect .tsx files 41 | { files: ["*.js?(x)", "*.ts?(x)"] }, 42 | ], 43 | }; 44 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/typescript-config/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "declaration": true, 6 | "declarationMap": true, 7 | "esModuleInterop": true, 8 | "incremental": false, 9 | "isolatedModules": true, 10 | "lib": ["es2022", "DOM", "DOM.Iterable"], 11 | "module": "NodeNext", 12 | "moduleDetection": "force", 13 | "moduleResolution": "NodeNext", 14 | "noUncheckedIndexedAccess": true, 15 | "resolveJsonModule": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "target": "ES2022" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/typescript-config/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "plugins": [{ "name": "next" }], 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "allowJs": true, 10 | "jsx": "preserve", 11 | "noEmit": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/typescript-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/typescript-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/typescript-config/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "jsx": "react-jsx", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import("eslint").Linter.Config} */ 2 | module.exports = { 3 | root: true, 4 | extends: ["@repo/eslint-config/react-internal.js"], 5 | parser: "@typescript-eslint/parser", 6 | parserOptions: { 7 | project: "./tsconfig.lint.json", 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@repo/ui", 3 | "version": "0.0.0", 4 | "private": true, 5 | "exports": { 6 | "./Comments": "./src/Comments.tsx", 7 | "./Users": "./src/Users.tsx" 8 | }, 9 | "scripts": { 10 | "lint": "eslint . --max-warnings 0", 11 | "generate:component": "turbo gen react-component" 12 | }, 13 | "devDependencies": { 14 | "@repo/eslint-config": "workspace:*", 15 | "@repo/typescript-config": "workspace:*", 16 | "@turbo/gen": "^1.11.3", 17 | "@types/node": "^20.10.6", 18 | "@types/eslint": "^8.56.1", 19 | "@types/react": "^18.2.46", 20 | "@types/react-dom": "^18.2.18", 21 | "eslint": "^8.56.0", 22 | "react": "^18.2.0", 23 | "typescript": "^5.3.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/src/Comments.tsx: -------------------------------------------------------------------------------- 1 | import SearchableComments from "./SearchableComments"; 2 | import { Comment } from "./types"; 3 | 4 | const getComments = async () => 5 | ( 6 | await fetch("https://jsonplaceholder.typicode.com/comments") 7 | ).json() as Promise; 8 | 9 | export default async function Comments() { 10 | const comments = await getComments(); 11 | 12 | const search = async (search: string) => { 13 | "use server"; 14 | const comments = await getComments(); 15 | return comments 16 | .filter( 17 | (comment) => 18 | comment.name.toLowerCase().includes(search) || 19 | comment.body.toLowerCase().includes(search) 20 | ) 21 | .slice(0, 20); 22 | }; 23 | 24 | return ( 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/src/SearchableComments.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | import { Comment } from "./types"; 4 | 5 | export default function SearchableComments({ 6 | comments, 7 | search, 8 | }: { 9 | comments: Comment[]; 10 | search: (search: string) => Promise; 11 | }) { 12 | const [searchTerm, setSearchTerm] = useState(""); 13 | const [searchResults, setSearchResults] = useState(comments); 14 | 15 | const handleChange = async (e: React.ChangeEvent) => { 16 | setSearchTerm(e.target.value); 17 | setSearchResults(await search(e.target.value)); 18 | }; 19 | 20 | return ( 21 |
22 |
23 | 29 | 32 |
33 |

Comments

34 |
35 | {searchResults.map((comment) => ( 36 |
37 |
38 |

{comment.name}

39 |

{comment.body}

40 |
41 |
42 | ))} 43 |
44 |
45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/src/Users.tsx: -------------------------------------------------------------------------------- 1 | import { User } from "./types"; 2 | 3 | export default async function Users() { 4 | const res = await fetch("https://jsonplaceholder.typicode.com/users"); 5 | const users = (await res.json()) as User[]; 6 | 7 | return ( 8 |
9 |

Users

10 |
11 | {users.slice(0, 20).map((user) => ( 12 |
13 |
14 |

{user.name}

15 |

{user.phone}

16 |
17 |
18 | ))} 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: string; 9 | email: string; 10 | name: string; 11 | phone: string; 12 | } 13 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": ["src"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/tsconfig.lint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": ["src", "turbo"], 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/turbo/generators/config.ts: -------------------------------------------------------------------------------- 1 | import type { PlopTypes } from "@turbo/gen"; 2 | 3 | // Learn more about Turborepo Generators at https://turbo.build/repo/docs/core-concepts/monorepos/code-generation 4 | 5 | export default function generator(plop: PlopTypes.NodePlopAPI): void { 6 | // A simple generator to add a new React component to the internal UI library 7 | plop.setGenerator("react-component", { 8 | description: "Adds a new react component", 9 | prompts: [ 10 | { 11 | type: "input", 12 | name: "name", 13 | message: "What is the name of the component?", 14 | }, 15 | ], 16 | actions: [ 17 | { 18 | type: "add", 19 | path: "src/{{kebabCase name}}.tsx", 20 | templateFile: "templates/component.hbs", 21 | }, 22 | { 23 | type: "append", 24 | path: "index.tsx", 25 | pattern: /"exports": {(?)/g, 26 | template: '"./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",', 27 | }, 28 | ], 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /app-search-turborepo/packages/ui/turbo/generators/templates/component.hbs: -------------------------------------------------------------------------------- 1 | export const {{ pascalCase name }} = ({ children }: { children: React.ReactNode }) => { 2 | return ( 3 |
4 |

{{ pascalCase name }} Component

5 | {children} 6 |
7 | ); 8 | }; 9 | -------------------------------------------------------------------------------- /app-search-turborepo/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "apps/*" 3 | - "packages/*" 4 | -------------------------------------------------------------------------------- /app-search-turborepo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@repo/typescript-config/base.json" 3 | } 4 | -------------------------------------------------------------------------------- /app-search-turborepo/turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["**/.env.*local"], 4 | "pipeline": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "outputs": [".next/**", "!.next/cache/**"] 8 | }, 9 | "lint": { 10 | "dependsOn": ["^lint"] 11 | }, 12 | "dev": { 13 | "cache": false, 14 | "persistent": true 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app-search/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app-search/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /app-search/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /app-search/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /app-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-comments", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app-search/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /app-search/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-search/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-search/src/app/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import SearchableComments from "./SearchableComments"; 2 | import { Comment } from "@/types"; 3 | 4 | const getComments = async () => 5 | ( 6 | await fetch("https://jsonplaceholder.typicode.com/comments", { 7 | cache: "no-cache", 8 | }) 9 | ).json() as Promise; 10 | 11 | export default async function Comments() { 12 | const comments = await getComments(); 13 | 14 | const search = async (search: string) => { 15 | "use server"; 16 | const comments = await getComments(); 17 | return comments 18 | .filter( 19 | (comment) => 20 | comment.name.toLowerCase().includes(search) || 21 | comment.body.toLowerCase().includes(search) 22 | ) 23 | .slice(0, 20); 24 | }; 25 | 26 | return ( 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /app-search/src/app/components/SearchableComments.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | import { Comment } from "@/types"; 4 | 5 | export default function SearchableComments({ 6 | comments, 7 | search, 8 | }: { 9 | comments: Comment[]; 10 | search: (search: string) => Promise; 11 | }) { 12 | const [searchTerm, setSearchTerm] = useState(""); 13 | const [searchResults, setSearchResults] = useState(comments); 14 | 15 | const handleChange = async (e: React.ChangeEvent) => { 16 | setSearchTerm(e.target.value); 17 | setSearchResults(await search(e.target.value)); 18 | }; 19 | 20 | return ( 21 |
22 |
23 | 29 | 32 |
33 |

Comments

34 |
35 | {searchResults.map((comment) => ( 36 |
37 |
38 |

{comment.name}

39 |

{comment.body}

40 |
41 |
42 | ))} 43 |
44 |
45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /app-search/src/app/components/Users.tsx: -------------------------------------------------------------------------------- 1 | import { User } from "@/types"; 2 | 3 | export default async function Users() { 4 | const res = await fetch("https://jsonplaceholder.typicode.com/users", { 5 | cache: "no-cache", 6 | }); 7 | const users = (await res.json()) as User[]; 8 | 9 | return ( 10 |
11 |

Users

12 |
13 | {users.slice(0, 20).map((user) => ( 14 |
15 |
16 |

{user.name}

17 |

{user.phone}

18 |
19 |
20 | ))} 21 |
22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app-search/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/app-search/src/app/favicon.ico -------------------------------------------------------------------------------- /app-search/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app-search/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | 20 |
{children}
21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app-search/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |

Home Page

7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /app-search/src/app/users/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "../components/Comments"; 2 | import Users from "../components/Users"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |

Users Page

8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /app-search/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: string; 9 | email: string; 10 | name: string; 11 | phone: string; 12 | } 13 | -------------------------------------------------------------------------------- /app-search/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /app-search/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /app-simple/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app-simple/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /app-simple/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /app-simple/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /app-simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-comments", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app-simple/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /app-simple/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-simple/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-simple/src/app/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import { Comment } from "@/types"; 2 | 3 | export default async function Comments() { 4 | const res = await fetch("https://jsonplaceholder.typicode.com/comments"); 5 | const comments = (await res.json()) as Comment[]; 6 | 7 | return ( 8 |
9 |

Comments

10 |
11 | {comments.slice(0, 20).map((comment) => ( 12 |
13 |
14 |

{comment.name}

15 |

{comment.body}

16 |
17 |
18 | ))} 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /app-simple/src/app/components/Users.tsx: -------------------------------------------------------------------------------- 1 | import { User } from "@/types"; 2 | 3 | export default async function Users() { 4 | const res = await fetch("https://jsonplaceholder.typicode.com/users"); 5 | const users = (await res.json()) as User[]; 6 | 7 | return ( 8 |
9 |

Users

10 |
11 | {users.slice(0, 20).map((user) => ( 12 |
13 |
14 |

{user.name}

15 |

{user.phone}

16 |
17 |
18 | ))} 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /app-simple/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/app-simple/src/app/favicon.ico -------------------------------------------------------------------------------- /app-simple/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app-simple/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | 20 |
{children}
21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app-simple/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |

Home Page

7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /app-simple/src/app/users/page.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "../components/Comments"; 2 | import Users from "../components/Users"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |

Users Page

8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /app-simple/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: string; 9 | email: string; 10 | name: string; 11 | phone: string; 12 | } 13 | -------------------------------------------------------------------------------- /app-simple/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /app-simple/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /app-suspense/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app-suspense/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /app-suspense/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | 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. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /app-suspense/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /app-suspense/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-comments", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app-suspense/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /app-suspense/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-suspense/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app-suspense/src/app/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import { COMMENTS_DELAY } from "@/constants"; 2 | 3 | export default async function Comments() { 4 | await new Promise((resolve) => setTimeout(resolve, COMMENTS_DELAY)); 5 | const res = await fetch("https://jsonplaceholder.typicode.com/comments", { 6 | cache: "no-cache", 7 | }); 8 | const comments = (await res.json()) as { 9 | id: number; 10 | name: string; 11 | body: string; 12 | }[]; 13 | 14 | return ( 15 |
16 |

Comments

17 |
18 | {comments.slice(0, 20).map((comment) => ( 19 |
20 |
21 |

{comment.name}

22 |

{comment.body}

23 |
24 |
25 | ))} 26 |
27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /app-suspense/src/app/components/Users.tsx: -------------------------------------------------------------------------------- 1 | import { USERS_DELAY } from "@/constants"; 2 | 3 | export default async function Users() { 4 | await new Promise((resolve) => setTimeout(resolve, USERS_DELAY)); 5 | const res = await fetch("https://jsonplaceholder.typicode.com/users", { 6 | cache: "no-cache", 7 | }); 8 | const users = (await res.json()) as { 9 | id: string; 10 | email: string; 11 | name: string; 12 | phone: string; 13 | }[]; 14 | 15 | return ( 16 |
17 |

Users

18 |
19 | {users.slice(0, 20).map((user) => ( 20 |
21 |
22 |

{user.name}

23 |

{user.phone}

24 |
25 |
26 | ))} 27 |
28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /app-suspense/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/app-suspense/src/app/favicon.ico -------------------------------------------------------------------------------- /app-suspense/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app-suspense/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode; 16 | }>) { 17 | return ( 18 | 19 | 20 |
{children}
21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app-suspense/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from "react"; 2 | import Comments from "./components/Comments"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |

Home Page

8 | Loading...
}> 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /app-suspense/src/app/users/page.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from "react"; 2 | import Comments from "../components/Comments"; 3 | import Users from "../components/Users"; 4 | 5 | export default function Home() { 6 | return ( 7 |
8 |

Users Page

9 |
10 |
11 | Loading users...
}> 12 | 13 | 14 |
15 |
16 | Loading comments...
}> 17 | 18 | 19 |
20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /app-suspense/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const USERS_DELAY = 3000; 2 | export const COMMENTS_DELAY = 3000; 3 | -------------------------------------------------------------------------------- /app-suspense/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /app-suspense/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /pages-search/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /pages-search/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /pages-search/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 20 | 21 | [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`. 22 | 23 | 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. 24 | 25 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 26 | 27 | ## Learn More 28 | 29 | To learn more about Next.js, take a look at the following resources: 30 | 31 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 32 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 33 | 34 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 35 | 36 | ## Deploy on Vercel 37 | 38 | 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. 39 | 40 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 41 | -------------------------------------------------------------------------------- /pages-search/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /pages-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pages-simple", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pages-search/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /pages-search/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/pages-search/public/favicon.ico -------------------------------------------------------------------------------- /pages-search/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-search/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-search/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "@/styles/globals.css"; 2 | import type { AppProps } from "next/app"; 3 | 4 | export default function App({ Component, pageProps }: AppProps) { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /pages-search/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /pages-search/src/pages/api/comment-search.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from "next"; 3 | import { Comment } from "@/types"; 4 | 5 | export default async function handler( 6 | req: NextApiRequest, 7 | res: NextApiResponse 8 | ) { 9 | let search = ""; 10 | if (typeof req.query.q === "string") { 11 | search = req.query.q; 12 | } 13 | 14 | const cres = await fetch("https://jsonplaceholder.typicode.com/comments"); 15 | const comments = (await cres.json()) as Comment[]; 16 | 17 | res 18 | .status(200) 19 | .json( 20 | comments 21 | .filter( 22 | (comment) => 23 | comment.name.toLowerCase().includes(search) || 24 | comment.body.toLowerCase().includes(search) 25 | ) 26 | .slice(0, 20) 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /pages-search/src/pages/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useState } from "react"; 3 | 4 | export default function Comments({ 5 | comments, 6 | }: { 7 | comments: { 8 | id: number; 9 | name: string; 10 | body: string; 11 | }[]; 12 | }) { 13 | const [searchTerm, setSearchTerm] = useState(""); 14 | const [searchResults, setSearchResults] = useState(comments); 15 | 16 | const handleChange = async (e: React.ChangeEvent) => { 17 | setSearchTerm(e.target.value); 18 | fetch(`/api/comment-search?q=${encodeURIComponent(e.target.value)}`, { 19 | method: "GET", 20 | headers: { 21 | "Content-Type": "application/json", 22 | }, 23 | }) 24 | .then((res) => res.json()) 25 | .then((data) => { 26 | setSearchResults(data); 27 | }); 28 | }; 29 | 30 | return ( 31 |
32 |
33 | 39 | 42 |
43 |

Comments

44 |
45 | {searchResults.map((comment) => ( 46 |
47 |
48 |

{comment.name}

49 |

{comment.body}

50 |
51 |
52 | ))} 53 |
54 |
55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /pages-search/src/pages/components/Users.tsx: -------------------------------------------------------------------------------- 1 | export default function Users({ 2 | users, 3 | }: { 4 | users: { 5 | id: number; 6 | name: string; 7 | phone: string; 8 | }[]; 9 | }) { 10 | return ( 11 |
12 |

Users

13 |
14 | {users.map((user) => ( 15 |
16 |
17 |

{user.name}

18 |

{user.phone}

19 |
20 |
21 | ))} 22 |
23 |
24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /pages-search/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | import { Comment } from "@/types"; 3 | 4 | export async function getServerSideProps() { 5 | const res = await fetch("https://jsonplaceholder.typicode.com/comments"); 6 | const comments = (await res.json()) as Comment[]; 7 | 8 | return { 9 | props: { 10 | comments: comments.slice(0, 20), 11 | }, 12 | }; 13 | } 14 | 15 | export default function Home({ comments }: { comments: Comment[] }) { 16 | return ( 17 |
18 |

Home Page

19 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /pages-search/src/pages/users.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | import Users from "./components/Users"; 3 | import { Comment, User } from "@/types"; 4 | 5 | export async function getServerSideProps() { 6 | const cres = await fetch("https://jsonplaceholder.typicode.com/comments"); 7 | const comments = (await cres.json()) as Comment[]; 8 | 9 | const ures = await fetch("https://jsonplaceholder.typicode.com/users"); 10 | const users = (await ures.json()) as Comment[]; 11 | 12 | return { 13 | props: { 14 | users: users.slice(0, 20), 15 | comments: comments.slice(0, 20), 16 | }, 17 | }; 18 | } 19 | 20 | export default function Home({ 21 | users, 22 | comments, 23 | }: { 24 | comments: Comment[]; 25 | users: User[]; 26 | }) { 27 | return ( 28 |
29 |

Users Page

30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /pages-search/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pages-search/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: number; 9 | name: string; 10 | phone: string; 11 | } 12 | -------------------------------------------------------------------------------- /pages-search/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /pages-search/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "paths": { 16 | "@/*": ["./src/*"] 17 | } 18 | }, 19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 20 | "exclude": ["node_modules"] 21 | } 22 | -------------------------------------------------------------------------------- /pages-simple/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /pages-simple/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /pages-simple/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 20 | 21 | [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`. 22 | 23 | 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. 24 | 25 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 26 | 27 | ## Learn More 28 | 29 | To learn more about Next.js, take a look at the following resources: 30 | 31 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 32 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 33 | 34 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 35 | 36 | ## Deploy on Vercel 37 | 38 | 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. 39 | 40 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 41 | -------------------------------------------------------------------------------- /pages-simple/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /pages-simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pages-simple", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pages-simple/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /pages-simple/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/pages-simple/public/favicon.ico -------------------------------------------------------------------------------- /pages-simple/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-simple/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-simple/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "@/styles/globals.css"; 2 | import type { AppProps } from "next/app"; 3 | 4 | export default function App({ Component, pageProps }: AppProps) { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /pages-simple/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /pages-simple/src/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-simple/src/pages/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import { Comment } from "@/types"; 2 | 3 | export default function Comments({ comments }: { comments: Comment[] }) { 4 | return ( 5 |
6 |

Comments

7 |
8 | {comments.map((comment) => ( 9 |
10 |
11 |

{comment.name}

12 |

{comment.body}

13 |
14 |
15 | ))} 16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /pages-simple/src/pages/components/Users.tsx: -------------------------------------------------------------------------------- 1 | import { User } from "@/types"; 2 | 3 | export default function Users({ users }: { users: User[] }) { 4 | return ( 5 |
6 |

Users

7 |
8 | {users.map((user) => ( 9 |
10 |
11 |

{user.name}

12 |

{user.phone}

13 |
14 |
15 | ))} 16 |
17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /pages-simple/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | import { Comment } from "@/types"; 3 | 4 | export async function getServerSideProps() { 5 | const res = await fetch("https://jsonplaceholder.typicode.com/comments"); 6 | const comments = (await res.json()) as Comment[]; 7 | 8 | return { 9 | props: { 10 | comments: comments.slice(0, 20), 11 | }, 12 | }; 13 | } 14 | 15 | export default function Home({ comments }: { comments: Comment[] }) { 16 | return ( 17 |
18 |

Home Page

19 | 20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /pages-simple/src/pages/users.tsx: -------------------------------------------------------------------------------- 1 | import Comments from "./components/Comments"; 2 | import Users from "./components/Users"; 3 | import { Comment, User } from "@/types"; 4 | 5 | export async function getServerSideProps() { 6 | const cres = await fetch("https://jsonplaceholder.typicode.com/comments"); 7 | const comments = (await cres.json()) as Comment[]; 8 | 9 | const ures = await fetch("https://jsonplaceholder.typicode.com/users"); 10 | const users = (await ures.json()) as Comment[]; 11 | 12 | return { 13 | props: { 14 | users: users.slice(0, 20), 15 | comments: comments.slice(0, 20), 16 | }, 17 | }; 18 | } 19 | 20 | export default function Home({ 21 | users, 22 | comments, 23 | }: { 24 | comments: Comment[]; 25 | users: User[]; 26 | }) { 27 | return ( 28 |
29 |

Users Page

30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /pages-simple/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pages-simple/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: number; 9 | name: string; 10 | phone: string; 11 | } 12 | -------------------------------------------------------------------------------- /pages-simple/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /pages-simple/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "paths": { 16 | "@/*": ["./src/*"] 17 | } 18 | }, 19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 20 | "exclude": ["node_modules"] 21 | } 22 | -------------------------------------------------------------------------------- /pages-suspense/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /pages-suspense/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.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 | -------------------------------------------------------------------------------- /pages-suspense/README.md: -------------------------------------------------------------------------------- 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 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 20 | 21 | [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`. 22 | 23 | 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. 24 | 25 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 26 | 27 | ## Learn More 28 | 29 | To learn more about Next.js, take a look at the following resources: 30 | 31 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 32 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 33 | 34 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 35 | 36 | ## Deploy on Vercel 37 | 38 | 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. 39 | 40 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 41 | -------------------------------------------------------------------------------- /pages-suspense/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /pages-suspense/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pages-simple", 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 | "next": "14.1.0", 13 | "react": "^18", 14 | "react-dom": "^18" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/container-queries": "^0.1.1", 18 | "@types/node": "^20", 19 | "@types/react": "^18", 20 | "@types/react-dom": "^18", 21 | "autoprefixer": "^10.0.1", 22 | "eslint": "^8", 23 | "eslint-config-next": "14.1.0", 24 | "postcss": "^8", 25 | "tailwindcss": "^3.3.0", 26 | "typescript": "^5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pages-suspense/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /pages-suspense/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/nextjs-killed-react/553f306153084c97f4dbb820c3f569e562be9eea/pages-suspense/public/favicon.ico -------------------------------------------------------------------------------- /pages-suspense/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-suspense/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages-suspense/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const USERS_DELAY = 3000; 2 | export const COMMENTS_DELAY = 20; 3 | export const SSR_THRESHOLD = 200; 4 | -------------------------------------------------------------------------------- /pages-suspense/src/getCommentsServer.ts: -------------------------------------------------------------------------------- 1 | import { Comment } from "./types"; 2 | 3 | import { COMMENTS_DELAY, SSR_THRESHOLD } from "./constants"; 4 | 5 | export async function getCommentsServer() { 6 | return new Promise((resolve) => { 7 | let comments: Comment[] | null = null; 8 | 9 | try { 10 | let timedOut = false; 11 | 12 | setTimeout(() => { 13 | if (!comments) { 14 | timedOut = true; 15 | resolve(null); 16 | } 17 | }, SSR_THRESHOLD); 18 | 19 | new Promise((resolve) => { 20 | setTimeout(() => { 21 | resolve(null); 22 | }, COMMENTS_DELAY); 23 | }) 24 | .then(() => fetch("https://jsonplaceholder.typicode.com/comments")) 25 | .then((res) => res.json()) 26 | .then((c) => { 27 | if (!timedOut) { 28 | comments = c; 29 | resolve(c.slice(0, 20)); 30 | } 31 | }) 32 | .catch((e) => { 33 | console.error(e); 34 | }); 35 | } catch (e) {} 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /pages-suspense/src/getUsersServer.ts: -------------------------------------------------------------------------------- 1 | import { User } from "./types"; 2 | 3 | import { USERS_DELAY, SSR_THRESHOLD } from "./constants"; 4 | 5 | export async function getUsersServer() { 6 | return new Promise((resolve) => { 7 | try { 8 | let users: User[] | null = null; 9 | let timedOut = false; 10 | 11 | setTimeout(() => { 12 | if (!users) { 13 | timedOut = true; 14 | resolve(null); 15 | } 16 | }, SSR_THRESHOLD); 17 | 18 | new Promise((resolve) => { 19 | setTimeout(() => { 20 | resolve(null); 21 | }, USERS_DELAY); 22 | }) 23 | .then(() => fetch("https://jsonplaceholder.typicode.com/users")) 24 | .then((res) => res.json()) 25 | .then((c) => { 26 | if (!timedOut) { 27 | users = c; 28 | resolve(c.slice(0, 20)); 29 | } 30 | }) 31 | .catch((e) => { 32 | console.error(e); 33 | }); 34 | } catch (e) {} 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "@/styles/globals.css"; 2 | import type { AppProps } from "next/app"; 3 | 4 | export default function App({ Component, pageProps }: AppProps) { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from "next/document"; 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/api/comments.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | import { Comment } from "@/types"; 4 | import { COMMENTS_DELAY } from "@/constants"; 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse 9 | ) { 10 | await new Promise((resolve) => setTimeout(resolve, COMMENTS_DELAY)); 11 | const creq = await fetch("https://jsonplaceholder.typicode.com/comments"); 12 | const comments = (await creq.json()) as Comment[]; 13 | 14 | res.status(200).json(comments.slice(0, 20)); 15 | } 16 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/api/users.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from "next"; 2 | 3 | import { User } from "@/types"; 4 | import { USERS_DELAY } from "@/constants"; 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse 9 | ) { 10 | await new Promise((resolve) => setTimeout(resolve, USERS_DELAY)); 11 | const ures = await fetch("https://jsonplaceholder.typicode.com/users"); 12 | const users = (await ures.json()) as User[]; 13 | 14 | res.status(200).json(users.slice(0, 20)); 15 | } 16 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Comment } from "@/types"; 3 | 4 | export default function Comments({ 5 | comments: initialComments, 6 | }: { 7 | comments: Comment[] | null; 8 | }) { 9 | const [comments, setComments] = useState(initialComments); 10 | 11 | useEffect(() => { 12 | async function fetchComments() { 13 | const res = await fetch("/api/comments"); 14 | const comments = (await res.json()) as Comment[]; 15 | setComments(comments); 16 | } 17 | if (!initialComments) { 18 | fetchComments(); 19 | } 20 | }, [initialComments]); 21 | 22 | if (!comments) return
Loading comments from client...
; 23 | 24 | return ( 25 |
26 |

Comments

27 |
28 | {(comments ?? []).map((comment) => ( 29 |
30 |
31 |

{comment.name}

32 |

{comment.body}

33 |
34 |
35 | ))} 36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/components/Users.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | import { User } from "@/types"; 4 | 5 | export default function Users({ 6 | users: initialUsers, 7 | }: { 8 | users: User[] | null; 9 | }) { 10 | const [users, setUsers] = useState(initialUsers); 11 | 12 | useEffect(() => { 13 | async function fetchUsers() { 14 | const res = await fetch("/api/users"); 15 | const users = (await res.json()) as User[]; 16 | setUsers(users); 17 | } 18 | if (!initialUsers) { 19 | fetchUsers(); 20 | } 21 | }, [initialUsers]); 22 | 23 | if (!users) return
Loading users from client...
; 24 | 25 | return ( 26 |
27 |

Users

28 |
29 | {(users ?? []).map((user) => ( 30 |
31 |
32 |

{user.name}

33 |

{user.phone}

34 |
35 |
36 | ))} 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { Comment } from "@/types"; 2 | import { getCommentsServer } from "@/getCommentsServer"; 3 | 4 | import Comments from "./components/Comments"; 5 | 6 | export async function getServerSideProps() { 7 | const comments = await getCommentsServer(); 8 | 9 | return { 10 | props: { 11 | comments, 12 | }, 13 | }; 14 | } 15 | 16 | export default function Home({ comments }: { comments: Comment[] | null }) { 17 | return ( 18 |
19 |

Home Page

20 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /pages-suspense/src/pages/users.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | import { getCommentsServer } from "@/getCommentsServer"; 4 | import { getUsersServer } from "@/getUsersServer"; 5 | 6 | import { Comment, User } from "@/types"; 7 | import { USERS_DELAY } from "@/constants"; 8 | 9 | import Comments from "./components/Comments"; 10 | import Users from "./components/Users"; 11 | 12 | export async function getServerSideProps() { 13 | const comments = await getCommentsServer(); 14 | const users = await getUsersServer(); 15 | 16 | return { 17 | props: { 18 | users, 19 | comments, 20 | }, 21 | }; 22 | } 23 | 24 | export default function Home({ 25 | users, 26 | comments, 27 | }: { 28 | comments: Comment[] | null; 29 | users: User[] | null; 30 | }) { 31 | return ( 32 |
33 |

Users Page

34 |
35 |
36 | 37 |
38 |
39 | 40 |
41 |
42 |
43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /pages-suspense/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pages-suspense/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Comment { 2 | id: number; 3 | name: string; 4 | body: string; 5 | } 6 | 7 | export interface User { 8 | id: number; 9 | name: string; 10 | phone: string; 11 | } 12 | -------------------------------------------------------------------------------- /pages-suspense/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | }, 17 | }, 18 | plugins: [require("@tailwindcss/container-queries")], 19 | }; 20 | export default config; 21 | -------------------------------------------------------------------------------- /pages-suspense/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "paths": { 16 | "@/*": ["./src/*"] 17 | } 18 | }, 19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 20 | "exclude": ["node_modules"] 21 | } 22 | --------------------------------------------------------------------------------