Skip to main content

Outline

< > Step Code

Click on the link below 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>
  )
}

Congratulations!

You have completed the Optimizely CMS SaaS Development Fundamentals course. Now, you have gained a solid understanding of core development concepts, including but not limited to data fetching, content modeling, dynamic routing, multilingual support and generating static parameters within the CMS SaaS platform. This foundational knowledge empowers you to build robust and scalable applications using CMS SaaS, and prepares you for our advanced development course, where you'll explore more complex optimization, customization, and real-world implementation strategies.