Resources
This page covers generic resource usage in Doors for src and href.
Use it for:
- files on disk
- embedded or virtual filesystem content
- generated bytes or strings
- handler-backed links
- proxied URLs
Generic resources usually fall into two groups:
- default resources, served through private, user-scoped URLs
- cached resources, served from shared resource storage with hash-based URLs
For JavaScript resources, see JavaScript. For stylesheet resources, see Styles.
Start
If you already have a normal URL, use a normal attribute:
<img src="/assets/logo.png">
<img src="https://cdn.example.com/logo.png">
<a href="https://example.com/report.pdf">Open report</a>
Use a resource when the content belongs to your app and Doors should turn it into a browser URL:
<img src=(doors.ResourceLocalFS("./private/logo.png"))>
<a href=(doors.ResourceBytes(reportPDF)) name="report.pdf">
Download report
</a>
In practice:
- plain URL: write the URL directly
- app-owned content: use a resource
- managed resources are private by default
Syntax
You can attach a resource either as a direct attribute value or with modifier syntax.
Direct attribute value:
<img src=(doors.ResourceLocalFS("./private/chart.png"))>
<a href=(doors.ResourceBytes(reportPDF)) name="report.pdf">
Download
</a>
Modifier syntax:
<img (doors.ResourceLocalFS("./private/chart.png"))>
<a
(doors.ResourceBytes(reportPDF))
name="report.pdf">
Download
</a>
Modifier syntax assigns the value to src or href from the tag name.
Use modifier syntax with actual resource values such as
doors.ResourceBytes(...)ordoors.ResourceLocalFS(...). Raw[]bytevalues and handler functions are supported onsrc=andhref=values, but not as standalone modifiers.
Sources
File on disk
<img src=(doors.ResourceLocalFS("./private/chart.png"))>
Embedded or virtual filesystem
//go:embed assets
var assets embed.FS
<img src=(doors.ResourceFS(assets, "assets/chart.png"))>
Bytes already in memory
<a href=(doors.ResourceBytes(reportPDF)) name="report.pdf">
Download report
</a>
String content already in memory
<iframe src=(doors.ResourceString(htmlSnippet)) name="preview.html"></iframe>
Simple custom response
<img src=(doors.ResourceHandler(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
w.Write(chartSVG)
})) name="chart.svg">
Full hook with Door context
<a href=(doors.ResourceHook(func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool {
w.Header().Set("Content-Type", "application/pdf")
w.Write(reportPDF)
return false
})) name="report.pdf">
Download
</a>
If a hook returns true, the resource is served only once. That is useful for one-time downloads and other short-lived links.
The
ctxargument is the Doors runtime context for framework APIs. The*http.Requeststill has its normalr.Context()request context.
Proxy
<iframe src=(doors.ResourceProxy("https://example.com/embed"))></iframe>
Plain URLs
For generic src and href, already-hosted URLs should be written as plain strings:
<img src="https://cdn.example.com/logo.png">
<a href="/downloads/report.pdf">Open report</a>
Shorthands
For plain src= and href= usage, resources support a few shorthand forms.
[]byte
[]byte is treated like doors.ResourceBytes(...):
<img src=(pngBytes)>
<a href=(pdfBytes) name="report.pdf">
Download
</a>
Simple handler
A plain handler is treated like doors.ResourceHandler(...):
<img src=(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
w.Write(chartSVG)
}) name="chart.svg">
Full hook
A full hook-style handler is treated like doors.ResourceHook(...):
<a href=(func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool {
w.Header().Set("Content-Type", "application/pdf")
w.Write(reportPDF)
return true
}) name="report.pdf">
Download once
</a>
Cache
Add cache when the resource should be cacheable on the client side instead of being downloaded again on each render:
<img
src=(doors.ResourceFS(assets, "assets/logo.png"))
cache>
<a
href=(reportPDF)
cache
type="application/pdf">
Open report
</a>
What cache changes:
- the browser gets a hash-based URL it can reuse
- the resource becomes publicly reachable by that URL
- Doors keeps the cached entry in RAM
Use it for stable public content such as:
- embedded files
- local files that should behave like public assets
- generated bytes or strings that are not user-specific
Do not use it for large files. Cached entries are stored in RAM.
cache only works with static resource sources:
doors.ResourceFS(...)doors.ResourceLocalFS(...)doors.ResourceBytes(...)doors.ResourceString(...)- raw
[]byte
Handler, hook, proxy, and plain string sources cannot use cache.
Without cache, managed resources stay private to the current Door instance and can get a different URL on another render.
Even when name is set, a cached resource URL still contains a unique identifier. That makes cache a better fit for views and reusable assets than for user-facing download links where you want the cleanest possible filename.
Content Type
Use type when a managed generic resource should set the response content type:
<img
src=(doors.ResourceFS(assets, "assets/chart.svg"))
type="image/svg+xml">
That applies to managed generic src and href resources. It does not apply to handler-backed resources.
Notes
Use name when the generated URL should carry a readable file name:
<a
href=(doors.ResourceBytes(reportPDF))
name="report.pdf">
Download report
</a>
This is useful for browser filename hints, inspection, and extension-based content handling.
Resources can be attached to the usual src and href elements. In practice, the most common ones are:
aimgiframelinkscriptvideoaudiosource
For generic non-script, non-stylesheet usage:
- use a plain URL when the URL already exists
- use a resource when your Go code owns the content
- prefer modifier syntax when the resource is the main point of the element
- use
cacheonly for stable public content - use
namewhen the generated URL should look like a real file
<script>, <style>, and <link rel="stylesheet"> have richer resource behavior than the generic flow described here.