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:
- Use v0 to generate designs
- Create new blocks in Optimizely SaaS CMS based on types generated by v0
- Add fragments in
Block.graphql
- Create block components in Next.js
- 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!