From 24fd71e3ef3d15250fe971721b2addcb2c887914 Mon Sep 17 00:00:00 2001
From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com>
Date: Mon, 2 Sep 2024 12:07:25 +0300
Subject: [PATCH 01/20] Render blog
Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com>
---
apps/engineeringblog/app/page.tsx | 37 +++++++++++-
apps/engineeringblog/content/post-01.mdx | 11 ++++
apps/engineeringblog/content/post-02.mdx | 11 ++++
apps/engineeringblog/content/post-03.mdx | 11 ++++
apps/engineeringblog/package.json | 1 +
pnpm-lock.yaml | 76 +++++++-----------------
6 files changed, 91 insertions(+), 56 deletions(-)
create mode 100644 apps/engineeringblog/content/post-01.mdx
create mode 100644 apps/engineeringblog/content/post-02.mdx
create mode 100644 apps/engineeringblog/content/post-03.mdx
diff --git a/apps/engineeringblog/app/page.tsx b/apps/engineeringblog/app/page.tsx
index 424794867..69529c34a 100644
--- a/apps/engineeringblog/app/page.tsx
+++ b/apps/engineeringblog/app/page.tsx
@@ -1,9 +1,42 @@
import { Box, Container } from "@mui/material";
+import fs from "fs";
+import path from "path";
+import matter from "gray-matter";
-export default function index() {
+export function getAllPosts() {
+ const postsDirectory = path.join(process.cwd(), "content");
+ const fileNames = fs
+ .readdirSync(postsDirectory)
+ .filter((fileName) => fileName.endsWith(".mdx"));
+
+ return fileNames.map((fileName) => {
+ const filePath = path.join(postsDirectory, fileName);
+ const fileContents = fs.readFileSync(filePath, "utf8");
+ const { data } = matter(fileContents);
+
+ return {
+ slug: fileName.replace(/\.mdx$/, ""),
+ title: data.title,
+ description: data.description,
+ date: data.date,
+ featuredImage: data?.featuredImage,
+ };
+ });
+}
+
+export default async function index() {
+ const posts = await getAllPosts();
return (
- Homepage
+
+ {posts.map((post) => (
+
+ {post.title}
+ {post.description}
+ {post.date}
+
+ ))}
+
);
}
diff --git a/apps/engineeringblog/content/post-01.mdx b/apps/engineeringblog/content/post-01.mdx
new file mode 100644
index 000000000..821390f04
--- /dev/null
+++ b/apps/engineeringblog/content/post-01.mdx
@@ -0,0 +1,11 @@
+---
+title: "Post 01"
+date: "2020-01-01"
+description: "This is the first post"
+---
+
+Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
+
+## Section 1
+
+Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/content/post-02.mdx b/apps/engineeringblog/content/post-02.mdx
new file mode 100644
index 000000000..b45f29f9a
--- /dev/null
+++ b/apps/engineeringblog/content/post-02.mdx
@@ -0,0 +1,11 @@
+---
+title: "Post 02"
+date: "2020-02-02"
+description: "This is the second post"
+---
+
+Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
+
+## Section 1
+
+Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/content/post-03.mdx b/apps/engineeringblog/content/post-03.mdx
new file mode 100644
index 000000000..68d4128a6
--- /dev/null
+++ b/apps/engineeringblog/content/post-03.mdx
@@ -0,0 +1,11 @@
+---
+title: "Post 03"
+date: "2020-03-03"
+description: "This is the third post"
+---
+
+Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
+
+## Section 1
+
+Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/package.json b/apps/engineeringblog/package.json
index 00218ad5a..8e51ee164 100644
--- a/apps/engineeringblog/package.json
+++ b/apps/engineeringblog/package.json
@@ -22,6 +22,7 @@
"@mui/material-nextjs": "^5.16.1",
"@mui/utils": "^5.16.6",
"@next/mdx": "^14.2.5",
+ "gray-matter": "^4.0.3",
"next": "^14.2.5",
"react": "^18",
"react-dom": "^18"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9303013f3..9b677e157 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -97,7 +97,7 @@ importers:
version: 1.0.7(@swc/core@1.7.6(@swc/helpers@0.5.5))(ajv@8.17.1)(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))(sass@1.69.4)
'@payloadcms/db-mongodb':
specifier: ^1.7.1
- version: 1.7.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.623.0))(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))
+ version: 1.7.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.621.0))(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))
'@payloadcms/plugin-cloud-storage':
specifier: ^1.1.3
version: 1.1.3(@aws-sdk/client-s3@3.623.0)(@aws-sdk/lib-storage@3.623.0(@aws-sdk/client-s3@3.623.0))(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))
@@ -133,7 +133,7 @@ importers:
version: 1.9.4
migrate-mongo:
specifier: ^11.0.0
- version: 11.0.0(mongodb@4.17.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.623.0)))
+ version: 11.0.0(mongodb@4.17.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.621.0)))
monaco-editor:
specifier: ^0.50.0
version: 0.50.0
@@ -236,7 +236,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0))
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
identity-obj-proxy:
specifier: ^3.0.0
version: 3.0.0
@@ -435,7 +435,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5)))
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
identity-obj-proxy:
specifier: ^3.0.0
version: 3.0.0
@@ -872,7 +872,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5)))
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
identity-obj-proxy:
specifier: ^3.0.0
version: 3.0.0
@@ -936,6 +936,9 @@ importers:
'@next/mdx':
specifier: ^14.2.5
version: 14.2.6(@mdx-js/loader@3.0.1(webpack@5.93.0))(@mdx-js/react@3.0.1(@types/react@18.3.3)(react@18.3.1))
+ gray-matter:
+ specifier: ^4.0.3
+ version: 4.0.3
next:
specifier: ^14.2.5
version: 14.2.5(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.3)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4)
@@ -975,7 +978,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0)
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
prettier:
specifier: ^3.3.3
version: 3.3.3
@@ -1192,7 +1195,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(esbuild@0.21.5))
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
eslint-plugin-module-resolver:
specifier: ^1.5.0
version: 1.5.0
@@ -1291,7 +1294,7 @@ importers:
version: 5.0.0-alpha.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3)
formik-mui-lab:
specifier: ^1.0.0
- version: 1.0.0(zaghcs6biehwgpwawq74yfrfry)
+ version: 1.0.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/lab@5.0.0-alpha.155(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3)
jwt-decode:
specifier: ^4.0.0
version: 4.0.0
@@ -1376,7 +1379,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0)
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
identity-obj-proxy:
specifier: ^3.0.0
version: 3.0.0
@@ -1566,7 +1569,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5)))
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
jest:
specifier: ^29.7.0
version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.6(@swc/helpers@0.5.5))(@types/node@20.14.14)(typescript@5.5.4))
@@ -1690,7 +1693,7 @@ importers:
version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0)
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
prettier:
specifier: ^3.3.3
version: 3.3.3
@@ -18221,7 +18224,7 @@ snapshots:
- utf-8-validate
- webpack-dev-server
- '@payloadcms/db-mongodb@1.7.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.623.0))(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))':
+ '@payloadcms/db-mongodb@1.7.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.621.0))(payload@2.25.0(@swc/helpers@0.5.5)(@types/react@18.3.3)(encoding@0.1.13)(typescript@5.5.4)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))':
dependencies:
bson-objectid: 2.0.4
deepmerge: 4.3.1
@@ -23701,7 +23704,7 @@ snapshots:
array.prototype.find: 2.2.3
debug: 3.2.7
enhanced-resolve: 0.9.1
- eslint-plugin-import: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
find-root: 1.1.0
hasown: 2.0.2
interpret: 1.4.0
@@ -23719,7 +23722,7 @@ snapshots:
array.prototype.find: 2.2.3
debug: 3.2.7
enhanced-resolve: 0.9.1
- eslint-plugin-import: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
find-root: 1.1.0
hasown: 2.0.2
interpret: 1.4.0
@@ -23737,7 +23740,7 @@ snapshots:
array.prototype.find: 2.2.3
debug: 3.2.7
enhanced-resolve: 0.9.1
- eslint-plugin-import: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
find-root: 1.1.0
hasown: 2.0.2
interpret: 1.4.0
@@ -23755,7 +23758,7 @@ snapshots:
array.prototype.find: 2.2.3
debug: 3.2.7
enhanced-resolve: 0.9.1
- eslint-plugin-import: 2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0))(eslint@8.57.0)
find-root: 1.1.0
hasown: 2.0.2
interpret: 1.4.0
@@ -23803,16 +23806,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.8.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))(eslint@8.57.0):
- dependencies:
- debug: 3.2.7
- optionalDependencies:
- eslint: 8.57.0
- eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0))
- transitivePeerDependencies:
- - supports-color
-
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))))(eslint@8.57.0):
dependencies:
array-includes: 3.1.8
@@ -23894,31 +23887,6 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.29.1(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0):
- dependencies:
- array-includes: 3.1.8
- array.prototype.findlastindex: 1.2.5
- array.prototype.flat: 1.3.2
- array.prototype.flatmap: 1.3.2
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.57.0
- eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.1(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.93.0(@swc/core@1.7.6(@swc/helpers@0.5.5))(webpack-cli@4.10.0)))(eslint@8.57.0)
- hasown: 2.0.2
- is-core-module: 2.15.0
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- object.groupby: 1.0.3
- object.values: 1.2.0
- semver: 6.3.1
- tsconfig-paths: 3.15.0
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
-
eslint-plugin-jest-dom@5.4.0(@testing-library/dom@10.1.0)(eslint@8.57.0):
dependencies:
'@babel/runtime': 7.25.0
@@ -24545,8 +24513,8 @@ snapshots:
combined-stream: 1.0.8
mime-types: 2.1.35
- formik-mui-lab@1.0.0(zaghcs6biehwgpwawq74yfrfry):
- dependencies:
+ ? formik-mui-lab@1.0.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/lab@5.0.0-alpha.155(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(formik@2.4.6(react@18.3.1))(react@18.3.1)(tiny-warning@1.0.3)
+ : dependencies:
'@emotion/react': 11.13.0(@types/react@18.3.3)(react@18.3.1)
'@emotion/styled': 11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)
'@mui/lab': 5.0.0-alpha.155(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.6(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.0(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -26991,7 +26959,7 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
- migrate-mongo@11.0.0(mongodb@4.17.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.623.0))):
+ migrate-mongo@11.0.0(mongodb@4.17.1(@aws-sdk/client-sso-oidc@3.623.0(@aws-sdk/client-sts@3.621.0))):
dependencies:
cli-table3: 0.6.5
commander: 9.5.0
From 4d31d0ae533f288873434d55ceeab11e8269687b Mon Sep 17 00:00:00 2001
From: Kipruto <43873157+kelvinkipruto@users.noreply.github.com>
Date: Mon, 2 Sep 2024 12:57:07 +0300
Subject: [PATCH 02/20] Working blog page
---
apps/engineeringblog/app/page.tsx | 29 ++++---
.../components/Article/ArticleCard.tsx | 71 ++++++++++++++++++
.../components/Article/index.ts | 3 +
apps/engineeringblog/content/post-01.mdx | 1 +
apps/engineeringblog/content/post-02.mdx | 1 +
apps/engineeringblog/package.json | 1 +
.../public/images/logo-dark.png | Bin 0 -> 982 bytes
.../public/images/logo-light.png | Bin 0 -> 982 bytes
pnpm-lock.yaml | 3 +
9 files changed, 99 insertions(+), 10 deletions(-)
create mode 100644 apps/engineeringblog/components/Article/ArticleCard.tsx
create mode 100644 apps/engineeringblog/components/Article/index.ts
create mode 100644 apps/engineeringblog/public/images/logo-dark.png
create mode 100644 apps/engineeringblog/public/images/logo-light.png
diff --git a/apps/engineeringblog/app/page.tsx b/apps/engineeringblog/app/page.tsx
index 69529c34a..6654e50da 100644
--- a/apps/engineeringblog/app/page.tsx
+++ b/apps/engineeringblog/app/page.tsx
@@ -1,7 +1,9 @@
-import { Box, Container } from "@mui/material";
+import { Container, Grid } from "@mui/material";
import fs from "fs";
import path from "path";
import matter from "gray-matter";
+import ArticleCard from "@/engineeringblog/components/Article";
+import { format } from "date-fns";
export function getAllPosts() {
const postsDirectory = path.join(process.cwd(), "content");
@@ -18,7 +20,7 @@ export function getAllPosts() {
slug: fileName.replace(/\.mdx$/, ""),
title: data.title,
description: data.description,
- date: data.date,
+ date: format(new Date(data.date), "MMM dd, yyyy"),
featuredImage: data?.featuredImage,
};
});
@@ -26,17 +28,24 @@ export function getAllPosts() {
export default async function index() {
const posts = await getAllPosts();
+
+ if (!posts) {
+ return
No posts!
;
+ }
+
return (
-
- {posts.map((post) => (
-
- {post.title}
- {post.description}
- {post.date}
-
+
+ {posts?.map((article) => (
+
+
+
))}
-
+
);
}
diff --git a/apps/engineeringblog/components/Article/ArticleCard.tsx b/apps/engineeringblog/components/Article/ArticleCard.tsx
new file mode 100644
index 000000000..b39785700
--- /dev/null
+++ b/apps/engineeringblog/components/Article/ArticleCard.tsx
@@ -0,0 +1,71 @@
+import {
+ Card,
+ CardActionArea,
+ CardContent,
+ CardMedia,
+ Typography,
+} from "@mui/material";
+import React from "react";
+
+type Article = {
+ slug: string;
+ title: string;
+ description: string;
+ date: string;
+ featuredImage: string;
+};
+
+export type ArticleCardProps = {
+ article: Article;
+};
+
+const ArticleCard = React.forwardRef(function ArticleCard(
+ props: ArticleCardProps,
+ ref: React.Ref,
+) {
+ const { article } = props;
+
+ return (
+
+
+
+
+ {article.title}
+
+ {article.date}
+
+
+
+
+ );
+});
+
+export default ArticleCard;
diff --git a/apps/engineeringblog/components/Article/index.ts b/apps/engineeringblog/components/Article/index.ts
new file mode 100644
index 000000000..e93a343b5
--- /dev/null
+++ b/apps/engineeringblog/components/Article/index.ts
@@ -0,0 +1,3 @@
+import ArticleCard from "./ArticleCard";
+
+export default ArticleCard;
diff --git a/apps/engineeringblog/content/post-01.mdx b/apps/engineeringblog/content/post-01.mdx
index 821390f04..dc897d5d2 100644
--- a/apps/engineeringblog/content/post-01.mdx
+++ b/apps/engineeringblog/content/post-01.mdx
@@ -2,6 +2,7 @@
title: "Post 01"
date: "2020-01-01"
description: "This is the first post"
+featuredImage: "/images/logo-dark.png"
---
Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
diff --git a/apps/engineeringblog/content/post-02.mdx b/apps/engineeringblog/content/post-02.mdx
index b45f29f9a..9d80ee3bb 100644
--- a/apps/engineeringblog/content/post-02.mdx
+++ b/apps/engineeringblog/content/post-02.mdx
@@ -2,6 +2,7 @@
title: "Post 02"
date: "2020-02-02"
description: "This is the second post"
+featuredImage: "/images/logo-light.png"
---
Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
diff --git a/apps/engineeringblog/package.json b/apps/engineeringblog/package.json
index 8e51ee164..19c5d695a 100644
--- a/apps/engineeringblog/package.json
+++ b/apps/engineeringblog/package.json
@@ -22,6 +22,7 @@
"@mui/material-nextjs": "^5.16.1",
"@mui/utils": "^5.16.6",
"@next/mdx": "^14.2.5",
+ "date-fns": "^3.6.0",
"gray-matter": "^4.0.3",
"next": "^14.2.5",
"react": "^18",
diff --git a/apps/engineeringblog/public/images/logo-dark.png b/apps/engineeringblog/public/images/logo-dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..570eda132a4b73a148e92233369f6d0e34a3d84d
GIT binary patch
literal 982
zcmeAS@N?(olHy`uVBq!ia0y~yV7v{)|5=!UB5yOZ)PadlKZr2TTH%qPP}Kyw6n3e{fpyH2@&lhY-R%K$L7h_@8|BZ^Zlxyb|~SpTB!QM
zKLv$o!2PgoZv2Ji7YoxDenXMmy?6J2J)>go?51uA__BS|IPQFN$vpkIREh
zgaTub!N2c!uq)`Hg1i;BF>r9_V8QK_xyyfR{<~`0sb6am6J_-l2T;;-(%L5I}ozu}&?tW1^d&_LQ
z?cbK|*zuSj7O3A7C$75fnD_TEL}0tiyU^b&Hhb-4UcUD@#86wFcgI~<+4VP8i+zHJ
z-t2{zdU>}B_8*(yy6*Ij((kFo)vfD7Hy_Ny
zdOkA}=(J*}s=F=SztcWuZ@#s2H^ZZCmQiA-b2qhj&(?=Z`~JDOt153jC(!fn;t%y&
z?$VzoZG;pjze_#_zGm7Hdi}B9yql%}R%?~r^GA)M!ta+Ksp|f|b1NDtj^$XsKinX8
zam%W`i0B2gs&D-Z7N1&xnrz#F$>Dxf_!-^oQ)p53=uzD9<dlKZr2TTH%qPP}Kyw6n3e{fpyH2@&lhY-R%K$L7h_@8|BZ^Zlxyb|~SpTB!QM
zKLv$o!2PgoZv2Ji7YoxDenXMmy?6J2J)>go?51uA__BS|IPQFN$vpkIREh
zgaTub!N2c!uq)`Hg1i;BF>r9_V8QK_xyyfR{<~`0sb6am6J_-l2T;;-(%L5I}ozu}&?tW1^d&_LQ
z?cbK|*zuSj7O3A7C$75fnD_TEL}0tiyU^b&Hhb-4UcUD@#86wFcgI~<+4VP8i+zHJ
z-t2{zdU>}B_8*(yy6*Ij((kFo)vfD7Hy_Ny
zdOkA}=(J*}s=F=SztcWuZ@#s2H^ZZCmQiA-b2qhj&(?=Z`~JDOt153jC(!fn;t%y&
z?$VzoZG;pjze_#_zGm7Hdi}B9yql%}R%?~r^GA)M!ta+Ksp|f|b1NDtj^$XsKinX8
zam%W`i0B2gs&D-Z7N1&xnrz#F$>Dxf_!-^oQ)p53=uzD9<
Date: Mon, 2 Sep 2024 13:28:02 +0300
Subject: [PATCH 03/20] Render single blog
Signed-off-by: Kipruto <43873157+kelvinkipruto@users.noreply.github.com>
---
apps/engineeringblog/app/[slug]/page.tsx | 30 +++++++++++++++++++
apps/engineeringblog/app/articles/page.tsx | 3 --
.../app/articles/sample-1/demo-1.tsx | 17 -----------
.../app/articles/sample-1/page.mdx | 14 ---------
apps/engineeringblog/app/page.tsx | 7 ++++-
5 files changed, 36 insertions(+), 35 deletions(-)
create mode 100644 apps/engineeringblog/app/[slug]/page.tsx
delete mode 100644 apps/engineeringblog/app/articles/page.tsx
delete mode 100644 apps/engineeringblog/app/articles/sample-1/demo-1.tsx
delete mode 100644 apps/engineeringblog/app/articles/sample-1/page.mdx
diff --git a/apps/engineeringblog/app/[slug]/page.tsx b/apps/engineeringblog/app/[slug]/page.tsx
new file mode 100644
index 000000000..b7499b8a3
--- /dev/null
+++ b/apps/engineeringblog/app/[slug]/page.tsx
@@ -0,0 +1,30 @@
+import fs from "fs";
+import matter from "gray-matter";
+import path from "path";
+import { format } from "date-fns";
+
+async function getBlogPost(slug: string) {
+ const postsDirectory = path.join(process.cwd(), "content");
+ const filePath = path.join(postsDirectory, `${slug}.mdx`);
+ const fileContents = fs.readFileSync(filePath, "utf8");
+ const { data, content } = matter(fileContents);
+
+ return {
+ slug,
+ title: data.title,
+ description: data.description,
+ date: format(new Date(data.date), "MMM dd, yyyy"),
+ content,
+ };
+}
+
+export default async function Page({ params }: { params: { slug: string } }) {
+ const post = await getBlogPost(params.slug);
+ return (
+
+
{post.title}
+
{post.date}
+
+
+ );
+}
diff --git a/apps/engineeringblog/app/articles/page.tsx b/apps/engineeringblog/app/articles/page.tsx
deleted file mode 100644
index 34de2708e..000000000
--- a/apps/engineeringblog/app/articles/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ArticlesHome() {
- return List of Articles
;
-}
diff --git a/apps/engineeringblog/app/articles/sample-1/demo-1.tsx b/apps/engineeringblog/app/articles/sample-1/demo-1.tsx
deleted file mode 100644
index ffa3c9cb3..000000000
--- a/apps/engineeringblog/app/articles/sample-1/demo-1.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import Stack from "@mui/material/Stack";
-import Button from "@mui/material/Button";
-
-export function Demo1() {
- return (
-
-
Demo 1
-
This is a demo component with MUI components belows.
-
-
- Text
- Contained
- Outlined
-
-
- );
-}
diff --git a/apps/engineeringblog/app/articles/sample-1/page.mdx b/apps/engineeringblog/app/articles/sample-1/page.mdx
deleted file mode 100644
index 6e6943c42..000000000
--- a/apps/engineeringblog/app/articles/sample-1/page.mdx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Demo1 } from "./demo-1";
-
-# Sample article 1
-
-This is a sample article 1.
-
-
-
-Sample React component above imported by the following code:
-
-````tsx
-
-```tsx
-````
diff --git a/apps/engineeringblog/app/page.tsx b/apps/engineeringblog/app/page.tsx
index 6654e50da..2c0e1d0d5 100644
--- a/apps/engineeringblog/app/page.tsx
+++ b/apps/engineeringblog/app/page.tsx
@@ -34,7 +34,12 @@ export default async function index() {
}
return (
-
+
Date: Tue, 3 Sep 2024 10:46:20 +0300
Subject: [PATCH 04/20] Update blog content
---
apps/engineeringblog/app/page.tsx | 8 +-
.../content/exploring-next-js.mdx | 42 ++++++
.../content/javascript-generators.mdx | 140 ++++++++++++++++++
.../content/mastering-docker.mdx | 96 ++++++++++++
apps/engineeringblog/content/post-01.mdx | 12 --
apps/engineeringblog/content/post-02.mdx | 12 --
apps/engineeringblog/content/post-03.mdx | 11 --
.../public/blog/exploring-next-js.png | Bin 0 -> 14264 bytes
.../public/blog/javascript-generators.jpeg | Bin 0 -> 14104 bytes
.../public/blog/mastering-docker.png | Bin 0 -> 20924 bytes
.../public/images/logo-dark.png | Bin 982 -> 0 bytes
.../public/images/logo-light.png | Bin 982 -> 0 bytes
12 files changed, 280 insertions(+), 41 deletions(-)
create mode 100644 apps/engineeringblog/content/exploring-next-js.mdx
create mode 100644 apps/engineeringblog/content/javascript-generators.mdx
create mode 100644 apps/engineeringblog/content/mastering-docker.mdx
delete mode 100644 apps/engineeringblog/content/post-01.mdx
delete mode 100644 apps/engineeringblog/content/post-02.mdx
delete mode 100644 apps/engineeringblog/content/post-03.mdx
create mode 100644 apps/engineeringblog/public/blog/exploring-next-js.png
create mode 100644 apps/engineeringblog/public/blog/javascript-generators.jpeg
create mode 100644 apps/engineeringblog/public/blog/mastering-docker.png
delete mode 100644 apps/engineeringblog/public/images/logo-dark.png
delete mode 100644 apps/engineeringblog/public/images/logo-light.png
diff --git a/apps/engineeringblog/app/page.tsx b/apps/engineeringblog/app/page.tsx
index 2c0e1d0d5..c984784d1 100644
--- a/apps/engineeringblog/app/page.tsx
+++ b/apps/engineeringblog/app/page.tsx
@@ -1,4 +1,5 @@
import { Container, Grid } from "@mui/material";
+import { Section } from "@commons-ui/core";
import fs from "fs";
import path from "path";
import matter from "gray-matter";
@@ -34,12 +35,7 @@ export default async function index() {
}
return (
-
+
response.json()).then((data) => gen.next(data));
+```
+
+2. **Infinite Sequences**
+ Generators are perfect for creating infinite sequences because they yield values one at a time and only compute the next value when requested.
+
+```javascript
+function* idGenerator() {
+ let id = 1;
+ while (true) {
+ yield id++;
+ }
+}
+
+const gen = idGenerator();
+console.log(gen.next().value); // 1
+console.log(gen.next().value); // 2
+console.log(gen.next().value); // 3
+```
+
+3. **Controlling Iterations**
+ Generators provide precise control over how a loop iterates, which is useful in scenarios like lazy evaluation, where you want to compute values only when needed.
+
+```javascript
+function* fibonacci() {
+ let [a, b] = [0, 1];
+ while (true) {
+ yield a;
+ [a, b] = [b, a + b];
+ }
+}
+
+const fib = fibonacci();
+console.log(fib.next().value); // 0
+console.log(fib.next().value); // 1
+console.log(fib.next().value); // 1
+console.log(fib.next().value); // 2
+```
+
+4. **Middleware in Redux-Saga**
+ In the Redux ecosystem, generators are a core feature of Redux-Saga, a middleware library for handling side effects. Sagas, which are written as generator functions, manage asynchronous operations in a clean and readable way, making the flow of data easier to understand.
+
+```javascript
+function* fetchUserData() {
+ try {
+ const user = yield call(Api.fetchUser, action.payload.userId);
+ yield put({ type: "USER_FETCH_SUCCEEDED", user });
+ } catch (e) {
+ yield put({ type: "USER_FETCH_FAILED", message: e.message });
+ }
+}
+```
+
+### Conclusion
+
+JavaScript Generators are a versatile and powerful feature that can simplify complex tasks by providing more control over function execution. They offer a way to manage asynchronous operations, handle large data streams, and build complex algorithms in a more readable and maintainable manner. While async/await has become the standard for handling asynchronous code, generators still hold their place in scenarios that require custom iteration logic or when working with libraries like Redux-Saga.
diff --git a/apps/engineeringblog/content/mastering-docker.mdx b/apps/engineeringblog/content/mastering-docker.mdx
new file mode 100644
index 000000000..5ac48cd62
--- /dev/null
+++ b/apps/engineeringblog/content/mastering-docker.mdx
@@ -0,0 +1,96 @@
+---
+title: "Mastering Docker: A Comprehensive Guide for Developers"
+date: "2020-03-03"
+description: "Docker has revolutionized the way we build, ship, and run applications. It simplifies software development by creating isolated environments, known as containers, that bundle an application and its dependencies together. This ensures consistency across multiple environments and reduces the 'it works on my machine' problem. In this article, we'll dive deep into Docker, exploring its architecture, benefits, common use cases, and best practices."
+featuredImage: "/blog/mastering-docker.png"
+---
+
+### What is Docker?
+
+Docker is an open-source platform that enables developers to automate the deployment of applications inside lightweight, portable containers. Containers are a form of virtualization, but unlike traditional virtual machines (VMs), they share the host system's kernel, making them more efficient in terms of resources and startup time.
+
+Docker provides a standardized unit of software, called a container, that packages code and all its dependencies so the application runs reliably on different computing environments.
+
+### Docker Components
+
+1. **Docker Engine**: The core component that runs on the host OS, Docker Engine is responsible for creating and managing containers. It includes:
+
+ - **Docker Daemon** : The background service running on the host that manages Docker containers.
+ - **Docker CLI**: A command-line interface for interacting with Docker Daemon, enabling users to build, run, and manage containers.
+ - **Docker API**: An interface that allows Docker to be controlled programmatically.
+
+2. **Docker Images**: These are read-only templates used to create containers. An image is built from a series of layers, each representing a different set of filesystem changes, including application code, libraries, and configurations.
+
+3. **Docker Containers**: A running instance of a Docker image, containers are isolated environments that run applications. Each container operates independently, with its own filesystem, networking, and process space.
+
+4. **Docker Hub**: A cloud-based repository where Docker users can store and share container images. Docker Hub contains official images, which are curated by Docker, and community images, which are created by developers around the world.
+
+5. **Docker Compose**: A tool that allows users to define and run multi-container Docker applications. With Docker Compose, you can define a multi-container environment in a single docker-compose.yml file, specifying services, networks, and volumes.
+
+6. **Docker Swarm**: A native clustering and orchestration tool for Docker. It turns a pool of Docker hosts into a single, virtual Docker host, allowing you to scale and manage containers across multiple servers.
+
+### How Docker Works
+
+Docker utilizes a client-server architecture. The Docker client talks to the Docker daemon, which does the heavy lifting of building, running, and managing Docker containers.
+
+1. **Building Docker Images**: Developers start by creating a `Dockerfile`, a text file containing a list of instructions on how to build an image. The `Dockerfile` specifies the base image, application code, dependencies, and any other configurations. When the docker build command is run, Docker reads the `Dockerfile` and creates an image based on those instructions.
+
+2. **Running Docker Containers**: Once the image is built, it can be instantiated as a container using the docker run command. The container runs in an isolated environment, ensuring that the application behaves the same regardless of where it is deployed.
+
+3. **Container Lifecycle**: Docker containers can be started, stopped, and restarted. They can be ephemeral, meaning they run, perform their task, and then terminate, or they can be long-running, staying active as services.
+
+4. **Networking and Volumes**: Docker containers can communicate with each other and the outside world through networks. Volumes are used for persistent storage, allowing data to be stored and shared across containers, even after they stop running.
+
+### Benefits of Using Docker
+
+1. **Consistency Across Environments**: Docker ensures that applications run consistently across different environments, eliminating discrepancies between development, testing, and production environments.
+
+2. **Resource Efficiency**: Containers are lightweight and share the host OS's kernel, making them faster to start and requiring fewer resources compared to VMs.
+
+3. **Simplified Dependency Management**: Docker images contain everything an application needs to run, including libraries and dependencies. This simplifies deployment and reduces the risk of version conflicts.
+
+4. **Scalability**: Docker containers can be easily scaled across multiple machines, enabling horizontal scaling. Tools like Docker Swarm and Kubernetes provide powerful orchestration capabilities for managing large-scale containerized applications.
+
+5. **Isolation**: Containers run in isolated environments, reducing the risk of conflicts between applications running on the same host. This isolation also enhances security by limiting the impact of vulnerabilities.
+
+6. **Portability**: Docker containers can run on any machine with Docker installed, whether it's a developer's laptop, a test server, or a production environment in the cloud.
+
+### Common Use Cases for Docker
+
+1. **Microservices Architecture**: Docker is a natural fit for microservices, where each service is developed, deployed, and scaled independently. Containers allow microservices to run in isolated environments, making it easier to manage dependencies and reduce conflicts.
+
+2. **Continuous Integration/Continuous Deployment (CI/CD)**: Docker streamlines the CI/CD pipeline by providing consistent environments for testing and deployment. This reduces the chances of bugs slipping into production and speeds up the development process.
+
+3. **Dev/Test Environments**: Developers can use Docker to create reproducible development and testing environments. This ensures that all team members are working with the same setup, reducing "it works on my machine" issues.
+
+4. **Legacy Application Modernization**: Docker can be used to containerize legacy applications, allowing them to run on modern infrastructure without requiring significant changes to the codebase.
+
+5. **Data Science and Machine Learning**: Docker provides a consistent environment for data scientists to run their code, ensuring that experiments and models can be reproduced easily. This is particularly useful when sharing work with others or deploying models to production.
+
+### Docker Best Practices
+
+1. **Keep Images Small**: Minimize the size of Docker images by using slim base images and cleaning up unnecessary files during the build process. Smaller images are faster to build, pull, and deploy.
+
+2. **Use Multi-Stage Builds**: Multi-stage builds allow you to use multiple FROM statements in a Dockerfile, enabling you to separate the build environment from the runtime environment. This reduces the final image size by only including what is necessary for running the application.
+
+3. **Leverage Caching**: Docker caches each layer of the image during the build process. Structure your Dockerfile so that the most frequently changed instructions appear later in the file, allowing Docker to reuse cached layers and speed up subsequent builds.
+
+4. **Tag Images Meaningfully**: Use meaningful tags for your Docker images, such as v1.0.0 or latest. This helps in tracking and managing different versions of your images.
+
+5. **Use Volumes for Persistent Data**: Store persistent data in Docker volumes rather than inside containers. This ensures that data is not lost when a container is removed or replaced.
+
+6. **Limit Container Privileges**: Run containers with the least privileges necessary. Avoid running containers as the root user unless absolutely necessary, as this can pose security risks.
+
+7. **Monitor and Log Containers**: Use monitoring and logging tools to keep an eye on your containers' performance and health. Tools like Prometheus, Grafana, and ELK stack can help you track metrics and diagnose issues.
+
+8. **Automate with Docker Compose**: For multi-container applications, use Docker Compose to define and manage services in a docker-compose.yml file. This simplifies the process of starting and stopping multiple containers.
+
+9. **Use Docker Swarm or Kubernetes for Orchestration**: For larger deployments, use Docker Swarm or Kubernetes to manage and scale your containerized applications. These tools provide features like load balancing, service discovery, and automated failover.
+
+10. **Regularly Update and Patch Images**: Keep your Docker images up to date with the latest security patches. Use automated tools like Docker Bench for Security to scan your Docker environment for vulnerabilities.
+
+### Conclusion
+
+Docker has transformed the way we develop, deploy, and manage applications, making it an essential tool for modern software development. By containerizing applications, Docker ensures consistency, efficiency, and scalability across different environments, from development to production.
+
+Whether you're building microservices, streamlining your CI/CD pipeline, or modernizing legacy applications, Docker provides the tools and flexibility needed to succeed. By following best practices and leveraging Docker's powerful features, you can create robust, secure, and maintainable applications that stand the test of time.
diff --git a/apps/engineeringblog/content/post-01.mdx b/apps/engineeringblog/content/post-01.mdx
deleted file mode 100644
index dc897d5d2..000000000
--- a/apps/engineeringblog/content/post-01.mdx
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "Post 01"
-date: "2020-01-01"
-description: "This is the first post"
-featuredImage: "/images/logo-dark.png"
----
-
-Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
-
-## Section 1
-
-Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/content/post-02.mdx b/apps/engineeringblog/content/post-02.mdx
deleted file mode 100644
index 9d80ee3bb..000000000
--- a/apps/engineeringblog/content/post-02.mdx
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "Post 02"
-date: "2020-02-02"
-description: "This is the second post"
-featuredImage: "/images/logo-light.png"
----
-
-Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
-
-## Section 1
-
-Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/content/post-03.mdx b/apps/engineeringblog/content/post-03.mdx
deleted file mode 100644
index 68d4128a6..000000000
--- a/apps/engineeringblog/content/post-03.mdx
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "Post 03"
-date: "2020-03-03"
-description: "This is the third post"
----
-
-Enim non qui velit nulla elit irure minim incididunt tempor. Lorem eu incididunt fugiat cupidatat aute. Veniam esse laboris irure nostrud. Proident et mollit ea ex. Elit commodo veniam irure laboris dolore cupidatat deserunt esse esse reprehenderit ipsum magna.
-
-## Section 1
-
-Veniam ea tempor mollit officia magna deserunt nulla fugiat. In ipsum non magna officia deserunt do nulla irure dolor labore culpa voluptate ipsum officia. Ut nulla nisi ullamco ipsum laboris. Eiusmod occaecat ipsum ullamco voluptate dolor qui non nostrud voluptate aliquip eu.
diff --git a/apps/engineeringblog/public/blog/exploring-next-js.png b/apps/engineeringblog/public/blog/exploring-next-js.png
new file mode 100644
index 0000000000000000000000000000000000000000..647317c19b355770a0835b1bae7401d75a80293a
GIT binary patch
literal 14264
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
E1M?v7kpKVy
literal 0
HcmV?d00001
diff --git a/apps/engineeringblog/public/blog/javascript-generators.jpeg b/apps/engineeringblog/public/blog/javascript-generators.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..149873d68964faa783c093dabc411691003a8e0b
GIT binary patch
literal 14104
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
literal 0
HcmV?d00001
diff --git a/apps/engineeringblog/public/blog/mastering-docker.png b/apps/engineeringblog/public/blog/mastering-docker.png
new file mode 100644
index 0000000000000000000000000000000000000000..a45dad0b4a379e34576e50523c41ea6d9e80e844
GIT binary patch
literal 20924
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