Mulaomerović Mahir
Web developer

Hostin blog post without using a database

2024-01-01

A brief overview of the blog without a database. The posts of this blog are markdown files. This article showcases the application architecture and serves as the foundation for a series of articles to follow.

Weighing the pros and cons, I found the downsides of this approach small enough to be ignored, so I proceeded with building this project.


This post will serve as preparation for upcoming posts. The goal is to explain this process in a series of articles for someone who has never worked with Next.js but has basic knowledge of React, HTML, CSS, and JavaScript.


Getting Started


The first step is to install Next.js. I won't reinvent the wheel and explain something that is perfectly explained where it should be sought:

https://nextjs.org/docs/getting-started/installation


During the Next.js installation, it would be wise to choose the option of including Tailwind.


If you take a look at the Next.js documentation, you'll see that two concepts are mentioned frequently: App Router and Page Router. App Router is the new paradigm for building Next.js applications, while Page Router is the old one.


The foundation of my application was set long before App Router appeared, so I continued to develop it using Page Router. I plan to migrate to App Router and document the process, as this will likely be used more frequently with Next.js in the future.


Here are the folder structure images for Page Router and App Router respectively.


Image 1: App Router folder structure in Next.js

Image 2: Page Router folder structure in Next.js

Furthermore, the Next.js configuration file remains untouched.


For Tailwind configuration, minimal additions are made, only including the dominant colors and font to be used. This can be seen in the code box.


module.exports = { mode: 'jit', purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], darkMode: false, // or 'media' or 'class' theme: { colors: { main:{ light: "#F9FAFB", grey:"#D1D5DB", dark: "#111827", blue: "#1E3A8A", red:'#FF0000' } }, extend: { fontFamily:{ outfit: "'Outfit', sans-serif" } }, }, variants: { extend: {}, }, plugins: [], }

Since the web app is very simple, here is the folder structure of the application.


Image 3: App structure

The Pages folder contains three main files for this application and one folder: Index.js, lab.js, app.js, and the blog folder, which contains index.js and [slug].js.


Index.js in the Pages folder is the Home page and represents the most basic HTML page with simple CSS details. It couldn't be simpler.


import Layout from "../../components/Layout"; import Card from "../../components/Card"; import fs from "fs"; import path from "path"; import matter from "gray-matter"; export default function Blog({ posts }) { return ( <Layout> <div className="flex flex-col content-center min-h-screen"> <div className="text-4xl font-semibold md:w-2/6 md:text-6xl border-b-2 mb-12 pt-8"> Articles </div> <div className="flex w-15 self-auto flex-col"> {posts.map((post) => ( <Card key={post.slug} slug={post.slug} author={post.frontmatter.author} category={post.frontmatter.category} content={post.frontmatter.content} date={post.frontmatter.date} description={post.frontmatter.description} title={post.frontmatter.title} /> ))} </div> </div> </Layout> ); } export async function getStaticProps() { const files = fs.readdirSync(path.join("posts")); const posts = files.map((filename) => { const slug = filename.replace(".md", ""); const markdownWithMeta = fs.readFileSync( path.join("posts", filename), "utf-8" ); const { data: frontmatter } = matter(markdownWithMeta); return { slug, frontmatter, }; }); return { props: { posts: posts, }, }; }

Lab.js is the Lab page, which also doesn't have any special effects, at least not at the time of writing this article. It contains a list of projects, which are in a separate application's folder structure. Show a picture of the component folder.


import Layout from "../components/Layout"; import React from "react"; import RestApiProject from "../components/lab-components/Projects/RestApiProject"; import WebSitesProject from "../components/lab-components/Projects/WebSitesProject"; import FullStackAppProject from "../components/lab-components/Projects/FullStackAppProject"; import EthSolAppProject from "../components/lab-components/Projects/EthSolAppProject"; export default function Lab() { return ( <Layout> <div className="min-h-screen"> <EthSolAppProject /> <FullStackAppProject /> <WebSitesProject /> <RestApiProject /> </div> </Layout> ); }

_app.js, although sounding daunting, doesn't have anything special in it. It just renders pages.


import 'tailwindcss/tailwind.css' function MyApp({ Component, pageProps }) { return <div> <Component {...pageProps} /> </div> } export default MyApp

_app.js is a special file used to initialize pages. It's used to include global CSS, persist layout between page changes, and manage state across different pages. This file wraps around your entire application and is executed on every page change.


We will address the Blog folder separately in another article in detail. And this is enough for the first article, so as not to go too broad and deep.

Mahirnextjs tailwindjs architecture guide mardown blog