Key part is this wrapper:

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:

  • private resources, served through Door-scoped hook URLs
  • cached resources, served from shared resource storage with hash-based URLs

Private is the default. Add cache only when the resource should become shared and cacheable.

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
  • 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.

It is most useful when the element exists mainly to serve that resource:

<video (doors.ResourceLocalFS("./private/clip.mp4")) controls></video>

<iframe (doors.ResourceString(previewHTML)) name="preview.html"></iframe>

Use modifier syntax with actual resource values such as doors.ResourceBytes(...) or doors.ResourceLocalFS(...). Raw []byte values and handler functions are supported on src= and href= 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.

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 become a shared cached resource instead of a Door-scoped hook URL:

<img
	src=(doors.ResourceFS(assets, "assets/logo.png"))
	cache>

<a
	href=(reportPDF)
	cache
	content-type="application/pdf">
	Open report
</a>

Behavior

With cache, Doors serves the content from resource storage.

That means:

  • it is cached internally by Doors
  • it is cacheable in the browser
  • the generated path contains a hash, so the URL changes when the content changes

cache is suitable 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

Limits

Do not use cache for large files. Cached resource 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.

Cached resources are not private. Once cache is present, the URL becomes a shared resource URL rather than a Door-scoped private hook URL.

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.

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:

  • a
  • img
  • iframe
  • link
  • script
  • video
  • audio
  • source

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 cache only for stable public content
  • use name when 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.