Type-safe Remix loader
for pages built in Faster Front's CMS.
pnpm add @fasterfront/cms
For generating the types according to the latest version of your DB:
pnpm ff
You can also add this directly to your dev
script on package.json eg:
{
"scripts": {
"dev": "ff && remix dev"
}
}
Let's suppose you have a /team
route on your Remix application that looks like this:
{
"en-US": {
"meta": {
"title": "Team",
"description": "Learn more about Faster Front team!"
},
"team": {
"type": "list",
"value": {
"entity": "member",
"fields": ["id", "fullName", "avatar", "bio"],
"sortOrder": {
"property": "fullName",
"direction": "asc"
}
}
}
}
}
The member
entity looks like this:
type Member = {
// CMS: Primary key (could be used for creating a /team/:id route)
id: string
// CMS Type: Text
fullName: string
// CMS Type: Image
avatar: {
alt: string
src: string
srcSet: string
sizes: string
}
// CMS Type: RichText
bio: string
}
On routes/_layout/team/index.tsx
, you can just use usePageData
for getting the data (fully typed!):
import { usePageData } from '@fasterfront/cms'
import Image from '@fasterfront/image'
export { pageMeta as meta } from '@fasterfront/cms'
export { pageLoader as loader } from '@fasterfront/cms/loaders.server'
type Path = '/team'
export default function Team() {
const { meta, team } = usePageData<Path>()
return (
<section>
<h1>{meta.title}</h1>
<p>{meta.description}</p>
<ul>
{team.map((member) => (
<li key={member.id}>
<div>
<Image data={member.avatar} />
<span>{member.fullName}</span>
</div>
<div dangerouslySetInnerHTML={{ __html: member.bio }} />
</li>
))}
</ul>
</section>
)
}
That's it! Simple and fun!