3 Directory Listings
Ric Harvey edited this page 2025-12-03 15:15:17 +00:00

Directory Listings

Directory listings provide an Apache-style file browser for directories that don't have an index.html file. This feature is disabled by default and can be enabled on a per-repository basis.

Overview

When enabled, the directory listing feature displays a beautifully formatted HTML page showing all files and folders in a directory, similar to Apache's directory indexing but with a modern, responsive design.

When Are Directory Listings Shown?

Directory listings are displayed when all of these conditions are met:

  1. directory_index: true is set in the repository's .pages file
  2. A directory URL is requested (no file extension in path)
  3. No index.html file exists in that directory
  4. The directory exists and contains files

If any condition is not met, a 404 error is returned instead.

Features

Visual Design

  • Modern Interface: Clean, professional design with gradient header
  • Responsive Layout: Works perfectly on desktop, tablet, and mobile devices
  • Color-Coded Icons:
    • 📁 Yellow folder icons for directories
    • 📄 Blue file icons for files
    • ⬅️ Gray back arrow for parent directory
  • Hover Effects: Interactive row highlighting on hover
  • Typography: Clean, readable system fonts

Functionality

  • File Information: Shows file name, type (File/Directory), and size
  • Parent Navigation: "Parent Directory" link to go up one level (when not at root)
  • Clickable Entries: All files and folders are clickable links
  • Human-Readable Sizes: File sizes shown as B, KB, MB, or GB
  • Breadcrumb Path: Shows current location with username/repository
  • Sorted Entries: Files and folders listed in API-provided order

Performance

  • Cached: Directory listings are cached for 60 seconds
  • Fast API Calls: Uses Forgejo's directory contents API
  • Lightweight: No external dependencies, pure Go implementation

Configuration

Enable Directory Listings

Add directory_index: true to your repository's .pages file:

enabled: true
directory_index: true

Disable Directory Listings (Default)

Either omit the field or set it to false:

enabled: true
directory_index: false

Or simply don't include it (defaults to false):

enabled: true

Usage Examples

Example 1: Documentation Repository

Use Case: Documentation with nested folders

.pages file:

enabled: true
directory_index: true

Repository structure:

public/
├── index.html         (homepage)
├── api/
│   ├── v1/
│   │   └── reference.html
│   └── v2/
│       └── reference.html
└── guides/
    ├── installation.html
    └── configuration.html

URLs:

  • https://username.pages.domain.com/docs/ → shows index.html
  • https://username.pages.domain.com/docs/api/shows directory listing (no index.html)
  • https://username.pages.domain.com/docs/api/v1/shows directory listing
  • https://username.pages.domain.com/docs/guides/shows directory listing

Example 2: File Archive

Use Case: Public file sharing/downloads

.pages file:

enabled: true
directory_index: true

Repository structure:

public/
├── downloads/
│   ├── app-v1.0.zip
│   ├── app-v1.1.zip
│   └── app-v2.0.zip
└── assets/
    ├── logo.png
    └── banner.jpg

URLs:

  • https://username.pages.domain.com/files/downloads/shows list of all zip files
  • https://username.pages.domain.com/files/assets/shows list of image files

Example 3: Mixed Content

Use Case: Some directories with index, some without

.pages file:

enabled: true
directory_index: true

Repository structure:

public/
├── index.html         (has index)
├── blog/
│   ├── index.html     (has index)
│   └── 2024/          (no index - will show listing)
│       ├── post1.html
│       └── post2.html
└── resources/         (no index - will show listing)
    ├── document.pdf
    └── spreadsheet.xlsx

URLs:

  • https://username.pages.domain.com/site/ → shows index.html
  • https://username.pages.domain.com/site/blog/ → shows index.html
  • https://username.pages.domain.com/site/blog/2024/shows directory listing
  • https://username.pages.domain.com/site/resources/shows directory listing

Directory Listing Display

What Users See

When a directory listing is shown, users see a page with:

Header:

  • Title: "Index of /path/to/directory"
  • Breadcrumb: "username/repository"
  • Gradient purple background

Table:

  • Name column: File/folder name with icon
  • Type column: "File" or "Directory"
  • Size column: Human-readable file size (or "-" for directories)

Footer:

  • "Powered by Bovine Pages Server"

Sample Directory Listing

┌─────────────────────────────────────────────────┐
│  Index of /downloads                            │
│  username/repository                            │
└─────────────────────────────────────────────────┘
┌─────────────────────────┬──────────┬───────────┐
│ Name                    │ Type     │ Size      │
├─────────────────────────┼──────────┼───────────┤
│ ⬅️  Parent Directory    │ -        │ -         │
│ 📁 archives             │ Directory│ -         │
│ 📄 app-v1.0.zip        │ File     │ 2.3 MB    │
│ 📄 app-v2.0.zip        │ File     │ 3.1 MB    │
│ 📄 readme.txt          │ File     │ 1.2 KB    │
└─────────────────────────┴──────────┴───────────┘
           Powered by Bovine Pages Server

Security Considerations

What Directory Listings Expose

When directory listings are enabled, all files and folders in directories without index.html become visible to anyone who can access your site.

⚠️ Important Security Notes:

  1. Don't Store Secrets: Never put sensitive files in public directories with directory listings enabled
  2. Check File Permissions: Remember that if someone can see the filename, they can access the file
  3. Consider Privacy: File names themselves may reveal sensitive information
  4. Use Password Protection: Combine with password protection for sensitive archives

Good Use Cases:

  • Public documentation repositories
  • Open source project downloads
  • Public file archives
  • Resource libraries
  • Asset directories for websites

Bad Use Cases:

  • Private documents repository
  • Directories with sensitive filenames
  • Backup directories
  • Configuration files
  • Internal-only resources

Combine with Password Protection

For semi-private file sharing, combine directory listings with password protection:

enabled: true
directory_index: true
password: your-sha256-hash-here

This allows authorized users to browse files while keeping them private from the public.

Limitations

Profile Sites (.profile Repository)

⚠️ Directory listings do not work for profile site directories.

Why This Limitation Exists:

The URL structure for pages domain requests uses the first path segment to determine whether you're accessing:

  • A repository (e.g., https://username.pages.domain.com/myrepo)
  • A file in the profile site (e.g., https://username.pages.domain.com/about.html)

The system uses file extensions to distinguish between these cases:

  • Has extension (.html, .css, etc.) → Profile site file
  • No extension → Repository name

Because directories don't have file extensions, a URL like https://username.pages.domain.com/downloads/ is interpreted as a repository named "downloads", not as a directory in the profile site.

Workaround:

If you need directory listings for your profile site, use a regular repository instead:

  1. Create a repository (e.g., mysite)
  2. Enable directory listings in that repository's .pages file
  3. Access directories via: https://username.pages.domain.com/mysite/downloads/

Custom Domains Work Normally:

If you use a custom domain for your profile site, directory listings work as expected because the URL structure is different:

  • Custom domain: https://custom.domain.com/downloads/ Works
  • Pages domain: https://username.pages.domain.com/downloads/ Interpreted as repository

Technical Details

How It Works

  1. Request Arrives: User navigates to a directory URL (e.g., /downloads/)
  2. Try index.html: Plugin first tries to serve index.html from that directory
  3. Check Configuration: If no index.html, checks .pages file for directory_index: true
  4. Fetch Directory: Calls Forgejo API to list directory contents
  5. Generate HTML: Creates beautiful HTML listing page
  6. Serve & Cache: Serves the page and caches it for 60 seconds

API Calls

The feature uses Forgejo's repository contents API:

GET /api/v1/repos/{owner}/{repo}/contents/{path}

This returns a JSON array of files and directories with metadata.

Performance Impact

  • Additional API Call: One extra API call when directory listing is triggered
  • Minimal Overhead: Listing generation is very fast (< 1ms for typical directories)
  • Caching: Results cached for 60 seconds to reduce repeated API calls
  • No Impact on Files: Regular file serving is unaffected

Mobile Responsiveness

On mobile devices (< 768px width):

  • Type and Size columns are hidden
  • Table shows only the Name column with icons
  • Maintains full functionality with cleaner layout
  • Touch-friendly link targets

Troubleshooting

Directory Listing Not Showing

Problem: Expected directory listing but seeing 404 error

Checklist:

  1. Is directory_index: true in your .pages file?
  2. Are you accessing a directory (URL ends with / or no extension)?
  3. Does the directory NOT have an index.html file?
  4. Does the directory exist and contain files?
  5. Is the .pages file properly formatted YAML?

Test:

# Check .pages file
curl https://git.example.com/api/v1/repos/username/repo/contents/.pages

# Check directory exists
curl https://git.example.com/api/v1/repos/username/repo/contents/public/yourdir

Showing Empty Listing

Problem: Directory listing shows but has no files

Possible Causes:

  1. Directory is truly empty
  2. All files start with . (hidden files) - Forgejo API may not return them
  3. Directory only contains subdirectories (check if you're in the right place)

index.html Takes Precedence

Problem: Directory listing doesn't show even though enabled

Explanation: This is expected behavior! If an index.html file exists, it takes precedence over directory listings. This is by design.

Solution: If you want directory listing for a specific directory, remove or rename its index.html file.

Styling Issues

Problem: Directory listing appears but styling is broken

Possible Causes:

  1. Browser caching old version - Clear cache and reload
  2. Content-Security-Policy blocking inline styles - Check browser console
  3. Very old browser - Requires modern browser with CSS Grid support

Comparison with Other Solutions

vs. Apache Directory Index

Similarities:

  • Shows file and folder listings
  • Navigable directory structure
  • File size display

Advantages over Apache:

  • Modern, beautiful design
  • Responsive mobile layout
  • Color-coded icons
  • Per-repository configuration
  • Integrated with git repository structure

Differences:

  • No column sorting (yet)
  • No date modified column
  • Opt-in (disabled by default)

vs. index.html with File List

Why Use Directory Listings Instead:

  • Automatic - no manual HTML updates
  • Always current - reflects repository state
  • Less maintenance - no need to update file list
  • Works for any directory depth

When to Use Manual index.html:

  • Custom styling and branding
  • Descriptions and metadata for files
  • Custom grouping and categorization
  • SEO optimization

Examples in the Wild

Documentation Repository

A documentation site with directory listings for API versions:

https://username.pages.domain.com/docs/
├── index.html                    (main docs page)
├── v1/                          (directory listing)
│   ├── endpoints.html
│   └── authentication.html
└── v2/                          (directory listing)
    ├── endpoints.html
    └── authentication.html

Download Archive

A software project with versioned downloads:

https://username.pages.domain.com/downloads/
└── releases/                     (directory listing)
    ├── v1.0.0/                  (directory listing)
    │   ├── app-linux.tar.gz
    │   └── app-windows.zip
    └── v2.0.0/                  (directory listing)
        ├── app-linux.tar.gz
        └── app-windows.zip

Future Enhancements

Potential features for future versions:

  • 📊 Column sorting (by name, size, type)
  • 📅 Last modified date display
  • 🔍 Search/filter functionality
  • 📁 Custom icons by file extension
  • 🎨 Themeable design
  • 📝 Custom header/footer content
  • 📦 Bulk download (zip)

Support