Welcome to the first workshop in this series! The final goal of the project is to create a table of contents for the headings in an MDX blog post.
Note: as mentioned in the prerequisites, this challenge is meant for folks who are already familiar with React, Next.js and MDX. If you’ve never worked with these technologies, this series will be quite daunting.
Goals for the entire series
1. Table of contents
workshops 1 and 2
There will be a table of contents that contains all of the h2
and h3
level headings in the blog post.
2. Responsive display
workshop 3
The table of contents will only display when the viewport is wide enough.
3. Sticky positioning
workshop 3
The table of contents will be “sticky” – that is, it won’t scroll off the page when you scroll to see later parts of the blog post.
4. Scroll to headings
workshops 4, 5 and 6
- Each item in the table of contents will be link that will scroll the corresponding blog post heading to the top of the viewport.
- For users who do not have “prefers-reduced-motion” enabled, the page will scroll smoothly to the appropriate heading.
- The scroll will account for the height of the sticky page header at the top.
Scaffoding code
All right! Time to get started with workshop #1: Extract the headings from the MDX.
This workshop starts out with the MDX blog site already written . The blog posts were generated by ChatGPT and shouldn’t be taken seriously. 😅
Before you can start the workshop, you’ll need to follow the “Getting Started” instructions in the project README .
If you’re interested in a series for how to write the MDX blog site that comes with the scaffolding code, please let me know by tagging me in a post on LinkedIn or Twitter !
Workshop goal
- By the end of this workshop, you should see a list of level 2 and level 3 headings in the console when you visit a blog post page.
You can work by using the resources at the bottom of this page only (and your own research and skills), or by looking at the hints – or even by visiting the solution page and then going back and writing the code from memory.
Workshop context
- This workshop is an intermediate step before displaying the table of contents. There is no UI associated with this particular workshop.
- You can assume the headings in the blog post MDX files are written using Markdown syntax (an
h1
is indicated by a single#
,h2
by##
,h3
by###
etc.) - ”Heading” vs. “Header”: I get these mixed up a lot. In HTML-land, a heading is an element of the form
h#
, such ash1
,h2
, etc. A header is an element that shows across the top of an HTML page. - Why level 2 and level 3 headings only? There’s only one level 1 heading , and you can get to it by scrolling to the top of the page. It’s an arbitrary decision to stop at level 3 headings; I’m going on the assumption that level 4 headings will clutter up the table of contents, and folks won’t need to navigate anywhere that specific. Also, none of the blog post (so far) have level 4 headings.
Hints
Hint 1
You can get the MDX content from the blog post in loadBlogPost
, in the src/helpers/file-helpers.ts file. This would be a good place to look for the headings. You can then return the headings from loadBlogPost
(in addition to the frontmatter
and content
items that are already being returned).
Hint 2
Parsing the MDX is best done with regular expressions . If you’re not up on your regular expressions, here’s an example of extracting MDX headings this way . Note: for now we’re not intersted in the id
or the slug
— just the title
and the level
.
Hint 3
You can adapt the example heading extraction code to add the headings to the array only if the level
value is 2
or 3
.
Hint 4
loadBlogPost
is called from src/components/BlogPost/BlogPost.tsx . This is where you can destructure the headings
from the return value and then print them to the console (using console.log
).
Hint 5
Because BlogPost
is a React Server Component , the console.log
output will be shown in the terminal where you’re running npm run dev
– not in the browser console.