Each instance below enhances a plain search input with on-device AI
Suggestions: plain rewordings (typo fixes, finished-out phrases,
broader related terms) mixed freely with fielded/boolean
reformulations wherever Fields are configured, never labeled or
capped by which kind of improvement a given one is. Type a
natural-language query, wait a moment for Suggestions to appear, then
accept one to see that instance's configured Action run. Requires
Chrome with the on-device LanguageModel available. Expand
the <query-shaper> line under any search box below
to see exactly how it's configured.
Fields declared as an inline JSON schema; Format lucene;
Action opensearch against a hand-built template (no
published OpenSearch document for archive.org). examples
cover a range with an open ("before"/wildcard) bound, a grouped OR
combined with negation, a typo, and a vague input deliberately given
five varied Suggestions.
<query-shaper for="ia-search" ... /><query-shaper
for="ia-search"
fields='[{"name":"mediatype"},{"name":"year","type":"number"},{"name":"creator"},{"name":"subject"},{"name":"language"}]'
examples='[
{"input":"climate change documentaries from 2020","suggestions":["mediatype:movies AND subject:\"climate change\" AND year:2020"]},
{"input":"documentaries from before 2015","suggestions":["mediatype:movies AND year:[* TO 2015]"]},
{"input":"audio recordings or texts about jazz, not from 2020","suggestions":["(mediatype:audio OR mediatype:texts) AND subject:jazz AND -year:2020"]},
{"input":"documentries about space","suggestions":["mediatype:movies AND subject:space","documentaries about space"]},
{"input":"vintage sci-fi films","suggestions":["mediatype:movies AND subject:\"science fiction\"","vintage science fiction movies","classic sci-fi films","mediatype:movies AND subject:vintage","old science fiction movies"]}
]'
format="lucene"
action="opensearch"
template="https://archive.org/search?query={searchTerms}"
></query-shaper>
Format lucene; Action opensearch, with the
template sourced directly from Open Library's real
OpenSearch description document.
examples cover a bounded range, a wildcard open range, a
combined field + negation, a grouped OR, a typo, and a vague input
given five varied Suggestions. notes directly targets a
real bug seen live: the model once assigned "Harry Potter" to
author instead of title.
<query-shaper for="ol-search" ... /><query-shaper
for="ol-search"
fields='[{"name":"author"},{"name":"title"},{"name":"language","description":"ISO 639 code"},{"name":"first_publish_year","type":"number"}]'
examples='[
{"input":"harry potter books published before 2000","suggestions":["title:\"harry potter\" AND first_publish_year:[1000 TO 2000]"]},
{"input":"books by cory doctorow in english","suggestions":["author:\"cory doctorow\" AND language:en"]},
{"input":"books published up to 2005","suggestions":["first_publish_year:[* TO 2005]"]},
{"input":"books by asimov but not in french","suggestions":["author:\"isaac asimov\" AND -language:fr"]},
{"input":"tolkien books in english or spanish","suggestions":["author:\"j.r.r. tolkien\" AND (language:en OR language:es)"]},
{"input":"harry poter books","suggestions":["title:\"harry potter\"","harry potter books"]},
{"input":"classic fantasy novels","suggestions":["title:fantasy","fantasy novels","classic fantasy books","title:\"lord of the rings\"","fantasy literature classics"]}
]'
notes="A book or series title (e.g. "Harry Potter", "Lord of the Rings") always belongs in the title field, never author: only a real person's name belongs in author."
format="lucene"
action="opensearch"
template="https://openlibrary.org/search?q={searchTerms}&mode=everything"
></query-shaper>
gov collection search
The gov collection itself is fixed configuration baked
into the template, never a Field the model varies.
Format lucene; the {searchTerms} placeholder
sits in a path segment, not a query string. examples
cover a bare term mixed with fielded conditions (since "climate
policy" isn't itself a declared Field), negation, a wildcard open
range in each direction, a typo, and a vague input given five varied
Suggestions.
<query-shaper for="wb-search" ... /><query-shaper
for="wb-search"
fields='[{"name":"language"},{"name":"site"},{"name":"year","type":"number"},{"name":"pubdate","type":"date"}]'
examples='[
{"input":"government sites about climate policy after 2015","suggestions":["site:gov AND year:[2015 TO *] climate policy"]},
{"input":"English language government sites","suggestions":["language:en AND site:gov"]},
{"input":"sites excluding .com domains from 2020","suggestions":["-site:com AND year:2020"]},
{"input":"old government pages up to 2010","suggestions":["site:gov AND year:[* TO 2010]"]},
{"input":"goverment sites","suggestions":["site:gov","government sites"]},
{"input":"climate change resources","suggestions":["climate change","site:gov climate change","climate policy resources","environmental policy sites","site:org climate change"]}
]'
format="lucene"
action="opensearch"
template="https://web.archive.org/collection-search/gov/{searchTerms}"
></query-shaper>
No fields attribute at all: the model is never told
about any backend fields, so Suggestions stay plain rewordings
(typo fixes, finished-out phrases, broader related terms) and never
attempt a fielded reformulation, since there's nothing declared to
reformulate against.
<query-shaper for="generic-none" /><query-shaper for="generic-none"></query-shaper>
A loosely specified, human-written Fields description still produces
sensible Expression Suggestions, helped along here by
examples, since a harder-to-parse prose Fields
declaration measurably needed more encouragement to attempt a
fielded Suggestion at all, covering a range, negation, and grouping.
<query-shaper for="generic-freeform" ... /><query-shaper
for="generic-freeform"
fields="title, author, language:iso-639-1, date (allowed patterns YYYY[-MM[-DD]]), categories (comma-separated list)"
examples='[
{"input":"French novels from the 1920s","suggestions":["language:fr AND date:[1920 TO 1929]","french novels 1920s"]},
{"input":"books by Verne in French","suggestions":["author:\"jules verne\" AND language:fr"]},
{"input":"novels not in english, from before 1950","suggestions":["-language:en AND date:[* TO 1950]"]},
{"input":"adventure or mystery novels in french","suggestions":["(categories:adventure OR categories:mystery) AND language:fr"]},
{"input":"vernes novels","suggestions":["author:\"jules verne\"","verne's novels"]}
]'
></query-shaper>
The more precise, structured declaration path. examples
cover a range, the boolean field, negation, a grouped OR, a typo,
and a vague input deliberately given five varied Suggestions mixing
fielded and plain-rewording styles.
<query-shaper for="generic-json" ... /><query-shaper
for="generic-json"
fields='[{"name":"category"},{"name":"price","type":"number"},{"name":"in_stock","type":"boolean"}]'
examples='[
{"input":"electronics under $50","suggestions":["category:electronics AND price:[0 TO 50]","cheap electronics"]},
{"input":"laptops in stock","suggestions":["category:laptop AND in_stock:true"]},
{"input":"cheap electronics, not laptops","suggestions":["category:electronics AND -category:laptop AND price:[0 TO 50]"]},
{"input":"electronics or gadgets under $50","suggestions":["(category:electronics OR category:gadgets) AND price:[0 TO 50]"]},
{"input":"electroncis under $50","suggestions":["category:electronics AND price:[0 TO 50]","electronics under $50"]},
{"input":"cheap stuff","suggestions":["price:[0 TO 20]","category:electronics AND price:[0 TO 20]","affordable items","budget electronics","discounted electronics"]}
]'
></query-shaper>
.format render function
The escape hatch for backends neither built-in preset covers. A
render function can't be expressed as an attribute, so it's set
imperatively on the .format property once the element
is defined. This one renders field=value pairs joined
by ; instead of lucene or
url-params syntax.
<query-shaper for="generic-custom" ... /><query-shaper
id="generic-custom-shaper"
for="generic-custom"
fields='[{"name":"category"},{"name":"price","type":"number"}]'
></query-shaper>
<script type="module">
customElements.whenDefined('query-shaper').then(() => {
document.querySelector('#generic-custom-shaper').format = (fields) =>
fields.map((f) => `${f.field ?? 'q'}=${f.value}`).join(';')
})
</script>
output Action
Fills the Target as usual, and also writes the accepted Suggestion's
raw text to a built-in <output> element rendered
below the popup (no destination selector given, so it
uses that default). Useful for showing or logging exactly what was
applied, since fill alone leaves no other trace of it.
<query-shaper for="generic-output" action="output" ... /><query-shaper
for="generic-output"
fields='[{"name":"title"},{"name":"location"},{"name":"remote","type":"boolean"}]'
examples='[
{"input":"remote frontend jobs","suggestions":["title:frontend AND remote:true"]},
{"input":"jobs in berlin, not remote","suggestions":["location:berlin AND remote:false"]},
{"input":"backend or devops roles, remote only","suggestions":["(title:backend OR title:devops) AND remote:true"]}
]'
action="output"
></query-shaper>