o:type

The o:type global attribute sets the content type of an exported file or worker asset. Without it, the type comes from the extension of the file name.

Syntax

html
<script type=application/json o:=app.webmanifest o:type=application/manifest+json>{"name":"Demo"}</script>
<script type=text/plain o:=notes.txt o:type="text/plain;charset=utf-8">Café notes</script>
<script type=text/markdown worker:fs=notes.md o:type=text/markdown>…</script>

Value

type/subtype

A MIME type, optionally with parameters such as ;charset=utf-8. Quote a value that contains =, as ;charset=utf-8 does. The value is used as written and is not validated: o:type="" produces an empty content type on RTEdge.net and ;charset=utf-8 in the playground.

Default

Without the attribute, the type comes from the extension table, then from the MIME type of a data: URL, then from the binary or text default.

Description

The extension is the text after the last . of the file name, lowercased, so x.JS is text/javascript. Both environments use the same extension table; RTEdge.net adds one entry, wasm.

Exported files

PlaygroundRTEdge.net
Ordero:type, the extension table, the MIME type of a data: URL (binary images only), application/octet-stream (binary), text/plain.h:content-type (used as written; nothing else is added), then o:type, the extension table, the data: MIME type, application/octet-stream (binary), text/plain;charset=utf-8.
Charset;charset=utf-8 is appended unless the value already contains charset=. This also applies to binary types: image/png;charset=utf-8.Nothing is appended to o:type or to table values.
h:content-typeHas no effect.Wins over o:type.

Worker assets

For a worker:fs asset, env.FS[key].type is o:type, else the type for the extension of the key (the whole key when it has no dot, so worker:fs=json gets application/json), else the MIME type of a data: URL, else application/octet-stream for binary data. It is undefined for a text key with an unknown extension. No charset is added.

Usage notes

Charset

For non-ASCII text that visitors open directly, such as .txt, .md and .csv files, give the charset yourself: o:type="text/plain;charset=utf-8". Quote the value, because an unquoted value that contains = is an HTML parse error, even though browsers accept it. A page exported from a <template> should start with <meta charset=utf-8>, since RTEdge.net serves table types without a charset.

Types missing from the table

The table has no entry for webmanifest, map, yaml, yml, toml, vtt, jsx, tsx or glb, and none for wasm in the playground. Those names fall back to the default text type, so set o:type on them. ts maps to video/mp2t, so a TypeScript file needs o:type as well.

Elements that share a name

When elements share a file name, the file keeps the type of the first element. The o:type of the later ones is silently ignored.

o:type and h:content-type

The playground ignores h:content-type, and RTEdge.net lets it win. Set o:type when you want the same result in both. For worker:fs assets, set o:type rather than h:content-type.

A wrong type blocks scripts and styles

Responses on RTEdge.net carry x-content-type-options: nosniff. A script or stylesheet served with the wrong type therefore does not run or apply, so check the type of every export you load that way.

On deploy

Deploy strips o:type from the served HTML and from export bodies. The deployed source keeps it.

Pre-compressed WebAssembly

Experimental On RTEdge.net, a platform rule gives a path that ends in .wasm.br the headers Content-Encoding: br and Content-Type: application/wasm. It is meant for pre-compressed exports such as <img hidden o:=app.wasm.br src="data:;base64,…">. The playground has no such rule and serves application/octet-stream;charset=utf-8. The encoding a browser finally receives can differ from the header, so test a real export before you rely on it.

Note: The .wasm.br rule may change.

Extension table

Both environments map these extensions, case-insensitively, to these types. Table types are served without a charset on RTEdge.net, and with ;charset=utf-8 appended in the playground.

GroupExtensions and types
Textcss → text/css
csv → text/csv
htm, html → text/html
ics → text/calendar
js, mjs → text/javascript
md → text/markdown
txt → text/plain
Datajson → application/json
jsonld → application/ld+json
xml → application/xml
xhtml → application/xhtml+xml
xul → application/vnd.mozilla.xul+xml
Fontseot → application/vnd.ms-fontobject
otf → font/otf
ttf → font/ttf
woff → font/woff
woff2 → font/woff2
Imagesapng → image/apng
avif → image/avif
bmp → image/bmp
gif → image/gif
ico → image/vnd.microsoft.icon
jpeg, jpg → image/jpeg
png → image/png
svg → image/svg+xml
tif, tiff → image/tiff
webp → image/webp
Audio and video3g2 → video/3gpp2
3gp → video/3gpp
aac → audio/aac
avi → video/x-msvideo
mid, midi → audio/midi
mp3 → audio/mpeg
mp4 → video/mp4
mpeg → video/mpeg
oga → audio/ogg
ogv → video/ogg
ogx → application/ogg
opus → audio/ogg
ts → video/mp2t
wav → audio/wav
weba → audio/webm
webm → video/webm
Documentsabw → application/x-abiword
azw → application/vnd.amazon.ebook
doc → application/msword
docx → application/vnd.openxmlformats-officedocument.wordprocessingml.document
epub → application/epub+zip
odp → application/vnd.oasis.opendocument.presentation
ods → application/vnd.oasis.opendocument.spreadsheet
odt → application/vnd.oasis.opendocument.text
pdf → application/pdf
ppt → application/vnd.ms-powerpoint
pptx → application/vnd.openxmlformats-officedocument.presentationml.presentation
rtf → application/rtf
vsd → application/vnd.visio
xls → application/vnd.ms-excel
xlsx → application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Archives and binaries7z → application/x-7z-compressed
arc → application/x-freearc
bin → application/octet-stream
bz → application/x-bzip
bz2 → application/x-bzip2
cda → application/x-cdf
gz → application/gzip
jar → application/java-archive
mpkg → application/vnd.apple.installer+xml
rar → application/vnd.rar
tar → application/x-tar
zip → application/zip
Scriptscsh → application/x-csh
php → application/x-httpd-php
sh → application/x-sh
RTEdge.net onlywasm → application/wasm

RTEdge.net refuses requests for some names whatever their type; see Reserved paths.

Examples

Text with a charset

html
<script type=text/plain o:=notes.txt o:type="text/plain;charset=utf-8">Café, naïve, 日本語</script>
<iframe src=notes.txt></iframe>

A web app manifest

html
<script type=application/json o:=app.webmanifest o:type=application/manifest+json>{"name":"Demo"}</script>
<output id=kind></output>
<script type=module>
  kind.value = (await fetch('app.webmanifest')).headers.get('content-type')
</script>

The extension webmanifest has no table entry, so o:type sets the type. The output shows application/manifest+json;charset=utf-8; on RTEdge.net the header is application/manifest+json.

Specifications

Not part of any specification. o:type is an RTCode.io and RTEdge.net feature.

It builds on these standards:

Specification
IANA Media Types registry
RFC 9110: HTTP Semantics

Availability

FeaturePlaygroundRTEdge.netNotes
o:type on exports and worker assetsYesYesUsed as written, without validation.
h:content-type overrides the typeNoYesIgnored in the playground.
;charset=utf-8 appendedYesNoThe playground appends it to every type, binary types included.
wasm in the extension tableNoYesSet o:type=application/wasm in the playground.
.wasm.br header rule ExperimentalNoYesPlayground serves an octet stream.
Agent File Sync (Agent Folder Share)YesNoIn an export that holds the whole element, an agent's change to o:type is restored. Edit it in 📄.html. Chrome or Edge on desktop.

See also