DEV Community

Cover image for shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 1
Ramu Narasinga
Ramu Narasinga

Posted on

shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 1

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.

  1. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 1
  2. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 2 (Coming soon)
  3. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 3 (Coming soon)
  4. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 4 (Coming soon)
  5. shadcn-ui/ui codebase analysis: How is “Blocks” page built — Part 5 (Coming soon)

In part 1, we will look at the following:

  1. Where to find blocks page code in the shadcn-ui/ui repository?
  2. getAllBlockIds function
  3. _getAllBlocks function

These function further call other utility functions that will be explained in the other parts.

Where to find blocks page code in the shadcn-ui/ui repository?

blocks/page.tsx is where you will find Blocks page related code in the shadcn-ui/ui repository

Just because it has only 10 lines of code does not mean it is a simple page, there is a lot going on behind these lines, especially in the lib/blocks.ts, but don’t worry, we will understand the utility functions used in depth later in this article and other parts as well.

BlocksPage gets the blocks from a function named getAllBlockIds() which is imported from lib/blocks and these blocks are mapped with a BlockDisplay component that shows blocks on the Blocks page. Let’s find out what is in getAllBlockIds()

getAllBlockIds function

The below code snippet is picked from lib/blocks.ts

export async function getAllBlockIds(
  style: Style\["name"\] = DEFAULT\_BLOCKS\_STYLE
) {
  const blocks = await \_getAllBlocks(style)
  return blocks.map((block) => block.name)
}
Enter fullscreen mode Exit fullscreen mode

This code snippet is self explanatory, style parameter gets a default value DEFAULT_BLOCKS_STYLE because in the Blocks page, we call getAllBlockIds without any params as shown below:

const blocks = await getAllBlockIds()
Enter fullscreen mode Exit fullscreen mode

But wait, what is the value in DEFAULT\_BLOCKS\_STYLE?

At line 14 in lib/blocks, you will find this below code:

const DEFAULT\_BLOCKS\_STYLE = "default" satisfies Style\["name"\]
Enter fullscreen mode Exit fullscreen mode

“default” satisfies Style[“name”], Style is from register/styles. I just admire the quality of Typescript written in this shadcn-ui/ui. So, _getAllBlocks gets called with a param named style that is initiated to “default”. So far, the code is straight forward. Let’s now understand what is in _getAllBlocks

_getAllBlocks function

The below code snippet is picked from lib/blocks.ts

async function \_getAllBlocks(style: Style\["name"\] = DEFAULT\_BLOCKS\_STYLE) {
  const index = z.record(registryEntrySchema).parse(Index\[style\])

  return Object.values(index).filter(
    (block) => block.type === "components:block"
  )
}
Enter fullscreen mode Exit fullscreen mode

Even though, getAllBlockIds from above calls this function with a parameter, this function still has a default value set to the style parameter.

const index = z.record(registryEntrySchema).parse(Index\[style\])
Enter fullscreen mode Exit fullscreen mode

Code above has the following:

z.record

Record schema in Zod are used to validate types such as Record. This is particularly useful for storing or caching items by ID.

registryEntrySchema

registryEntrySchema defines a schema for the blocks

export const registryEntrySchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  dependencies: z.array(z.string()).optional(),
  devDependencies: z.array(z.string()).optional(),
  registryDependencies: z.array(z.string()).optional(),
  files: z.array(z.string()),
  source: z.string().optional(),
  type: z.enum(\[
    "components:ui",
    "components:component",
    "components:example",
    "components:block",
  \]),
  category: z.string().optional(),
  subcategory: z.string().optional(),
  chunks: z.array(blockChunkSchema).optional(),
})
Enter fullscreen mode Exit fullscreen mode

parse(Index[style])

parse is a schema method to check data is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.

Example:

const stringSchema = z.string();

stringSchema.parse("fish"); // => returns "fish"
stringSchema.parse(12); // throws error
Enter fullscreen mode Exit fullscreen mode

Index is imported from _registry_folder and contains all the components used in shadcn-ui/ui.

Looks like this file gets auto generated by scripts/build-registry.ts and this is also used in CLI package to add shadcn components into your project, more on this in the upcominhg articles.

Basically, we validate Index[“default”] against the registry schema to ensure the auto generated code is valid and is ready for further processing such as showing in blocks page.

_getAllBlocks filters the blocks based on the block type as shown below:

return Object.values(index).filter(
    (block) => block.type === "components:block"
  )
Enter fullscreen mode Exit fullscreen mode

This is how you are able to see components that are specific to Blocks page.

Conclusion:

We looked at two important module functions named getAllBlockIds and _getAllBlocks. I find this code to be pretty self explanatory, I do admire the way zod’s Record schema validations are used on the auto generated registry index json.

Want to learn how to build shadcn-ui/ui from scratch? Check out build-from-scratch

About me:

Website: https://ramunarasinga.com/

Linkedin: https://www.linkedin.com/in/ramu-narasinga-189361128/

Github: https://github.com/Ramu-Narasinga

Email: ramu.narasinga@gmail.com

References:

  1. https://github.com/shadcn-ui/ui/blob/main/apps/www/app/(app)/blocks/page.tsx
  2. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L20
  3. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/blocks.ts#L75
  4. https://github.com/shadcn-ui/ui/blob/main/apps/www/registry/schema.ts#L16

Top comments (0)