Skip to content

Commit

Permalink
Improve content editing features, enable preview and SEO (#59)
Browse files Browse the repository at this point in the history
Why:
- collection and content management had some issues, such as `Author`
`slug` field not populating automatically (issue #13 ), social links
were not being correctly pushed to the frontend;

How:
- this update fixes issue #13 by enabling author collection to generate
a slug from the author name field;
- SEO plugin is now enabled, allowing for content-specific meta to be
generated from the dashboard;
- Live preview and Page Preview are also now correctly enabled and
available for all collections (screenshots below);
- minor changes to how Author Socials' field are rendered, making them
optional, improving clarity;
- deleted unused collections and respective dependencies;
- add improvements to content editing legibility and add a toolbar to
give more options to the user instead of just relying on `/` commands;

Screenshots:

## New Author socials fields

![imagem](https://github.com/user-attachments/assets/c3cd6149-d138-4f97-a2ae-b2864723b9e0)



## SEO Plugin 

Configuring meta description:

![imagem](https://github.com/user-attachments/assets/173de3f9-5f79-47c9-baf0-63f64c8c03ef)

How it is rendered when sharing:

![imagem](https://github.com/user-attachments/assets/4ccb67aa-80cb-4473-a2bf-69e3757f0551)

## Live Preview

![imagem](https://github.com/user-attachments/assets/e303550f-0017-4819-bc99-298128b5dfad)


## Updated Lexical editor


![imagem](https://github.com/user-attachments/assets/0a1a10a4-1cbc-496c-bfd7-6f05a77ed3d7)
  • Loading branch information
rccsousa authored Oct 22, 2024
1 parent 60913c2 commit a3cc05e
Show file tree
Hide file tree
Showing 97 changed files with 651 additions and 6,451 deletions.
7 changes: 3 additions & 4 deletions src/app/(pages)/authors/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Header } from "../../../_components/Header";
import { fetchContentBySlug } from "@/app/_utilities/contentFetchers";
import { Author } from "@/payload-types";
import { Metadata } from "next";
import { generateMeta } from "@/utilities/generateMeta";

export const dynamic = 'force-dynamic'

Expand Down Expand Up @@ -43,9 +44,7 @@ export async function generateMetadata({ params: paramsPromise}): Promise<Metada
slug: slug,
type: "authors",
})
// @ts-ignore
return generateMeta({doc: author})

return {
// @ts-ignore
title: `Subvisual | ${author.name}`
}
}
11 changes: 5 additions & 6 deletions src/app/(pages)/blogposts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { fetchContentBySlug } from "@/app/_utilities/contentFetchers";
import { Blogpost } from "@/payload-types";
import { Header } from "@/app/_components/Header";
import { Metadata } from "next";
import { generateMeta } from "@/utilities/generateMeta";

const headerStyle = {
'--dynamic-background': 'var(--sub-purple-400)',
Expand Down Expand Up @@ -58,7 +59,7 @@ export default async function BlogpostPage({ params: paramsPromise }) {
</div>
</div>
{// @ts-ignore
blogpost.relatedPosts?.length > 0 && <RelatedContent content={blogpost} />
blogpost.related?.length > 0 && <RelatedContent content={blogpost} />
}
<Subscribe />

Expand All @@ -68,13 +69,11 @@ export default async function BlogpostPage({ params: paramsPromise }) {

export async function generateMetadata({ params: paramsPromise}): Promise<Metadata> {
const { slug } = await paramsPromise
const blogpost = await fetchContentBySlug({
const post = await fetchContentBySlug({
slug: slug,
type: "blogposts",
})
// @ts-ignore
return generateMeta({doc: post})

return {
// @ts-ignore
title: `Subvisual | ${blogpost.title}`
}
}
14 changes: 14 additions & 0 deletions src/app/(pages)/case-studies/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
//
// import { fetchDoc } from '../../../_api/fetchDoc'

import { Metadata } from "next";
import { fetchContentBySlug } from "@/app/_utilities/contentFetchers";
import { generateMeta } from "@/utilities/generateMeta";

export const dynamic = 'force-dynamic'

export default async function CaseStudiesPage() {
Expand All @@ -25,3 +29,13 @@ export default async function CaseStudiesPage() {
</div>
)
}

export async function generateMetadata({ params: paramsPromise}): Promise<Metadata> {
const { slug } = await paramsPromise
const caseStudy = await fetchContentBySlug({
slug: slug,
type: "podcasts",
})
// @ts-ignore
return generateMeta({doc: caseStudy})
}
14 changes: 6 additions & 8 deletions src/app/(pages)/podcasts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Subscribe } from '../../../_blocks/Subscribe'
import { Header } from '@/app/_components/Header'
import { fetchContentBySlug } from "@/app/_utilities/contentFetchers";
import { Metadata } from "next";
import { generateMeta } from "@/utilities/generateMeta";

export const dynamic = 'force-dynamic'

Expand All @@ -33,22 +34,19 @@ export default async function PodcastEpisodesPage({params: paramsPromise}) {
<Header style={headerStyle} />
<EpisodeHead episode={episode} />
<EpisodeContent episode={episode} />
<RelatedContent content={episode} />
{/* @ts-ignore */}
{episode.related?.length > 0 && <RelatedContent content={episode} />}
<Subscribe />
</div>
)
}

export async function generateMetadata({ params: paramsPromise}): Promise<Metadata> {
const { slug } = await paramsPromise
const podcast = await fetchContentBySlug({
const episode = await fetchContentBySlug({
slug: slug,
type: "podcasts",
})

return {
// @ts-ignore
title: `Subvisual | ${podcast.title}`,

}
// @ts-ignore
return generateMeta({doc: episode})
}
14 changes: 14 additions & 0 deletions src/app/(pages)/talks-and-roundtables/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
//
// import { fetchDoc } from '../../../_api/fetchDoc'

import { Metadata } from "next";
import { fetchContentBySlug } from "@/app/_utilities/contentFetchers";
import { generateMeta } from "@/utilities/generateMeta";

export const dynamic = 'force-dynamic'

export default async function TalksAndRoundTablesPage() {
Expand All @@ -25,3 +29,13 @@ export default async function TalksAndRoundTablesPage() {
</div>
)
}

export async function generateMetadata({ params: paramsPromise}): Promise<Metadata> {
const { slug } = await paramsPromise
const talk = await fetchContentBySlug({
slug: slug,
type: "talks-and-roundtables",
})
// @ts-ignore
return generateMeta({doc: talk})
}
42 changes: 20 additions & 22 deletions src/app/(payload)/admin/importMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { RichTextField as RichTextField_1 } from '@payloadcms/richtext-lexical/c
import { getGenerateComponentMap as getGenerateComponentMap_2 } from '@payloadcms/richtext-lexical/generateComponentMap'
import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_3 } from '@payloadcms/richtext-lexical/client'
import { FixedToolbarFeatureClient as FixedToolbarFeatureClient_4 } from '@payloadcms/richtext-lexical/client'
import { HeadingFeatureClient as HeadingFeatureClient_5 } from '@payloadcms/richtext-lexical/client'
import { UnderlineFeatureClient as UnderlineFeatureClient_6 } from '@payloadcms/richtext-lexical/client'
import { BoldFeatureClient as BoldFeatureClient_7 } from '@payloadcms/richtext-lexical/client'
import { ItalicFeatureClient as ItalicFeatureClient_8 } from '@payloadcms/richtext-lexical/client'
import { LinkFeatureClient as LinkFeatureClient_9 } from '@payloadcms/richtext-lexical/client'
import { UnderlineFeatureClient as UnderlineFeatureClient_5 } from '@payloadcms/richtext-lexical/client'
import { BoldFeatureClient as BoldFeatureClient_6 } from '@payloadcms/richtext-lexical/client'
import { ItalicFeatureClient as ItalicFeatureClient_7 } from '@payloadcms/richtext-lexical/client'
import { LinkFeatureClient as LinkFeatureClient_8 } from '@payloadcms/richtext-lexical/client'
import { SlugComponent as SlugComponent_9 } from '@/fields/slug/SlugComponent'
import { OverviewComponent as OverviewComponent_10 } from '@payloadcms/plugin-seo/client'
import { MetaTitleComponent as MetaTitleComponent_11 } from '@payloadcms/plugin-seo/client'
import { MetaImageComponent as MetaImageComponent_12 } from '@payloadcms/plugin-seo/client'
import { MetaDescriptionComponent as MetaDescriptionComponent_13 } from '@payloadcms/plugin-seo/client'
import { PreviewComponent as PreviewComponent_14 } from '@payloadcms/plugin-seo/client'
import { SlugComponent as SlugComponent_15 } from '@/fields/slug/SlugComponent'
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_16 } from '@payloadcms/richtext-lexical/client'
import { BlocksFeatureClient as BlocksFeatureClient_17 } from '@payloadcms/richtext-lexical/client'
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_15 } from '@payloadcms/richtext-lexical/client'
import { BlocksFeatureClient as BlocksFeatureClient_16 } from '@payloadcms/richtext-lexical/client'
import { HeadingFeatureClient as HeadingFeatureClient_17 } from '@payloadcms/richtext-lexical/client'
import { UploadFeatureClient as UploadFeatureClient_18 } from '@payloadcms/richtext-lexical/client'
import { BlockquoteFeatureClient as BlockquoteFeatureClient_19 } from '@payloadcms/richtext-lexical/client'
import { RelationshipFeatureClient as RelationshipFeatureClient_20 } from '@payloadcms/richtext-lexical/client'
Expand All @@ -29,29 +29,28 @@ import { InlineCodeFeatureClient as InlineCodeFeatureClient_27 } from '@payloadc
import { SuperscriptFeatureClient as SuperscriptFeatureClient_28 } from '@payloadcms/richtext-lexical/client'
import { SubscriptFeatureClient as SubscriptFeatureClient_29 } from '@payloadcms/richtext-lexical/client'
import { StrikethroughFeatureClient as StrikethroughFeatureClient_30 } from '@payloadcms/richtext-lexical/client'
import { LinkToDoc as LinkToDoc_31 } from '@payloadcms/plugin-search/client'
import { default as default_32 } from '@/components/BeforeDashboard'
import { default as default_33 } from '@/components/BeforeLogin'
import { default as default_31 } from '@/components/BeforeDashboard'
import { default as default_32 } from '@/components/BeforeLogin'

export const importMap = {
"@payloadcms/richtext-lexical/client#RichTextCell": RichTextCell_0,
"@payloadcms/richtext-lexical/client#RichTextField": RichTextField_1,
"@payloadcms/richtext-lexical/generateComponentMap#getGenerateComponentMap": getGenerateComponentMap_2,
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_3,
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_4,
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_5,
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_6,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_7,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_8,
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_9,
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_5,
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_6,
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_7,
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_8,
"@/fields/slug/SlugComponent#SlugComponent": SlugComponent_9,
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_10,
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_11,
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_12,
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_13,
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_14,
"@/fields/slug/SlugComponent#SlugComponent": SlugComponent_15,
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_16,
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_17,
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_15,
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_16,
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_17,
"@payloadcms/richtext-lexical/client#UploadFeatureClient": UploadFeatureClient_18,
"@payloadcms/richtext-lexical/client#BlockquoteFeatureClient": BlockquoteFeatureClient_19,
"@payloadcms/richtext-lexical/client#RelationshipFeatureClient": RelationshipFeatureClient_20,
Expand All @@ -65,7 +64,6 @@ export const importMap = {
"@payloadcms/richtext-lexical/client#SuperscriptFeatureClient": SuperscriptFeatureClient_28,
"@payloadcms/richtext-lexical/client#SubscriptFeatureClient": SubscriptFeatureClient_29,
"@payloadcms/richtext-lexical/client#StrikethroughFeatureClient": StrikethroughFeatureClient_30,
"@payloadcms/plugin-search/client#LinkToDoc": LinkToDoc_31,
"@/components/BeforeDashboard#default": default_32,
"@/components/BeforeLogin#default": default_33
"@/components/BeforeDashboard#default": default_31,
"@/components/BeforeLogin#default": default_32
}
19 changes: 19 additions & 0 deletions src/app/(payload)/custom.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.rich-text-lexical * {
max-width: 600px;
margin: 0 auto;
line-height: 2em;
}

.rich-text-lexical h1 {
font-size: var(--size-40);
}

.rich-text-lexical h2,
.rich-text-lexical h3,
.rich-text-lexical h4,
.rich-text-lexical h5,
.rich-text-lexical h6 {
font-size: var(--size-28);

}

6 changes: 2 additions & 4 deletions src/app/_blocks/AuthorContentGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ContentCard from "../../_components/ContentCard";
import { calculateTotalArticles } from "../../_utilities/calculateTotalArticles";
import styles from "./styles.module.css";

export default function AuthorContentGrid({content}) {
export default function AuthorContentGrid({ content }) {

return (
<div className={styles.gridContainer}>
Expand All @@ -18,9 +18,7 @@ export default function AuthorContentGrid({content}) {
<div className={styles.contentGrid}>
{Object.keys(content).map(key =>
content[key].map((contentPiece, i) => (
<div key={i} className={styles.contentCard}>
<ContentCard contentType={key} content={contentPiece} />
</div>
<ContentCard contentType={key} content={contentPiece} rounded/>
)),
)}
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/app/_blocks/BlogpostContent/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@

@media (min-width: 1024px) {

.content h1,
.content h1 {
font-size: var(--size-40);
}

.content h2,
.content h3,
.content h4,
Expand Down
7 changes: 4 additions & 3 deletions src/app/_blocks/EpisodeContent/Contributors/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { AuthorPill } from "@/app/_components/AuthorPill";

import SocialLinks from "@/app/_components/SocialLinks"
export default function Contributors({ className, authors }) {
return (
<div className={className}>
<p className={"outline"}>CONTRIBUTORS</p>
<p className={'outline'}>CONTRIBUTORS</p>
{authors.map((author, i) => (
<div>
{/* Author has to be passed as an Array for compatibility reasons */}
<AuthorPill authors={[author]} />
<SocialLinks socials={author.socials} />
</div>
))}
</div>
);
)
}
2 changes: 1 addition & 1 deletion src/app/_blocks/EpisodeContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function EpisodeContent({ episode }) {
<div className={styles.sharingAndCategories}>
<hr/>
<Share />
<Categories categories={categories} />
{categories && <Categories categories={categories} />}
<RSSFeed className={styles.RSSFeed} />
</div>
</div>
Expand Down
6 changes: 1 addition & 5 deletions src/app/_blocks/HubContentGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ export default function HubContentGrid({ content }) {
<div className={styles.contentGrid}>
{filteredContent.map((article, i) => (
<div className={styles.contentCard}>
<ContentCard

contentType={article.contentType}
content={article.content}
/>
<ContentCard contentType={article.contentType} content={article.content} rounded={false} />
</div>
))}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/_blocks/HubHead/Highlights/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export async function Highlights({ content, main }) {
<div className={styles.metadataContainer}>

<span className={styles.categories}>
{categories.map((category, i) => <CategoryPill key={i} title={category.title} />)}
{categories && categories.map((category, i) => <CategoryPill key={i} title={category.title} />)}
</span>


Expand Down
7 changes: 3 additions & 4 deletions src/app/_blocks/RelatedContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styles from "./styles.module.css";
import ContentCard from "@/app/_components/ContentCard";

export function RelatedContent({ content }) {

return (
<div className={styles.container}>

Expand All @@ -19,10 +20,8 @@ export function RelatedContent({ content }) {
}}
>
{content.related.map((contentPiece, i) => (
<div key={i} className={styles.contentCard}>
<ContentCard contentType={"Blogposts"} content={contentPiece} />
<br />
<Link href={`${contentPiece.slug}`}>{contentPiece.title}</Link>
<div style={{width: '400px'}}>
<ContentCard contentType={"Blogposts"} content={contentPiece} rounded />
</div>
))}
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/app/_components/AuthorSummary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import styles from "./styles.module.css";
import { Author } from "@/payload-types";

export default function AuthorSummary({ author }) {
const { name, role, bio, linkedIn, gitHub, medium, x, featuredImage } = author;
const { authorName, role, bio, linkedIn, gitHub, medium, x, featuredImage, socials } = author;

// TODO: Convert this to an array with names in collection config
const socials = [linkedIn, gitHub, medium, x].filter(Boolean);


return (
<div className={styles.gridContainer}>
Expand All @@ -20,7 +20,7 @@ export default function AuthorSummary({ author }) {
</div>
}
<div className={styles.authorInfo}>
<h5>{name}</h5>
<h5>{authorName}</h5>
<p>{role}</p>
<SocialLinks socials={socials} />
</div>
Expand Down
23 changes: 0 additions & 23 deletions src/app/_components/Authors/index.tsx

This file was deleted.

Loading

0 comments on commit a3cc05e

Please sign in to comment.