Skip to content

NextJS Full-Stack Template: Developer Notes - #1

Open
wildky wants to merge 8 commits into
reviewfrom
project
Open

wildky wants to merge 8 commits into
reviewfrom
project

Conversation

@wildky

@wildky wildky commented Jul 31, 2024

Copy link
Copy Markdown
Contributor

This is a simple NextJS full stack app demo using the app router, illustrating some best practices and integrations with helpful tools, including Prisma, MUI, and Clerk.

Live demo: https://list-app-nine.vercel.app/

This PR reviews the entire code base so I can highlight noteworthy decisions and bits of code across the entire demo application. Enjoy!

Some things covered here:

  • Best practices with NextJS app router (project scaffolding, RSC, server actions with form data, use client directive, etc.)
  • Separation of concerns: core business logic (/src/lib/models) separated from things like UI form parsing and cache revalidation (src/app/actions.ts)
  • Setting up and using MUI (app layout, theming)
  • Setting up and using Prisma (schema, migrations, and prisma client usage)
  • Setting up and using Clerk auth (middleware, app layout, protected routes, getting authenticated user data and using it for authorization checks, using built in components, etc.)
  • Prettier configuration with NextJS eslint
  • Zod validation

@vercel

vercel Bot commented Jul 31, 2024

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
list-app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 31, 2024 1:12am

@wildky wildky left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline comments to highlight noteworthy bits of code!

Comment thread .eslintrc.json
@@ -0,0 +1,3 @@
{
"extends": ["next/core-web-vitals", "prettier"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This small change allows you to use prettier with nextjs pre-configured eslinting

Comment thread .prettierrc.json
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"plugins": ["prettier-plugin-organize-imports"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this prettier plugin with all of my projects - it keeps files nice and tidy

Comment thread package.json
"private": true,
"scripts": {
"dev": "next dev",
"build": "prisma generate && prisma migrate deploy && next build",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running prisma generate and prisma migrate deploy keeps the prisma client and database schema up to date.

In a production application with a more complex dev cycle, you may not want to include prisma migrate deploy as part of the build process, but I find it works well when just starting small projects.

Comment thread prisma/schema.prisma
updatedAt DateTime @updatedAt
authorId String

@@index([authorId])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Clerk is being used to manage our users, we don't need a User table in our database. However, we still want to query items based on their relationship to the user, so we should add an index on the relationship keys to make sure these queries remain performant.

Comment thread src/app/actions.ts
import { getCurrentAuthUser } from '@/lib/models/user'
import { revalidatePath } from 'next/cache'

export const addItemAction = async (formData: FormData): Promise<void> => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can put all of our server actions here. If we create many of them, we may want to break them down into finer categories (similar to how the /lib/models directory is organized)

Comment thread src/lib/utils.ts
@@ -0,0 +1,9 @@
export const pluralize = (count: number, singular: string, plural: string): string => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little utility function for pluralizing a word in UI that I use in all of my projects

Comment thread src/lib/utils.ts
return count === 1 ? singular : plural
}

export const formatErrorMessage = (error: unknown) => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little utility function for rendering error message in the UI so you don't need to write this logic again and again when we are checking errors returned from the server.

Comment thread src/middleware.ts
@@ -0,0 +1,16 @@
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, any route that starts with /dashboard will require user to be authenticated, and if they are not, it will automatically re-route them to the sign in page

Comment thread src/theme.ts
Comment on lines +3 to +15
import { Roboto } from 'next/font/google'

const roboto = Roboto({
weight: ['300', '400', '500', '700'],
subsets: ['latin'],
display: 'swap',
})

let theme = createTheme({
typography: {
fontFamily: roboto.style.fontFamily,
},
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Demo using next/font with MUI theme

Comment thread src/theme.ts
Comment on lines +18 to +37
components: {
MuiDialogActions: {
styleOverrides: {
root: {
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(3),
paddingBottom: theme.spacing(3),
},
},
},
MuiButton: {
styleOverrides: {
root: {
textTransform: 'none',
fontWeight: 700,
},
},
},
},
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few style overrides to make the design look more elegant

@wildky wildky changed the title Developer Notes NextJS Full-Stack Template: Developer Notes Aug 1, 2024

This branch was successfully deployed

1 active deployment
Preview d2c75429 Deployed Jul 31, 2024 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant