From 5b7ccf0b671e2999b62befc729a3e517a0433728 Mon Sep 17 00:00:00 2001 From: Bertrand Yuan Date: Mon, 15 Dec 2025 23:48:10 +0800 Subject: initial commit -- the front-end prototype The initial code is base on Anirudh's work. More to see at: https://github.com/techwithanirudh/shadcn-blog Therefore, the code in this commit is under MIT license. --- content/first-post.mdx | 18 ++++ content/markdown-examples.mdx | 100 ++++++++++++++++++ content/pages.mdx | 237 ++++++++++++++++++++++++++++++++++++++++++ content/using-mdx.mdx | 38 +++++++ 4 files changed, 393 insertions(+) create mode 100644 content/first-post.mdx create mode 100644 content/markdown-examples.mdx create mode 100644 content/pages.mdx create mode 100644 content/using-mdx.mdx (limited to 'content') diff --git a/content/first-post.mdx b/content/first-post.mdx new file mode 100644 index 0000000..dbf5f2f --- /dev/null +++ b/content/first-post.mdx @@ -0,0 +1,18 @@ +--- +title: 'First post' +description: This first blog post marks the start of a new journey in sharing ideas, learnings, and experiences. It sets the tone for curiosity, creativity, and personal growth, laying the foundation for future explorations in tech and storytelling. +date: 2025-03-20 +tags: ['nextjs', 'blogging', 'learning'] +image: /images/blog/first-post.png +author: You +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. + +Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. + +Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. + +Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi. + +Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. \ No newline at end of file diff --git a/content/markdown-examples.mdx b/content/markdown-examples.mdx new file mode 100644 index 0000000..d550721 --- /dev/null +++ b/content/markdown-examples.mdx @@ -0,0 +1,100 @@ +--- +title: Markdown Examples +description: Learn to use Markdown for clean, structured formatting in blogs, docs, and notes. Explore examples, pro tips, and practical use cases to level up your writing and make your content easier to read, share, and maintain across platforms. +date: 2025-03-22 +tags: ['guide', 'style', 'markdown'] +image: /images/blog/markdown-examples.png +author: You +--- + +# Markdown Examples + +## h2 Heading + +### h3 Heading + +#### h4 Heading + +##### h5 Heading + +###### h6 Heading + +## Emphasis + +**This is bold text** + +_This is italic text_ + +~~Strikethrough~~ + +## Blockquotes + +> Develop. Preview. Ship. – Vercel + +## Lists + +Unordered + +- Lorem ipsum dolor sit amet +- Consectetur adipiscing elit +- Integer molestie lorem at massa + +Ordered + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + +## Code + +Inline `code` + +```js +export default function Nextra({ Component, pageProps }) { + return ( + <> + + + + + + + ) +} +``` + +## Tables + +| **Option** | **Description** | +| ---------- | --------------------------------------------------------------------------------------------------------------------------- | +| First | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. | +| Second | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. | +| Third | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. | + +## Links + +- [Next.js](https://nextjs.org) +- [Fumadocs](https://fumadocs.vercel.app/) +- [Vercel](http://vercel.com) + +### Footnotes + +- Footnote [^1]. +- Footnote [^2]. + +[^1]: Footnote **can have markup** + + and multiple paragraphs. + +[^2]: Footnote text. diff --git a/content/pages.mdx b/content/pages.mdx new file mode 100644 index 0000000..0e26bf8 --- /dev/null +++ b/content/pages.mdx @@ -0,0 +1,237 @@ +--- +title: Next.js Pages +date: 2025-03-21 +description: Dive into the details of Next.js Pages with examples, dynamic routing, pre-rendering strategies like Static Generation and SSR, and pro tips for building fast, SEO-friendly web apps. Packed with insights and tricks from my latest project! +tags: ['nextjs', 'web'] +image: /images/blog/pages.png +author: You +--- + +In Next.js, a **page** is a [React Component](https://react.dev/reference/react/Component) exported from a `.js`, `.jsx`, `.ts`, or `.tsx` file in the `pages` directory. Each page is associated with a route based on its file name. + +**Example**: If you create `pages/about.js` that exports a React component like below, it will be accessible at `/about`. + +```javascript +function About() { + return
About
+} + +export default About +``` + +### Pages with Dynamic Routes + +Next.js supports pages with dynamic routes. For example, if you create a file called `pages/posts/[id].js`, then it will be accessible at `posts/1`, `posts/2`, etc. + +> To learn more about dynamic routing, check the [Dynamic Routing documentation](https://nextjs.org/docs/routing/dynamic-routes). + +## Pre-rendering + +By default, Next.js **pre-renders** every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO. + +Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive. (This process is called _hydration_.) + +### Two forms of Pre-rendering + +Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page. + +- [**Static Generation (Recommended)**](#static-generation-recommended): The HTML is generated at **build time** and will be reused on each request. +- [**Server-side Rendering**](#server-side-rendering): The HTML is generated on **each request**. + +Importantly, Next.js lets you **choose** which pre-rendering form you'd like to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others. + +We **recommend** using **Static Generation** over Server-side Rendering for performance reasons. Statically generated pages can be cached by CDN with no extra configuration to boost performance. However, in some cases, Server-side Rendering might be the only option. + +You can also use **Client-side Rendering** along with Static Generation or Server-side Rendering. That means some parts of a page can be rendered entirely by client side JavaScript. To learn more, take a look at the [Data Fetching](https://nextjs.org/docs/basic-features/data-fetching/client-side) documentation. + +## Static Generation (Recommended) + +If a page uses **Static Generation**, the page HTML is generated at **build time**. That means in production, the page HTML is generated when you run `next build` . This HTML will then be reused on each request. It can be cached by a CDN. + +In Next.js, you can statically generate pages **with or without data**. Let's take a look at each case. + +### Static Generation without data + +By default, Next.js pre-renders pages using Static Generation without fetching data. Here's an example: + +```javascript +function About() { + return
About
+} + +export default About +``` + +Note that this page does not need to fetch any external data to be pre-rendered. In cases like this, Next.js generates a single HTML file per page during build time. + +### Static Generation with data + +Some pages require fetching external data for pre-rendering. There are two scenarios, and one or both might apply. In each case, you can use a special function Next.js provides: + +1. Your page **content** depends on external data: Use `getStaticProps`. +2. Your page **paths** depend on external data: Use `getStaticPaths` (usually in addition to `getStaticProps`). + +#### Scenario 1: Your page **content** depends on external data + +**Example**: Your blog page might need to fetch the list of blog posts from a CMS (content management system). + +```javascript +// TODO: Need to fetch `posts` (by calling some API endpoint) +// before this page can be pre-rendered. +function Blog({ posts }) { + return ( + + ) +} + +export default Blog +``` + +To fetch this data on pre-render, Next.js allows you to `export` an `async` function called `getStaticProps` from the same file. This function gets called at build time and lets you pass fetched data to the page's `props` on pre-render. + +```javascript +function Blog({ posts }) { + // Render posts... +} + +// This function gets called at build time +export async function getStaticProps() { + // Call an external API endpoint to get posts + const res = await fetch('https://.../posts') + const posts = await res.json() + + // By returning { props: { posts } }, the Blog component + // will receive `posts` as a prop at build time + return { + props: { + posts + } + } +} + +export default Blog +``` + +To learn more about how `getStaticProps` works, check out the [Data Fetching documentation](https://nextjs.org/docs/basic-features/data-fetching/get-static-props). + +#### Scenario 2: Your page paths depend on external data + +Next.js allows you to create pages with **dynamic routes**. For example, you can create a file called `pages/posts/[id].js` to show a single blog post based on `id`. This will allow you to show a blog post with `id: 1` when you access `posts/1`. + +> To learn more about dynamic routing, check the [Dynamic Routing documentation](https://nextjs.org/docs/routing/dynamic-routes). + +However, which `id` you want to pre-render at build time might depend on external data. + +**Example**: suppose that you've only added one blog post (with `id: 1`) to the database. In this case, you'd only want to pre-render `posts/1` at build time. + +Later, you might add the second post with `id: 2`. Then you'd want to pre-render `posts/2` as well. + +So your page **paths** that are pre-rendered depend on external data**.** To handle this, Next.js lets you `export` an `async` function called `getStaticPaths` from a dynamic page (`pages/posts/[id].js` in this case). This function gets called at build time and lets you specify which paths you want to pre-render. + +```javascript +// This function gets called at build time +export async function getStaticPaths() { + // Call an external API endpoint to get posts + const res = await fetch('https://.../posts') + const posts = await res.json() + + // Get the paths we want to pre-render based on posts + const paths = posts.map((post) => ({ + params: { id: post.id } + })) + + // We'll pre-render only these paths at build time. + // { fallback: false } means other routes should 404. + return { paths, fallback: false } +} +``` + +Also in `pages/posts/[id].js`, you need to export `getStaticProps` so that you can fetch the data about the post with this `id` and use it to pre-render the page: + +```javascript +function Post({ post }) { + // Render post... +} + +export async function getStaticPaths() { + // ... +} + +// This also gets called at build time +export async function getStaticProps({ params }) { + // params contains the post `id`. + // If the route is like /posts/1, then params.id is 1 + const res = await fetch(`https://.../posts/${params.id}`) + const post = await res.json() + + // Pass post data to the page via props + return { props: { post } } +} + +export default Post +``` + +To learn more about how `getStaticPaths` works, check out the [Data Fetching documentation](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths). + +### When should I use Static Generation? + +We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request. + +You can use Static Generation for many types of pages, including: + +- Marketing pages +- Blog posts +- E-commerce product listings +- Help and documentation + +You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation. + +On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request. + +In cases like this, you can do one of the following: + +- Use Static Generation with **Client-side Rendering:** You can skip pre-rendering some parts of a page and then use client-side JavaScript to populate them. To learn more about this approach, check out the [Data Fetching documentation](https://nextjs.org/docs/basic-features/data-fetching/client-side). +- Use **Server-Side Rendering:** Next.js pre-renders a page on each request. It will be slower because the page cannot be cached by a CDN, but the pre-rendered page will always be up-to-date. We'll talk about this approach below. + +## Server-side Rendering + +> Also referred to as "SSR" or "Dynamic Rendering". + +If a page uses **Server-side Rendering**, the page HTML is generated on **each request**. + +To use Server-side Rendering for a page, you need to `export` an `async` function called `getServerSideProps`. This function will be called by the server on every request. + +For example, suppose that your page needs to pre-render frequently updated data (fetched from an external API). You can write `getServerSideProps` which fetches this data and passes it to `Page` like below: + +```javascript +function Page({ data }) { + // Render data... +} + +// This gets called on every request +export async function getServerSideProps() { + // Fetch data from external API + const res = await fetch(`https://.../data`) + const data = await res.json() + + // Pass data to the page via props + return { props: { data } } +} + +export default Page +``` + +As you can see, `getServerSideProps` is similar to `getStaticProps`, but the difference is that `getServerSideProps` is run on every request instead of on build time. + +To learn more about how `getServerSideProps` works, check out our [Data Fetching documentation](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props) + +## Summary + +We've discussed two forms of pre-rendering for Next.js. + +- **Static Generation (Recommended):** The HTML is generated at **build time** and will be reused on each request. To make a page use Static Generation, either export the page component, or export `getStaticProps` (and `getStaticPaths` if necessary). It's great for pages that can be pre-rendered ahead of a user's request. You can also use it with Client-side Rendering to bring in additional data. +- **Server-side Rendering:** The HTML is generated on **each request**. To make a page use Server-side Rendering, export `getServerSideProps`. Because Server-side Rendering results in slower performance than Static Generation, use this only if absolutely necessary. \ No newline at end of file diff --git a/content/using-mdx.mdx b/content/using-mdx.mdx new file mode 100644 index 0000000..b91d0af --- /dev/null +++ b/content/using-mdx.mdx @@ -0,0 +1,38 @@ +--- +title: 'Using MDX' +description: Learn MDX in Next.js to mix Markdown with React. This guide shows setup with @next/mdx, usage tips, and examples to embed JSX in posts—ideal for blogs, docs, and interactive tutorials. +date: '2025-03-23' +tags: ['nextjs', 'mdx', 'guide'] +image: /images/blog/using-mdx.png +author: You +--- + +import { Button } from '@/components/ui/button' + +This Next.js app is configured with MDX support using the [`@next/mdx`](https://nextjs.org/docs/app/building-your-application/configuring/mdx) plugin. If you decide not to use MDX, you can remove the configuration from your `next.config.js`. + +## Why MDX? + +MDX is Markdown on steroids — it lets you embed JSX directly inside Markdown. This means you can [mix Markdown with React components](https://mdxjs.com/docs/what-is-mdx/) to build rich, interactive content. + +Perfect for blog posts, documentation, or tutorials that need some React magic ✨. + +## Example + +Here's how you can use a React component directly in MDX: + + + +Yep, that button is fully interactive — thanks to MDX + React. + +## More Links + +- [MDX Syntax Documentation](https://mdxjs.com/docs/what-is-mdx/) +- [Next.js MDX Setup Guide](https://nextjs.org/docs/app/building-your-application/configuring/mdx) +- [Client Components in App Router](https://nextjs.org/docs/app/building-your-application/rendering/client-components) + +> **Note:** Components used in `.mdx` files should be **Client Components** if they use state, effects, or interactivity. + +--- + +Let me know if you're using the Pages Router instead or want the full setup guide with `next.config.js` and loader info — happy to drop that in too. -- cgit v1.2.3