How to make hugo generate links with "/index.html" instead of simply "/" by the end of the link

Hello guys!

First of all, I would like to address myself to the creator(s) of this great software that is Hugo.
For me, it is the best static site generator I ever used!
Thank you very much for your inspiring work.
I truly hope you be successful.

I came across an issue that I would like very much to be configurable.
A bit of context, first:
I have uploaded my site to AWS S3 and it is now possible to open the initial page, but if I click on ‘posts’ or ‘about’ links, I have a link pointing to a folder instead of the file itself.
I believe you know already what I am talking about, but basically it is like this:
https://mysite.be/about/
but since in AWS S3, I cannot point to a folder, I got “AccessDenied”.
If I add the file myself on the link, then it is ok:
https://mysite.be/about/index.html

Question: Is there a way I can configure either hugo to generate such links with files?

Thank you all in advance for your time and effort to make such a great software.

1 Like

Hello Mr. divinerites.

Thank you you very much for your time.
It is very kind of you. I appreciate it.
I have tried to set up “uglyurls = true” on my config.toml file and after that, I’ve got a blank page for “posts” link and a 404 page for “about” link.
I wonder if my config.toml would have something wrong in it.
Can you take a look?

config.toml file:
---------------------
indent preformatted text by 4 spaces
baseURL = “https://site.be
title = “Blog”
DefaultContentLanguage = “en”
theme = “hello-friend-ng”
PygmentsCodeFences = true
PygmentsStyle = “monokai”
rssLimit = 10 # Maximum number of items in the RSS feed.
copyright = “All rights reserved to Blog.” # This message is only used by the RSS template.

# googleAnalytics = ""
# disqusShortname = ""

archetypeDir = "archetypes"
contentDir   = "content"
dataDir      = "data"
layoutDir    = "layouts"
publishDir   = "public"
buildDrafts  = false
buildFuture  = false
buildExpored = false
canonifyURLs = true
enableRobotsTXT = true
enableGitInfo   = false
enableEmoji     = true
enableMissingTranslationPlaceholders = false
disableRSS     = false
disableSitemap = false
disable404     = false
disableHugoGeneratorInject = false

uglyurls = true                               # <<<-------------- UGLYURLS parameter

[permalinks]
  posts = "/posts/:year/:month/:title/"

[author]
  name = "Blog Author"

[blackfriday]
  hrefTargetBlank = true

[taxonomies]
  tag      = "tags"
  category = "categories"

[params]
  dateform        = "Jan 2, 2006"
  dateformShort   = "Jan 2"
  dateformNum     = "2006-01-02"
  dateformNumTime = "2006-01-02 15:04 +0100"

  # Metadata mostly used in document's head
  description = "Nice theme for homepages and blogs"
  keywords = ""
  images = [""]

  homeSubtitle = "Welcome to blog"

  # Prefix of link to the git commit detail page. GitInfo must be enabled.
  # gitUrl = ""

  # Set disableReadOtherPosts to true in order to hide the links to other posts.
  disableReadOtherPosts = false

  # Integrate Javascript files or stylesheets by adding the url to the external assets or by
  # linking local files with their path relative to the static folder, e.g. "css/styles.css"
  customCSS = []
  customJS  = []

  # Toggle this option need to rebuild SCSS, requires extended version of Hugo
  justifyContent = false  # Set "text-align: justify" to .content.

  # Directory name of your blog content (default is `content/posts`)
  contentTypeName = "posts"

  # Default theme "light" or "dark"
  defaultTheme = "dark"
  themeColor = "#252627"

  # Colors for favicons
  [params.favicon.color]
    mask = "#252627"
    msapplication = "#252627"
    theme = "#252627"

  [params.logo]
    logoText     = "$ cd /home/"
    logoHomeLink = "/"
    # Set true to remove the logo cursor entirely.
    # logoCursorDisabled = false
    # Set to a valid CSS color to change the cursor in the logo.
    # logoCursorColor    = "#67a2c9"
    logoCursorColor    = "#338333"
    # Set to a valid CSS time value to change the animation duration, "0s" to disable.
    # logoCursorAnimate  = "2s"
    logoCursorAnimate  = "3s"

  # Social icons
#  [[params.social]]
#    name = "twitter"
#    url  = "https://twitter.com/"

  [[params.social]]
    name = "email"
    url  = "mailto:myblogger@gmail.com"

#  [[params.social]]
#    name = "github"
#    url  = "https://github.com/"

[languages]
  [languages.en]
    subtitle  = "Welcome to blog"
    weight    = 1
    copyright = '<a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">CC BY-NC 4.0</a>'

  [languages.fr]
    subtitle  = "Bienvenue au blog"
    weight    = 2
    copyright = '<a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">CC BY-NC 4.0</a>'

[menu]
  [[menu.main]]
    identifier = "about"
    name       = "About"
    url        = "about/" # <<<-------------- I NEED THIS TO BECOME something like: <mysite>/about/index.html

  [[menu.main]]
    identifier = "posts"
    name       = "Posts"
    url        = "posts/" # <<<-------------- I NEED THIS TO BECOME something like: <mysite>/posts/index.html
------------------------------------

If I set ‘url’ parameter inside ‘[[menu.main]]’, I got errors with ‘uglyurls = true’.
For the moment, About link returns ‘404 page not found’ and ‘Posts’ link returns a blank page.

Just put whatever you need.

[menu] 
   [[menu.main]] 
      identifier = "about" 
      name = "About" 
      url = "about/index.html"

Hello Mr. divinerites,

Once again thank you very much for your intervention.
As spartan as it was, it was helpful. Not without some sweat, but greatly useful.
After working years only on desktop, mostly with Java and C#, I am quite inexperienced with anything related to web and this is my first site on AWS after years putting content on gogglepages, so I confess I was hoping for a bit more of detail, but that was indeed not necessary.
To summarize, your config.toml change proposition did not work, but the fact that I was free to try something else gave, trial by trial, more and more understanding on how Hugo organizes itself in order to generate static content.
Before showing what worked for me, please let me show what I have tried and what happened after each trial in the hopes I could either get some insights of why it did not work and, should my trials reveal a bug on Hugo, I would be glad to share with the community to improve it.

Attempt #1

[menu]
  [[menu.main]]
    identifier = "about"
    name       = "About"
    url        = "about**.html**/index.html"
[[menu.main]]
  identifier = "posts"
  name       = "Posts"
  url        = "posts.html"

In this 1rst attempt the result was:
Working on debug (hugo server) but not for generation. For generation, it says:
Error building site: failed to render pages: open /home/user01/sites/site01/public/about.html: is a directory


You may have noticed that about**.html**/index.html, I put the link having about**.html** as a directory because config.toml parameter “uglyurls = true” was creating about.html a directory.

Attempt #2

[menu]
  [[menu.main]]
    identifier = "contact"
    name       = "Contact"
    url        = "contact/index.html"
  [[menu.main]]
    identifier = "posts"
    name       = "Posts"
    url        = "posts.html"

In this 2nd attempt, it seams to work for generation (did not push to the server to try), but not for debug.


Attempt #3
This time, I thought I could be facing a problem due to some piece of hard-coded software that handles “About” differently, so I have adapted strategy.
Before, my about.md was in the root of “content” folder, so I changed its name to contact.md and put it inside a folder named “contact”, after that, on my file contact.md, I removed the following from its Front Matter: # aliases = [“about-us”,“contact”]
After that I just changed my config.toml to my definitive version that is now git commit :wink:

[menu]
  [[menu.main]]
    identifier = "contact"
    name       = "Contact"
    url        = "contact/contact.html"
  [[menu.main]]
    identifier = "posts"
    name       = "Posts"
    url        = "posts.html"

I truly hope this helps somebody that may come across this kind of problem.

1 Like

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