spry-mkssr Tool

What is spry-mkssr?

spry-mkssr is a command-line tool that generates Spry Static Resource files from any input file. It handles compression, hashing, and metadata generation so your web application can serve optimized static content efficiently.

The tool can generate two types of output:

  • SSR files (.ssr) - Pre-compiled resource files read at runtime
  • Vala source files - Embedded resources compiled into your binary

Command-Line Usage

Bash
spry-mkssr [OPTION?] INPUT_FILE

# Examples:
spry-mkssr styles.css                    # Creates styles.css.ssr
spry-mkssr -o bundle.ssr app.js          # Creates bundle.ssr
spry-mkssr --vala logo.png               # Creates LogoResource.vala
spry-mkssr --vala --ns=MyApp styles.css  # Creates StylesResource.vala in MyApp namespace

Options

Option Description
-o, --output=FILE Output file name (default: input.ssr or ClassNameResource.vala)
-c, --content-type=TYPE Override content type (e.g., text/css, application/javascript)
-n, --name=NAME Override resource name (default: input filename)
--vala Generate Vala source file instead of SSR
--ns=NAMESPACE Namespace for generated Vala class (requires --vala)
-v, --version Show version information

Generating SSR Files

By default, spry-mkssr generates .ssr files that can be read at runtime by FileStaticResource:

Bash
# Generate an SSR file from a CSS file
spry-mkssr styles.css
# Output: styles.css.ssr

# Generate with custom output name
spry-mkssr -o resources/bundle.css.ssr styles.css
# Output: resources/bundle.css.ssr

# The resource name in URLs will be "styles.css"
# URL: /_spry/res/styles.css

The generated SSR file contains:

  • Magic header - "spry-sr\0" identifier
  • Resource name - Used in URLs
  • Content type - MIME type for HTTP headers
  • SHA-512 hash - For ETag generation
  • Encoding headers - Offset and size for each encoding
  • Compressed data - gzip, zstd, brotli, and identity

Generating Vala Source Files

Use the --vala flag to generate a Vala source file that embeds the resource directly into your binary:

Bash
# Generate a Vala source file for embedding
spry-mkssr --vala styles.css
# Output: StylesResource.vala

# The generated class name is derived from the filename
# styles.css → StylesResource

This creates a class that extends ConstantStaticResource with the resource data embedded as const uint8[] arrays.

Namespace Configuration

Use --ns to place the generated class in a namespace:

Bash
# Generate with namespace
spry-mkssr --vala --ns=MyApp.Static styles.css
# Output: StylesResource.vala

# Generated class:
# namespace MyApp.Static {
#     public class StylesResource : ConstantStaticResource {
#         ...
#     }
# }

Generated Vala Class Structure

The generated Vala class follows this structure:

Vala
// Generated by spry-mkssr
public class DocsResource : ConstantStaticResource {

    // Resource metadata
    public override string name { get { return "docs.css"; } }
    public override string file_hash { get { return "a1b2c3d4..."; } }
    public override string content_type { get { return "text/css"; } }

    // Select best encoding based on client support
    public override string get_best_encoding(Set<string> supported) {
        if (supported.has("br")) return "br";
        if (supported.has("zstd")) return "zstd";
        if (supported.has("gzip")) return "gzip";
        return "identity";
    }

    // Return the data for a specific encoding
    public override unowned uint8[] get_encoding(string encoding) {
        switch (encoding) {
            case "br": return BR_DATA;
            case "zstd": return ZSTD_DATA;
            case "gzip": return GZIP_DATA;
            default: return IDENTITY_DATA;
        }
    }

    // Embedded compressed data
    private const uint8[] IDENTITY_DATA = { /* ... */ };
    private const uint8[] GZIP_DATA = { /* ... */ };
    private const uint8[] ZSTD_DATA = { /* ... */ };
    private const uint8[] BR_DATA = { /* ... */ };
}

Integrating with Meson

The recommended way to use spry-mkssr is with meson's custom_target to generate resources at build time:

Meson
# Generate a Vala resource file from CSS
docs_css_resource = custom_target('docs-css-resource',
    input: 'Static/docs.css',
    output: 'DocsCssResource.vala',
    command: [spry_mkssr, '--vala', '--ns=Demo.Static', 
              '-n', 'docs.css', '-c', 'text/css', 
              '-o', '@OUTPUT@', '@INPUT@']
)

# Then include in your executable sources:
executable('my-app',
    app_sources,
    docs_css_resource,  # Add generated file
    dependencies: [spry_dep]
)

Complete meson.build Example

Meson
# Find the spry-mkssr tool
spry_mkssr = find_program('spry-mkssr')

# Generate multiple resources
css_resource = custom_target('css-resource',
    input: 'Static/styles.css',
    output: 'StylesResource.vala',
    command: [spry_mkssr, '--vala', '--ns=MyApp.Resources',
              '-o', '@OUTPUT@', '@INPUT@']
)

js_resource = custom_target('js-resource',
    input: 'Static/app.js',
    output: 'AppResource.vala',
    command: [spry_mkssr, '--vala', '--ns=MyApp.Resources',
              '-c', 'application/javascript',
              '-o', '@OUTPUT@', '@INPUT@']
)

# Build executable with embedded resources
executable('my-app',
    'Main.vala',
    css_resource,
    js_resource,
    dependencies: [spry_dep]
)

💡 Tip: The @INPUT@ and @OUTPUT@ placeholders are automatically replaced by meson with the actual file paths.

Compression Details

spry-mkssr compresses resources with the highest compression levels:

Encoding Level Best For
gzip 9 (maximum) Universal compatibility
zstd 19 (maximum) Modern browsers, fast decompression
brotli 11 (maximum) Best compression for text assets
identity N/A No compression (always included)

Encodings are only included if they result in smaller file sizes than the original. The tool reports compression statistics during generation:

Bash
$ spry-mkssr --vala docs.css
Compressing with gzip...
  gzip: 16094 -> 3245 bytes (20.2%)
Compressing with zstd...
  zstd: 16094 -> 2987 bytes (18.6%)
Compressing with brotli...
  brotli: 16094 -> 2654 bytes (16.5%)
Generated: DocsResource.vala

Content Type Detection

spry-mkssr automatically detects content types based on file extensions using GLib's content type guessing. You can override this with the -c flag:

Bash
# Automatic detection (recommended)
spry-mkssr styles.css        # → text/css
spry-mkssr app.js            # → application/javascript
spry-mkssr logo.png          # → image/png

# Manual override
spry-mkssr -c text/plain data.json   # Force text/plain
spry-mkssr -c application/wasm module.wasm  # Custom MIME type

Resource Naming

By default, the resource name is derived from the input filename. For Vala source generation, the class name is created by converting the resource name to PascalCase and appending "Resource":

Input File Resource Name Generated Class
docs.css docs.css DocsResource.vala → DocsResource
htmx.min.js htmx.min.js HtmxMinResource.vala → HtmxMinResource
-n htmx.js htmx.min.js htmx.js HtmxResource.vala → HtmxResource

Use the -n flag to set a specific resource name:

Bash
# Default naming
spry-mkssr --vala htmx.min.js
# Resource: "htmx.min.js", Class: HtmxMinResource

# Custom resource name
spry-mkssr --vala -n htmx.js htmx.min.js
# Resource: "htmx.js", Class: HtmxResource
# URL: /_spry/res/htmx.js

# This is useful for:
# - Hiding .min suffix from URLs
# - Using versioned files with clean names
# - Renaming resources for organization

Next Steps