Pass extra dynamic data when routing to a page

I need to pass some extra data to my page in addition to the route and query parameters. The problem: I'm migrating my blog to Nuxt Content and I have a page /tags/{tag} that display articles concerning a specific tag. Some articles contain tags like "GitHub Actions" or "CI/CD" that give the following URLs /tags/github-actions or tags/cicd . I need to have the same URLs to avoid redirections but with these URLs with a modified tag (github-actions instead of github%20actions for example) I won't be able to retrieve the original tag to display it on my page and retrieve related articles. If the modified tag ( github-actions ) is passed as a route parameter I need a way to pass the original tag (GitHub Actions) as well. What solutions I have considered: - Pass the original as query parameter => my existing tags URL will still break without the additional query parameter - Use navigation guards to make some sort of redirection => not exactly sure how it could work and it seems complex - once on the tag page, retrieve all blog posts, map their tags to the modified tags version to get the original tags and the corresponding articles => it seems to be a complicated workaround
8 Replies
JuanP Barba
JuanP Barba8mo ago
Why can't you just map the modified tag to the original tag in /tags/{tag}? I mean, if you create a map with all the tags
Alexandre Nédélec
I could, it's similar to the last option I considered. Retrieve all the tags, modify them and put the original tag and the modified tag in a map. I could do that in an endpoint that I could call from my tag page, I guess with SSG the endpoint would only be called once at build time. That's probably a good option, I just wanted to make sure there was no other easier mechanism (maybe a routing concept I don't know about) to do the same thing.
JuanP Barba
JuanP Barba8mo ago
Yes, using SSG the endpoint will be called only at build time I think there could be better solutions that rely on your data rather than on Nuxt itself. I mean, I'm not sure how you are getting the tags or how you are generating the /tags/{tag} page right now... Perhaps a small example of the /tags/{tag} page could help.
Alexandre Nédélec
I'm using this query :
const {data: posts} = await useAsyncData(`tags-${tag}`, () => queryContent<BlogPost>('/posts')
.where({tags: {$contains: tag}, _extension: 'md' })
.sort({ date: -1 })
.find())
const {data: posts} = await useAsyncData(`tags-${tag}`, () => queryContent<BlogPost>('/posts')
.where({tags: {$contains: tag}, _extension: 'md' })
.sort({ date: -1 })
.find())
Tags in my FrontMatter look like that :
badge:
label: Tooling
tags:
- Azure CLI
- Azure
- shell
---
badge:
label: Tooling
tags:
- Azure CLI
- Azure
- shell
---
Maybe people don't usually have this issue when they have no existing URLs they don't want to break, or when they don't care about the format of the URL (space and special caracters being encoded in the url)
JuanP Barba
JuanP Barba8mo ago
The only thing that comes to mind is that you add the tag's slug to the keys of the posts as well... If you don't want to make this modification, I would go with route rules and SSG for /tags/{tag}. It will increase the build time, but I think all solutions for this issue (without extra key or getting tags out of posts) will ultimately involve some build script.
Alexandre Nédélec
I think I will go the route rule and SSG. Thanks for the help and advice! I wonder which library I should use to modify my tags to kebab case and remove things like dot and slash just-kebab-case seems a good option
JuanP Barba
JuanP Barba8mo ago
GitHub
GitHub - unjs/scule: 🧵 String Case Utils
🧵 String Case Utils. Contribute to unjs/scule development by creating an account on GitHub.
Alexandre Nédélec
I've just discovered it and try it but it does not handle properly spaces. By the way, for anyone coming across this question, here is the code I ended up writing:
import {serverQueryContent} from "#content/server";
import {getTagSlug} from "~/utils/tag";

export default defineEventHandler(async (event) => {
const tags = await serverQueryContent(event)
.where({ _type: 'markdown', navigation: { $ne: false } })
.only('tags')
.find()

const tagsBySlug = new Map<string, string>(tags
?.flatMap(t => t.tags ?? [])
.map(tag => [getTagSlug(tag), tag]));

return [ ...tagsBySlug]
})
import {serverQueryContent} from "#content/server";
import {getTagSlug} from "~/utils/tag";

export default defineEventHandler(async (event) => {
const tags = await serverQueryContent(event)
.where({ _type: 'markdown', navigation: { $ne: false } })
.only('tags')
.find()

const tagsBySlug = new Map<string, string>(tags
?.flatMap(t => t.tags ?? [])
.map(tag => [getTagSlug(tag), tag]));

return [ ...tagsBySlug]
})
import kebabCase from "just-kebab-case";

export const getTagSlug = (tag: string) => kebabCase(tag.toLowerCase().replace('/', ''))
import kebabCase from "just-kebab-case";

export const getTagSlug = (tag: string) => kebabCase(tag.toLowerCase().replace('/', ''))
Want results from more Discord servers?
Add your server