├── .env ├── .eslintrc.json ├── .gitignore ├── README.md ├── app ├── globals.css ├── issues │ ├── IssueList.js │ ├── [issueId] │ │ ├── IssueDetails.js │ │ ├── IssueDetails.module.css │ │ ├── error.js │ │ ├── loading.js │ │ └── page.js │ ├── layout.js │ ├── layout.module.css │ └── page.js ├── layout.js └── page.js ├── components └── ui │ ├── MainNavigation.js │ └── MainNavigation.module.css ├── next.config.js ├── package-lock.json ├── package.json ├── prisma ├── demo.db ├── schema.prisma └── seed.js ├── public ├── favicon.ico └── vercel.svg └── util └── time.js /.env: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="file:./demo.db" -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 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 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 16 | 17 | [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`. 18 | 19 | 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. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | 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. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html { 6 | font-family: sans-serif; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | background-color: #f5edfb; 12 | color: #2e2931; 13 | } 14 | 15 | ul { 16 | list-style: none; 17 | padding: 0; 18 | margin: 0; 19 | } 20 | 21 | .center { 22 | text-align: center; 23 | } -------------------------------------------------------------------------------- /app/issues/IssueList.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | function IssuesList({ issues }) { 4 | return ( 5 | 18 | ); 19 | } 20 | 21 | export default IssuesList; 22 | -------------------------------------------------------------------------------- /app/issues/[issueId]/IssueDetails.js: -------------------------------------------------------------------------------- 1 | import classes from './IssueDetails.module.css'; 2 | 3 | function IssueDetails({ issue }) { 4 | return ( 5 |
6 |
7 |

{issue.title}

8 |

{issue.summary}

9 |
10 |

{issue.description}

11 |
12 | ); 13 | } 14 | 15 | export default IssueDetails; 16 | -------------------------------------------------------------------------------- /app/issues/[issueId]/IssueDetails.module.css: -------------------------------------------------------------------------------- 1 | .details { 2 | background-color: #b7b3bb; 3 | padding: 3rem; 4 | height: 100vh; 5 | } -------------------------------------------------------------------------------- /app/issues/[issueId]/error.js: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | function IssueErrorPage({error}) { 4 | return

{error.message}

5 | } 6 | 7 | export default IssueErrorPage; -------------------------------------------------------------------------------- /app/issues/[issueId]/loading.js: -------------------------------------------------------------------------------- 1 | function IssuesLoading() { 2 | return

Loading issues data...

3 | } 4 | 5 | export default IssuesLoading; -------------------------------------------------------------------------------- /app/issues/[issueId]/page.js: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | import { wait } from '../../../util/time'; 3 | 4 | import IssueDetails from './IssueDetails'; 5 | 6 | async function IssueDetailsPage({ params }) { 7 | const prisma = new PrismaClient(); 8 | const issue = await prisma.issue.findFirst({ where: { id: +params.issueId } }); 9 | // await wait(3); 10 | if (!issue) { 11 | throw new Error('Issue not found!') 12 | } 13 | 14 | return ; 15 | } 16 | 17 | export default IssueDetailsPage; 18 | -------------------------------------------------------------------------------- /app/issues/layout.js: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | 3 | import IssuesList from './IssueList'; 4 | import classes from './layout.module.css'; 5 | 6 | async function IssuesLayout({ children }) { 7 | const prisma = new PrismaClient(); 8 | const issues = await prisma.issue.findMany(); 9 | 10 | return ( 11 |
12 | 15 | {children} 16 |
17 | ); 18 | } 19 | 20 | export default IssuesLayout; 21 | -------------------------------------------------------------------------------- /app/issues/layout.module.css: -------------------------------------------------------------------------------- 1 | .layout { 2 | display: grid; 3 | grid-template-columns: 25% 75%; 4 | } 5 | 6 | .sidebar { 7 | height: 100vh; 8 | padding: 0 2rem; 9 | background-color: #29252e; 10 | } 11 | 12 | .sidebar ul { 13 | display: flex; 14 | flex-direction: column; 15 | } 16 | 17 | .sidebar li { 18 | padding: 1rem; 19 | border-bottom: 2px solid #46404c; 20 | color: white; 21 | } 22 | 23 | .sidebar a { 24 | color: #cda7fa; 25 | text-decoration: none; 26 | } 27 | 28 | .sidebar a:hover { 29 | color: #b47df7; 30 | } -------------------------------------------------------------------------------- /app/issues/page.js: -------------------------------------------------------------------------------- 1 | export default function IssuesPage() { 2 | return ( 3 |

Please select an issue

4 | ) 5 | } -------------------------------------------------------------------------------- /app/layout.js: -------------------------------------------------------------------------------- 1 | import './globals.css'; 2 | import MainNavigation from '../components/ui/MainNavigation'; 3 | 4 | export default function RootLayout({ children }) { 5 | return ( 6 | 7 | 8 | Create Next App 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 |
{children}
17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /app/page.js: -------------------------------------------------------------------------------- 1 | export default function Home() { 2 | return ( 3 |

The Starting Page

4 | ) 5 | } 6 | -------------------------------------------------------------------------------- /components/ui/MainNavigation.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import classes from './MainNavigation.module.css'; 4 | 5 | function MainNavigation() { 6 | return ( 7 | 17 | ); 18 | } 19 | 20 | export default MainNavigation; 21 | -------------------------------------------------------------------------------- /components/ui/MainNavigation.module.css: -------------------------------------------------------------------------------- 1 | .nav { 2 | display: flex; 3 | justify-content: center; 4 | padding: 3rem 0; 5 | background-color: #430672; 6 | } 7 | 8 | .nav ul { 9 | display: flex; 10 | gap: 2rem; 11 | } 12 | 13 | .nav a { 14 | text-decoration: none; 15 | color: white; 16 | } 17 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | experimental: { 4 | appDir: true, 5 | }, 6 | } 7 | 8 | module.exports = nextConfig 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-13-demo", 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 | "@prisma/client": "^4.3.1", 13 | "next": "13.0.0", 14 | "react": "18.2.0", 15 | "react-dom": "18.2.0" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "18.11.7", 19 | "@types/react": "18.0.23", 20 | "@types/react-dom": "18.0.7", 21 | "eslint": "8.26.0", 22 | "eslint-config-next": "13.0.0", 23 | "prisma": "^4.3.1", 24 | "typescript": "4.8.4" 25 | }, 26 | "prisma": { 27 | "seed": "node prisma/seed.js" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /prisma/demo.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/academind/nextjs-13-first-look-demo/696b3b17e899acee05f957409241b41e78e70b21/prisma/demo.db -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "sqlite" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model Issue { 14 | id Int @id @default(autoincrement()) 15 | title String 16 | summary String 17 | description String 18 | } 19 | -------------------------------------------------------------------------------- /prisma/seed.js: -------------------------------------------------------------------------------- 1 | const { PrismaClient } = require('@prisma/client'); 2 | 3 | async function seed() { 4 | const prisma = new PrismaClient(); 5 | await prisma.issue.deleteMany(); 6 | await prisma.issue.create({ 7 | data: { 8 | title: 'NextJS 12 Limitations', 9 | summary: 10 | "NextJS is great but in certain scenarios, it's capabilities are limited", 11 | description: 12 | 'NextJS currently still has some limitations. For example, when working with nested layouts, cumbersome, non-efficient solutions must be used in many cases.', 13 | }, 14 | }); 15 | await prisma.issue.create({ 16 | data: { 17 | title: 'Some other issue', 18 | summary: 'This is a totally different issue!', 19 | description: 'The content here is very different', 20 | }, 21 | }); 22 | } 23 | 24 | seed(); 25 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/academind/nextjs-13-first-look-demo/696b3b17e899acee05f957409241b41e78e70b21/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /util/time.js: -------------------------------------------------------------------------------- 1 | export function wait(seconds) { 2 | return new Promise((resolve, reject) => 3 | setTimeout(() => resolve(), seconds * 1000) 4 | ); 5 | } 6 | --------------------------------------------------------------------------------