Next JS App Directory
Starting a new project with Next.js is a breeze with create-next-app
, automating setup tasks for you. Here's how to get started.
Set Up Your Project
Open your terminal and run:
npx create-next-app@latest
During installation, you'll be prompted to configure your project. Here are the options:
What is your project named? next-js-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/* No / Yes
After the prompts, create-next-app will create a folder with your project name and install the required dependencies.
Open Your Project in VS Code
Open your project in Visual Studio Code or any preferred code editor.
Clean Up and Customize
Within the app directory, you'll find page.js
and globals.css
files. Clean up and modify them according to your needs. Remember not to remove the Tailwind CSS configuration in globals.css
.
Create Pages
Create your pages within the project structure. For example, to handle a form request:
Inside the app/add folder, create a page.js
file and add your form handling code.
"use client";
import { useRef } from "react";
import add from "./add";
function page(props) {
const formRef = useRef();
return (
<form
className="max-w-md mx-auto"
ref={formRef}
action={async (formData) => {
const response = await add(formData);
formRef.current?.reset();
}}
>
<div className="relative z-0 w-full mb-5 group">
<input
type="email"
name="floating_email"
id="floating_email"
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label
htmlFor="floating_email"
className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6"
>
Email address
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="password"
name="floating_password"
id="floating_password"
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label
htmlFor="floating_password"
className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6"
>
Password
</label>
</div>
<div className="grid md:grid-cols-2 md:gap-6">
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
name="floating_first_name"
id="floating_first_name"
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label
htmlFor="floating_first_name"
className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6"
>
First name
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
name="floating_last_name"
id="floating_last_name"
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label
htmlFor="floating_last_name"
className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6"
>
Last name
</label>
</div>
</div>
<div className="grid md:grid-cols-2 md:gap-6">
<div className="relative z-0 w-full mb-5 group">
<input
type="tel"
pattern="[0-9]{10}"
name="floating_phone"
id="floating_phone"
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label
htmlFor="floating_phone"
className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6"
>
Phone number (1234567890)
</label>
</div>
</div>
<button
type="submit"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center"
>
Submit
</button>
</form>
);
}
export default page;
To handle form requests, create another file named add.js
with the appropriate code. This file won't be visible on the client side due to the "use server" directive.
"use server";
export default async function add(formData) {
const formDataObject = {};
formData.forEach((value, key) => {
if (formDataObject.hasOwnProperty(key)) {
if (!Array.isArray(formDataObject[key])) {
formDataObject[key] = [formDataObject[key]];
}
formDataObject[key].push(value);
} else {
formDataObject[key] = value;
}
});
console.log("================SAVE this via API====================");
console.log(JSON.stringify(formDataObject));
console.log("====================================");
}
export async function get() {
//Get API use here
return {
floating_email: "[email protected]",
floating_password: "test",
floating_first_name: "E3",
floating_last_name: "Docs",
floating_phone: "0000000000",
};
}
Similarly, create other pages as needed, like a list page update the code accordingly.
import { get } from "../add/add";
async function page(props) {
const getAll = await get();
return (
<div className="relative overflow-x-auto shadow-md sm:rounded-lg">
<table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<tbody>
<tr>
<th scope="col" className="px-6 py-3">
</th>
<td scope="col" className="px-6 py-3">
{getAll.floating_email}
</td>
</tr>
<tr>
<th scope="col" className="px-6 py-3">
Password
</th>
<td scope="col" className="px-6 py-3">
{getAll.floating_password}
</td>
</tr>
<tr>
<th scope="col" className="px-6 py-3">
First name
</th>
<td scope="col" className="px-6 py-3">
{getAll.floating_password}
</td>
</tr>
<tr>
<th scope="col" className="px-6 py-3">
Last floating_first_name
</th>
<td scope="col" className="px-6 py-3">
{getAll.floating_last_name}
</td>
</tr>
<tr>
<th scope="col" className="px-6 py-3">
Phone number
</th>
<td scope="col" className="px-6 py-3">
{getAll.floating_phone}
</td>
</tr>
</tbody>
</table>
</div>
);
}
export default page;
now both page are set let's set menu bar with layout.js
import { Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Create Next Js App Example",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<nav className="flex items-center justify-between flex-wrap bg-teal-500 p-6">
<div className="flex items-center flex-shrink-0 text-white mr-6">
<svg
className="fill-current h-8 w-8 mr-2"
width="54"
height="54"
viewBox="0 0 54 54"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M13.5 22.1c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05zM0 38.3c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05z" />
</svg>
<span className="font-semibold text-xl tracking-tight">
NextJs App Directory
</span>
</div>
<div className="block lg:hidden">
<button className="flex items-center px-3 py-2 border rounded text-teal-200 border-teal-400 hover:text-white hover:border-white">
<svg
className="fill-current h-3 w-3"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<title>Menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" />
</svg>
</button>
</div>
<div className="w-full block flex-grow lg:flex lg:items-center lg:w-auto">
<div className="text-sm lg:flex-grow">
<Link
href={"/"}
className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4"
>
Home
</Link>
<Link
href={"/add"}
className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4"
>
Add
</Link>
<Link
href={"/list"}
className="block mt-4 lg:inline-block lg:mt-0 text-teal-200 hover:text-white mr-4"
>
List
</Link>
</div>
</div>
</nav>
{children}
</body>
</html>
);
}
Run Your Next.js App
Once everything is set up, run your Next.js app:
npm run dev
Navigate to http://localhost:3000/ in your browser to see your app in action. You should now have additional pages like "Add" and "List" along with the Home Page.
Next.js Examples
Form Example
API GET Example