Configure permalink structure depending on output formats

Hi there,

I’m wondering if it’s possible to configure permalinks structure depending on the output format.

Let’s say I have an objects section, which renders HTML and a custom JSON format.

# Example: content/objects/123456.md
---
slug: descriptive-filename-123456
---

In the _index.md I define my additional custom JSON output format for this section.

# content/objects/_index.md
---
outputs:
- html
cascade:
  outputs:
  - html
  - jsonAPI
---

My permalinks and outputFormats config looks like:

# hugo.yaml
permalinks:
  page:
    objects: "/objects/:slugorfilename"

outputFormats:
  jsonAPI:
    baseName: "index"
    mediaType: application/json
    isPlainText: true
    notAlternative: true
    permalinkable: true
    path: "/api/"

The resulting URLs for both output formats are:

  • HTML: /objects/descriptive-filename-123456/
  • jsonAPI: /api/objects/descriptive-filename-123456/index.json

My question:
Is it possible to use the filename in the custom JSON output? Like:

  • HTML: /objects/descriptive-filename-123456/
  • jsonAPI: /api/objects/123456/index.json (or even better: /api/objects/123456.json)

I am very thankful for any feedback!

Joachim

hugo v0.120.4

You can configure permalinks by language, but not by output format.

You can achieve the desired results…

public/
├── api/
│   ├── 123.json
│   └── 456.json
├── objects/
│   ├── descriptive-filename-123/
│   │   └── index.html
│   ├── descriptive-filename-456/
│   │   └── index.html
│   └── index.html
├── api.json
├── favicon.ico
└── index.html

…by combing module mounts, uglyURLs, cascades, and permalinks:

hugo.toml
uglyURLs = true

[outputformats.html]
noUgly = true

[outputformats.jsonapi]
isPlainText = true
mediaType = 'application/json'
notAlternative = true
permalinkable = true

[[module.mounts]]
source = 'content'
target = 'content'

[[module.mounts]]
source = 'content/objects'
target = 'content/api'

[permalinks.page]
api = '/:section/:filename'
objects = '/:section/:slugorfilename'

[[cascade]]
outputs = ['jsonapi']
[cascade._build]
list = 'never'
[cascade._target]
path = '/api/**'

For example…

git clone --single-branch -b hugo-forum-topic-47406 https://github.com/jmooring/hugo-testing hugo-forum-topic-47406
cd hugo-forum-topic-47406
hugo server
1 Like

Oh right, I can use mounts to achieve this.
Hugo is so powerful, love it!

Thanks!

1 Like

It occurred to me that you may be able to do this without an alternate output format by using resources.FromString.

layouts/objects/single.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}

  {{ $map := dict
    "content" .Content
    "date" .Date
    "title" .Title
  }}
  {{ $path := printf "/api/%s.json" .File.ContentBaseName }}
  {{ (resources.FromString $path (jsonify $map)).Publish }}

{{ end }}

This works well for generating stubs, but may not provide everything you need.

2 Likes

That’s even better. Simple and clean, exactly what I was looking for!
Thanks again :pray:

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.