In Hugo, themes can be managed in two main ways:

  1. Using Git Submodules
  2. Using Go Modules

Both approaches aim to simplify theme management, but they have differences in setup, flexibility, and functionality. Let’s explore them in detail and compare.


1. Git Submodules for Theme Management

Git submodules allow you to include a Git repository (e.g., a theme) as a subdirectory in your project. This approach links your project to the theme’s repository, preserving version history.

Steps to Add a Hugo Theme as a Submodule:

  1. Initialize Git in Your Hugo Site:

    1
    
    git init
    
  2. Add the Theme as a Submodule:

    1
    
    git submodule add https://github.com/themepath/theme.git themes/theme-name
    
  3. Update Your Hugo Configuration: Add the theme to your config.toml:

    1
    
    theme = "theme-name"
    
  4. Clone the Project with Submodules (When Sharing): When cloning the repository, include submodules:

    1
    
    git clone --recurse-submodules <repo-url>
    
  5. Update the Theme Submodule: To pull the latest changes from the theme:

    1
    2
    
    cd themes/theme-name
    git pull origin main
    
  6. Commit Submodule Updates: If you update the submodule, commit the change in the parent repository:

    1
    2
    
    git add themes/theme-name
    git commit -m "Updated theme submodule"
    

Advantages of Git Submodules:

  • Git-native workflow: No need to learn additional tools.
  • Version tracking: You can lock a theme to a specific commit.

Disadvantages:

  • Complexity: Managing submodules can be tricky, especially during merges or updates.
  • Cloning overhead: Requires special commands for cloning (--recurse-submodules).
  • Manual updates: Must manually pull theme changes and commit them to the parent repository.

2. Go Modules for Theme Management

Go modules provide a more modern and streamlined approach for dependency management in Hugo. With Go modules, themes are treated as external dependencies and managed using go.mod and hugo.mod.

Steps to Add a Hugo Theme as a Go Module:

  1. Initialize Go Modules in Your Hugo Site:

    1
    
    hugo mod init github.com/yourusername/yourproject
    
  2. Add the Theme as a Dependency:

    1
    
    hugo mod get github.com/themepath/theme
    
  3. Update Your Hugo Configuration: In config.toml:

    1
    2
    3
    
    module:
      imports:
        - path: github.com/themepath/theme
    
  4. Update Dependencies: Update the theme to the latest version:

    1
    
    hugo mod get -u
    
  5. Verify Dependencies: Check the integrity of dependencies:

    1
    
    hugo mod verify
    
  6. Theme Storage and Caching: Hugo automatically caches Go modules in a local directory (e.g., ~/go/pkg/mod).

Advantages of Go Modules:

  • Ease of Updates: Update dependencies with simple commands.
  • Version Locking: Ensures builds are reproducible with a go.sum file.
  • Performance: Hugo caches modules locally, speeding up builds.
  • Lightweight Repositories: Themes aren’t stored in the project directory.

Disadvantages:

  • Requires Go Installed: You need Go installed on your system.
  • Learning Curve: Might require some familiarity with Go modules.

Comparison: Git Submodules vs. Go Modules

FeatureGit SubmodulesGo Modules
Setup ComplexityModerate (requires Git knowledge)Easy (once Go is installed)
Version LockingBy commitBy version (or specific commit)
Ease of UpdatesManual git pullAutomated with hugo mod get -u
Dependency StorageStored in the project directory (themes/)Cached externally (e.g., ~/go/pkg/mod)
Reproducible BuildsRequires careful manual managementEnsured with go.sum
Collaboration (Cloning)Requires --recurse-submodulesSimple git clone
PerformanceSlower due to Git operationsFaster due to caching
Learning CurveLow (basic Git knowledge)Moderate (requires understanding Go)

1. Key Considerations for Git Submodules

a. Ensure Submodules Are Cloned

By default, a Git repository does not clone its submodules. For deployment platforms like Netlify or Vercel, you need to ensure the submodules are included during the build.

Solution:

  1. Set up the repository to initialize submodules during the build process.
    • For Netlify, add this to a file named netlify.toml:

      1
      2
      3
      4
      5
      6
      
      [build]
        command = "hugo --gc --minify"
        publish = "public"
      
      [build.environment]
        GIT_SUBMODULE_STRATEGY = "recursive"
      
    • For Vercel, you need a .vercel configuration or custom build script. Vercel typically does not clone submodules by default, so you may need to use a postinstall script in package.json:

      1
      2
      3
      
      "scripts": {
        "postinstall": "git submodule update --init --recursive"
      }
      

b. Version Locking

When using submodules, the submodule points to a specific commit. Ensure you push all changes and lock the submodule at the desired commit.

  • Verify with:
    1
    
    git submodule status
    

c. Access to Private Repositories

If the submodule is in a private repository, Netlify or Vercel might fail to fetch it due to authentication issues.

Solution:

  • Use a deploy key specifically for the submodule repository.
  • For Netlify:
    1. Add an SSH key in the Netlify site settings.
    2. Ensure the key has access to the submodule repository.
  • For Vercel:
    1. Use a GitHub or GitLab integration that includes submodule access.

d. Submodule Updates

Keep submodules updated manually with:

1
git submodule update --remote

and commit the changes to the parent repository.


2. Key Considerations for Go Modules

a. Ensure Go Is Installed

Platforms like Netlify or Vercel may not have Go installed by default, but Hugo sites using Go modules require it. Ensure the correct Go version is available during the build process.

Solution:

  • For Netlify, specify the Go version in the netlify.toml file:

    1
    2
    
    [build.environment]
      GO_VERSION = "1.20"
    
  • For Vercel, specify the Go runtime in your vercel.json or use a custom build command.

b. Module Initialization During Build

Go modules need to be initialized and dependencies fetched during deployment.

Solution:

  • Ensure the hugo build command fetches modules:
    1
    
    hugo --gc --minify
    
    Hugo automatically initializes and downloads dependencies.

c. Cache Go Module Dependencies

Caching speeds up deployments by avoiding repetitive downloads of Go modules.

  • Netlify: Modules are automatically cached in Netlify’s build environment.
  • Vercel: Dependencies can be cached if you use a go.mod and configure the .vercel build settings properly.

d. Private Module Access

If your Go module (e.g., a theme) is hosted in a private repository, you’ll need to configure authentication.

Solution:

  • Use a .netrc file or SSH key to authenticate for private repositories.
  • Add authentication environment variables:
    • GOPRIVATE for private repositories.
    • GIT_AUTH_TOKEN or equivalent for GitHub/GitLab.

Comparison for Deploying to Netlify or Vercel

AspectGit SubmodulesGo Modules
Ease of SetupModerate (requires submodule init/clone)Easier (dependencies fetched automatically)
Build CommandStandard Hugo build (hugo)Standard Hugo build (hugo)
Dependency ManagementManual updates (git pull)Automatic with hugo mod get
CachingNo built-in cachingBuilt-in caching for Go modules
Private RepositoriesRequires SSH key or token setupRequires GOPRIVATE or .netrc setup
Platform CompatibilitySupported on bothSupported on both
PerformanceSlower due to submodule cloningFaster with cached modules

Recommendations

  • For Simple or Legacy Projects: Use Git submodules if your team is already familiar with Git workflows, and the project doesn’t require frequent updates to themes or dependencies.

  • For Modern, Scalable Projects: Use Go modules if you value performance, caching, and ease of dependency management, especially for large-scale deployments.

  • Platform-Specific Notes:

    • On Netlify, both methods work well, but Go modules are easier to manage for complex projects.
    • On Vercel, Go modules are preferred for better caching and dependency handling.

By understanding the nuances of each method, you can choose the one that aligns with your workflow and deployment requirements. Whether you opt for Git submodules or Go modules, both offer effective ways to manage themes and dependencies in your Hugo projects.


Conclusion

  1. Git Submodules provide a Git-native way to manage themes but require manual updates and version tracking.
  2. Go Modules offer a modern approach with automated dependency management and caching for faster builds.
  3. Deploying to Netlify or Vercel requires specific considerations for Git submodules or Go modules, ensuring a smooth deployment process.

Recommendation

  • Use Git Submodules if:

    • You are familiar with Git workflows.
    • You want all files (including themes) in the same repository.
    • You don’t need frequent updates to the theme.
  • Use Go Modules if:

    • You want modern dependency management.
    • You work on large projects with multiple themes or dependencies.
    • You need consistent builds and version control.
    • You value faster builds with cached dependencies.

For modern workflows and larger projects, Go Modules are generally the better choice due to their speed, reproducibility, and ease of maintenance.

Deploying a Hugo site to platforms like Netlify or Vercel requires careful handling of dependencies, especially if you’re using Git submodules or Go modules for theme management. Each method has unique considerations for deployment. Here’s a breakdown:


References: