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
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:
# 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:
# 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:
# 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:
// 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:
# 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
# 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:
$ 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:
# 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:
# 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