├── .env.example ├── .eslintrc.json ├── .gitignore ├── .nvmrc ├── README.md ├── README_ES.md ├── app ├── dashboard │ ├── (overview) │ │ ├── loading.tsx │ │ └── page.tsx │ ├── customers │ │ └── page.tsx │ ├── invoices │ │ ├── [id] │ │ │ └── edit │ │ │ │ ├── not-found.tsx │ │ │ │ └── page.tsx │ │ ├── create │ │ │ └── page.tsx │ │ ├── error.tsx │ │ └── page.tsx │ └── layout.tsx ├── favicon.ico ├── layout.tsx ├── lib │ ├── actions.ts │ ├── data.ts │ ├── definitions.ts │ ├── placeholder-data.js │ └── utils.ts ├── login │ └── page.tsx ├── opengraph-image.png ├── page.tsx └── ui │ ├── acme-logo.tsx │ ├── button.tsx │ ├── customers │ └── table.tsx │ ├── dashboard │ ├── cards.tsx │ ├── latest-invoices.tsx │ ├── nav-links.tsx │ ├── revenue-chart.tsx │ └── sidenav.tsx │ ├── fonts.ts │ ├── global.css │ ├── home.module.css │ ├── invoices │ ├── breadcrumbs.tsx │ ├── buttons.tsx │ ├── create-form.tsx │ ├── edit-form.tsx │ ├── pagination.tsx │ ├── status.tsx │ └── table.tsx │ ├── login-form.tsx │ ├── search.tsx │ └── skeletons.tsx ├── auth.config.ts ├── auth.ts ├── middleware.ts ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── customers │ ├── amy-burns.png │ ├── balazs-orban.png │ ├── delba-de-oliveira.png │ ├── emil-kowalski.png │ ├── evil-rabbit.png │ ├── guillermo-rauch.png │ ├── hector-simpson.png │ ├── jared-palmer.png │ ├── lee-robinson.png │ ├── michael-novotny.png │ ├── steph-dietz.png │ └── steven-tey.png ├── hero-desktop.png └── hero-mobile.png ├── scripts └── seed.js ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Copy from .env.local on the Vercel dashboard 2 | # https://nextjs.org/learn/dashboard-app/setting-up-your-database#create-a-postgres-database 3 | POSTGRES_URL= 4 | POSTGRES_PRISMA_URL= 5 | POSTGRES_URL_NON_POOLING= 6 | POSTGRES_USER= 7 | POSTGRES_HOST= 8 | POSTGRES_PASSWORD= 9 | POSTGRES_DATABASE= 10 | 11 | # `openssl rand -base64 32` 12 | AUTH_SECRET= 13 | AUTH_URL=http://localhost:3000/api/auth -------------------------------------------------------------------------------- /.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 | 27 | # local env files 28 | .env*.local 29 | .env 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Acme dashboard full web application. 2 | 3 |  4 | 5 | ## Next.js App Router Course - Starter 6 | 7 | This is the starter template for the Next.js App Router Course. It contains the starting code for the dashboard application. 8 | 9 | For more information, see the [course curriculum](https://nextjs.org/learn) on the Next.js Website. 10 | 11 | ## Creating a new project 12 | 13 | ```bash 14 | npx create-next-app@latest nextjs-dashboard --use-npm --example "https:// 15 | github.com/vercel/next-learn/tree/main/dashboard/starter-example" 16 | 17 | ``` 18 | 19 | This command uses create-next-app, a Command Line Interface (CLI) tool that sets up a Next.js application for you. In the command above, you're also using the --example flag with the starter example for this course. 20 | 21 | ## Folder structure 22 | 23 | **/app:** Contains all the routes, components, and logic for your application, this is where you'll be mostly working from. 24 | **/app/lib:** Contains functions used in your application, such as reusable utility functions and data fetching functions. 25 | **/app/ui:** Contains all the UI components for your application, such as cards, tables, and forms. To save time, we've pre-styled these components for you. 26 | **/public:** Contains all the static assets for your application, such as images. 27 | **/scripts/:** Contains a file that you'll use to populate your database in a later chapter. 28 | 29 | Config Files: You'll also notice config files such as next.config.js at the root of your application. Most of these files are created and pre-configured when you start a new project using create-next-app. 30 | 31 | **app/lib/placeholder-data.js:** Each JavaScript object in the file represents a table in your database. For example, for the invoices table: 32 | 33 | **/app/lib/definitions.ts:** Here, we manually define the types that will be returned from the database. 34 | 35 | By using **TypeScript**, you can ensure you don't accidentally pass the wrong data format to your components or database, like passing a string to amount instead of a number. 36 | 37 | ### If you're a TypeScript developer: 38 | 39 | - Next.js detects if your project uses TypeScript and automatically installs the necessary packages and configuration. Next.js also comes with a TypeScript plugin for your code editor, to help with auto-completion and type-safety. 40 | 41 | - We're manually declaring the data types, but for better type-safety, we recommend tools like Prisma, which automatically generates types based on your database schema. 42 | 43 | ## Running the development server 44 | 45 | Run npm i or npm install to install the project's packages. 46 | 47 | ```bash 48 | npm install 49 | ``` 50 | 51 | Followed by npm run dev to start the development server. 52 | 53 | ```bash 54 | npm run dev 55 | ``` 56 | 57 | ```npm run dev``` starts your Next.js development server on port 3000. Let's check to see if it's working. Open http://localhost:3000 on your browser. 58 | 59 | ## CSS Styling 60 | 61 | In this chapter... 62 | 63 | Here are the topics we’ll cover 64 | 65 | - How to add a global CSS file to your application. 66 | 67 | - Two different ways of styling: Tailwind and CSS modules. 68 | 69 | - How to conditionally add class names with the clsx utility package. 70 | 71 | ### Global styles 72 | 73 | **/app/ui:** If you look inside folder, you'll see a file called global.css. You can use this file to add CSS rules to all the routes in your application - such as CSS reset rules, site-wide styles for HTML elements like links, and more. 74 | 75 | You can import global.css in any component in your application, but it's usually good practice to add it to your top-level component. In Next.js, this is the root layout (more on this later). 76 | 77 | > **/app/layout.tsx** 78 | ```TypeScript 79 | import '@/app/ui/global.css'; 80 | ``` 81 | 82 | If you take a look inside global.css, you'll notice some @tailwind directives. 83 | 84 | ```css 85 | @tailwind base; 86 | @tailwind components; 87 | @tailwind utilities; 88 | ``` 89 | 90 | ### Tailwind 91 | 92 | Tailwind is a CSS framework that speeds up the development process by allowing you to quickly write utility classes directly in your JSX markup. The CSS styles are shared globally, but each utility is singularly focused and applied to each individual element. This means you don't have to worry about style collisions, maintaining separate stylesheets, or your CSS bundle size growing as your application grows. 93 | 94 | When you use create-next-app to start a new project, Next.js will ask if you want to use Tailwind. If you select yes, it will automatically install the necessary packages and configure Tailwind in your application. 95 | 96 | If you look at /app/page.tsx, you'll see that we're using Tailwind classes in the example. 97 | 98 | ```tsx 99 |
100 | ``` 101 | 102 | ### CSS Modules 103 | 104 | If you prefer writing traditional CSS rules or keeping your styles separate from your JSX, CSS Modules are a great alternative. 105 | 106 | CSS Modules allow you to scope CSS to a component by automatically creating unique class names, so you don't have to worry about name collisions. 107 | 108 | Here's how you could create the same shape from the quiz above using CSS modules. 109 | 110 | > **app/ui/home.module.css** 111 | ```css 112 | .shape { 113 | height: 0; 114 | width: 0; 115 | border-bottom: 30px solid black; 116 | border-left: 20px solid transparent; 117 | border-right: 20px solid transparent; 118 | } 119 | ``` 120 | 121 | > Provide a way to make CSS classes locally scoped to components by default, enabling better modularity and reducing the risk of styling conflicts. 122 | 123 | ### Library clsx 124 | 125 | There may be cases where you may need to conditionally style an element based on state or some other condition. 126 | 127 | - Suppose that you want to create an InvoiceStatus component which accepts status. The status can be 'pending' or 'paid'. 128 | - If it's 'paid', you want the color to be green. If it's 'pending', you want the color to be gray. 129 | 130 | You can use clsx to conditionally apply the classes, like this: 131 | 132 | ```tsx 133 | import clsx from 'clsx'; 134 | 135 | export default function InvoiceStatus({ status }: { status: string }) { 136 | return ( 137 | 146 | // ... 147 | )} 148 | ``` 149 | 150 | ## Optimizing Fonts and Images 151 | 152 | In the previous chapter, you learned how to style your Next.js application. Let's continue working on your home page by adding a custom font and a hero image. 153 | 154 | In this chapter... 155 | 156 | Here are the topics we’ll cover 157 | 158 | - ✏️ How to add custom fonts with next/font. 159 | 160 | - 🛣️ How to add images with next/image. 161 | 162 | - ✅ How fonts and images are optimized in Next.js. 163 | 164 | 165 | ### Why optimize fonts? 166 | 167 | Fonts play a significant role in the design of a website, but using custom fonts in your project can affect performance if the font files need to be fetched and loaded. 168 | 169 | Cumulative Layout Shift is a metric used by Google to evaluate the performance and user experience of a website. With fonts, layout shift happens when the browser initially renders text in a fallback or system font and then swaps it out for a custom font once it has loaded. This swap can cause the text size, spacing, or layout to change, shifting elements around it. 170 | 171 |  172 | 173 | Next.js automatically optimizes fonts in the application when you use the next/font module. It does so by downloading font files at build time and hosting them with your other static assets. This means when a user visits your application, there are no additional network requests for fonts which would impact performance. 174 | 175 | ### Adding a primary font 176 | 177 | In your /app/ui folder, create a new file called fonts.ts. You'll use this file to keep the fonts that will be used throughout your application. 178 | 179 | Import the Inter font from the next/font/google module - this will be your primary font. 180 | Then, specify what subset you'd like to load. In this case, 'latin': 181 | 182 | ```tsx 183 | import { Inter } from 'next/font/google'; 184 | 185 | export const inter = Inter({ subsets: ['latin'] }); 186 | ``` 187 | 188 | Finally, add the font to the element in /app/layout.tsx 189 | 190 | By adding Inter to the element, the font will be applied throughout your application. Here, you're also adding the Tailwind antialiased class which smooths out the font. It's not necessary to use this class, but it adds a nice touch to your fonts. 191 | 192 | ```css 193 | .antialiased { 194 | -webkit-font-smoothing: antialiased; 195 | -moz-osx-font-smoothing: grayscale; 196 | } 197 | ``` 198 | 199 | ```tsx 200 | {children} 201 | ``` 202 | 203 | > You can also add fonts to specific elements of your application. 204 | 205 | --- 206 | 207 | ### Why optimize images? 208 | 209 | Next.js can serve static assets, like images, under the top-level /public folder. Files inside /public can be referenced in your application. 210 | 211 | If you look inside the folder, you'll see there's are two images: hero-desktop.png and hero-mobile.png. These two images are completely different, and they'll be shown depending on the user's device is a desktop or mobile. 212 | 213 | With regular HTML, you would add an image as follows: 214 | 215 | ```tsx 216 |Dashboard Page
; 322 | } 323 | ``` 324 | Now, make sure that the development server is running and visit http://localhost:3000/dashboard. 325 | 326 | Let's practice creating more routes. In your dashboard, create two more pages: 327 | 328 | - Customers Page: The page should be accessible on http://localhost:3000/dashboard/customers. For now, it should return a \Customers Page\
element. 329 | 330 | - Invoices Page: The invoices page should be accessible on http://localhost:3000/dashboard/invoices. For now, also return a \Invoices Page\
element. 331 | 332 | You should have the following folder structure: 333 | 334 |  335 | 336 | 337 | ### Creating the dashboard layout 338 | 339 | Dashboards also have some sort of navigation that is shared across multiple pages. In Next.js, you can use a special layout.tsx file to create UI that is shared between multiple pages. Let's create a layout for the dashboard! 340 | 341 | Inside the /dashboard folder, add a new file called layout.tsx and paste the following code: 342 | 343 | ```tsx 344 | import SideNav from '@/app/ui/dashboard/sidenav'; 345 | 346 | export default function Layout({ children }: { children: React.ReactNode }) { 347 | return ( 348 |