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

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

Thanks!

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.

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