In this repo is a simple implementation of a markdown static blog, a demo can be seen here, Features include:
Hopefully, from this project and the video, you can learn:
You can follow along with Jolly Coding as we build this on YouTube.
Much of the design of this project is taken from shadcn in his projects, such as shadcn/ui and Taxonomy
npx shadcn-ui@latest init
✔ Which style would you like to use? › Default
✔ Which color would you like to use as base color? › Slate
✔ Would you like to use CSS variables for colors? … no / yes
// app/layout.tsx
import { cn } from "@/lib/utils";
<body
className={cn(
"min-h-screen bg-background font-sans antialiased",
inter.variable
)}
>
{children}
</body>;
// tailwind.config.ts
import { fontFamily } from "tailwindcss/defaultTheme";
...
extend: {
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
...
npx shadcn-ui@latest add button
npm install velite -D
// vilite.config.ts
import { defineConfig, defineCollection, s } from "velite";
const computedFields = <T extends { slug: string }>(data: T) => ({
...data,
slugAsParams: data.slug.split("/").slice(1).join("/"),
});
const posts = defineCollection({
name: "Post",
pattern: "blog/**/*.mdx",
schema: s
.object({
slug: s.path(),
title: s.string().max(99),
description: s.string().max(999).optional(),
date: s.isodate(),
published: s.boolean().default(true),
body: s.mdx(),
})
.transform(computedFields),
});
export default defineConfig({
root: "content",
output: {
data: ".velite",
assets: "public/static",
base: "/static/",
name: "[name]-[hash:6].[ext]",
clean: true,
},
collections: { posts },
mdx: {
rehypePlugins: [],
remarkPlugins: [],
},
});
// next.config.mjs
import { build } from "velite";
/** @type {import('next').NextConfig} */
export default {
// othor next config here...
webpack: (config) => {
config.plugins.push(new VeliteWebpackPlugin());
return config;
},
};
class VeliteWebpackPlugin {
static started = false;
apply(/** @type {import('webpack').Compiler} */ compiler) {
// executed three times in nextjs
// twice for the server (nodejs / edge runtime) and once for the client
compiler.hooks.beforeCompile.tapPromise("VeliteWebpackPlugin", async () => {
if (VeliteWebpackPlugin.started) return;
VeliteWebpackPlugin.started = true;
const dev = compiler.options.mode === "development";
await build({ watch: dev, clean: !dev });
});
}
}
npx shadcn-ui@latest add sheet
npm i next-themes
npx shadcn-ui@latest add dropdown-menu
npm install -D @tailwindcss/typography
// tailwind.config.ts
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
//mdx-components.tsx
const components = {
Image,
Callout,
};
npm i rehype-autolink-headings rehype-pretty-code rehype-slug
import rehypeSlug from "rehype-slug";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
...
mdx: {
rehypePlugins: [
rehypeSlug,
[rehypePrettyCode, { theme: "github-dark" }],
[
rehypeAutolinkHeadings,
{
behavior: "wrap",
properties: {
className: ["subheading-anchor"],
ariaLabel: "Link to section",
},
},
],
],
remarkPlugins: [],
},
npx shadcn-ui@latest add pagination
npx shadcn-ui@latest add avatar
customize your own og playgroud
npm install github-slugger
npx shadcn-ui@latest add badge
npx shadcn-ui@latest add card