Build An Invoice App With Next.js 14, App Router, Server Actions, And Custom JWT Auth
In today's fast-paced digital world, efficient invoice management is crucial for businesses of all sizes. Building an invoice application can streamline financial processes, improve cash flow, and enhance overall business operations. In this comprehensive guide, we'll explore how to create a modern invoice application using Next.js 14, leveraging its powerful features such as the App Router, Server Actions, and Custom JWT Authentication. By the end of this article, you'll have a solid understanding of the key concepts and techniques involved in building a robust and secure invoice management system.
Embracing Next.js 14 for Invoice App Development
Next.js 14, the latest iteration of the popular React framework, provides a rich set of features and capabilities that make it an excellent choice for building modern web applications, including invoice management systems. The App Router, a cornerstone of Next.js 14, enables a file-system-based routing system that simplifies the organization and navigation of your application. Server Actions, another key feature, allow you to execute server-side logic directly from your React components, enhancing performance and security. Custom JWT Authentication provides a secure and flexible way to manage user authentication and authorization within your application. By harnessing these features, you can create an invoice app that is not only functional but also scalable, maintainable, and secure. The App Router simplifies the routing mechanism, while Server Actions allow for direct execution of server-side logic from React components, enhancing performance and security. Custom JWT Authentication ensures secure user management within the application.
Key Features of Our Invoice App
Before diving into the implementation details, let's outline the key features of our invoice application:
- User Authentication and Authorization: Securely manage user accounts and access control using Custom JWT Authentication.
- Invoice Creation and Management: Allow users to create, edit, and delete invoices with ease.
- Client Management: Maintain a database of clients with relevant information.
- Invoice Generation: Generate professional-looking invoices in PDF format.
- Payment Tracking: Track invoice payments and generate reports.
- Dashboard: Provide an overview of key metrics, such as outstanding invoices and total revenue.
These features form the foundation of a comprehensive invoice management system. Throughout this article, we'll delve into the technical aspects of implementing each feature using Next.js 14, Server Actions, and Custom JWT Authentication. Our focus will be on creating a user-friendly interface that simplifies invoice management for businesses of all sizes. User authentication will be handled using Custom JWT Authentication, ensuring secure access control. Invoice creation and management will be streamlined, allowing users to easily generate, edit, and delete invoices. Client management will enable users to maintain a database of clients with relevant details. Invoice generation will produce professional-looking PDFs, and payment tracking will help monitor invoice payments and generate reports. The dashboard will provide a comprehensive overview of key metrics, such as outstanding invoices and total revenue.
Setting Up Your Next.js 14 Project
To begin, let's set up a new Next.js 14 project. Open your terminal and run the following command:
npx create-next-app@latest invoice-app
This command will create a new Next.js project named "invoice-app". Navigate into the project directory:
cd invoice-app
Next, install the necessary dependencies:
npm install bcrypt jsonwebtoken @prisma/client prisma
bcrypt
: For password hashing.jsonwebtoken
: For generating and verifying JWT tokens.@prisma/client
andprisma
: For database access using Prisma.
Once the dependencies are installed, initialize Prisma:
npx prisma init --datasource-provider postgresql
This command will create a prisma
directory in your project, containing the Prisma schema file (schema.prisma
) and the .env
file. Update the .env
file with your PostgreSQL database connection URL:
DATABASE_URL="postgresql://user:password@host:port/database?schema=public"
Replace user
, password
, host
, port
, and database
with your actual database credentials. Next, define your database schema in the schema.prisma
file. For our invoice app, we'll need models for users, clients, and invoices. Setting up your Next.js 14 project involves creating a new project, installing dependencies, and initializing Prisma for database access. The bcrypt
library is used for secure password hashing, while jsonwebtoken
facilitates JWT token generation and verification. @prisma/client
and prisma
enable database interactions using Prisma. After installing dependencies, Prisma is initialized, and the database connection URL is configured in the .env
file. The Prisma schema is then defined, outlining the structure of the database models for users, clients, and invoices.
Implementing Custom JWT Authentication
Creating User Model
First, let's define the User model:
model User {
id String @id @default(uuid())
email String @unique
password String
name String?
invoices Invoice[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Creating Client Model
Next, create the Client model:
model Client {
id String @id @default(uuid())
name String
email String?
phone String?
address String?
invoices Invoice[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Creating Invoice Model
Finally, define the Invoice model:
model Invoice {
id String @id @default(uuid())
invoiceNumber String @unique
clientId String
client Client @relation(fields: [clientId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
issueDate DateTime
dueDate DateTime
amount Float
status String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Run the following command to generate the Prisma client and apply the migrations:
npx prisma migrate dev
This command will create the database tables based on your schema. With the database schema defined, we can now implement the Custom JWT Authentication. This involves creating functions for user registration, login, and token verification. We'll utilize bcrypt
for password hashing and jsonwebtoken
for creating and verifying JWT tokens. Implementing Custom JWT Authentication begins with defining the User, Client, and Invoice models in the Prisma schema. The User model includes fields for ID, email, password, name, invoices, and timestamps. The Client model contains fields for ID, name, email, phone, address, invoices, and timestamps. The Invoice model includes fields for ID, invoice number, client ID, user ID, issue date, due date, amount, status, and timestamps. After defining the schema, the Prisma client is generated, and migrations are applied to create the database tables. This sets the stage for implementing user registration, login, and token verification using bcrypt
for password hashing and jsonwebtoken
for JWT token management.
Implementing Server Actions for Invoice Operations
Server Actions in Next.js 14 allow you to execute server-side logic directly from your React components. This is particularly useful for handling form submissions, database interactions, and other server-side operations. For our invoice app, we'll use Server Actions to implement the following functionalities:
- Creating Invoices: Create a new invoice in the database.
- Updating Invoices: Update an existing invoice.
- Deleting Invoices: Delete an invoice from the database.
- Fetching Invoices: Retrieve invoices from the database.
To create a Server Action, you simply define an async function with the "use server"
directive at the top. This tells Next.js to execute the function on the server. For example, let's create a Server Action to create a new invoice:
// app/actions.ts
"use server";
import { db } from "@/lib/db";
import { Invoice } from "@prisma/client";
export async function createInvoice(data: Omit<Invoice, "id" | "createdAt" | "updatedAt">): Promise<Invoice> {
const invoice = await db.invoice.create({
data,
});
return invoice;
}
This Server Action takes invoice data as input and creates a new invoice in the database using Prisma. Similarly, you can create Server Actions for updating, deleting, and fetching invoices. These Server Actions can then be called directly from your React components, providing a seamless way to interact with the server. Implementing Server Actions for invoice operations is a crucial step in building a dynamic invoice app. Server Actions in Next.js 14 enable the execution of server-side logic directly from React components. This approach is ideal for handling form submissions, database interactions, and other server-side tasks. In our invoice app, Server Actions are used to create, update, delete, and fetch invoices. To define a Server Action, an async function is created with the "use server"
directive at the top. This directive instructs Next.js to execute the function on the server. For instance, a Server Action can be created to handle invoice creation, taking invoice data as input and creating a new invoice in the database using Prisma. Similarly, Server Actions can be implemented for updating, deleting, and fetching invoices, providing a seamless way to interact with the server from React components.
Building the User Interface with React Components
The user interface of our invoice app will be built using React components. We'll create components for various parts of the application, such as:
- Invoice List: Displays a list of invoices.
- Invoice Form: Allows users to create and edit invoices.
- Client List: Displays a list of clients.
- Client Form: Allows users to create and edit clients.
- Dashboard: Provides an overview of key metrics.
Each component will be responsible for rendering a specific part of the UI and handling user interactions. For example, the Invoice Form component will render a form with fields for invoice details, such as invoice number, client, issue date, due date, and amount. It will also handle form submissions and call the appropriate Server Actions to create or update invoices. By breaking down the UI into reusable components, we can create a modular and maintainable application. Each component can be developed and tested independently, making it easier to manage the complexity of the application. Building the user interface with React components is a fundamental aspect of creating a user-friendly invoice app. The UI is structured using reusable components, each responsible for rendering a specific part of the application and handling user interactions. Components are created for displaying invoice lists, invoice forms, client lists, client forms, and the dashboard. The Invoice Form component, for instance, renders a form with fields for invoice details and handles form submissions, calling the appropriate Server Actions to create or update invoices. This component-based approach promotes modularity and maintainability, allowing for independent development and testing of individual components, thereby simplifying the management of application complexity.
Generating PDF Invoices
Generating professional-looking invoices in PDF format is a crucial feature for any invoice application. There are several libraries available for generating PDFs in Node.js, such as pdfmake
and html-pdf
. For this example, we'll use pdfmake
, which allows us to define the PDF document structure using JavaScript objects.
First, install the pdfmake
package:
npm install pdfmake
Next, create a Server Action to generate the PDF invoice:
// app/actions.ts
"use server";
import { db } from "@/lib/db";
import { Invoice } from "@prisma/client";
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
export async function generateInvoicePdf(invoiceId: string): Promise<string> {
const invoice = await db.invoice.findUnique({
where: {
id: invoiceId,
},
include: {
client: true,
},
});
if (!invoice) {
throw new Error("Invoice not found");
}
const documentDefinition = {
content: [
{ text: "Invoice", style: "header" },
{ text: `Invoice Number: ${invoice.invoiceNumber}`, style: "subheader" },
{ text: `Issue Date: ${invoice.issueDate.toLocaleDateString()}` },
{ text: `Due Date: ${invoice.dueDate.toLocaleDateString()}` },
{ text: `Client: ${invoice.client.name}` },
{ text: `Amount: ${invoice.amount}` },
],
styles: {
header: { fontSize: 22, bold: true },
subheader: { fontSize: 18, bold: true },
},
};
const pdfDoc = pdfMake.createPdfKitDocument(documentDefinition);
return new Promise((resolve, reject) => {
const chunks: Uint8Array[] = [];
pdfDoc.on("data", (chunk) => chunks.push(chunk));
pdfDoc.on("end", () => resolve(Buffer.concat(chunks).toString("base64")));
pdfDoc.on("error", reject);
pdfDoc.end();
});
}
This Server Action fetches the invoice from the database, defines the PDF document structure using pdfmake
, and generates the PDF document as a base64-encoded string. You can then use this string to display the PDF in the browser or download it. Generating PDF invoices is a vital feature for any invoice application, ensuring professional-looking documents. Libraries like pdfmake
and html-pdf
facilitate PDF generation in Node.js. In this example, pdfmake
is used, allowing the definition of the PDF document structure using JavaScript objects. The pdfmake
package is installed, and a Server Action is created to generate the PDF invoice. This Server Action fetches the invoice from the database, defines the PDF document structure using pdfmake
, and generates the PDF document as a base64-encoded string. This string can then be used to display the PDF in the browser or facilitate downloading. The use of pdfmake
simplifies the process of creating structured and visually appealing PDF invoices.
Conclusion
In this article, we've explored how to build a modern invoice application using Next.js 14, leveraging its powerful features such as the App Router, Server Actions, and Custom JWT Authentication. We've covered key aspects of the development process, including setting up the project, implementing user authentication, creating Server Actions for invoice operations, building the user interface with React components, and generating PDF invoices. By following these steps, you can create a robust and scalable invoice management system that meets the needs of your business. In conclusion, building a modern invoice application using Next.js 14 offers numerous advantages, leveraging features such as the App Router, Server Actions, and Custom JWT Authentication. This article has provided a comprehensive guide to the development process, covering project setup, user authentication implementation, Server Action creation for invoice operations, user interface construction with React components, and PDF invoice generation. By adhering to these steps, a robust and scalable invoice management system can be created to meet specific business requirements. The use of Next.js 14 and its associated features streamlines the development process and enhances the overall functionality and user experience of the invoice application.
This is a starting point, and you can further enhance the application by adding features such as payment integration, recurring invoices, and reporting. Remember to always prioritize security and user experience when building web applications. As a next step, consider integrating payment gateways, implementing recurring invoice functionality, and adding comprehensive reporting capabilities. Throughout the development process, prioritizing security and user experience is paramount. Further enhancements can be made to the application based on specific business needs and user feedback. Continuous improvement and adaptation are key to creating a successful and user-centric invoice management system.