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 asindex.mdinside 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 animagessub-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 (likeimages/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