Any free CMS that uses Hugo's page bundles?

I tried one in the past and it saved images to static folder.

Farhad from Sitepins cms here. we don’t support hugo page bundles yet, but this is a great callout. adding to our roadmap to see if we can support it in an upcoming update.

[Sveltia CMS](GitHub - sveltia/sveltia-cms: Leading Git-based headless CMS. Successor to Netlify/Decap CMS. Modern UX, first-class i18n support, mobile support + 100s of improvements. Framework-agnostic, open source & free. · GitHub) is great, I got implemented on 2 websites, each working differnetly, some of them got images in Static folder, others got in Assets with Page bundles. Its all about configuration. Claude can help you, using hit-and-miss approach to achieve end goal.

A follow up response:


Yes, you can absolutely achieve this using Sveltia CMS. It is free, lightweight, and can be configured to natively support Hugo’s page bundle structure.

To make it work, you need to adjust the collections section of your config.yml so that it dynamically creates a folder for each new post and stores the assets relative to that folder.

Here is how the specific settings in the configuration handle page bundles:

  • path: "{{year}}/{{month}}/{{day}}/{{slug}}/index": This creates a new directory for the post based on the date and slug, and saves the text file as index.md inside it.
  • media_folder_relative: true: This is the crucial setting. It forces the CMS to store media relative to the markdown file rather than in a global static folder.
  • media_folder: "images": This creates an images sub-directory inside your specific page bundle to keep your files organised (e.g., content/2026/08/03/my-post/images/).
  • public_folder: "images": This ensures that when you insert an image into your post, the markdown or front matter outputs the correct relative path (like images/photo.jpg), which Hugo requires to process page resources properly.

Here is a complete, working example configuration you can adapt for your site:

site_url: https://example.com
display_name: Example CMS
app_title: Example CMS 
logo:
  src: https://example.com/svg/example_logo.svg

locale: en

# Forces all media uploads and filenames to be URL-safe for Hugo
slug:
  encoding: "ascii"
  clean_accents: true
  sanitize_replacement: "-"
  timezone: "local"

backend:
  name: github
  repo: user/example_hugo
  branch: main
  auth_methods: [oauth]
  skip_ci: true
  logout_redirect_url: 'https://example.com'
  commit_messages:
    create: "Added post: {{slug}} (by {{author-name}})"
    update: "Updated post: {{slug}} (by {{author-name}})"
    delete: "Deleted post: {{slug}} (by {{author-name}})"
    uploadMedia: "Uploaded file: {{path}} (by {{author-name}})"
    deleteMedia: "Deleted file: {{path}} (by {{author-name}})"

publish_mode: editorial_workflow

yaml_formatting:
  indent_sequences: true

local_backend: true

media_folder: "static/images"
public_folder: "/images"

i18n:
  default_locale: en
  locales:
    - en

collections:
  - name: "posts"
    label: "Posts"
    folder: "content"
    duplicate: true 
    nested: true
    relative_assets: true
    slug: "{{slug}}"
    extension: "md"
    
    # --- PAGE BUNDLE CONFIGURATION ---
    path: "{{year}}/{{month}}/{{day}}/{{slug}}/index"
    media_folder: "images"
    public_folder: "images"
    media_folder_relative: true
    # ---------------------------------
    
    identifier_field: [ date, title ]
    sortable_fields:
      fields: [ date ]
      default:
        field: date
        direction: descending
    thumbnail: "featuredImage" 
    summary: "{{date}} | {{title}}"
    view_groups:
      groups:
        - name: year
          label: "Year"
          field: date
          pattern: \d{4}
        - name: date
          label: "Date"
          field: date
          pattern: \d{4}-\d{2}-\d{2}
      default: year
    fields:
      - label: "Author"
        name: "author"
        widget: "hidden"
        default: "{{author-name}}" 
      - label: "Post status"
        name: "status"
        widget: "select"
        options: 
          - { label: "Draft", value: "draft" }
          - { label: "Review", value: "review" }
          - { label: "Final", value: "final" }
        default: "draft"
      - label: "Title"
        name: "title"
        widget: "string"
      - label: "SEO Description (Meta Description)"
        name: "description"
        widget: "text" 
        required: false
        hint: "Short description visible in Google search results (recommended up to 255 characters)."
      - label: "Date"
        name: "date"
        widget: "datetime"
        default: "{{now}}"
        input_timezone: "local"
        type: "date"
        min: "2024-01-01" 
        display_format: "D MMMM YYYY"
      - label: "Featured Image"
        name: "featuredImage"
        widget: "image"
        required: false
      - label: "Image description (SEO/Alt)"
        name: "featuredImageAlt"
        widget: "string"
        required: false
        hint: "Describe what is in the image for visually impaired users and search engines."
      - label: "Content"
        name: "body"
        widget: "markdown"
        sanitize_preview: false
        line_numbers: true
        media_library:
          allow_external_urls: false 
          max_file_size: 4194304 
      - label: "Tags"
        name: "tags"
        widget: "list"
        required: false
        allow_duplicate: false