Static Resources Overview

What are Static Resources?

Spry provides a built-in system for serving static assets like CSS, JavaScript, images, and fonts. The static resource system handles content negotiation, compression, and caching automatically.

Unlike traditional web frameworks that serve static files directly from disk, Spry's static resources are pre-compressed and can be embedded directly into your binary for single-binary deployments.

Types of Static Resources

Spry provides three implementations of the StaticResource interface:

FileStaticResource

Reads pre-compiled .ssr (Spry Static Resource) files from disk at runtime. These files contain the resource data along with pre-compressed versions (gzip, zstd, brotli) and metadata.

  • Loaded from .ssr files generated by spry-mkssr
  • Contains all compression variants in a single file
  • Includes SHA-512 hash for ETags

MemoryStaticResource

Holds static resource data entirely in memory. Useful for dynamically generated resources or when you want to load resources from a custom source.

  • All data held in RAM
  • Supports all compression formats
  • Created programmatically at runtime

ConstantStaticResource

Embeds static resources directly into your binary at compile time. The resource data becomes part of your executable, enabling true single-binary deployments.

  • Compiled into your binary
  • Generated by spry-mkssr with --vala flag
  • Zero runtime file I/O

The StaticResource Interface

All static resources implement the StaticResource interface, which defines the contract for serving static content:

Vala
public interface StaticResource : Object {
    // The unique name of this resource (e.g., "docs.css")
    public abstract string name { get; }

    // Returns the best encoding supported by the client
    public abstract string get_best_encoding(Set<string> supported);

    // Returns the ETag for a specific encoding
    public abstract string get_etag_for(string encoding);

    // Converts the resource to an HTTP result
    public abstract HttpResult to_result(string encoding, 
                                         StatusCode status = StatusCode.OK) 
        throws Error;
}

The StaticResourceProvider Endpoint

Spry includes a built-in endpoint for serving static resources. The StaticResourceProvider handles all the complexity of content negotiation and caching.

Route Pattern

Static resources are served from the route:

/_spry/res/{resource}

Where {resource} is the name of the resource (e.g., docs.css, htmx.js).

Content Negotiation

The provider automatically selects the best compression format based on the client's Accept-Encoding header. Supported encodings:

  • gzip - Universal browser support
  • zstd - Modern, high-performance compression
  • br (Brotli) - Best compression ratios for text
  • identity - No compression (always available)

ETag-Based Caching

Each resource generates an ETag based on its content hash and encoding. The provider handles If-None-Match requests, returning 304 Not Modified when the client's cached version is current.

Vala
// ETag format: "{encoding}-{hash}"
// Example: "br-a1b2c3d4e5f6..."

// The provider checks If-None-Match automatically:
if (request.headers.get_or_empty("If-None-Match").contains(etag)) {
    return new HttpEmptyResult(StatusCode.NOT_MODIFIED);
}

// Fresh content is returned with the ETag header
response.set_header("ETag", etag);

Using Resources in Templates

Spry provides the spry-res attribute for easily referencing static resources in your HTML templates. This attribute automatically generates the correct URL for your resource.

HTML
<!-- Stylesheets -->
<link rel="stylesheet" spry-res="docs.css">

<!-- JavaScript -->
<script spry-res="htmx.js"></script>
<script spry-res="htmx-sse.js"></script>

<!-- Images -->
<img spry-res="logo.png" alt="Logo">

<!-- Results in URLs like: -->
<!-- /_spry/res/docs.css -->
<!-- /_spry/res/htmx.js -->

The spry-res attribute works with any element that has href or src attributes:

  • for stylesheets
  • for JavaScript
  • for images
  • for media elements

How It Works

1

Build Time

Use spry-mkssr to generate .ssr files or Vala source files

2

Registration

Register resources via dependency injection

3

Request

Client requests /_spry/res/resource-name

4

Negotiation

Server selects best encoding based on Accept-Encoding

5

Response

Compressed content sent with ETag for caching

Next Steps