Skip to content

Latest commit

 

History

History
386 lines (227 loc) · 14 KB

index.md

File metadata and controls

386 lines (227 loc) · 14 KB

nextjs-application-template is a sample Next.js 14 application that illustrates:

The goal of this template is to help you get quickly started doing Next.js development by providing a reasonable directory structure for development and deployment, a set of common extensions to the core framework, and boilerplate code to implement basic page display, navigation, forms, roles, and database manipulation.

To keep this codebase simple and small, some important capabilities are intentionally excluded from this template:

  • Unit Testing
  • Security
  • Deployment

Examples of the these capabilities will be provided elsewhere.

Installation

First, install PostgreSQL. Then create a database for your application.


$ createdb nextjs-application-template
Password:
$

Second, go to https://github.com/ics-software-engineering/nextjs-application-template, and click the "Use this template" button. Complete the dialog box to create a new repository that you own that is initialized with this template's files.

Third, go to your newly created repository, and click the "Clone or download" button to download your new GitHub repo to your local file system. Using GitHub Desktop is a great choice if you use MacOS or Windows.

Fourth, cd into the directory of your local copy of the repo, and install third party libraries with:


$ npm install

Fifth, create a .env file from the sample.env. Set the DATABASE_URL variable to match your PostgreSQL database that you created in the first step. See the Prisma docs Connect your database. Then run the Prisma migration npx prisma migrate dev to set up the PostgreSQL tables.


$ npx prisma migrate dev
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "<your database name>", schema "public" at "localhost:5432"

Applying migration `20240708195109_init`

The following migration(s) have been applied:

migrations/
└─ 20240708195109_init/
└─ migration.sql

Your database is now in sync with your schema.

✔ Generated Prisma Client (v5.16.1) to ./node_modules/@prisma/client in 51ms

$

Then seed the database with the /config/settings.development.json data using npx prisma db seed.


$ npx prisma db seed
Environment variables loaded from .env
Running seed command `ts-node --compiler-options {"module":"CommonJS"} prisma/seed.ts` ...
Seeding the database
Creating user: [email protected] with role: ADMIN
Creating user: [email protected] with role: USER
Adding stuff: Basket ([email protected])
Adding stuff: Bicycle ([email protected])
Adding stuff: Banana ([email protected])
Adding stuff: Boogie Board ([email protected])

🌱 The seed command has been executed.
$

Running the system

Once the libraries are installed and the database seeded, you can run the application by invoking the "dev" script in the package.json file:


$ npm run dev

> [email protected] dev
> next dev

▲ Next.js 14.2.4

- Local: http://localhost:3000
- Environments: .env

✓ Starting...
✓ Ready in 1619ms

Viewing the running app

If all goes well, the template application will appear at http://localhost:3000. You can login using the credentials in settings.development.json, or else register a new account.

ESLint

You can verify that the code obeys our coding standards by running ESLint over the code in the src/ directory with:

$ npm run lint

> [email protected] lint
> next lint

✔ No ESLint warnings or errors
$

Walkthrough

The following sections describe the major features of this template.

Directory structure

The top-level directory structure is:


.github # holds the GitHub Continuous Integration action and Issue template.

config/ # holds configuration files, such as settings.development.json

doc/ # holds developer documentation, user guides, etc.

prisma/ # holds the Prisma ORM schema and seed.ts files.

public/ # holds the public images.

src/ # holds the application files.

tests/ # holds the Playwright acceptance tests.

.eslintrc.json # The ESLint configuration.

.gitignore # don't commit VSCode settings files, node_modules, and settings.production.json

This structure separates documentation files (such as screenshots) and configuration files (such as the settings files) from the actual Next.js application.

The src/ directory has this structure:


app/

  add/ # The add route
    page.tsx # The Add Stuff Page

  admin/
    page.tsx # The Admin Page

  api/auth/[...nextauth]/
    route.ts # The NextAuth configuration

  auth/
    change-password/
      page.tsx # The Change Password Page

    signin/
      page.tsx # The Sign In Page

    signout/
      page.tsx # The Sign Out Page

    signup/
      page.tsx # The Sign Up / Register Page

  edit/
    page.tsx # The Edit Stuff Page

  list/
    page.tsx # The List Stuff Page

  not-authorized/
    page.tsx # The Not Authorized Page

  layout.tsx # The layout of the application

  page.tsx # The Landing Page

  providers.tsx # Session providers.

  components/
    AddStuffForm.tsx # The React Hook Form for adding stuff.

    EditStuffForm.tsx # The Edit Stuff Form.

    Footer.tsx # The application footer.

    LoadingSpinner.tsx # Indicates working.

    Navbar.tsx # The application navbar.

    StuffItem.tsx # Row in the list stuff page.

    StuffItemAdmin.tsx # Row in the admin list stuff page.

  lib/

    dbActions.ts # Functions to manipulate the Postgres database.

    page-protections.ts # Functions to check for logged in users and their roles.

    prisma.ts # Singleton Prisma client.

    validationSchemas.ts # Yup schemas for validating forms.

  tests/ # playwright acceptance tests.

Application functionality

The application implements a simple CRUD application for managing "Stuff", which is a PostgreSQL table consisting of a name (String), a quantity (Number), a condition (one of 'excellent', 'good', 'fair', or 'poor') and an owner.

By default, each user only sees the Stuff that they have created. However, the settings file enables you to define default accounts. If you define a user with the role "admin", then that user gets access to a special page which lists all the Stuff defined by all users.

Landing page

When you retrieve the app at http://localhost:3000, this is what should be displayed:

The next step is to use the Login menu to either Login to an existing account or register a new account.

Login page

Clicking on the Login link, then on the Sign In menu item displays this page:

Register page

Alternatively, clicking on the Login link, then on the Sign Up menu item displays this page:

Landing (after Login) page, non-Admin user

Once you log in (either to an existing account or by creating a new one), the navbar changes as follows:

You can now add new Stuff documents, and list the Stuff you have created. Note you cannot see any Stuff created by other users.

Add Stuff page

After logging in, here is the page that allows you to add new Stuff:

List Stuff page

After logging in, here is the page that allows you to list all the Stuff you have created:

You click the "Edit" link to go to the Edit Stuff page, shown next.

Edit Stuff page

After clicking on the "Edit" link associated with an item, this page displays that allows you to change and save it:

Landing (after Login), Admin user

You can define an "admin" user in the settings.json file. This user, after logging in, gets a special entry in the navbar:

Admin page (list all users stuff)

To provide a simple example of a "super power" for Admin users, the Admin page lists all of the Stuff by all of the users:

Note that non-admin users cannot get to this page, even if they type in the URL by hand.

Tables

The application implements two tables "Stuff" and "User". Each Stuff row has the following columns: id, name, quantity, condition, and owner. The User table has the following columns: id, email, password (hashed using bcrypt), role.

The Stuff and User models are defined in prisma/schema.prisma.

The tables are initialized in prisma/seed.ts using the command npx prisma db seed.

CSS

The application uses the React implementation of Bootstrap 5. You can adjust the theme by editing the src/app/globals.css file. To change the theme override the Bootstrap 5 CSS variables.

/* Change bootstrap variable values.
 See https://getbootstrap.com/docs/5.2/customize/css-variables/
 */
body {
  --bs-light-rgb: 236, 236, 236;
}

/* Define custom styles */
.gray-background {
  background-color: var(--bs-gray-200);
  color: var(--bs-dark);
  padding-top: 10px;
  padding-bottom: 20px;
}

Routing

For display and navigation among its four pages, the application uses Next.js App Router.

Routing is defined by the directory structure.

Authentication

For authentication, the application uses the NextAuth package.

When the database is seeded, a settings file (such as config/settings.development.json) is used to create users and stuff in the PostgreSQL database. That will lead to a default accounts being created.

The application allows users to register and create new accounts at any time.

Authorization

Only logged in users can manipulate Stuff items (but any registered user can manipulate any Stuff item, even if they weren't the user that created it.)

Configuration

The config directory is intended to hold settings files. The repository contains one file: config/settings.development.json.

The .gitignore file prevents a file named settings.production.json from being committed to the repository. So, if you are deploying the application, you can put settings in a file named settings.production.json and it will not be committed.

Quality Assurance

ESLint

The application includes a .eslintrc.json file to define the coding style adhered to in this application. You can invoke ESLint from the command line as follows:

[~/nextjs-application-template]-> npm run lint

> [email protected] lint
> next lint

✔ No ESLint warnings or errors
[~/nextjs-application-template]->

ESLint should run without generating any errors.

It's significantly easier to do development with ESLint integrated directly into your IDE (such as VSCode).