NextJS 15 crash Course
In this post we are going to learn NextJS 15 by creating an awesome web-app. This post have been inspired by this YouTube video by JavaScript Mastery.
First we need to create the project. So, open any terminal and give the create-next-app command. Make sure to choose the exact options as shown in the image below.
Now, in the page.tsx file which is our home page, we will remove everything. And then add a h1 with tailwind CSS class. In http://localhost:3000/ it is showing correctly.
Although we have the latest Next 15, but we need to update below in package.json file for our app to work.
We will be using Next auth in our project. So, we will install next-auth and add auth secret in .env.local file with npx auth secret command.
Now, create an auth.ts file in the root directory andadd the NextAuth code in it.
Now, create an api folder in the root. Inside it create auth folder and then inside it […nextauth]
Next, create a file route.ts file. Here, we are importing the previously created handlers from auth. And then export GET and POST.
We are going to create an OAuth app and the details of it are in the OAuth app documentation.
We are going to use OAuth authentication of github. So, first goto Settings in githib and then scroll down to Developer settings.
After this click on OAuth Apps and then New OAuth App.
In the next page give the app a name and the Homepage URL should be http://localhost:3000 . Give a proper description and the callback URL should be as given in image below.
After registering you will get a ClientIS and Client secrets and we need to save both of them.
Now, goto .env.local file and add the ke for AUTH_GITHUB_ID and AUTH_GITHUB_SECRET.
Now, in auth.ts we will use GitHub as the provider.
Now, we will create a (root) folder inside the app folder. This will act like a homepage. So, we have put our page.tsx file inside it.
Now, we will create the Navbar. So, create a Navbar.tsx file inside a components folder. Inside it we have a Link to goto the home page.
We are also using session from auth to see if the user is there. If we have user we will show Create, Logout and user name. Or else we will show the Login button.
Next, we will update the code in Navbar.tsx file. Here, we will wrap the button with a form. Logout will call the signOut() from auth. And Login will call the signIn function from auth with github as the params.
From the (root) folder, we have a layout.tsx file. Here, we will get the children props and call it with the Navbar component.
We have a problem in the github settings and here we will make the https to http.
Now, go to http://localhost:3000/ and we will see the Login button along with the header.
Once we clicked on the Login,. it will take us to GitHub authentication.
Now, it will ask us for authorization.
Once we suggesfully logged in, we will see the Create, Logout and user name on top right.
Now, in the tailwind.config.ts file we will add some default styles.
We have addes some more styles and also installed the package of tailwindcss-animate.
We have also added the tailwindcss typography package.
Next, we have added some font files in a folder called fonts. After that we have updated the root layout.tsx file to use these fonts.
In the return of layout.tsx file we will change the className in body yo this workSans.
Now, in http://localhost:3000/ we will see the updated fonts.
Now, in the global.css we will be using the Work Sans google font. And we have also updated the style files here.
We will use a component library called Shacdn in this project.
Now, in the terminal we will use the npx command to add shadcn in our project. Keep the configuration as shown in the image.
Now, in the page.tsx file of the (root) we will add some styles with text.
Now, http://localhost:3000/ shows us the perfect header in the homepage.
Now, we will create a Search bar in the home page. For this first create SearchFormReset.tsx in the components folder. Here, we have a button which onClick reset the form.
Now, create SearchForm.tsx inside the components folder. Here, we are using Form from next form. We have a input which have a div, which will show SearchFormReset if query is there. It also have a button with S.
Next, we are rendering the SearchForm from page.tsx file.
Now, in http://localhost:3000/ we will have the search bar.
Now, we will add the query params in the page.tsx file. Here, we have made the function as async. It will have a searchParama which is of type Promise and will have query.
Now, this query we will pass to the SearchForm as params.
Now, in the SearchForm.tsx file we will be receiving the query as a parameter.
Now, in http://localhost:3000/ we can see S because we have query params.
Now, if we type something in the input we will also see a X. And the query will be seen in http://localhost:3000/
Now, we will change the X to a proper style. For this we will use lucide-react in SearchFormReset.tsx file.
We will alsos be using Search from lucide-react in SearchForm.tsx file.
Now, our icons are much better in http://localhost:3000/
Now, we will add a button from shadcn. For this we will use the npx shadcn@latest add button command. It will generate a button.tsx file in ui folder.
Now, we will write logic to show cards in the home page. For this we will add the formatDate() in the utils.ts file first.
Now, in the next.config.ts file we have to add code to allows images including svg images from any site.
Now, create a file StartupCard.tsx in the components folder. Here, we will be extracting all the fields from the post. After that we are showing those fields inside the return statement.
Now, back in the page.tsx file we will first add a dummy posts. It is an array of objects, which contains various data in an object.
Now, we will create a new section in the page.tsx file inside the return statement. Here, we will map through the posts and send each item to the StartupCard.
Now, we will see a nice card with some details in http://localhost:3000/
Now, we will add all the other details in the StartupCard.tsx file.
Now, in http://localhost:3000/ we will see all the details of the startup.
Next, we will add Sanity in our project. Sanity is a CMS, which have a very good free tier and we will use it to store our data.
After login to sanity, we have given a Project name of next15-demo and clicked on Create project button.
It will give us some commands to enter in the terminal.
But we need to login to sanity also. So, we are giving the command npx sanity login first.
Now, we will give the npm command which we have given earlier. Choose the option as in the image below.
We also have to install the next-sanity in our project.
A folder if studio-next15-demo will be created and inside it .env.local will be created. Move the content of it to the .env.local in the root directory.
Now, we will use the sanity in our local for this project. So, go to http://localhost:3000/studio and login through google, as we have selected it earlier.
Now, click on Structure and we will see no No document types screen.
Now, inside the sanity folder and inside schemaTypes folder, create an author.ts file. Here, we have defined the type for the author.
Now, also create a startup.ts inside the schemaTypes folder. Here, we have defined the type for the startup.
Now, in the index.ts file in the schemaTypes folder we will add the author and startup.
Now, in a structure.ts file inside the sanity folder we need to put the author and startup.
Now, in the sanity.config.ts file we will use markdownSchema. We also need to add this plugin.
We also need to add the plugin of easymde. And now if we go to http://localhost:3000/studio/structure we will see the Authors and Startups folder.
After clicking on the Authors, we will add a new author. We have entered various fileds here and then click on the Publish button.
Also, after clicking on the Startups we have added a new startup with different fields and also clicked on the Publish button.
To get the data which we have just stored in sanity, we use a special type of query language. Here, we are searching the startup and getting various fields. We have also tested the same in the in-built editor.
Now, add this sql in the queries.ts file inside the lib folder, which is inside the sanity folder. Here, we are storing it inside a constant called STARTUPS_QUERY.
Now, in the page.tsx file we will get the posts through a fetch() from sanity.
Now, in http://localhost:3000/ we are getting data from sanity.
Now, give the below command in terminal to create the extract.json file, which will be required.
We also need to create a sanity-typegen.json file in the root directory.
Now, in the package.json file we need to add some scripts.
Now, run the command npm run typegen and it will create types for us in the types.ts file.
Back in the StartupCard.tsx file we will import Author and Startup from types. After that we will also give the StartupTypeCard type, to get rid of our type error.
Inside the return we have added the image and name in Image.
Now, the StartupTypeCard we will import in the page.tsx file.
In the client.ts file we will make the useCdn as false, so that our records in CDN are updated instantly.
Now, we will create a file live.ts inside the lib folder. We are also installing a package called server-only. And using it for the client.
In the .env.local we also have to add a variable called NEXT_PUBLIC_SANITY_API_VERSION.
Now, in the root page.tsx file we will use the SanityLive component. And also fetch the data from sanityFetch().
Back in the Sanity studio, we have added one more startup and clicked on the Publish button.
It will instantly appear in http://localhost:3000/
Back in the queries.ts file we will update the STARTUPS_QUERY for adding the search.
Now, we will add the params in page.tsx file.
Now, in http://localhost:3000/ if we search something it will appear.
Now, we will create the individual page. And for this startup folder inside the (root) folder. Inside the startup folder create a [id] folder and inside it page.tsx folder.
Now, click on any startup and you will get the id for it.
Back in our sql editor, we will update it to give us the id.
Now, we will add this query in the queries.ts file.
In next.config.ts file we need to add the object called devIndicators.
We will update the page.tsx file of the startup folder. Here, we have imported client, STARTUP_BY_ID_QUERY and notFound. After that we have used fetch to get the post.
Now, we got the correct title for the post.
Since, we are getting the data we will update the return statement in page.tsx file of the startup folder, to get all data in style.
Now, in http://localhost:3000/ we will get all the data of the startup.
Now, we also want to show an markdon content in startup page.tsx file. So, we have imported markdown-it.
Next, we have created a variable parsedContent to use it. Now, we are using an article to show the parsedContent.
Now, we will also see the markdown content in startup page.
Now, we will add the logic to create a post. For this we need to have a token in sanity.io. Here, click on the APIU tab and then Tokens.
Here, click on the Add API token button.
Give the token a name and then the Editor access and then Save button.
We need to add the token which we have received in the .env.local file.
Now, we need to export the token from the env.ts file.
Now, create a new file write-client.ts in the lib folder. Here, again we have to use the server-only and will create a writeClient variable using createClient().
Now, in the queries.ts file, we will add the query to get the author by github id.
Next, in auth.ts we also have to add a callbacks which will have a function called signIn. It will use client to use the AUTHOR_BY_GITHUB_ID_QUERY to check the id.
We will also add a function for jwt inside the callback in queries.ts file, were we are returning the token. Similarly, we have a function for session where we are returning the session.
We will now create a new file called next-auth.d.ts. Here, we will declare the Session and JWT for the typescript types.
Now, in the root page.tsx file we will get the session from the auth.
Now, in sanity studio, we have deleted the author created individually.
Back in http://localhost:3000/ we will see the usernmae to be there.
But back in Sanity Studio we can see the data updated from our github.
We can also see the correct session id in the terminal for which we had console.log()
Now, we will create the logic to create a startup page. For this create a create folder inside the startup folder. And inside it create a page.tsx file.
Now, going to http://localhost:3000/startup/create will show a blank page.
We will now create a form for this page. So, create StartupForm.tsx inside the ui folder. We are also installing input textarea and toast from shadcn.
We have then added the Input and Textarea to create a title and description field.
Next, we have created two Input and one MDEditor in StartupForm.tsx file.
We have also added a Button in in StartupForm.tsx file.
Now, we have rendered this StartupForm from the page.tsx file.
Now, going to http://localhost:3000/startup/create will show a nice form.
We will also add a validation.ts file for our form inside the lib folder. This is for validation the form.
Back in StartupForm.tsx file, we will import the validation and zod which is used for TypeScript validation.
The form will have an action which will be formAction. Also, the handleFormSubmit will take the formValues and validate it.
We will also add the Toaster component in the layout.tsx file.
Now, in StartupForm.tsx file, we import useToast and useRouter and use them. Inside the handleFormSubmit we are taking the result and pushing to /startup. We aer also showing the toast message at various places.
Now, write some content in http://localhost:3000/startup/create and click on Submit Your Pitch. Here, we have given wrong data at two places.
As, we have given wrong data we have got error popup and also error output below the text.
In the lib we will add utils.ts file. Here, we have created a new function called parseServerActionResponse()
Now, we will create a file of actions.ts and here, we will create the function of createPitch. It will take the session and also create a slug with the slugify package.
Back in the StartupForm.tsx file, we will use the createPitch() to pass the formData.
This time we will give proper data and click on the Create a pitch button.
Our pitch will be shown in http://localhost:3000/
This completes our post. You can find the code for the same here.