Resources
Making templates for articles, desks, authors, & tags
Introduction
resources
refers to pages generated from data from articles, desks, tags, and authors.- Pages for all of your resources live in the
/templates/resources
folder.
- Karbon uses file based routing, meaning your file routes will form the URL of your publication. Be aware of this when optimizing your Karbon publication for SEO.
- Using these defined routes, Karbon will generate your pages by pulling data from Storipress and/or other third party sources.
Folder Structure
Your resources files are all placed in the resources folder
---| node_modules/
---| nuxt.config.js
---| package.json
---| templates/
------| resources/
---------| article.vue
---------| author.vue
---------| desk.vue
---------| tag.vue
Usage
Create a page
In the .vue
pages under /templates/resources
, you can use setupPage
to get data needed for your page.
# /templates/resources/article.vue <script lang="ts" setup> const article = setupPage({ type: 'article' }) </script> <template> <div> <div class="text-sky-900">Article data</div> <ul> <li>id: {{ article.id }}</li> <li>title: {{ article.title }}</li> </ul> </div> </template>
Configure your URL
Karbon comes with a default resource configuration. This configuration can be overwritten in the nuxt.config.js
file.
export default defineNuxtConfig({ ..., karbon: { resources: { article:
Using these helper functions
You can use these helper functions that are specific to certain resources: createArticleRoute
, createTagRoute
, createTagCollectionRoute
, createDeskRoute
, createAuthorRoute
.
They allow you to define your desired route type more easily.
createArticleRoute
Use this function to generate routes for article resources
url
: URL structure, will explain the syntax in URL Syntax
createTagRoute
Use this function to generate routes for tag resources
url
: URL structure, will explain the syntax in URL Syntax
createTagCollectionRoute
Use this function to generate routes for tag collection resources
url
: URL structure, will explain the syntax in URL Syntax
groupKey: string
Setting the tag group key will find the tags under that group and automatically generate the related page. Please reference link for more details
createDeskRoute
Use this function to generate routes for desk resources
url
: URL structure, will explain the syntax in URL Syntax
createAuthorRoute
Use this function to generate routes for author resources
url
: URL structure, will explain the syntax in URL Syntax
Example
resources: { article: createArticleRoute('/posts/{id}'), desk: createDeskRoute('/desks/{id}'), author: createAuthorRoute('/author/{id}'), tag: createTagRoute('/tags/{id}'), collection: createTagCollectionRoute('/collection/{slug}', 'taggroup'), }
Using the createResourceRoute
helper
The createResourceRoute
helper is the underlying version of other helpers.
You probably don't need to use it.
import { createResourceRoute } from '@storipress/karbon' type Resources = 'article' | 'desk' | 'tag' | 'author' interface ResourceRouteOption { url: string resource: Resources groupKey?: string } function createResourceRoute(opt: ResourceRouteOption): ResourcePage<BaseMeta, RouteOptionsContext>
createResourceRoute
url
: URL structure, will explain the syntax in URL Syntax
resource: Resources
type of resource
type Resources = 'article' | 'desk' | 'tag' | 'author'
groupKey
: string
Setting the tag group key will find the tags under that group and automatically generate the related page. Please reference link for more details
resources: { collection: createResourceRoute({ resource: 'tag', groupKey: 'example_group', url: '/collection/{slug}', }) }
Deleting resources
To delete resources, simply delete any pages in the resources folder.
URL Syntax
URL syntax is look like: /posts/{slug}
, the dynamic parameters will be surround by {}
. With /posts/{slug}
, Karbon will fetch your articles and fill article’s slug into the {slug}
part and generate your page like /posts/example-slug
Resource Identity
id
, sid
or slug
in your URLIn Storipress, resource will be identity by either id
, sid
or slug
, For example, these identity could point to the same article:
id
:1
Anid
is a sequence number
sid
:abcdefg
Asid
is a short string version ofid
slug
:example-slug
Aslug
is an human readable string, which is safe for URL and it’s configuable for articles in Storipress
Karbon will combine the resource
option and the identitiable parameters (i.e. id
, sid
, slug
) to find your resource. Thus, it’s important to use one if the identitable parameters.
For example:
✅ These are valid URL config
/posts/{slug}
/{slug}/view
/{root_desk.slug}/{sid}
🔴 These are invalid because of missing identifiable parameters
/article # No identifiable parameter
/{root_desk.slug} # Only containing desk's slug is not valid
Optional parameter
?
like {?param}
will make a dynamic parameter optionalIn Storipress, article could live under a sub desk, but this is not enforce. Which mean your article may or may not live under a sub desk. What if you want to make your URL like:
/parent-desk/sub-desk/slug
for article that is under subdesk
/desk-without-subdesk/slug
for article that is not under subdesk
Here comes the optional parameter. You only need to configure your URL like
/{root_desk.slug}/{?sub_desk.slug}/{slug}
Please notice the ?
before the sub_desk.slug
which will make the parameter optional. If the article is not belong to a subdesk. Karbon will simply ignore the {sub_desk.slug}
part and also remove the following /
for you
Article parameters
We know the article is the most important part of your site. Thus, we provide a lot of additional parameters for your articles.
But before getting start, let me introduce you how to understand the document of parameters
Here is the simpliest form
parameter_name
: description forparameter_name
For example:
year
: Published year for the article inYYYY
format, e.g.2023
And you can use {year}
in your URL
Here comes the nested parameter
parent_param
: description forparent_param
child_param
: descriotion forchild_param
For example:
root_desk
: The toplevel desk for the articleslug
: The slug for the toplevel desk of the article
And you MUST use it like {root_desk.slug}
in your URL. Or it will result an error
Let’s start
year
: Published year for the article inYYYY
format, e.g.2023
month
: Published month for the article inMM
format, e.g.01
day
: Published day for the article indd
format, e.g.02
root_desk
: The toplevel desk for the articleid
: The id for the toplevel desk of the articlesid
: The sid for the toplevel desk of the articleslug
: The slug for the toplevel desk of the article
sub_desk
: The sub desk for the article, which can be optionalid
: The id for the sub desk of the articlesid
: The sid for the sub desk of the articleslug
: The slug for the sub desk of the article
Examples
This will generate the following URL/posts/
<parent-desk>
/<sub-desk>/<slug>
for your articles.
import { createResourceRoute } from '@storipress/karbon' export default defineNuxtConfig({ ..., storipress: { resources: { article: createResourceRoute({ resource: 'article', url: '/posts/{root_desk.slug}/{?sub_desk.slug}/{slug}', }) } } })
Customise Resource Page
If the createResourceRoute
helper doesn't meet your requirements, you can also define your own ResourcePage
object in the karbon.resources
of your nuxt.config.ts
to configure it.
Type
type BaseID<Type extends 'article' | 'desk' | 'tag' | 'author'> = | { type: Type id: string } | { type: Type slug: string } type ArticleID = | BaseID<'article'> | { type: 'article' sid: string } type DeskID = BaseID<'desk'> type AuthorID = BaseID<'author'> type TagID = BaseID<'tag'> type ResourceID = ArticleID | DeskID | AuthorID | TagID
interface Identifiable { id: string slug?: string sid?: string }
interface ResourcePage<Meta extends Identifiable> { enable: boolean route: string getIdentity(params: Record<string, string>): ResourceID toURL(resource: Meta): string isValid(params: Record<string, string>, resource: Meta): boolean groupKey?: string }
Params
getIdentity
, toURL
, and isValid
must be pure and not use any external variables or functions. This is because Karbon will serialize them as strings and pass them into the client context.enable
:boolean
Whether to enable this routing configuration.
route
:string
Use a string to set the URL, it has same syntax with vue-router. You can use :
as a prefix after /
to indicate that the value is passed as a URL params to getIdentity
, isValid
, toURL
for subsequent logic judgment.
getIdentity
:(params: Record<string, string>): ResourceID
Define a handler function that will receive the params parameter defined through route.
It needs to return a ResourceID
so that Karbon can find the correct Resource.
toURL
:(resource: Meta): string
Define a handler function to set the logic for building the URL, which will pass in the complete meta data of Resource
as parameters.
It needs to return a set of actual URL strings used to set the URL.
isValid
:(params: Record<string, string>, resource: Meta, _context: Ctx): boolean
Define a handler function to validate whether the current URL connection is valid. It will receive the params parameter defined through route, the complete meta data of Resource
, and ResourcePageContext
.
It needs to return a boolean
result to confirm that this URL provides access.
Common checks include verifying that a Resource can be properly matched.
groupKey
:string
Optional, see groupKey for details.
Example
export default defineNuxtConfig({ karbon: { resources: { article: { enable: true, route: '/posts/:desk/:articleId', getIdentity: ({ articleId }) => ({ type: 'article', id: articleId }), toURL: ({ id, desk }) => `/posts/${desk.slug}/${id}`, isValid: ({ desk }, { desk: {slug} }) => desk === slug, }, }, }, })
Last updated on February 3, 2023