Nextjs
Published in

Nextjs

NEXTJS + MARKDOWN + SEARCH BAR + BLOG

Build the Search functionality in a static blog with Next.js and Markdown

Build an entire static blog with markdown — full support of search and the search functionality. #Series three

In the previous articles, we build the home, Reading page, category and tag page from scratch. This article builds the Search bar functionality in static site generation (SSG) with gray-matternpm packages.

Build the Search functionality in a static blog with Next.js and Markdown
Build the Search functionality in a static blog with Next.js and Markdown

All the codes are available on GitHub Repo. You can also check the final website demo with vercel.

Content

  1. Project Setup
  2. Project Structure
  3. Posts And Images Dummy data
  4. Pages
  5. Layout
  6. Home Page
  7. Reading page
  8. Category Page
  9. Tag Page
  10. Search Page and Functionality
  11. SEO

In the article, we create the search functionality in a static blog and next article we add SEO and Sitemap Functionality in blog.

Search Page and Functionality

We create search bar functionality without using third party services. You can search any post base on title and description.

How does it work?

We store all post's frontmatter data into search.json file. Generate a search.json file use of the getStaticProps function in nextjs. getStaticProps help to fetch a post and pass it into props in the component.

Add search bar in nextjs
Create a dynamic composer json file

Requirement

  1. Nextjs
  2. Markdown Converter
  3. getStaticProps
  4. Design Search Component

Steps

  1. Search UI (Bootstrap, tailwind and any other)
  2. Markdown Converter
  3. getStaticProps

Search UI (Bootstrap, tailwind and any other)

Firstly we build UI with CSS to use any CSS framework. I chose the bootstrap to build Ui.

create search bar in static genrate nextjs website
Search bar UI

Markdown Converter

We use gray-matter npm package to convert our frontmatter into json file.

---author : "Rajdeep Singh"categories : ["Next.js", "Next", "Next.js Framework", "Next.js Tutorial", "React.js", "react.js tutorial"]date : "2020-11-10T11:42:46Z"description : "Easy Ways Add CSS in Next.js #SeriesPart2"image : "images/next.js-add-css-code.jpg"images : ["images/next.js-add-css-code.jpg"]slug : "how-to-add-css-in-next-js"summary : "Easy Ways Add CSS in Next.js #SeriesPart2 \n"tags : ["Next.js", "Next", "Next.js Framework", "Next.js Tutorial", "React.js", "react.js tutorial"]title : "How To Add CSS In Next js?"draft : false---...rest code...

getStaticProps

getStaticProps help to pass data into components. getStaticProps Help only for static site generation. If your data is dynamic, it does not work.

Steps:

  1. Collect posts
  2. Find slug and Frontmatter
  3. Remove Null in post tempPosts
  4. Create a search.json file (Important step)
  5. Return Data
  6. Summaries code

Collect posts

// Get files from the posts dirconst files = fs.readdirSync(path.join('posts'))

Find slug and Frontmatter

// Get slug and frontmatter from postsconst tempPosts = files.map((filename) => {
// Create slugconst slug = filename.replace('.md', '')// Get frontmatterconst markdownWithMeta = fs.readFileSync(path.join('posts', filename),'utf-8')// convert frontmatter to jsonconst { data: frontmatter } = matter(markdownWithMeta)// get publish postif (frontmatter.draft === false) {return { slug, frontmatter, }} else {return null}})

Remove Null in post tempPosts

//  remove null in tempPostsconst posts = tempPosts.filter(post => { return post && post })

Create a search.json file (Important step)

In the search file, we pass frontmatter data with a slug. Then, based on the slug, we read posts inside the nextjs app.

// convert json data into string
const jsonString = JSON.stringify(posts)
// write a search.json file
fs.writeFileSync('./search.json', jsonString, err => {
if (err) {console.log('Error writing file', err)} else {console.log('Successfully wrote file')}})

Return Data

return { props: { posts: posts.sort(sortByDate), }, }

Summaries code

export async function getStaticProps() {
// Get files from the posts dirconst files = fs.readdirSync(path.join('posts'))// Get slug and frontmatter from postsconst tempPosts = files.map((filename) => {// Create slugconst slug = filename.replace('.md', '')// Get frontmatterconst markdownWithMeta = fs.readFileSync(path.join('posts', filename),'utf-8')// convert frontmatter to jsonconst { data: frontmatter } = matter(markdownWithMeta)// get publish postif (frontmatter.draft === false) {return { slug, frontmatter, }} else {return null}})// remove null in tempPostsconst posts = tempPosts.filter(post => {return post && post})// convert post json data to stringconst jsonString = JSON.stringify(posts)// create search.json filefs.writeFileSync('./search.json', jsonString, err => {if (err) {console.log('Error writing file', err)} else {console.log('Successfully wrote file')}})// return datareturn { props: { posts: posts.sort(sortByDate), },}}

Design Search Component

In the shown search result, we build a separate search page inside nextjs. The path of the search page looks like pages/search.js .

In the component we use useRouter the nextjs hook to access the query. We filter the post base on the query and add it to the TempPosts variable. In the end, show all posts in the component.

const { query } = useRouter()const TempPosts = []// loop posts and filter all posts base on query and push into TempPosts variable.search.map((post) => {
if (post.frontmatter.draft === false) {if (post.frontmatter.title.toLowerCase().includes(query.q) || post.frontmatter.summary.toLowerCase().includes(query.q) || post.frontmatter.description.toLowerCase().includes(query.q)) {TempPosts.push(post)} else {TempPosts.push(null)}}})// remove null in postsconst posts = TempPosts.filter(path => {return path && path})

Summaries the Search Component code down below.

export default function Search() {const { query } = useRouter()const TempPosts = []search.map((post) => {if (post.frontmatter.draft === false) {if (post.frontmatter.title.toLowerCase().includes(query.q) || post.frontmatter.summary.toLowerCase().includes(query.q) || post.frontmatter.description.toLowerCase().includes(query.q)) {TempPosts.push(post)} else {TempPosts.push(null)}}})//   remove null in postsconst posts = TempPosts.filter(path => {return path && path})return (<div><Banner /><div className="container"><div className="row"><div className="col-lg-8 m-auto">{posts.length > 0 ?posts.map((post, index) => (<Post key={index} post={post} />)) : <div className='m-auto p-5 mx-5 '><h2 className='text-center'>{query.q ? `No post find base on ${query.q} ` : 'loadding.. '}</h2></div>}</div></div></div></div>)}

Conclusion

There is only one way to add search functionality in static site generation (SSR), which I mention in the article. But there is another way to add a search bar using the other service provided like google search, etc.

Other search providers are free, and some of paid. But my problem is when I add other search providers to my website. As a result, my website size increases and decreases website speed and performance.

My search functionally, which I mentioned in the article, is stable and faster. However, it does not increase website size and improve web performance. You do not need any third-party javascript.

You can follow me on Twitter and tweet with me.

https://twitter.com/@Official_R_deep

Suppose you like more articles about Linux, Ubuntu, and Raspberry pi 4. Then you visit my website.

https://officialrajdeepsingh.dev/

Read More content at Nextjs. Sign up for a free newsletter and join the nextjs community on medium.

--

--

--

Nextjs Publication is an unofficial publication of Nextjs. Our goal is to bring beginners and pro developer in one place, and everybody understands the basic concept of next.js.

Recommended from Medium

10 JavaScript topics that you should know.

Scroll Section to Section Animation with JavaScript

Persisting state with Redux-Persist.

A nice pattern for your (Redux) state

The Mediator Pattern in JavaScript

A minimal protractor project setup with detailed explanation

5 Tips for Composing Event Handler Functions in React

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rajdeep singh

Rajdeep singh

JavaScript || Reactjs || Nextjs || Python || Rust || Biotechnology || Bioinformatic || Front-end Developer || Writer || https://officialrajdeepsingh.dev/

More from Medium

Build the static blog with Next.js and Markdown

Data fetching overview in Next.js

Build Restaurant Website with Next.js and Cosmic

Sending Emails with NextJS and Amazon Simple Email Services (SES)