Step 13 of 21 (62% complete)

Add new blocks - About Page

Step Code

The code for this specific step can be found on the following branch:

Click on a link to view the code for this step on GitHub.

To add new blocks for the About page:

  1. Use v0 to generate designs
  2. Create new blocks in Optimizely SaaS CMS based on types generated by v0
  3. Add fragments in Block.graphql
  4. Create block components in Next.js
  5. Add dynamic imports in components/content-area/block.tsx
// other dynamic imports
const AvailabilityBlock = dynamic(() => import('../block/availability-block'))
const ProfileBlock = dynamic(() => import('../block/profile-block'))
const StoryBlock = dynamic(() => import('../block/story-block'))

export const blocks = {
 // other blocks
  AvailabilityBlock,
  ProfileBlock,
  StoryBlock
} as const

Example Blocks genrated by v0:

fragment ProfileBlockFragment on ProfileBlock {
  imageSrc
  bio
  name
  title
}

fragment AvailabilityBlockFragment on AvailabilityBlock {
  availability
  projectTypes
}

fragment StoryBlockFragment on StoryBlock {
  story
  highlights
}


fragment ItemsInContentArea on _IContent {
  #other blocks
  ...ProfileBlockFragment
  ...AvailabilityBlockFragment
  ...StoryBlockFragment
}
// components/block/story-block.tsx

import { Card, CardContent } from '@/components/ui/card'
import { StoryBlock as StoryBlockProps } from '@/lib/optimizely/types/generated'

interface HighlightProps {
  text?: string
}

function Highlight({ text }: HighlightProps) {
  return (
    <div className="my-6 rounded-lg bg-[#009379] p-4 text-white">
      <p>{text}</p>
    </div>
  )
}

export default function StoryBlock({ story, highlights }: StoryBlockProps) {
  return (
    <section className="container mx-auto px-4 py-16">
      <Card className="border-none">
        <CardContent className="p-8">
          <div className="mx-auto max-w-3xl">
            <p className="mb-8 text-xl leading-relaxed text-[#2d2d2d]">
              {story}
            </p>
            {highlights?.map((highlight, index) => (
              <Highlight key={index} text={highlight ?? ''} />
            ))}
          </div>
        </CardContent>
      </Card>
    </section>
  )
}
// components/block/profile-block.tsx

import Image from 'next/image'
import { Card, CardContent } from '@/components/ui/card'
import { ProfileBlock as ProfileBlockProps } from '@/lib/optimizely/types/generated'

export default function ProfileBlock({
  imageSrc,
  name,
  title,
  bio,
}: ProfileBlockProps) {
  return (
    <section className="container mx-auto px-4 py-16">
      <Card className="border-none bg-[#f9e6f0]">
        <CardContent className="p-8">
          <div className="grid items-start gap-12 md:grid-cols-2">
            <div className="relative mx-auto aspect-square w-full max-w-md">
              <Image
                src={imageSrc || '/placeholder.svg'}
                alt={title ?? ''}
                fill
                className="rounded-lg object-cover"
                priority
              />
            </div>
            <div className="space-y-4">
              <h1 className="text-3xl font-bold text-[#2d2d2d]">{name}</h1>
              <p className="text-xl text-[#2d2d2d]">{title}</p>
              <div className="mt-6">
                <h2 className="mb-2 text-lg font-semibold">Bio:</h2>
                <p className="leading-relaxed text-[#2d2d2d]">{bio}</p>
              </div>
            </div>
          </div>
        </CardContent>
      </Card>
    </section>
  )
}
// components/block/availability-block.tsx

import { Card, CardContent } from '@/components/ui/card'
import { AvailabilityBlock as AvailabilityBlockProps } from '@/lib/optimizely/types/generated'

export default function AvailabilityBlock({
  availability,
  projectTypes,
}: AvailabilityBlockProps) {
  return (
    <section className="container mx-auto px-4 py-16">
      <Card className="border-none">
        <CardContent className="p-8">
          <div className="mx-auto max-w-3xl space-y-6">
            <p className="leading-relaxed text-[#2d2d2d]">{availability}</p>
            <div>
              <p className="leading-relaxed text-[#2d2d2d]">
                Projects include:
              </p>
              <ul className="mt-2 list-inside list-disc space-y-1">
                {projectTypes?.map((type, index) => (
                  <li key={index} className="text-[#2d2d2d]">
                    {type}
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </CardContent>
      </Card>
    </section>
  )
}

Have questions? I'm here to help!

Contact Me