Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hugo with uglyURLs = true generates /public/section.html instead of /public/section/index.html #4428

Open
ChrisTucker2000 opened this issue Feb 19, 2018 · 36 comments

Comments

@ChrisTucker2000
Copy link

ChrisTucker2000 commented Feb 19, 2018

Discourse thread: https://discourse.gohugo.io/t/section-index-md-page-isnt-being-created/10627
Sample project: https://github.com/ChrisTucker2000/hugorepro

Steps to reproduce:

  1. Create a section index page, e.g. /content/cats/_index.md.
  2. Create an appropriate template file, e.g. /themes/mytheme/layouts/_default/list.html.
  3. Set uglyURLs = true in /config.toml.
  4. Build the website with hugo.

Expected result:

  • The page should be created as /public/cats/index.html.

Actual result:

  • The page is created as /public/cats.html.

Additional information:

There is a Hugo documentation page discussing how uglyURLs works: https://gohugo.io/content-management/urls/#ugly-urls
It clearly says on this page that /content/about/_index.md will map to https://example.com/about/ with uglyURLs = false and https://example.com/about/index.html with uglyURLs = true (so basically the same output file).
This is the behavior that I expect, but it is not the behavior I'm getting.

Therefore this is either a bug in Hugo itself, or a mistake in the documentation. I hope it's the former, because this behavior seems totally bizarre and insane to me.

@ChrisTucker2000
Copy link
Author

ChrisTucker2000 commented Feb 19, 2018

Thanks. So it was a problem with the documentation then.

Is there any way to make Hugo generate the output that I expect though? I don't think I want anything unusual. In my opinion, most people would expect _index.md to map to index.html in the same folder, not sectionname.html in the parent directory. I could set up a post-build task to rename and move each file, but I'd prefer to have Hugo cooperate rather than having to fight against it.

Personally, I would rather Hugo be changed to generate this the way one would naturally expect (i.e. I'm making a feature request).

@bep
Copy link
Member

bep commented Feb 19, 2018

Is there any way to make Hugo generate the output that I expect though?

You need to ask questions on the forum.

@bep
Copy link
Member

bep commented Feb 19, 2018

I will reopen this as I agree this looks a little funky.

  • I don't use uglyURLs myself, but we have plenty of test cases for it, so I just assumed that this was how it was designed (it is ugly, but that is the name).
  • We cannot easily break existing behaviour, but if someone can prove that this has changed in some recent Hugo version, then we should fix it (I assume for both sections and taxonomy terms).
  • But please don't use words such as "totally bizarre and insane" about other peoples' work, that is not how you start some fruitful discussion.

@bep bep reopened this Feb 19, 2018
@ChrisTucker2000
Copy link
Author

ChrisTucker2000 commented Feb 19, 2018

I suppose this is off-topic, but I do wonder why do you seem to have this impatient, dismissive, almost hostile attitude towards people that criticism of Hugo. I ask this not just because of your attitude in this thread (closing the issue with no comment, and then simply redirecting me to Discourse with no feedback on my comments at the time), but also because I've seen a similar attitude from you while searching all over the internet trying to figure out how Hugo works due to the lack of clear documentation.

For example, in issue #4367 you just dismissed them, closed the bug report, and told them to go to Discourse. The person replied confirming their opinion that it was a bug in Hugo, with more details and a repro scenario included, but there's been no response for weeks and the issue is still closed. It honestly puts me off Hugo and makes it seem as though you refuse to engage in any feedback or discussion, but maybe I'm just overreacting and have only seen a few bad examples.

You said it yourself there that "We prefer to use GitHub issues only for bugs and enhancements". I'm making a feature request (enhancement). I literally said that in my previous message. And I already have a thread on Discourse - it's literally in the first line in the OP.


As for the "totally bizarre and insane" line, perhaps it's not very nice, but I don't think that makes it untrue. I apologise if any feelings were hurt. Of course you don't want to be made to feel like your work is unappreciated - but similarly people who take the time to give feedback don't want to feel like they're just being dismissed. I didn't see any code of conduct included for this repository, and other open source projects that I've been involved in have been accepting of such language, as what matters at the end of the day is listening to feedback (even if harsh) and improving the software.

From the perspective of somebody who previously produced websites manually without a static site generator such as Hugo, this behavior seems completely unexpected. Ordinarily, a website will be made up of regular files (e.g. about.html, contact.html) and each directory will have an index.html file as the default page for that directory. When moving to Hugo, I want to take the same approach and expect the same behavior. I expect to be able to create an index.md or _index.md file in a directory, to represent the content for its default page, and have that be generated as index.html. I would never in my wildest dreams expect it to generate a mysection.html file in the parent directory (i.e. a completely unrelated place). I put the file in the section directory for a reason. That's where I want the content to be. Not in the parent directory.

Perhaps it's because I don't quite understand Hugo's supposed "special handling" of index.md and _index.md files though. In my travels I've come to understand that Hugo was changed at some point, but the documentation seems to be lacking on it. I've seen the slogan "everything is a page now" but it doesn't seem like that to me as an end-user. If everything is just a simple page, then why can't I just have "index.md" which changes to "index.html" just like with every other page?

The way I see "uglyURLs" personally is that it should be "normalURLs". I don't expect anything to be ugly, I expect them to just be normal. I don't want Hugo to mess with my filenames or URLs. I just want file.md to translate to file.html. Personally, I think the default "pretty URLs" are actually quite ugly, littering the directory structure with hundreds of folders and creating index.html files everywhere. I think that most people would prefer to do URL rewriting on the web server with Apache .htaccess rules or Nginx configuration files. Maybe I'm just in a different world though.

My current workaround to this is to rename _index.md to _intro.md and set url = "sectionname/index.html" in the front matter, but it's a hack and I have to do it for every single section index page. I would prefer it if Hugo handled this better automatically.

Edit: I'm already running into issues with the above hacky workaround. While Hugo generates the section/index.html files that I want when using this hack, it still generates the original junk files, and furthermore the generated sitemap.xml file links to the junk files and makes no mention of the section/index.html files. This means I also have to run a custom post-build task to delete the junk files, and do a series of find+replace searches in sitemap.xml. Interestingly, the section/index.xml files do have the right links though.

@onedrawingperday
Copy link
Contributor

@ChrisTucker2000 in case you don't know @bep is the lead dev for the Hugo project and he is working hard out of his own free time and pocket. So take it easy and show some respect.

Also long diatribes are difficult to read. Keep it short and to the point.

@vinniejames
Copy link

I somewhat agree with the request. While serving HTML from an Apache server (maybe others as well), without additional configuration the page is likely to return a 500 if a /folder and folder.html file share the same name

@ratfactor
Copy link

@ChrisTucker2000 and @vinniejames bring up some very valid technical challenges with the current "uglyURLs" behavior.

Perhaps a new setting could generate the output many of us are expecting:

public/<section>/index.html

...while not breaking existing sites which do depend on the current output:

public/<section>.html

Tongue-in-cheek, may I suggest a config property inspired by this conversation:

notBizarreAndInsaneURLs = true

😄

Seriously, though, the way the "Web works" since time immemorial has always been this sort of directory structure:

.
|-- stuff/
|    |-- foo1.html
|    |-- foo2.html
|    |-- foo3.html
|    `-- index.html           <--- the index for 'stuff/'!
|-- page1.html
|-- page2.html
|-- index.html                <--- the index for the site!

That's what web servers expect. That's what I expect. That's what works when serving a site from a filesystem without a web server. There's a reason it's called index.html!

Quite frankly, Hugo's current "ugly URL" behavior combined with the way it's named (undoubtedly meant in good humor) actually makes Hugo appear to consider this feature to be a "second class citizen" - that's unfriendly! Surely this is not what was intended.

Hugo is a wonderful application and I only wish to see it get better.

@stale
Copy link

stale bot commented Sep 1, 2018

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open.
If this is a feature request, and you feel that it is still relevant and valuable, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

@stale stale bot added the Stale label Sep 1, 2018
@ChrisTucker2000
Copy link
Author

This is still important to me.

@stale stale bot removed the Stale label Sep 1, 2018
@mpgirro
Copy link

mpgirro commented Oct 19, 2018

I would very much appreciate a configuration option for this issue too.

@TjeuKayim
Copy link

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

@f00b4r0
Copy link

f00b4r0 commented Mar 3, 2019

@bep

  • We cannot easily break existing behaviour, but if someone can prove that this has changed in some recent Hugo version, then we should fix it (I assume for both sections and taxonomy terms).

Hi, I stumbled upon this issue as I'm trying to upgrade from 0.21 (old, I know) to the most recent version (0.54 as of now) and it completely breaks my website.

Specifically, with 0.21 I used uglyURLs with the following architecture:

content/topic/index.md
content/topic/something.md
content/topic/someotherthing.md

and it would render like so

public/topic/index.html
public/topic/something.html
public/topic/someotherthing.html

Unfortunately with 0.54, having the index.md file in the topic directory makes hugo entirely ignore the other md files: it only renders public/topic/index.html and nothing else.
And if I rename index.md to _index.md then I get:

public/topic.html
public/topic/something.html
public/topic/someotherthing.html

I did a manual 'binary search' in the releases, this bug/change has been introduced in 0.32. 0.31.1 behaves as I expect, 0.32 breaks my website.

HTH

manpreetnarang pushed a commit to manpreetnarang/declaredesign.org that referenced this issue May 15, 2019
Workarounds for dealing with gohugoio/hugo#4428 and for the weird behavior of https://hugo-sandbox.netlify.com/hugodocs/content-management/page-bundles/#fn:fn-1

Because of those two problems, we can’t just name index pages index.Rmd or _index.Rmd because files aren’t copied correcly to the public folder.
@infin80
Copy link

infin80 commented May 21, 2019

Does this put an end to this issue?
https://gohugo.io/content-management/urls/#permalinks

MauriceBrg added a commit to MauriceBrg/hugoDocs that referenced this issue Apr 12, 2020
Update documentation to reflect status of this issue - (the --uglyurls CLI parameter no longer exists)
gohugoio/hugo#4428

See also: https://gohugo.io/getting-started/configuration/#configure-with-environment-variables
@thayerw
Copy link

thayerw commented Jun 7, 2020

I'm so glad I stumbled onto this ticket, though I wish it were 12 hours earlier as I'm nearly bald from pulling my hair out :)

I would definitely like to see this resolved at some point. It goes against the expected behaviour of directory indexes and can break functionality when creating local directory-based websites.

@thayerw
Copy link

thayerw commented Jun 7, 2020

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

@TjeuKayim: Thank you so much!

For anyone else that find themselves here, TjeuKayim's workaround does work, though you will also need to define the layout (e.g. layout: section) in the front matter or it will likely render with the single.html template. Obviously this depends on your theme templates, but that seems to be the most common layout design.

@s1-en
Copy link

s1-en commented Jun 10, 2020

I spent so long trying to figure out why I can't get this to work atall until I found this issue thread. All the existing solutions provided have some kind of drawback in one way or another. I just wanted to have the list page show up in the section's folder as index.html :/

davidsneighbour pushed a commit to gohugoio/hugoDocs that referenced this issue Jun 14, 2020
* Update urls.md

Update documentation to reflect status of this issue - (the --uglyurls CLI parameter no longer exists)
gohugoio/hugo#4428

See also: https://gohugo.io/getting-started/configuration/#configure-with-environment-variables

* Update urls.md

Remove a "use" that was not necessary.
@benolayinka
Copy link

This is really unfortunate. It also breaks a website we're migrating from Jekyll, with lots of relative image urls which no longer work with /public/section.html instead of /public/section/index.html, since the directory changes.

@benolayinka
Copy link

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

But this solution breaks branch bundles -> https://gohugo.io/content-management/page-bundles/

@vicmortelmans
Copy link

My workaround is to rename _index.html to something else (e.g. __index.html), and add slug = "index".

This will create the page at public/<section>/index.html

I suppose the above is applied in combination with the config setting uglyURLs = true. But by doing so, it looks to me like you have the same result as with uglyURLs = false. Back to where you started, not?

I deploy the site on a local filesystem (file:///...) and links with trailing slash, like "<section>/" are not working. So I was using uglyURLs, but because the mismatch between "content/<section>/index.md" and "public/<section>.html", my relative image URLs were broken.

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash:

"<section>/" ===> "<section>/index.html"

I wonder if that would be a viable concept for implementation in Hugo itself...

Best regards,
Vic

@gvegidy
Copy link

gvegidy commented Dec 29, 2021

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash:

"<section>/" ===> "<section>/index.html"

I wonder if that would be a viable concept for implementation in Hugo itself...

Yes, something like that would be really helpful. For example as option indexHtmlURLs = true.

I want to use it to create a offline copy my website that is to be used from disk with file:// urls.

@LunarWatcher
Copy link

LunarWatcher commented May 15, 2022

My hack is using url: /intro/ (in a file named /content/intro/_index.html; in general, just set the URL to be the desired path of the index file). Note that url: /intro/index.html does not work, and spews out XML instead, for some reason I do not understand. Like all other hacks, layout: single is also required

I couldn't for the life of me figure out where my index page went; it disappearing into intro.html didn't (and still doesn't) make any sense at all as a default.

@domogami
Copy link

A better fix would be to stay with uglyURLs = false and to postprocess the files in public, modifying all @href links, adding index.html to the trailing slash:
"<section>/" ===> "<section>/index.html"
I wonder if that would be a viable concept for implementation in Hugo itself...

Yes, something like that would be really helpful. For example as option indexHtmlURLs = true.

I want to use it to create a offline copy my website that is to be used from disk with file:// urls.

I would love to know if anything like this has been added because I am having the exact same problem and would love to convert <section>/ to <section>/index.html. For now I have resorted to manually changing the href links to include a hardcoded index.html. The service I am using to host wont render <section>/ links

@sbootes
Copy link

sbootes commented Oct 6, 2022

Even though this tread is closed, I have to say that as of 2022-10-06 nothing has changed. While ChrisTucker2000 may have used overly strong language, I have to agree with the issues he raised. As someone new to Hugo this month, I was about to abandon it altogether until I stumbled across this thread. I knew nothing about "ugly URLs" and coming from the Jekyll world I'm really struggling to understand Hugo. There's nothing intuitive about the system and while the documentation seems to be rigorous it isn't very unfriendly to novices. I hope something changes.

@nairboon
Copy link

This is still an issue as of v0.111.3

@jmooring
Copy link
Member

This would be substantially addressed if #10847 is accepted/merged. When uglyURLs = true, you would have to do this for each top-level section:

[permalinks.section]
posts = "/:sections[0:]/index/"

Given this content:

content/
├── posts/
│   ├── foo/
│   │   ├── bar.md
│   │   └── _index.md
│   └── post-1.md
└── _index.md

The site would be published to:

public/
├── posts/
│   ├── foo/
│   │   ├── bar.html
│   │   └── index.html
│   ├── index.html
│   └── post-1.html
├── favicon.ico
└── index.html

And this approach is backwards compatible (we don't break anybody).

@sbootes
Copy link

sbootes commented Apr 19, 2023

Hi @jmooring,

Thanks for looking into this. I hope #10847 is accepted/merged. It will be a big help! :-)

Any idea if automatic menu generation will respect the permalink URL or require different syntax to make it work?

@jmooring
Copy link
Member

@sbootes

automatic menu generation

Are you referring to the sectionPagesMenu configuration setting, or something else?

@sbootes
Copy link

sbootes commented Apr 19, 2023

@jmooring
For automatic menu generation I was thinking of defining menu entries in the front matter of each page then accessing through site.menu.main. Please forgive the reference, but in Jekyl permalinks with an ugly URL are picked up automatically even when pages are nested. I realize Hugo will do nested menus but I haven't gotten it to generate menus for pages in in sub-directories yet. I just assumed that the problem was with the uglyURLs. My apologies if the question wasn't clear or is straying out of scope.

@jmooring
Copy link
Member

@sbootes

I spoke too soon. We're publishing the pages in the right places, but the internal reference for section pages is broken. I can make it work with some trickery, but the section pages are then written with 2 dots before the extension (e.g., /posts/index..html). It works, but it's ugly.

I suspect this can be adjusted in #10847, but am reluctant to ask the PR author for additional work until we have an indication that the PR would be accepted.

For your other menu questions, please create a topic on the forum.

@mmallet-digipok
Copy link

I am happy to see I am not the only one struggling with uglyURLs. In my case, the hugo site is deployed in gitlab pages and the uglyURLs is required when using the gitlab pages preview feature, to see the site preview in mr/pr branch.

The root issue is on gitlab side as the preview implementation is hacky: the preview pages are not served the same way as the regular gitlab pages in gitlab and breaks the foo/bar/ to foo/bar/index.html redirections.

So I am indeed very interested is an option that works with uglyURLs and that would let me keep the html file name in the slug w/o changing the path.

I have /foo/bar/ directory that contains an _index.md file with its resources next to it (e.g. my-image.png referenced with « ./my-image.png » in markdown). When using uglyURLs, my links between pages are working but the page path and the image links become « /foo/bar.html » and « /foo/my-images.png » respectively, whereas the right image link should be « /foo/bar/my-images.png ».

I really hope it could be fixed :)

@jmooring
Copy link
Member

@mmallet-digipok The problem you describe is about properly resolving a markdown image destination to a URL, best handled with render hooks. For example:

git clone --single-branch -b hugo-github-issue-4428 https://github.com/jmooring/hugo-testing hugo-github-issue-4428
cd hugo-github-issue-4428
hugo server

Properly resolving markdown image and link destinations, regardless of site structure or configuration, is not a trivial exercise.

@mmallet-digipok
Copy link

@mmallet-digipok The problem you describe is about properly resolving a markdown image destination to a URL, best handled with render hooks. For example:

git clone --single-branch -b hugo-github-issue-4428 https://github.com/jmooring/hugo-testing hugo-github-issue-4428
cd hugo-github-issue-4428
hugo server

Properly resolving markdown image and link destinations, regardless of site structure or configuration, is not a trivial exercise.

I agree that it is probably not trivial. I am rather frustrated that gitlab provided just one half of a feature ;)

I checked your code but I don't see why I would inject 500+ lines of code to fix something that has been working correctly with uglyURLs turned off (and that is natively handled by hugo. Anyway what @ChrisTucker2000 described is exactly the issue I'm facing.

@mmallet-digipok
Copy link

@jmooring your render-image hook has convinced me: it is working fine for me now, thank you! I just hope this piece of code will be somehow part of the hugo codebase.

@jmooring
Copy link
Member

500+ lines of code

To clarify, the image render hook contains 73 lines of code. The link render hook contains 121 lines of code, but it does a lot a more, including the verification of URL fragments.

@ytrepidorosonomous
Copy link

This would be substantially addressed if #10847 is accepted/merged. When uglyURLs = true, you would have to do this for each top-level section:

[permalinks.section]
posts = "/:sections[0:]/index/"

Given this content:

content/
├── posts/
│   ├── foo/
│   │   ├── bar.md
│   │   └── _index.md
│   └── post-1.md
└── _index.md

The site would be published to:

public/
├── posts/
│   ├── foo/
│   │   ├── bar.html
│   │   └── index.html
│   ├── index.html
│   └── post-1.html
├── favicon.ico
└── index.html

And this approach is backwards compatible (we don't break anybody).

Was this addressed when the issue was merged? cc @jmooring

@jmooring
Copy link
Member

@ashtallama No, as described above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests