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(...) 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.

The ctx argument is the Doors runtime context for framework APIs. The *http.Request still has its normal r.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:

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