shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 2
In this article, I discuss how Blocks page is built on ui.shadcn.com. Blocks page has a lot of utilities used, hence I broke down this Blocks page analysis into 5 parts.
BlockDisplay is used in blocks/page.tsx. In part 1, I explained the code behind fetching blocks; When you visit blocks page on ui.shadcn.com, you will find a lot of blocks rendered, it is in fact from blocks array above. These blocks so far do not contain the code that translates to a components used in an individual block. BlockDisplay has it own logic to deal with rendering components for each block. Important concept here to remember is to pass the minimal information required.
Let’s try to understand the BlockDisplay code at a high level.
import { getBlock } from "@/lib/blocks"import { BlockPreview } from "@/components/block-preview"import { styles } from "@/registry/styles"export async function BlockDisplay({ name }: { name: string }) { const blocks = await Promise.all( styles.map(async (style) => { const block = await getBlock(name, style.name) const hasLiftMode = block?.chunks ? block?.chunks?.length > 0 : false // Cannot (and don't need to) pass to the client. delete block?.component delete block?.chunks return { ...block, hasLiftMode, } }) ) if (!blocks?.length) { return null } return blocks.map((block) => ( <BlockPreview key={`${block.style}-${block.name}`} block={block} /> ))}
There is a blocks array that is populated after Promise.all resolves. Promise.all has an array of styles imported from registry/styles. These styles are mapped over and each style is further processed.
getBlock is a utility function that accepts two parameters, name and style.name and there is also a flag named hasLiftMode that is based on block.chunks.length. block.components and block.chunks are deleted as they are not required on the client side.
These blocks are then mapped over and each block is used in BlockPreview.
Let’s take a step back now and get back on track with out function call stack. We got to readFile from getBlockCode. With this so far, we have understood the getBlockCode. We got to getBlockCode from _getBlockContent and only covered the first line as shown below
In part 3, I will explain how createTempSourceFile, createSourceFile and extractVariable work in order to understand getBlockCode completely. Keep in mind, we still need to get back to getBlock since this is used in BlockDisplay . Did you notice the chain of function calls here? functions following single responsibility principle and self explanatory and modular.
In part 2, I discuss the BlockDisplay component. This component has functions that are chained together so well that it respects the SRP and is quite module.
I will highlight the key function in this chain. It goes like this:
readFile is where you will find the code that reads the source code available at registry/ that loads the “blocks” and is rendered via an iframe. Jesus! I wasn’t expecting magic of this sort.
So far, this only completes getBlockContent explanation, I still need to get back to getBlock and BlockDisplay which has its own complex functions such as createTempSourceFile*,* createSourceFile and extractVariable. I have 0 clue as how they work, but I will make a good attempt to understand and explain them in an easy way in the next article.
Want to learn how to build shadcn-ui/ui from scratch? Check outbuild-from-scratch
Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.