Reuse content between sections

Hey all,

I am using Hugo to build multiple product documentations and I am trying to figure out what the best approach is to reuse content between these. The content for each product documentation is currently stored in its own subfolder under the content directory. Example:

/content
|_ /product-a
|_ /product-b
|_ /product-c

Now, we have some content that is shared between products. This can be a snippet of text or an entire page. Within this snippet/ entire page, we might need to adjust things like the product name to make it specific to the product. We also sometimes use shortcodes in this reused content to create specific output.

I tried putting the entire reused content into a shortcode and calling this shortcode with a product variable from within the product’s content file. This works nicely, but it breaks when the content in the shortcode calls other shortcodes. I could technically move all the shortcodes that I am using into a partial, but that seems redundant and also won’t make theme updates easy to adapt.

I also tried adding the reused content to the static/content folder, but I cannot access any files from within my product folders. It looks like it only works if I create the static/content directory under each product directory, such as in this example. And even if that worked, I am not sure if I could call shortcodes from within these files??

/static/content > does not seem to work
/content
|_ /product-a
|___ /static/content > seems to work within product-a, but not product-b or product-c
|_ /product-b
|___ /static/content > seems to work within product-b, but not product-a or product-c
|_ /product-c
|___ /static/content > seems to work within product-c, but not product-b or product-a

I recently heard that there is a way to import files as a module and map them to a specific directory in Hugo. I wasn’t sure if that might be the way to go? If I put the reused file into another GH repo and imported/ mounted it to the /content directory, how would I access these files from each product?

I hope my explanations make sense. Thank you so much for your help!
Nadine

TLDR

Put your shared content (*.md) files in the assets directory, access with resources.Get, and pass the resource .Content through .Page.RenderString.

Structure

assets/
└── snippets/
    └── snippet-01.md
content/
β”œβ”€β”€ product-a/
β”‚   β”œβ”€β”€ _index.md
β”‚   β”œβ”€β”€ product-a-1.md
β”‚   └── product-a-2.md
β”œβ”€β”€ product-b/
β”‚   β”œβ”€β”€ _index.md
β”‚   β”œβ”€β”€ product-b-1.md
β”‚   └── product-b-2.md
β”œβ”€β”€ product-c/
β”‚   β”œβ”€β”€ _index.md
β”‚   β”œβ”€β”€ product-c-1.md
β”‚   └── product-c-2.md
└── _index.md
layouts/shortcodes/
β”œβ”€β”€ another-shortcode.html
└── snippet.html

content/product-a/_index.md

+++
title = 'Product A'
date = 2022-11-16T11:55:56-08:00
draft = false
[[cascade]]
product_name = 'Foo'  --> so we can access from pages in this section
+++

content/product-a/product-a-1.md

+++
title = 'Product A - 1'
date = 2022-11-16T11:55:14-08:00
draft = false
+++

{{< snippet "snippets/snippet-01.md" >}}

assets/snippets/snippet-01.md

This is **bold** text.

It contains the "{{< param "product_name" >}}" product name.

And it calls another shortcode.

{{< another-shortcode >}}

layouts/shortcodes/snippet.html

details
{{- /*  Initialize. */}}
{{- $asset := "" }}

{{- /* Get params. */}}
{{- with (.Get 0) }}
  {{- $asset = . }}
{{- else }}
  {{- errorf "The %q shortcode requires a single positional parameter; the relative path to a file in the assets directory. See %s" .Name .Position}}
{{- end }}

{{- /* Get resource. */}}
{{- $r := "" }}
{{- with resources.Get $asset }}
  {{- $r = . }}
{{- else }}
  {{- errorf "The %q shortcode was unable to find %q. See %s" .Name $asset .Position}}
{{- end }}

{{- /* Render resource content. */}}
{{- $r.Content | .Page.RenderString }}

{{- /* Chomp trailing newlines. */ -}}

Example

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

@jmooring thank you so much for all the examples snippets. This was EXACTLY what I was looking for. I have added all these files. My snippet-01.md file currently only includes markdown. I am not calling other shortcodes just yet. However, the content is not displayed on my product page (product-a-1.md). The page stays empty. There are no errors in my build as far as I can tell. Do you have a tip how I can troubleshoot this?

When I clone and run the example repository that I posted, everything works fine.

Are you having trouble with the example repository, or your own project? If it’s the later, we’d need to look at it.

I have the issue in my repository. But let me first check out the sample repo. I did not do that yet. I will compare the files. I probably did something wrong.

@jmooring

I was finally able to get it to work in my environment as well. The only thing that is not working for me is a shortcode that I am using to filter content within the snippet.

This is the shortcode:

{{ $product := string ( .Get "product" )}} 
{{ $markdown := .Inner | markdownify }} 

{{ if eq .Site.Params.product $product }}
 {{ if (or (in .Inner " alert") (in .Inner " expand") (in .Inner " version") ) }} 
 {{ .Inner }} 
{{ else if not ( findRE "<[p][^>]*>" $markdown ) }}
  {{ $markdown }}
{{ else }} {{ .Inner | markdownify }} {{ end }} {{ end }} 

and I am calling this shortcode as follows from the snippet markdown file:

This is **bold** text.

|Column A|Column B|
|--|--|
|Value 1|Value 2|

{{< alert title="Keep in mind" color="warning" >}}
This is a red alert. 

{{< /alert >}}

{{< product product="gateway">}}
This is gateway content.
{{< /product >}}

In the above snippet, everything works, except for the product shortcode. I used the product shortcode in the past without issues so I think it is related to how it is processed within the snippet.html shortcode. I am getting the following error:

failed to render shortcode "snippet": failed to process shortcode: 
"/../layouts/shortcodes/snippet.html:20:22": execute of template failed: template: 
shortcodes/snippet.html:20:22: executing "shortcodes/snippet.html" at <.Page.RenderString>: error 
calling RenderString: "../test.md:14:6": failed to extract shortcode: shortcode "product" has no .Inner, yet
 a closing tag was provided

Maybe you have a tip for me what needs to be changed in the snippet shortcode to make this work?

Thank you so much for all your help! I appreciate it a LOT!!

I am unable to reproduce the problem based on what you have provided, and have updated the example site to include a β€œproduct” shortcode, matching your example.

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

Maybe you have a stray, malformed shortcode call somewhere else?

@jmooring I re-added my product shortcode and now it seems to work. I have no idea what it was, but I am so happy it is working now. :slight_smile: Thank you SO SO much for all your help! I appreciate it so much!

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