Skip to content

Commit 3f1526f

Browse files
committed
feat(web): apply meta from cms data
closed COD-303
1 parent 03505dd commit 3f1526f

21 files changed

Lines changed: 250 additions & 58 deletions

apps/web/app/components/render-pages-doc.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RenderBlocks } from '@codeware/shared/ui/payload-components';
2-
import type { NavigationDoc } from '@codeware/shared/util/payload-api';
2+
import type { NavigationDoc } from '@codeware/shared/util/payload-types';
33

44
/**
55
* Render a pages collection document.

apps/web/app/components/render-posts-doc.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RichText } from '@codeware/shared/ui/payload-components';
2-
import type { NavigationDoc } from '@codeware/shared/util/payload-api';
2+
import type { NavigationDoc } from '@codeware/shared/util/payload-types';
33

44
/**
55
* Render a posts collection document.

apps/web/app/root.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ import {
99
getSiteSettings
1010
} from '@codeware/shared/util/payload-api';
1111
import type { SiteSetting } from '@codeware/shared/util/payload-types';
12-
import type {
13-
LinksFunction,
14-
LoaderFunctionArgs,
15-
MetaFunction
16-
} from '@remix-run/node';
12+
import type { LinksFunction, LoaderFunctionArgs } from '@remix-run/node';
1713
import {
1814
Link,
1915
Links,
@@ -40,12 +36,6 @@ import { ClientHintCheck, getHints } from './utils/client-hints';
4036
import { getPayloadRequestOptions } from './utils/get-payload-request-options';
4137
import { type Theme, getTheme } from './utils/theme.server';
4238

43-
export const meta: MetaFunction<typeof loader> = ({ data }) => [
44-
{
45-
title: data?.siteSettings?.general?.appName ?? ''
46-
}
47-
];
48-
4939
export const links: LinksFunction = () => [
5040
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
5141
{

apps/web/app/routes/($collection).$slug.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
import { findNavigationDoc } from '@codeware/shared/util/payload-api';
2+
import { resolveMeta } from '@codeware/shared/util/payload-utils';
23
import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/node';
34
import { json, useLoaderData, useRouteError } from '@remix-run/react';
45

56
import { Container } from '../components/container';
67
import { ErrorContainer } from '../components/error-container';
78
import { RenderPagesDoc } from '../components/render-pages-doc';
89
import { RenderPostsDoc } from '../components/render-posts-doc';
10+
import { defaultAppName } from '../utils/default-app-name';
911
import { getPayloadRequestOptions } from '../utils/get-payload-request-options';
12+
import { getSiteSettingsFromRoot } from '../utils/get-site-settings-from-root';
1013

1114
type LoaderError = {
1215
message: string;
1316
status: number;
1417
};
1518

16-
// TODO: How to use it properly?
17-
export const meta: MetaFunction<typeof loader> = ({ data }) => {
18-
if (data?.doc.collection === 'pages') {
19-
return [{ title: data.doc.name }];
20-
}
21-
if (data?.doc.collection === 'posts') {
22-
return [{ title: data.doc.title }];
23-
}
24-
return [{ title: 'Page Not Found' }];
19+
export const meta: MetaFunction<typeof loader> = ({ data, matches }) => {
20+
// Get site settings from root loader data
21+
const siteSettings = getSiteSettingsFromRoot(matches);
22+
const appName = siteSettings?.general?.appName ?? defaultAppName;
23+
24+
const meta = resolveMeta(data?.doc);
25+
26+
return [{ title: `${appName} - ${meta?.title ?? 'Page'}` }];
2527
};
2628

2729
/**

apps/web/app/routes/_index.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { RenderBlocks } from '@codeware/shared/ui/payload-components';
2-
import type { SiteSetting } from '@codeware/shared/util/payload-types';
2+
import { resolveMeta } from '@codeware/shared/util/payload-utils';
33
import { type MetaFunction, useRouteError } from '@remix-run/react';
44

55
import { Container } from '../components/container';
66
import { ErrorContainer } from '../components/error-container';
7+
import { defaultAppName } from '../utils/default-app-name';
8+
import { getSiteSettingsFromRoot } from '../utils/get-site-settings-from-root';
79
import { useSiteSettings } from '../utils/use-site-settings';
810

911
type LoaderError = {
@@ -12,21 +14,13 @@ type LoaderError = {
1214
};
1315

1416
export const meta: MetaFunction = ({ matches }) => {
15-
// Get loading page from root loader data
16-
const rootData = matches.find((match) => match.id === 'root')?.data as Record<
17-
string,
18-
SiteSetting
19-
>;
17+
// Get site settings from root loader data
18+
const siteSettings = getSiteSettingsFromRoot(matches);
19+
const appName = siteSettings?.general?.appName ?? defaultAppName;
2020

21-
let title = 'Home';
21+
const meta = resolveMeta(siteSettings);
2222

23-
if (rootData && 'siteSettings' in rootData) {
24-
if (typeof rootData.siteSettings.general.landingPage === 'object') {
25-
title = rootData.siteSettings.general.landingPage.meta?.title ?? title;
26-
}
27-
}
28-
29-
return [{ title }];
23+
return [{ title: `${appName} - ${meta?.title ?? 'Home'}` }];
3024
};
3125

3226
export default function Index() {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* The default app name when the site settings are not found.
3+
*/
4+
export const defaultAppName = 'App' as const;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { SiteSetting } from '@codeware/shared/util/payload-types';
2+
import type { MetaFunction } from '@remix-run/react';
3+
4+
/**
5+
* Server side utility to get the site settings from the root loader data.
6+
*
7+
* @param matches - The `matches` object from the root loader.
8+
* @returns The site settings or `null` if not found.
9+
*/
10+
export const getSiteSettingsFromRoot = (
11+
matches: Parameters<MetaFunction>[0]['matches']
12+
) => {
13+
const rootData = matches.find((match) => match.id === 'root')?.data as
14+
| Record<'siteSettings', SiteSetting>
15+
| undefined;
16+
17+
return rootData?.siteSettings ?? null;
18+
};

libs/shared/util/payload-api/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export { apiKeyPrefix, authorizationHeader } from './lib/utils/definitions';
22
export type {
33
MethodOptions,
4-
NavigationDoc,
54
NavigationItem,
65
RequestBaseOptions,
76
RequestMethod

libs/shared/util/payload-api/src/lib/find-navigation-doc.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type {
2+
NavigationDoc,
23
NavigationReferenceCollection,
34
Page,
45
Post
56
} from '@codeware/shared/util/payload-types';
67

78
import { invokeRequest } from './utils/invoke-request';
8-
import type { NavigationDoc, RequestBaseOptions } from './utils/types';
9+
import type { RequestBaseOptions } from './utils/types';
910

1011
/**
1112
* Find a navigation document by the URL collection and slug parameters.
@@ -45,6 +46,14 @@ export const findNavigationDoc = async (
4546
collection: lookupCollection,
4647
header: page.header,
4748
layout: page.layout,
49+
meta: {
50+
description: page.meta?.description ?? undefined,
51+
image:
52+
(typeof page.meta?.image === 'object'
53+
? page.meta?.image
54+
: undefined) ?? undefined,
55+
title: page.meta?.title ?? undefined
56+
},
4857
name: page.name
4958
};
5059
}
@@ -56,6 +65,14 @@ export const findNavigationDoc = async (
5665
content: post.content,
5766
heroImage:
5867
typeof post.heroImage === 'object' ? post.heroImage : undefined,
68+
meta: {
69+
description: post.meta?.description ?? undefined,
70+
image:
71+
(typeof post.meta?.image === 'object'
72+
? post.meta?.image
73+
: undefined) ?? undefined,
74+
title: post.meta?.title ?? undefined
75+
},
5976
title: post.title
6077
};
6178
}

libs/shared/util/payload-api/src/lib/utils/types.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import type {
2-
Media,
3-
NavigationReferenceCollection,
4-
Page,
5-
Post
6-
} from '@codeware/shared/util/payload-types';
1+
import type { NavigationReferenceCollection } from '@codeware/shared/util/payload-types';
72

83
/**
94
* Available request options depending on the request method.
@@ -36,20 +31,6 @@ export type MethodOptions<T extends RequestMethod> = T extends 'GET'
3631
body: Record<string, unknown>;
3732
};
3833

39-
/**
40-
* Document details for a navigation item.
41-
*/
42-
export type NavigationDoc =
43-
// limit what can be exposed client side
44-
| ({
45-
collection: 'pages';
46-
} & Pick<Page, 'header' | 'layout' | 'name'>)
47-
| ({
48-
collection: 'posts';
49-
} & Pick<Post, 'content' | 'title'> & {
50-
heroImage?: Media | null | undefined;
51-
});
52-
5334
/**
5435
* Navigation tree item.
5536
*/

0 commit comments

Comments
 (0)