Hugo doesn't use theme archetypes

Hi

When I use a theme (eg Osprey) and use the command hugo new blog/test.md it doesn’t use the blog archetype which exists in base_path/themes/osprey/archetypes. According to the documentation, all I need to do is set the theme variable in the config file and this should work. The issue is though that if you look at the code, it will always fall back to the already existing default md.

Look at the findArchetype function in create/content.go

search := []string{ps.AbsPathify(ps.Cfg.GetString("archetypeDir"))}

if ps.Cfg.GetString("theme") != "" {
	themeDir := filepath.Join(ps.AbsPathify(ps.Cfg.GetString("themesDir")+"/"+ps.Cfg.GetString("theme")), "/archetypes/")
	if _, err := ps.Fs.Source.Stat(themeDir); os.IsNotExist(err) {
		jww.ERROR.Printf("Unable to find archetypes directory for theme %q at %q", ps.Cfg.GetString("theme"), themeDir)
	} else {
		search = append(search, themeDir)
	}
}

This code will add the base archetype dir to an array and append the theme’s archetype dir. Later on, we loop through the search paths but return at the first occurence found, which will always be default md, thus never checking the theme’s archetypes.

Possible solutions:

  1. Adjust the code to first check possible theme directories before falling back to the base directory. This is not what it should do according to the documentation (https://gohugo.io/content-management/archetypes/ ctrl-f lookup order) but it seems more logical to check for more-specific archetypes (skin-specific) before checking for archetypes in the base directory. This code should do the trick:

    var search []string
    // code appending theme dir
    search = append(search, ps.AbsPathify(ps.Cfg.GetString(“archetypeDir”)))

  2. Change the documentation telling people to remove default md from the base archetype dir. (seems slightly wrong)

  3. Tell people to copy theme archetypes to the base archetype dir. (seems very wrong)

My preferred method would be 1) but I’m not sure what the rest of you guys prefer.

The project directory is always the most specific directory. Are you saying that the theme archetype folder is not checked if the project’s is empty?

It is checked if the project’s is empty, but it isn’t checked if the project’s dir contains default md. If I had the following structures

archetypes/default.md
themes/themename/archetypes/blog.md

and I would do hugo new blog/foo.md, it would not use the blog md archetype from the theme because it checks the base archetypes first so it will find default md and stop looking. Same thing for hugo new --kind blog bar/foo.md, which definitely doesn’t seem like intended behaviour because we’re specifying the kind manually.

EDIT: Solution 1 isn’t ideal because it does make more sense to keep the current order (base dir trumps theme dir to allow user overriding) so I think it should go something like this:

  1. Check base dir for existing archetype (except for default or default md)
  2. If no archetype found, check theme dir for archetype.
  3. If no archetype found, fall back to default or default md in base dir.

This still has the issue that if the theme dir has a default md, it can’t be overridden, though.

2 Likes

I’m seeing the same behavior here. If /site/archetypes/default.md exists, nothing in /site/theme/archetypes will ever be used.

1 Like

Whether or not this behaviour is intended, it’s extremely confusing. As a first-time theme developer building something that relies on its own archetypes, I was totally baffled as to why they weren’t working as it’d always fall back to the default archetype in the project dir.

I get the idea of being able to override anything in a theme with your own local archetypes but it makes it very hard to get themes working out of the box. I had to include this in my README.

3 Likes

I agree. I think overriding archetypes should happen on an individual basis. I haven’t needed to do this yet so haven’t run into the problem myself but that’s not how I thought it would work based on the docs. Current implementation is confusing.

1 Like

As a new hugo user I struggled into this one.
First I checked Archetypes | Hugo
Then checked in Template lookup order | Hugo
Implemented an archivetype in the theme
But my archivetype in the theme was ignored - kind of confusing and not what I learned in the documentation.

  • ./themes/hugo-theme-w3css-basic/archetypes/blog.md
  • ./archetypes/default.md

$ hugo new blog/test-this1.md

=> blog is not used but default

Hugo Static Site Generator v0.30.2 linux/amd64 BuildDate: 2017-10-19T13:34:27+02:00
Isn’t this kind of a bug? Either Documentation or code…

1 Like

No, it is neither.

So Hugo only checks to see if something in the directory of ./archetypes is truthy, and it doesn’t check for specific namespaces?

Yes…

Very confusing indeed.

1 Like

To me it would be even more confusing if my carefully constructed archetype template was overridden by some random theme.

2 Likes

Shouldn’t default .md be a last resort kind of fallback though? Right now themes are completely ignored unless you delete the default .md from the base archetype directory. If I install a theme that has a blog .md archetype I would expect that archetype to actually be used when I call hugo new blog/foo.md

2 Likes

Because that is your use case. What if I have archetypes in my site layouts, because the front matter is very specific to my site? If that is the case, in order to incorporate an archetype from an outside source, I modify my site’s layouts.

We all get that you want to switch out your archetypes with ones supplied by a theme, but if your site is based around a theme to that extent, you can just remove the default archetype and it works.

The way it currently works is a flexible solution to a non-standard process that everyone can customize for their own purposes, with little effort, because we have a well-documented lookup order. :slight_smile:

If you have specific archetypes in your base archetype directory they should override any theme archetypes. This is as it works right now which is correct (both in the code and the documentation).

This is how it works now:

theme/archetypes

  • foo .md
  • bar .md

base/archetypes

  • foo .md
  • baz .md
  • default .md

hugo new foo/test .md creates a page using foo .md from the base dir (correct behaviour, foo is in the theme but gets overridden/preferred by the user-specific archetype in the base dir)
hugo new bar/test .md creates a page using default .md (wrong behaviour, I would expect it to use bar .md from the theme dir)
hugo new baz/test .md creates a page using baz .md (correct behaviour)
hugo new qux/test .md creates a page using default .md (correct behaviour)

So I’m wondering why it seems more natural or flexible that bar .md gets ignored because default .md exists in the base dir?

This isn’t carved in stone, but I haven’t been convinced by the current set of arguments.

There is no /content in the theme. That is “my thing” (i.e. the project). So how I want to set up my content is – up to me. And in all of my Hugo sites, I have a default.md archetype file. That is the file I want to use. Not one from one theme I happen to use.

And note, it isn’t ignored, it just has a lower precedence from the one I really want.

1 Like

And how about merging the properties? The behavior could be optional if a property “merge = true” is included in my default.md.
This way we can satisfy both theme and “my thing”.

I just ran into this behavior and was quite stumped for awhile because of it.

I expected, with no additional work from my part, to be able to make a site using hugo new site, pull a theme into an appropriate theme directory and be able to use the theme archetypes.

I never made a default.md file, I never did anything to intentionally supersede the themes archetypes, but that is what happened because hugo site new made a default.md.

I would expect my non-default archetypes to override the themes non-default archetypes. I would also expect my default.md to override the theme’s default.md. I would not expect my default.md to override the themes non-default archetypes.

The behavior I would like is:

  1. If I provide a more specific archetype than the theme, use it.
  2. If I don’t use the one from the theme, that’s why I got the theme.
  3. If I or the theme didn’t provide a specific archetype use my default.md.
  4. If I didn’t provide one use the theme’s default.md

The only way to use the theme specific archetypes while also using my default.md is to replace the theme’s default.md with my default.md. That seems really unintuitive. My default should live in my site, not in the theme.

And I definitely want a way to specify my own default, but I don’t want that at the expense of not being able to use a theme’s non-default archetypes.

It seems far more intuitive to simply delete the themes archetypes if I don’t want to use them. I expect to not want parts of a theme and to delete them if that is the case.

At the very least hugo new site should not automatically create a default.md because that will immediately break theme archetypes which is really not what I would expect from an empty site. If I had actually taken some action to specifically create a default.md I could sort of see it making sense.

2 Likes

Hi!

I was also expecting the behaviour wolfordj described and was very confused by the fact that archetype lookup order is not the same as the template lookup order. The top argument I see in favor of this behaviour is consistency in lookup order of templates and archetypes.

1 Like

I completely agree with the confusion stated by other users. I was googling the issue when I found this issue report.

Coming from other template-overriding worlds (such as the Jinga engine in Sphinx), it didn’t even occur to me that a template overriding mechanism such as this would work differently than per-file. Implicitly overriding the whole theme folder (in this case, the archetypes folder) just because one single bit of its contents has been overridden seems not only counter-intuitive, but also opposite to the principle of keeping the changes at a minimum.

I think the Sphinx way of doing things is very sensible, so I’d like to contribute by quoting the most relevant bits of their Templating page:

Sphinx will look for templates in the folders of templates_path first, and if it can’t find the template it’s looking for there, it falls back to the selected theme’s templates.

For example, to add a new link to the template area containing related links all you have to do is to add a new template called layout.html with the following contents: […]

Note: templates_path in this context would be equivalent to the archetypes folder in Hugo.

The example shown there would then override the contents of the theme’s layout.html file, but exclusively that one. It would seem nonsensical that just one single change in one single file would make the engine to override all other files from the theme! But precisely that is what Hugo does with the archetypes.