ContentQL ContentQL Docs

Blocks Creation

Good to Know

Check the payload blocks to get to know what blocks are in a website.

When you install ContentQL locally, sample blog-related data (such as authors, tags, blogs, and blog details) will be available by default.

File Naming Convention

To create a block, you need to know the folder structure and file naming convention that needs to be followed:

Component.tsx
config.ts

Pre-Requisite for Block Creation

  • Before creating blocks, ensure you have a basic understanding of Fields in Payload CMS.

Block Creation

hero Block Next, we’ll demonstrate how to create the above block, which includes a background image, heading, description, and two buttons(primary, secondary). To start, create a folder inside src/payload/blocks, and name it according to the block you’re creating. In this case, we’ll call it Hero.

Define the configuration for the block in config.ts:

blocks/Hero/config.ts
import { Block } from 'payload';
 
const HeroConfig: Block = {
  slug: 'Hero',
  interfaceName: 'HeroType',
  fields: [
    {
      name: 'heading',
      type: 'text',
      label: 'Heading',
    },
    {
      name: 'description',
      type: 'text',
      label: 'Description',
    },
    {
      name: 'buttonGroup',
      type: 'group',
      fields: [
        {
          name: 'primaryButton',
          type: 'text',
          label: 'Primary Button',
        },
        {
          name: 'secondaryButton',
          type: 'text',
          label: 'Secondary Button',
        },
      ],
    },
    {
      name: 'image',
      type: 'upload',
      label: 'Image',
      relationTo: 'media',
    }
  ],
};
 
export default HeroConfig;

Implement the UI for the block in Component.tsx:

blocks/Hero/Component.tsx
import { HeroType } from '@payload-types';
 
const Hero = ({ ...block }: HeroType) => { 
  return (
    <div className='bg-gray-900'>
      <div className='relative isolate overflow-hidden pt-14'>
        <img
          src={(block?.image as Media)?.url} 
          alt=''
          className='absolute inset-0 -z-10 h-full w-full object-cover'
        />
        <div
          className='absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80'
          aria-hidden='true'
        >
          <div className='relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-20 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]'></div>
        </div>
        <div className='mx-auto max-w-2xl py-32 sm:py-48 lg:py-56'>
          <div className='text-center'>
            <h1 className='text-4xl font-bold tracking-tight text-white sm:text-6xl'>
              {block?.heading}
            </h1>
            <p className='mt-6 text-lg leading-8 text-gray-300'>
              {block?.description}
            </p>
            <div className='mt-10 flex items-center justify-center gap-x-6'>
              <a
                href='#'
                className='rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-400'
              >
                {block?.buttonGroup?.primaryButton}
              </a>
              <a href='#' className='text-sm font-semibold leading-6 text-white'>
                {block?.buttonGroup?.secondaryButton}
                <span aria-hidden='true'>→</span>
              </a>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
 
export default Hero;

Import the component into the main blocks/blocks.ts file:

blocks/blocks.ts
import { DisqusComments } from '@contentql/core/client'
 
import { Details } from './Details'
import { Home } from './Home'
import { List } from './List'
import { Hero } from './Hero'
 
export const blocksJSX = {
  Home,
  Details,
  List,
  Hero, 
}

Import the block configuration into blocks/config.ts file:

blocks/config.ts
import DetailsConfig from './Details/config'
import HomeConfig from './Home/config'
import HeroConfig from './Hero/config'
import ListConfig from './List/config'
 
export const blocksConfig = [HeroConfig, DetailsConfig, ListConfig, FormConfig] 

You’ve successfully created a block! The types for it will be automatically generated in payload-types.ts using the interfaceName defined in the config.tsfile.

info

If types didn't auto-generated in payload-types.ts, run the following command: pnpm generate:types

Admin Panel

Once logged in to the admin panel, navigate to the “Pages” section and create a new page. After providing a title, you’ll see an option to add a “Page Layout.” All previously created blocks will appear in this list with respective label names.

sign up

Now select hero block and save it. Once you fill in the field values, you can now go to the page that you've created and see the magic! You’re now equipped to create themes and blocks in ContentQL! ✨

On this page