├── app ├── favicon.ico ├── posts │ ├── [postId] │ │ ├── loading.js │ │ └── page.js │ └── page.js ├── articles │ ├── featuredArticles │ │ └── page.js │ ├── [title] │ │ └── page.js │ ├── page.js │ └── layout.js ├── page.js ├── components │ ├── todo.jsx │ └── postDetails.jsx ├── layout.js ├── globals.css └── page.module.css ├── jsconfig.json ├── next.config.js ├── package.json ├── .gitignore ├── public ├── vercel.svg └── next.svg ├── README.md └── .vscode └── settings.json /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yarob50/nextjs-app-demo/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /app/posts/[postId]/loading.js: -------------------------------------------------------------------------------- 1 | export default function LoadingPostDetails() { 2 | return ( 3 |
4 |

Loading 👌🏻

5 |
6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /app/articles/featuredArticles/page.js: -------------------------------------------------------------------------------- 1 | const FeaturedArticlesPage = () => { 2 | return ( 3 |
4 |

Featured Articles

5 |
6 | ); 7 | }; 8 | 9 | export default FeaturedArticlesPage; 10 | -------------------------------------------------------------------------------- /app/articles/[title]/page.js: -------------------------------------------------------------------------------- 1 | export default function ShowArticlePage(props) { 2 | console.log(props); 3 | return ( 4 |
5 |

Show Article

6 |

{props.params.title}

7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /app/page.js: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import styles from "./page.module.css"; 3 | 4 | export default function Home() { 5 | return ( 6 |
7 |

Hello World

8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /app/articles/page.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function ArticlesPage() { 4 | return ( 5 |
6 |

Articles Page

7 | 8 | 9 | 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "next": "13.4.8", 13 | "react": "18.2.0", 14 | "react-dom": "18.2.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/articles/layout.js: -------------------------------------------------------------------------------- 1 | export const metadata = { 2 | title: "articles page", 3 | }; 4 | 5 | export default function ({ children }) { 6 | return ( 7 |
8 |

Articles

9 | 10 |
18 | {children} 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /app/components/todo.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState, useEffect } from "react"; 4 | 5 | export default function Todo() { 6 | const [todo, setTodo] = useState({}); 7 | 8 | useEffect(async () => { 9 | const response = await fetch( 10 | "https://jsonplaceholder.typicode.com/todos/1" 11 | ); 12 | const result = await response.json(); 13 | setTodo(result); 14 | }, []); 15 | 16 | return ( 17 |
18 |

{todo.title}

19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /app/posts/[postId]/page.js: -------------------------------------------------------------------------------- 1 | import PostDetails from "@/app/components/postDetails"; 2 | import { Suspense } from "react"; 3 | export default async function PostDetailsPage({ params }) { 4 | const postId = params.postId; 5 | 6 | const loaingJsx = ( 7 |
8 |

wait...

9 |
10 | ); 11 | return ( 12 |
13 |

Post Details

14 | 15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /.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 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/postDetails.jsx: -------------------------------------------------------------------------------- 1 | export default async function PostDetails({ postId }) { 2 | await new Promise((resolve) => { 3 | setTimeout(() => { 4 | resolve(); 5 | }, 2000); 6 | }); 7 | const response = await fetch( 8 | `https://jsonplaceholder.typicode.com/posts/${postId}`, 9 | { 10 | next: { 11 | revalidate: 120, 12 | }, 13 | } 14 | ); 15 | const post = await response.json(); 16 | 17 | return ( 18 |
19 |
29 |

{post.title}

30 | 31 |
32 | 33 |

{post.body}

34 |
35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /app/layout.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import "./globals.css"; 3 | import { Inter } from "next/font/google"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ children }) { 13 | return ( 14 | 15 | 16 | 36 | {children} 37 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /app/posts/page.js: -------------------------------------------------------------------------------- 1 | import Todo from "../components/todo"; 2 | 3 | import Link from "next/link"; 4 | 5 | export default async function PostsPage() { 6 | const response = await fetch("https://jsonplaceholder.typicode.com/posts", { 7 | next: { 8 | revalidate: 120, 9 | }, 10 | }); 11 | const posts = await response.json(); 12 | 13 | const postsJSX = posts.map((post) => { 14 | return ( 15 | 21 |
31 |

{post.title}

32 |

{post.body}

33 |
34 | 35 | ); 36 | }); 37 | 38 | console.log(posts); 39 | 40 | return ( 41 |
42 |

Posts Page

43 | 44 | {/* POSTS */} 45 |
53 | {postsJSX} 54 |
55 | {/*=== POSTS ==*/} 56 | 57 | {/*
58 | 59 |
*/} 60 |
61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /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 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 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 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "[Material Theme Lighter High Contrast]": { 4 | "settings.headerForeground": "#C6FF00", 5 | "menu.selectionForeground": "#C6FF00", 6 | "textLink.foreground": "#C6FF00", 7 | "menubar.selectionForeground": "#C6FF00", 8 | "pickerGroup.foreground": "#C6FF00", 9 | "editorSuggestWidget.highlightForeground": "#C6FF00", 10 | "scrollbarSlider.activeBackground": "#C6FF0050", 11 | "progressBar.background": "#C6FF00", 12 | "notificationLink.foreground": "#C6FF00", 13 | "panelTitle.activeBorder": "#C6FF00", 14 | "breadcrumb.activeSelectionForeground": "#C6FF00", 15 | "settings.modifiedItemIndicator": "#C6FF00", 16 | "list.highlightForeground": "#C6FF00", 17 | "list.activeSelectionForeground": "#C6FF00", 18 | "editor.findMatchBorder": "#C6FF00", 19 | "list.inactiveSelectionForeground": "#0f100f", 20 | "editorWidget.resizeBorder": "#C6FF00", 21 | "activityBarBadge.background": "#C6FF00", 22 | "selection.background": "#C6FF0040", 23 | "editorWidget.border": "#C6FF00", 24 | "statusBarItem.remoteBackground": "#C6FF00", 25 | "activityBar.activeBorder": "#C6FF00", 26 | "tab.activeBorder": "#C6FF00" 27 | }, 28 | "activityBar.background": "#4C2118", 29 | "titleBar.activeBackground": "#6A2E22", 30 | "titleBar.activeForeground": "#FDF9F8" 31 | } 32 | } -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --max-width: 1100px; 3 | --border-radius: 12px; 4 | --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", 5 | "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", 6 | "Fira Mono", "Droid Sans Mono", "Courier New", monospace; 7 | 8 | --foreground-rgb: 0, 0, 0; 9 | --background-start-rgb: 214, 219, 220; 10 | --background-end-rgb: 255, 255, 255; 11 | 12 | --primary-glow: conic-gradient( 13 | from 180deg at 50% 50%, 14 | #16abff33 0deg, 15 | #0885ff33 55deg, 16 | #54d6ff33 120deg, 17 | #0071ff33 160deg, 18 | transparent 360deg 19 | ); 20 | --secondary-glow: radial-gradient( 21 | rgba(255, 255, 255, 1), 22 | rgba(255, 255, 255, 0) 23 | ); 24 | 25 | --tile-start-rgb: 239, 245, 249; 26 | --tile-end-rgb: 228, 232, 233; 27 | --tile-border: conic-gradient( 28 | #00000080, 29 | #00000040, 30 | #00000030, 31 | #00000020, 32 | #00000010, 33 | #00000010, 34 | #00000080 35 | ); 36 | 37 | --callout-rgb: 238, 240, 241; 38 | --callout-border-rgb: 172, 175, 176; 39 | --card-rgb: 180, 185, 188; 40 | --card-border-rgb: 131, 134, 135; 41 | } 42 | 43 | @media (prefers-color-scheme: dark) { 44 | :root { 45 | --foreground-rgb: 255, 255, 255; 46 | --background-start-rgb: 0, 0, 0; 47 | --background-end-rgb: 0, 0, 0; 48 | 49 | --primary-glow: radial-gradient( 50 | rgba(1, 65, 255, 0.4), 51 | rgba(1, 65, 255, 0) 52 | ); 53 | --secondary-glow: linear-gradient( 54 | to bottom right, 55 | rgba(1, 65, 255, 0), 56 | rgba(1, 65, 255, 0), 57 | rgba(1, 65, 255, 0.3) 58 | ); 59 | 60 | --tile-start-rgb: 2, 13, 46; 61 | --tile-end-rgb: 2, 5, 19; 62 | --tile-border: conic-gradient( 63 | #ffffff80, 64 | #ffffff40, 65 | #ffffff30, 66 | #ffffff20, 67 | #ffffff10, 68 | #ffffff10, 69 | #ffffff80 70 | ); 71 | 72 | --callout-rgb: 20, 20, 20; 73 | --callout-border-rgb: 108, 108, 108; 74 | --card-rgb: 100, 100, 100; 75 | --card-border-rgb: 200, 200, 200; 76 | } 77 | } 78 | 79 | * { 80 | box-sizing: border-box; 81 | padding: 0; 82 | margin: 0; 83 | } 84 | 85 | html, 86 | body { 87 | max-width: 100vw; 88 | overflow-x: hidden; 89 | } 90 | 91 | body { 92 | color: rgb(var(--foreground-rgb)); 93 | background: linear-gradient( 94 | to bottom, 95 | transparent, 96 | rgb(var(--background-end-rgb)) 97 | ) 98 | rgb(var(--background-start-rgb)); 99 | } 100 | 101 | a { 102 | color: inherit; 103 | text-decoration: none; 104 | } 105 | 106 | @media (prefers-color-scheme: dark) { 107 | html { 108 | color-scheme: dark; 109 | } 110 | } 111 | 112 | .main-div { 113 | background: rgb(59, 0, 59); 114 | height: 100vh; 115 | } 116 | -------------------------------------------------------------------------------- /app/page.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: space-between; 5 | align-items: center; 6 | padding: 6rem; 7 | min-height: 100vh; 8 | } 9 | 10 | .description { 11 | display: inherit; 12 | justify-content: inherit; 13 | align-items: inherit; 14 | font-size: 0.85rem; 15 | max-width: var(--max-width); 16 | width: 100%; 17 | z-index: 2; 18 | font-family: var(--font-mono); 19 | } 20 | 21 | .description a { 22 | display: flex; 23 | justify-content: center; 24 | align-items: center; 25 | gap: 0.5rem; 26 | } 27 | 28 | .description p { 29 | position: relative; 30 | margin: 0; 31 | padding: 1rem; 32 | background-color: rgba(var(--callout-rgb), 0.5); 33 | border: 1px solid rgba(var(--callout-border-rgb), 0.3); 34 | border-radius: var(--border-radius); 35 | } 36 | 37 | .code { 38 | font-weight: 700; 39 | font-family: var(--font-mono); 40 | } 41 | 42 | .grid { 43 | display: grid; 44 | grid-template-columns: repeat(4, minmax(25%, auto)); 45 | width: var(--max-width); 46 | max-width: 100%; 47 | } 48 | 49 | .card { 50 | padding: 1rem 1.2rem; 51 | border-radius: var(--border-radius); 52 | background: rgba(var(--card-rgb), 0); 53 | border: 1px solid rgba(var(--card-border-rgb), 0); 54 | transition: background 200ms, border 200ms; 55 | } 56 | 57 | .card span { 58 | display: inline-block; 59 | transition: transform 200ms; 60 | } 61 | 62 | .card h2 { 63 | font-weight: 600; 64 | margin-bottom: 0.7rem; 65 | } 66 | 67 | .card p { 68 | margin: 0; 69 | opacity: 0.6; 70 | font-size: 0.9rem; 71 | line-height: 1.5; 72 | max-width: 30ch; 73 | } 74 | 75 | .center { 76 | display: flex; 77 | justify-content: center; 78 | align-items: center; 79 | position: relative; 80 | padding: 4rem 0; 81 | } 82 | 83 | .center::before { 84 | background: var(--secondary-glow); 85 | border-radius: 50%; 86 | width: 480px; 87 | height: 360px; 88 | margin-left: -400px; 89 | } 90 | 91 | .center::after { 92 | background: var(--primary-glow); 93 | width: 240px; 94 | height: 180px; 95 | z-index: -1; 96 | } 97 | 98 | .center::before, 99 | .center::after { 100 | content: ''; 101 | left: 50%; 102 | position: absolute; 103 | filter: blur(45px); 104 | transform: translateZ(0); 105 | } 106 | 107 | .logo { 108 | position: relative; 109 | } 110 | /* Enable hover only on non-touch devices */ 111 | @media (hover: hover) and (pointer: fine) { 112 | .card:hover { 113 | background: rgba(var(--card-rgb), 0.1); 114 | border: 1px solid rgba(var(--card-border-rgb), 0.15); 115 | } 116 | 117 | .card:hover span { 118 | transform: translateX(4px); 119 | } 120 | } 121 | 122 | @media (prefers-reduced-motion) { 123 | .card:hover span { 124 | transform: none; 125 | } 126 | } 127 | 128 | /* Mobile */ 129 | @media (max-width: 700px) { 130 | .content { 131 | padding: 4rem; 132 | } 133 | 134 | .grid { 135 | grid-template-columns: 1fr; 136 | margin-bottom: 120px; 137 | max-width: 320px; 138 | text-align: center; 139 | } 140 | 141 | .card { 142 | padding: 1rem 2.5rem; 143 | } 144 | 145 | .card h2 { 146 | margin-bottom: 0.5rem; 147 | } 148 | 149 | .center { 150 | padding: 8rem 0 6rem; 151 | } 152 | 153 | .center::before { 154 | transform: none; 155 | height: 300px; 156 | } 157 | 158 | .description { 159 | font-size: 0.8rem; 160 | } 161 | 162 | .description a { 163 | padding: 1rem; 164 | } 165 | 166 | .description p, 167 | .description div { 168 | display: flex; 169 | justify-content: center; 170 | position: fixed; 171 | width: 100%; 172 | } 173 | 174 | .description p { 175 | align-items: center; 176 | inset: 0 0 auto; 177 | padding: 2rem 1rem 1.4rem; 178 | border-radius: 0; 179 | border: none; 180 | border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); 181 | background: linear-gradient( 182 | to bottom, 183 | rgba(var(--background-start-rgb), 1), 184 | rgba(var(--callout-rgb), 0.5) 185 | ); 186 | background-clip: padding-box; 187 | backdrop-filter: blur(24px); 188 | } 189 | 190 | .description div { 191 | align-items: flex-end; 192 | pointer-events: none; 193 | inset: auto 0 0; 194 | padding: 2rem; 195 | height: 200px; 196 | background: linear-gradient( 197 | to bottom, 198 | transparent 0%, 199 | rgb(var(--background-end-rgb)) 40% 200 | ); 201 | z-index: 1; 202 | } 203 | } 204 | 205 | /* Tablet and Smaller Desktop */ 206 | @media (min-width: 701px) and (max-width: 1120px) { 207 | .grid { 208 | grid-template-columns: repeat(2, 50%); 209 | } 210 | } 211 | 212 | @media (prefers-color-scheme: dark) { 213 | .vercelLogo { 214 | filter: invert(1); 215 | } 216 | 217 | .logo { 218 | filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); 219 | } 220 | } 221 | 222 | @keyframes rotate { 223 | from { 224 | transform: rotate(360deg); 225 | } 226 | to { 227 | transform: rotate(0deg); 228 | } 229 | } 230 | --------------------------------------------------------------------------------