- Stable
3.1.6- Canary
4.0.0-alpha.10
- Guide
Guide
- Get Started
- Command Line Usage
- Add a Configuration File
- Copy Files to Output
- Add CSS, JS, Fonts
- Importing Content
- Configure Templates with Data
- Using Data in Templates
- Template Languages
- Template Features
- Environment Variables
- Internationalization (i18n)
- Watch Files and Dev Servers
- Common Pitfalls
- Advanced
- Plugins
- Services
WebC

On this page
| Type | Value |
|---|---|
| Eleventy Name | webc |
| File Extension | *.webc |
| npm | @11ty/webc and @11ty/eleventy-plugin-webc |
| GitHub | 11ty/webc and 11ty/eleventy-plugin-webc |
Why use WebC?
- Brings first-class components to Eleventy.
- Expand any HTML element (including custom elements) to HTML with defined conventions from web standards.
- This means that Web Components created with WebC are compatible with server-side rendering (without duplicating author-written markup)
- WebC components are Progressive Enhancement friendly.
Performance
- Create streamlined component-driven, cache-friendly page-specific JavaScript and CSS bundles. Users load only the code they need to render that page (or that island).
- Easily configurable boundaries for critical component CSS and JavaScript.
- Works great with is-land for web component hydration.
- Get first-class incremental builds (for page templates, components, and Eleventy layouts) when used with
--incremental - Streaming friendly (stream on the Edge 👀)
Compatible with Standards
- Uses
parse5to parse WebC HTML as modern browsers do (a nod to @DasSurma’s work with Vite here) - Shadow DOM and Declarative Shadow DOM friendly (easily switch components between Light DOM and Shadow DOM)
Authoring
- Encourages no-quirks mode HTML authoring (and a doctype is optional). WebC throws a helpful error if it encounters quirks mode markup.
- Easily scope component CSS (or use your own scoping utility).
- Tired of importing components? Use global or per-page no-import components.
- Async-friendly: All configuration extensions/hooks into WebC are async-friendly out of the box.
- For more complex templating needs, render any existing Eleventy template syntax (Liquid, markdown, Nunjucks, etc.) inside of WebC.
Resources
Introduction to WebC (11ty.rocks) by
W. Evan Sheehan
Understanding WebC Features and Concepts (11ty.rocks) by
Stephanie Eckles
- WebC Number Counter Example Source Code and Demo
- Seven Demos of Progressive Enhancement using Image Comparison Components and Source Code
- First Experience Building with Eleventy's WebC Plugin
zachleat.com: Adding Components to Eleventy with WebC: a brief history of the motivation behind WebC including influences from the Svelte and Vue communities.
11ty.webc.fun: a collection of WebC recipes!
Robin Cussol: Optimize your img tags with Eleventy Image and WebC
Installation
It’s on npm at @11ty/eleventy-plugin-webc!
npm install @11ty/eleventy-plugin-webc
To add support for .webc files in Eleventy, add the plugin in your Eleventy configuration file:
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function(eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc);
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc);
};
Full options list (defaults shown)
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// Glob to find no-import global components
// (The default changed from `false` in Eleventy WebC v0.7.0)
components: "_components/**/*.webc",
// Adds an Eleventy WebC transform to process all HTML output
useTransform: false,
// Additional global data used in the Eleventy WebC transform
transformData: {},
// Options passed to @11ty/eleventy-plugin-bundle
bundlePluginOptions: {},
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// Glob to find no-import global components
// (The default changed from `false` in Eleventy WebC v0.7.0)
components: "_components/**/*.webc",
// Adds an Eleventy WebC transform to process all HTML output
useTransform: false,
// Additional global data used in the Eleventy WebC transform
transformData: {},
// Options passed to @11ty/eleventy-plugin-bundle
bundlePluginOptions: {},
});
};
View the full options list for the Bundle plugin. As an example, you can use the transforms array to modify bundle content with postcss.
Syntax highlighting
Because WebC is HTML, you can configure your editor to treat .webc files as HTML for syntax highlighting. Your editor of choice should have some documentation on how to get this working.
Usage
There are a few different ways to use WebC in Eleventy:
Add a new .webc file
Adding the plugin enables support for .webc files in your Eleventy project. Create a new .webc HTML file in your Eleventy input directory and Eleventy processes it for you. .webc files operate in WebC bundler mode, aggregating the CSS and JS in use on each individual page into a bundle of the assets in use on the page.
WebC uses an HTML parser to process input files: use any HTML here!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
</head>
<body>
WebC *is* HTML.
</body>
</html>
Non-traditional WebC usage
Use the Render plugin
Using Eleventy’s built-in Render plugin allows you to render WebC inside of an existing Liquid, Nunjucks, or 11ty.js template.
{% renderTemplate "webc" %}
<my-custom-component></my-custom-component>
{% endrenderTemplate %}
{% renderTemplate "webc" %}
<my-custom-component></my-custom-component>
{% endrenderTemplate %}
export default async function () {
let content = await this.renderTemplate(
`<my-custom-component></my-custom-component>`,
"webc"
);
return content;
};
module.exports = async function () {
let content = await this.renderTemplate(
`<my-custom-component></my-custom-component>`,
"webc"
);
return content;
};
Pre-process HTML input as WebC
You can use the configuration option to change the default HTML preprocessor (from liquid) to webc. This might look like htmlTemplateEngine: "webc". Read more on the Eleventy documentation: Default Template Engine for HTML Files.
Post-process HTML output as WebC
This is a catch-all option that lets WebC process .html output files in your project (skipping any .webc input files to avoid double-processing templates). It uses Eleventy transforms and is most useful when you want to get up and running with WebC on an existing project quickly.
A few drawbacks to the transform method:
- This is the slowest build-performance method to implement WebC in a project, so try the other methods first!
- The WebC Eleventy transform operates with bundler mode disabled, which means it processes WebC but does not aggregate component JS or CSS. (Upvote this enhancement request)
The transform is disabled by default, you will need to use the useTransform option to enable it.
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
useTransform: true,
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
useTransform: true,
});
};
Components and output
HTML-only components
- Related: Defining Components in WebC
When WebC does not find <style>, <link rel="stylesheet">, or <script> elements a component file, WebC leaves the host component tag out of the output HTML by default. To keep the component tags in the output, add webc:keep to the host component.
my-component) here. You can use p, blockquote, h1, img, or any valid HTML tag name.Hello possum.
<!DOCTYPE html>
<title>WebC Example</title>
<my-component></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
</head>
<body>
Hello possum.
</body>
</html>
Hello possum.
<!DOCTYPE html>
<title>WebC Example</title>
<my-component webc:keep></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
</head>
<body>
<my-component>Hello possum.</my-component>
</body>
</html>
Asset bundling
When WebC finds <style>, <link rel="stylesheet">, or <script> elements in a component file, WebC includes the host component tag in the output HTML by default, so you can style it or reach it from client scripts. To drop the component tag from the output, add webc:nokeep to the host component.
This example also shows how Eleventy automatically bundles scripts and styles, learn more about CSS and JS in WebC.
<p class="possum">Hello possum.</p>
<style>
.possum { color: rebeccapurple }
</style>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<my-component></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>.possum { color: rebeccapurple }</style>
</head>
<body>
<my-component><p class="possum">Hello possum.</p></my-component>
</body>
</html>
<p class="possum">Hello possum.</p>
<style>
.possum { color: rebeccapurple }
</style>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<my-component webc:nokeep></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>.possum { color: rebeccapurple }</style>
</head>
<body>
<p class="possum">Hello possum.</p>
</body>
</html>
webc:keep
Keeps the host tag of an HTML-only component in the output.
<my-html-only-component webc:keep></my-html-only-component>
Keeps a <style>, <link rel="stylesheet">, or <script> element as written in the output instead of adding it to the bundle.
<!-- without webc:keep, WebC removes these from the output
and adds their content to the page’s CSS and JS bundles -->
<style webc:keep>
.possum { color: rebeccapurple }
</style>
<script webc:keep>
console.log("Hello possum.");
</script>
Keeps a <slot> element in the output for a client-side custom element to fill. Read more at Slots.
webc:nokeep
Drops the host tag of a component with CSS or JavaScript from the output.
<my-stylish-component webc:nokeep></my-stylish-component>
Inserts content into the output as-is, without adding an element around it.
<template @raw="content" webc:nokeep></template>
webc:is
Replaces the element’s tag name with a component name. Both examples are equivalent to <my-component></my-component>.
<div webc:is="my-component"></div>
<div
webc:is="my-component"
webc:import="./some-other-directory/my-component.webc"
></div>
webc:import
Imports the component definition for the element from a path relative to the current file, or from an npm package with the npm: prefix.
Note: WebC expands any component it already knows about without an import, such as every file matching the default _components/**/*.webc glob.
- Related: Defining Components in WebC (global or scoped)
<my-component
webc:import="./some-other-directory/my-component.webc"
></my-component>
<syntax-highlight
language="js"
webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight"
>
function myFunction() { return true; }
</syntax-highlight>
Added in @11ty/webc@0.6.2With the npm: prefix, WebC uses the tag name (syntax-highlight) to look for a component at node_modules/@11ty/eleventy-plugin-syntaxhighlight/syntax-highlight.webc. This also works with a tag name override via webc:is. Eleventy plugins can supply WebC components this way. See the Syntax Highlighter plugin (4.2.0 or newer) for an example.
Attributes, props and slots
Which one to use
Attributes and props pass values into a component and are available inside it as variables by name (camelCased). Slots pass child markup. They differ in how the value is evaluated and whether it reaches the output HTML.
| Syntax | Value | In output | Use when |
|---|---|---|---|
| Attribute | String | Yes* | The value belongs on an element in the output, such as id, class, or data-*. |
| Prop | String | No | The component needs the value but it should not appear in the HTML. |
| Dynamic attribute | Any JavaScript value | Yes* | The attribute value comes from page data or an expression. |
| Dynamic prop | Any JavaScript value | No | Pass page data or a non-string value (number, object, array) into the component. |
| Slot | HTML | Yes** | The page supplies markup, not just a value, or the component wraps arbitrary content. |
* Rendered when the host tag is kept in the output, or when the component places them with webc:root or @attributes.
** Rendered where the component places its <slot>.
Attributes and webc:root
Attributes on a host component are available inside the component definition. webc:root merges the element’s attributes onto the host component tag, and keeps that tag in the output even for an HTML-only component. WebC merges the class and style attribute values from both.
<template webc:root class="possum">Hello possum.</template>
<my-component class="item"></my-component>
<my-component class="item possum">Hello possum.</my-component>
Note: The webc:root element must be at the top level of the component definition. Nested inside another element, it has no effect.
Override the host component tag
webc:root="override" replaces the host component tag with the element itself, with the attributes merged.
<button webc:root="override" class="possum">Hello possum.</button>
<my-component class="item"></my-component>
<button class="possum item">Hello possum.</button>
- Added in @11ty/webc@0.9.0Previously, this required
webc:rootandwebc:keeptogether on an element.
Props (Properties)
Any attribute prefixed with @ becomes a prop: a server-only attribute that the component reads by name and that WebC removes from the output HTML.
<div class="story-card">
<h1 @text="title"></h1>
<p @text="publication"></p>
</div>
<story-card
@title="Top 10 Fashionable Possums"
@publication="Possum Times"
></story-card>
<div class="story-card">
<h1>Top 10 Fashionable Possums</h1>
<p>Possum Times</p>
</div>
In the HTML specification, attribute names are lower-case. Added in @11ty/webc@0.8.0WebC converts attribute and prop names with dashes (i.e. @author-name) to camelCase for JavaScript (i.e. authorName), so <story-card @author-name="Susan Possum"></story-card> is accessed within the component as <p @text="authorName"></p>. More at issue #71.
Dynamic attributes and properties
A colon (:) prefix makes the value of an attribute or prop a JavaScript expression instead of a string. The expression has access to host component attributes, props, and page data.
This example extends the props example: the title prop and the href attribute now read from page data.
<div class="story-card">
<h1 @text="title"></h1>
<p @text="publication"></p>
<a :href="href">Read more</a>
</div>
---
title: Top 10 Fashionable Possums
---
<story-card
:@title="title"
@publication="Possum Times"
:href="page.url"
></story-card>
<div class="story-card">
<h1>Top 10 Fashionable Possums</h1>
<p>Possum Times</p>
<a href="/top-ten.html">Read more</a>
</div>
- Added in @11ty/webc@0.9.0The
:@prefix for dynamic props. - WebC converts names with dashes to camelCase, as with props.
webc:bucketis currently the onlywebc:*attribute that accepts a dynamic value. Follow #143 and #148 for more.
@attributes
Added in @11ty/webc@0.9.0Renders the host component’s attributes on the element. Props are not included, so @attributes is a way to pass through attributes like id or data-* without listing each one.
<div class="story-card" @attributes>
<h1 @text="title"></h1>
<p @text="publication"></p>
</div>
<story-card
@title="Top 10 Fashionable Possums"
@publication="Possum Times"
id="top-story"
data-story-id="42"
></story-card>
<div class="story-card" id="top-story" data-story-id="42">
<h1>Top 10 Fashionable Possums</h1>
<p>Possum Times</p>
</div>
A host attribute with the same name as one on the element replaces it: class="featured" on <story-card> would replace class="story-card" in the output. To merge class and style values instead, use webc:root on the element in the component file in place of @attributes (e.g. <div class="story-card" webc:root>).
Given a value, @attributes renders each entry of a JavaScript object as an attribute instead.
<div @attributes="({ class: 'story-card', id: `story-${storyId}` })"></div>
<story-card @story-id="42"></story-card>
<div class="story-card" id="story-42"></div>
Wrap the object in parentheses so JavaScript does not parse it as a block with a label. Without a value, @attributes is shorthand for @attributes="webc.attributes".
Slots
WebC places the child content of a component using <slot> and [slot], following web component conventions. This example uses an HTML-only component.
<p><slot>This text is the default fallback.</slot></p>
<!-- example with content -->
<my-component>This text will replace slot.</my-component>
<!-- example with fallback -->
<my-component></my-component>
<!-- example with content -->
<p>This text will replace slot.</p>
<!-- example with fallback -->
<p>This text is the default fallback.</p>
To output a <slot> element in the compiled markup (for use in client JavaScript), add the webc:keep attribute to it (e.g. <slot webc:keep>).
<style> or <script> elements), WebC implies <slot></slot> and includes the default slot content automatically, per web component conventions. If the component file does contain content markup, include <slot> to place the default slot content.Named slots
Named slots (e.g. <h1 slot="title">) work too. Each [slot] element is placed at the <slot> with the matching name. This example passes the same content as the props example through slots instead.
<div class="story-card">
<slot name="title"></slot>
<slot name="publication"></slot>
</div>
<story-card>
<h1 slot="title">Top 10 Fashionable Possums</h1>
<p slot="publication">Possum Times</p>
</story-card>
<div class="story-card">
<h1>Top 10 Fashionable Possums</h1>
<p>Possum Times</p>
</div>
Rendering content
@html
Replaces the element’s content with the result of a JavaScript expression, processed as WebC. To skip that processing, use @raw. Like other props, WebC removes the prop key from the output. Add webc:nokeep to output the result without the element.
---
summary: "A <em>very</em> fashionable possum."
---
<p @html="summary"></p>
<template @html="summary" webc:nokeep></template>
<p>A <em>very</em> fashionable possum.</p>
A <em>very</em> fashionable possum.
- Added in @11ty/webc@0.5.0WebC processes the returned content as WebC, so you can return any WebC content here.
@raw
Added in @11ty/webc@0.7.1Replaces the element’s content with the result of a JavaScript expression without reprocessing it as WebC. This is a shorthand for webc:raw @html. A common use is placing the page content in an Eleventy layout.
- Added in @11ty/webc@0.6.0Before
@raw, addwebc:rawto an@htmlelement to prevent processing the result as WebC.webc:raw @htmlstill works.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebC Example</title>
</head>
<body>
<template @raw="content" webc:nokeep></template>
</body>
</html>
---
layout: layout.webc
---
<p>Hello possum.</p>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebC Example</title>
</head>
<body>
<p>Hello possum.</p>
</body>
</html>
In a layout, content is the page’s finished output. Whether to place it with @raw or @html depends on the template language of the pages that use the layout:
.webcpages are already processed by WebC, so use@raw="content"to place the output as-is.- Pages in another template language, such as Markdown or Nunjucks, are not processed by WebC on their own, so any WebC components or props in their output reach the layout unrendered. Use
@html="content"to give them their single WebC pass. - A mix of both can share one layout by branching on the page’s input path:
<template webc:if="page.inputPath.endsWith('.webc')" @raw="content" webc:nokeep></template>
<template webc:else @html="content" webc:nokeep></template>
@text
Added in @11ty/webc@0.6.0Replaces the element’s content with the HTML-escaped result of a JavaScript expression. Add webc:nokeep to output the text without the element.
---
title: Top 10 Fashionable Possums
summary: A <em>very</em> fashionable possum collection.
possum: Susan
---
<h1 @text="title"></h1>
<!-- given the content, summary should use @html,
but let's use @text and check the result -->
<p @text="summary"></p>
<template @text="possum" webc:nokeep></template>
<h1>Top 10 Fashionable Possums</h1>
<!-- given the content, summary should use @html,
but let's use @text and check the result -->
<p>A <em>very</em> fashionable possum collection.</p>
Susan
webc:if
Added in @11ty/webc@0.7.1Renders the element only when the JavaScript expression in its value is truthy at build time. Like dynamic attributes, the expression has access to component attributes, props, and page data. If the expression returns a promise, WebC awaits it before the check.
---
title: Top 10 Fashionable Possums
draft: true
---
<h1 webc:if="title" @text="title"></h1>
<p webc:if="draft">This story is a draft.</p>
<p webc:if="!draft">This story is published.</p>
<h1>Top 10 Fashionable Possums</h1>
<p>This story is a draft.</p>
For more complex conditional logic, use a webc:type="js" render function.
webc:elseif and webc:else
Added in @11ty/webc@0.10.0webc:elseif renders the element when the preceding webc:if or webc:elseif sibling did not, and its own JavaScript expression is truthy. webc:else renders the element when no preceding sibling in the chain did. HTML comments between the siblings are allowed.
---
possumCount: 3
---
<p webc:if="possumCount > 10">There are many possums!</p>
<p webc:elseif="possumCount > 0">There are some possums.</p>
<p webc:else>There are no possums :(</p>
<p>There are some possums.</p>
webc:for
Added in @11ty/webc@0.10.0Repeats the element for each entry of an iterable (Array, String, Map, Set, and others) or an object, using JavaScript for syntax. Use of for iterables and in for objects. You can name the loop variables whatever you like. A second loop variable receives the zero-based index.
---
possums:
- Susan
- Finn
- Jake
---
<ol>
<li webc:for="name of possums" @text="name"></li>
</ol>
<ul>
<li webc:for="(name, index) of possums" @text="`${index}: ${name}`"></li>
</ul>
<ol>
<li>Susan</li>
<li>Finn</li>
<li>Jake</li>
</ol>
<ul>
<li>0: Susan</li>
<li>1: Finn</li>
<li>2: Jake</li>
</ul>
Each entry can be an object. This example renders a table row per possum.
---
possums:
- { name: Susan, hobby: Being strong }
- { name: Finn, hobby: Dungeon crawling }
---
<table>
<thead>
<tr>
<th>Name</th>
<th>Hobby</th>
</tr>
</thead>
<tbody>
<tr webc:for="possum of possums">
<td @text="possum.name"></td>
<td @text="possum.hobby"></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Name</th>
<th>Hobby</th>
</tr>
</thead>
<tbody>
<tr>
<td>Susan</td>
<td>Being strong</td>
</tr>
<tr>
<td>Finn</td>
<td>Dungeon crawling</td>
</tr>
</tbody>
</table>
Use in for a plain object, such as when you want to list its properties without knowing the keys ahead of time. The loop variables receive the key, the value, and the zero-based index ((key, value, index) in possum).
---
possum: { name: Susan, hobby: Being strong }
---
<table>
<tbody>
<tr webc:for="(key, value) in possum">
<th @text="key"></th>
<td @text="value"></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th>name</th>
<td>Susan</td>
</tr>
<tr>
<th>hobby</th>
<td>Being strong</td>
</tr>
</tbody>
</table>
To repeat several elements at once, loop on a <template> with webc:nokeep.
---
possums:
- { name: Susan, hobby: Being strong }
- { name: Finn, hobby: Dungeon crawling }
---
<dl>
<template webc:for="possum of possums" webc:nokeep>
<dt @text="possum.name"></dt>
<dd @text="`Hobby: ${possum.hobby}`"></dd>
</template>
</dl>
<dl>
<dt>Susan</dt>
<dd>Hobby: Being strong</dd>
<dt>Finn</dt>
<dd>Hobby: Dungeon crawling</dd>
</dl>
Loops can be nested, but the inner loop cannot access the outer loop’s variables yet. Follow issue #175 for progress.
Scripts and styles
webc:setup
Added in @11ty/webc@0.9.0Runs the <script> element once on the server and exposes its top-level declarations as data to the component. Use it to provide data and markup to the rest of the component.
This is similar to using JavaScript as a custom Eleventy front matter type, although data in webc:setup is scoped to the component and does not flow back up into the Data Cascade.
<script webc:setup>
const possums = ["Susan", "Finn", "Jake"];
</script>
<h2 @text="`${possums.length} fashionable possums`"></h2>
<ul>
<li webc:for="name of possums" @text="name"></li>
</ul>
<possum-list></possum-list>
<h2>3 fashionable possums</h2>
<ul>
<li>Susan</li>
<li>Finn</li>
<li>Jake</li>
</ul>
To use instance-specific data, declare a function in the setup script and pass the attributes or props in as arguments from the component markup.
<script webc:setup>
function greeting(name, hobby) {
return `Hello ${name}, do you enjoy ${hobby.toLowerCase()}?`;
}
</script>
<p @text="greeting(name, hobby)"></p>
<possum-greeting @name="Susan" @hobby="Being strong"></possum-greeting>
<possum-greeting @name="Finn" @hobby="Dungeon crawling"></possum-greeting>
<p>Hello Susan, do you enjoy being strong?</p>
<p>Hello Finn, do you enjoy dungeon crawling?</p>
Works with var, let, const, function, and Array and Object destructuring assignment. Uses the node-retrieve-globals package.
webc:type
Treats the element’s content as a JavaScript render function (js), or as another Eleventy template syntax (11ty, named in 11ty:type). The Eleventy WebC plugin bundles four types:
webc:type="js"Added in @11ty/webc@0.7.1webc:type="render"(superseded bywebc:type="js")webc:type="11ty"(Eleventy only)webc:type="css:scoped"(internal, used bywebc:scoped, but overridable)
Adding your own webc:type custom transform directly to WebC is not yet available in the Eleventy WebC plugin. If you would like to see this added, please let us know.
webc:type="js"
Added in @11ty/webc@0.7.1Runs the content as server JavaScript. The value of the last statement replaces the element and is processed as WebC. If the value is a promise, WebC resolves it. The script has access to the component’s attributes and props.
<script webc:type="js">
if (!alt) {
throw new Error(`Missing alt attribute on <img src="${src}">`);
}
`<img src="${src}" alt="${alt}">`;
</script>
<img src="susan.jpeg" alt="Susan Possum in a purple jacket">
<img src="susan.jpeg" alt="Susan Possum in a purple jacket">
<script webc:type="js">
if (!alt) {
throw new Error(`Missing alt attribute on <img src="${src}">`);
}
`<img src="${src}" alt="${alt}">`;
</script>
<img src="finn.jpeg">
[11ty] Original error message: Missing alt attribute on <img src="finn.jpeg">
The same component with the superseded webc:type="render", which exports a function and reads attributes from this. Unlike js, render does not imply webc:is="template", so add it to drop the void <img> host tag:
<script webc:type="render" webc:is="template">
export default function () {
if (!this.alt) {
throw new Error(`Missing alt attribute on <img src="${this.src}">`);
}
return `<img src="${this.src}" alt="${this.alt}">`;
}
</script>
A render function can generate CSS too. Add webc:is="style" and WebC adds the result to the CSS bundle like any other component style.
<script webc:type="js" webc:is="style">
`.possum { color: ${color}; }`;
</script>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<possum-theme @color="rebeccapurple"></possum-theme>
<p class="possum">Hello possum.</p>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>.possum { color: rebeccapurple; }</style>
</head>
<body>
<possum-theme></possum-theme>
<p class="possum">Hello possum.</p>
</body>
</html>
The same component with the superseded webc:type="render":
<script webc:type="render" webc:is="style">
export default function () {
return `.possum { color: ${this.color}; }`;
}
</script>
Notes:
- To generate scoped CSS with JavaScript, add
webc:scopedto the element as well (<script webc:type="js" webc:is="style" webc:scoped>). - For simple conditions,
webc:ifmay be all you need. - Added in @11ty/webc@0.9.0
webc:type="js"implieswebc:is="template", so WebC reprocesses the returned content as WebC (HTML). Set your ownwebc:isattribute to generate a different tag (e.g.webc:is="script"orwebc:is="style"). - Added in @11ty/webc@0.9.0
webc:type="js"implieswebc:nokeep, so the outer element is left out of the output. Addwebc:keepto keep it.
Extra data for JavaScript render functions
webc.attributes: Added in @11ty/webc@0.9.0 an object literal representing the current element’s attributes.webc.renderAttributes: Added in @11ty/webc@0.9.0 a method to render public attributes to a string.webc.filterPublicAttributes: Added in @11ty/webc@0.10.1 a method to filterwebc.attributes, returning an object with only public attributes. Usage:webc.filterPublicAttributes(webc.attributes)webc.escapeText: Added in @11ty/webc@0.10.1 encodes all characters that have to be escaped in HTML text (via theentitiespackage)webc.escapeAttribute: Added in @11ty/webc@0.10.1 encodes all characters that have to be escaped in HTML attributes (via theentitiespackage)
Read more at Issue #104.
This <img> component re-uses every attribute from the host component. The same expression is useful in an error message, e.g. `Missing alt attribute on <img${webc.renderAttributes(webc.attributes)}>` (the rendered string starts with a space, so leave none before ${).
<script webc:type="js">
`<img ${webc.renderAttributes(webc.attributes)}>`;
</script>
<img
src="possum.jpeg"
alt="Susan Possum in a purple jacket"
loading="lazy"
class="portrait"
>
<img
src="possum.jpeg"
alt="Susan Possum in a purple jacket"
loading="lazy"
class="portrait"
>
webc:type="11ty" and 11ty:type
Renders the content with the Eleventy template syntax, or comma-separated chain of syntaxes, named in 11ty:type. The Eleventy WebC plugin wires the WebC custom transforms feature to the Eleventy Render plugin to make this possible.
webc:type="11ty" feature is exclusive to the Eleventy WebC plugin and is not available in standalone WebC.11ty:type accepts any valid template syntax.
---
title: Top 10 Fashionable Possums
---
<template webc:type="11ty" 11ty:type="liquid,md">
{% assign publication = "Possum Times" %}
## {{ title }}
_{{ publication }}_
</template>
<h2>Top 10 Fashionable Possums</h2>
<p><em>Possum Times</em></p>
- The template has full access to the data cascade, including
titleset in front matter. - Added in @11ty/webc@0.5.0WebC processes content returned on
<template>(orwebc:is="template") elements as WebC, so you can return any WebC content here. - You can add your own custom template engine, which is then available here too (e.g.
<style webc:type="11ty" 11ty:type="sass">).
Helper functions
WebC helpers are JavaScript functions available in dynamic attributes, @html, @raw, and render functions.
Eleventy-provided helpers
Added in @11ty/eleventy-plugin-webc@0.5.0Eleventy WebC provides JavaScript template functions and universal filters automatically as WebC helpers.
This includes url, slugify, log, and others.
<a :href="url('/possums/')">All possums</a>
<a href="/possums/">All possums</a>
Supply your own helper
export default function (eleventyConfig) {
// via a universal filter
eleventyConfig.addFilter("shout", (text) => text.toUpperCase());
// or via a JavaScript template function directly
eleventyConfig.addJavaScriptFunction("siteName", () => "Possum Times");
};
module.exports = function (eleventyConfig) {
// via a universal filter
eleventyConfig.addFilter("shout", (text) => text.toUpperCase());
// or via a JavaScript template function directly
eleventyConfig.addJavaScriptFunction("siteName", () => "Possum Times");
};
---
title: Top 10 Fashionable Possums
---
<h1 @text="shout(title)"></h1>
<p @text="siteName()"></p>
<h1>TOP 10 FASHIONABLE POSSUMS</h1>
<p>Possum Times</p>
webc:scoped
Scopes the <style> element to the component by prefixing every selector with a generated class, or with the class name given as the value. The generated class name is a hash of the style content, so WebC de-duplicates identical component styles. WebC replaces :host with the generated class selector.
To choose your own prefix, give webc:scoped a value. Prefer a named prefix when anything outside the component refers to the class, such as other stylesheets, scripts, or tests: the generated name changes whenever you edit the style content, while a named prefix stays the same and keeps the output CSS readable. WebC checks for duplicate prefixes in your component tree and throws an error when it finds a collision.
<style webc:scoped>
:host {
color: blue;
}
h1 {
color: rebeccapurple;
}
</style>
<h1>Top 10 Fashionable Possums</h1>
<p>Hello possum.</p>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<my-component></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>.wt-d_fkgu{color:blue}.wt-d_fkgu h1{color:rebeccapurple}</style>
</head>
<body>
<my-component class="wt-d_fkgu">
<h1>Top 10 Fashionable Possums</h1>
<p>Hello possum.</p>
</my-component>
</body>
</html>
<style webc:scoped="possum">
:host {
color: blue;
}
h1 {
color: rebeccapurple;
}
</style>
<h1>Top 10 Fashionable Possums</h1>
<p>Hello possum.</p>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<my-component></my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>.possum{color:blue}.possum h1{color:rebeccapurple}</style>
</head>
<body>
<my-component class="possum">
<h1>Top 10 Fashionable Possums</h1>
<p>Hello possum.</p>
</my-component>
</body>
</html>
- Progressive enhancement requires ubiquitous browser support before you use it for content in the critical rendering path.
- It duplicates the
<style>element in each instance of the component.
Expand for a Declarative Shadow DOM example
WebC leaves the <style> inside a shadow root template as is, so it is not bundled and repeats in every instance. WebC also fills the <slot> at build time.
<template shadowrootmode="open">
<style>
h1 {
color: rebeccapurple;
}
</style>
<slot></slot>
</template>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<my-component>
<h1>Top 10 Fashionable Possums</h1>
</my-component>
<my-component>
<h1>Hello possum.</h1>
</my-component>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style></style>
</head>
<body>
<my-component>
<template shadowrootmode="open">
<style>
h1 {
color: rebeccapurple;
}
</style>
<h1>Top 10 Fashionable Possums</h1>
</template>
</my-component>
<my-component>
<template shadowrootmode="open">
<style>
h1 {
color: rebeccapurple;
}
</style>
<h1>Hello possum.</h1>
</template>
</my-component>
</body>
</html>
webc:bucket
Sends the element’s bundled CSS or JavaScript to a named asset bucket instead of the default one, so you can output it somewhere else on the page, for example at the end of <body> instead of in <head>. Output a bucket with getBundle(type, name). Read more at Asset bucketing.
<style>
footer { color: rebeccapurple }
</style>
<script webc:bucket="defer">
console.log("Hello possum.");
</script>
<footer>Hello possum.</footer>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<div>
<my-footer></my-footer>
</div>
<style @raw="getBundle('css', 'defer')" webc:keep></style>
<script @raw="getBundle('js', 'defer')" webc:keep></script>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style>footer { color: rebeccapurple }</style>
</head>
<body>
<div>
<my-footer>
<footer>Hello possum.</footer>
</my-footer>
</div>
<style></style>
<script>console.log("Hello possum.");</script>
</body>
</html>
<style>
footer { color: rebeccapurple }
</style>
<script>
console.log("Hello possum.");
</script>
<footer>Hello possum.</footer>
<!DOCTYPE html>
<title>WebC Example</title>
<style @raw="getBundle('css')" webc:keep></style>
<div webc:bucket="defer">
<my-footer></my-footer>
</div>
<style @raw="getBundle('css', 'defer')" webc:keep></style>
<script @raw="getBundle('js', 'defer')" webc:keep></script>
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
<style></style>
</head>
<body>
<div>
<my-footer>
<footer>Hello possum.</footer>
</my-footer>
</div>
<style>footer { color: rebeccapurple }</style>
<script>console.log("Hello possum.");</script>
</body>
</html>
- Added to any other element,
webc:bucketcascades to every element and component inside it, as in the second example. - The value can be a JavaScript expression with the
:prefix, e.g.:webc:bucket="bucketName".
Opting out of WebC processing
webc:raw
Skips WebC processing for everything inside the element, so components, @ and : attributes are output as written. Attributes on the element itself are still processed. This works well with the <template> element, which WebC leaves in the output.
<template webc:raw>
<story-card @title="Top 10 Fashionable Possums"></story-card>
<style>
p { color: rebeccapurple }
</style>
</template>
<my-component></my-component>
<template>
<story-card @title="Top 10 Fashionable Possums"></story-card>
<style>
p { color: rebeccapurple }
</style>
</template>
- Related:
@rawproperty
webc:ignore
Added in @11ty/webc@0.9.0Removes the element and its content from processing and output entirely. This is useful for server-side comments or usage documentation in a component.
<template webc:ignore>
Usage:
<story-card @title="Top 10 Fashionable Possums"></story-card>
</template>
<div class="story-card">
<h1 @text="title"></h1>
</div>
<story-card @title="Top 10 Fashionable Possums"></story-card>
<div class="story-card">
<h1>Top 10 Fashionable Possums</h1>
</div>
Server-only comments
Added in @11ty/webc@0.10.0
Add one or more dashes to the start and end of an HTML comment and WebC removes it from the output. A standard HTML comment is rendered to the output as usual.
<!------- WebC removes this comment ------->
<!--- WebC removes this comment --->
<!-- WebC does NOT remove this comment -->
<p>Hello possum.</p>
<my-component></my-component>
<!-- WebC does NOT remove this comment -->
<p>Hello possum.</p>
Subtleties and limitations
Void elements
Custom elements are not supported as void elements, they require both a starting and ending tag (as per the HTML specification). This means a WebC component cannot be self-closing. To work around this limitation, use webc:is on a void element (e.g. <img webc:is="my-image" src="possum.jpeg">), or name the component file after the void element itself (e.g. _components/img.webc).
Head components
The HTML parser moves custom element children of <head> into the <body>. To work around this limitation, use webc:is on an element that is allowed in <head>, such as <template>.
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!DOCTYPE html>
<html lang="en">
<head>
<template webc:is="site-meta"></template>
<title>WebC Example</title>
</head>
<body>
<p>Hello possum.</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WebC Example</title>
</head>
<body>
<p>Hello possum.</p>
</body>
</html>
Table components
WebC uses the parse5 library, so it parses and tokenizes every WebC file the same way a web browser does. If you put a <table> element in a custom WebC element and pass its <tr> and <td> elements through a slot, the parser sees the <tr> and <td> elements as orphans. It removes them during the initial parse and places the table internals as siblings of the table.
To work around this limitation, use webc:is for the <table>, <tr>, and <td> elements.
<template webc:is="table">
<slot></slot>
</template>
<possum-table>
<template webc:is="tr">
<template webc:is="td">Susan</template>
<template webc:is="td">Is strong</template>
</template>
</possum-table>
<table>
<tr>
<td>Susan</td>
<td>Is strong</td>
</tr>
</table>
Rendering modes
Eleventy has two rendering modes: page and component. WebC chooses the mode from the markup you supply. The page mode renders full HTML pages. The component mode renders fragments of HTML. Most of the time you do not need to think about this distinction, but it is documented here for completeness.
pageis used when the markup starts with<!doctype(or<!DOCTYPE) or<html(WebC forces no-quirks parsing).componentis used otherwise.
Differences from HTML parsing
Added in @11ty/webc@0.9.0WebC processes content inside of both <template> and <noscript> elements. The HTML parser treats these as plaintext.
Eleventy + WebC Features
Front Matter
WebC in Eleventy works automatically with standard Eleventy conventions for front matter (though front matter in Eleventy is optional).
---
layout: "my-layout.webc"
---
WebC *is* HTML.
Expand to see an example my-layout.webc
The above example assumes the existence of _includes/my-layout.webc (an Eleventy layout).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
</head>
<body @raw="content"></body>
</html>
Front matter (per standard Eleventy conventions) is supported in page-level templates only (.webc files in your input directory), not in components.
Defining Components
Components are the magic of WebC and there are a few ways to define components in WebC:
- Use global no-import components specified in your config file.
- Specify a glob of no-import components at a directory or template level in the data cascade.
- You can use
webc:importinside of your components to import another component directly.
Global no-import Components
Use the components property in the options passed to addPlugin in your Eleventy configuration file to specify project-wide WebC component files available for use in any page.
The components option accepts:
- String (file path or glob)
- Array (of file paths or globs) Added in @11ty/eleventy-plugin-webc@0.9.2
npm:prefix aliases Added in @11ty/eleventy-plugin-webc@0.9.2
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// Glob to find no-import global components
// This path is relative to the project-root!
// The default value is shown:
components: "_components/**/*.webc",
// or an Array (Eleventy WebC v0.9.2+)
components: [
"_components/**/*.webc",
"npm:@11ty/is-land/*.webc",
"npm:@11ty/eleventy-plugin-syntaxhighlight/*.webc",
],
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// Glob to find no-import global components
// This path is relative to the project-root!
// The default value is shown:
components: "_components/**/*.webc",
// or an Array (Eleventy WebC v0.9.2+)
components: [
"_components/**/*.webc",
"npm:@11ty/is-land/*.webc",
"npm:@11ty/eleventy-plugin-syntaxhighlight/*.webc",
],
});
};
The path for components is relative to your project root (not your project’s input directory).
The file names of components found in the glob determine the global tag name used in your project (e.g. _components/my-component.webc will give you access to <my-component>).
Declaring Components in Front Matter
You can also use and configure specific components in front matter (or, via any part of the data cascade—scoped to a folder or a template) by assigning a glob (or array of globs) to the property at webc.components:
---
layout: "my-layout.webc"
webc:
components: "./webc/*.webc"
---
<my-webc-component>WebC *is* HTML.</my-webc-component>
By default these paths are relative to the template file. If you’re setting this in the data cascade in a directory data file that will apply multiple child folders deep, it might be better to:
- Use the global no-import components option.
- Use
~/as a prefix (e.g.~/my-directory/webc/*.webc) to alias to the project’s root directory.
Official WebC Components
The following plugins offer official WebC components for use in your projects:
@11ty/is-landsupplies<is-land>- Example:
<is-land webc:import="npm:@11ty/is-land"> - Read more at Use with
is-land
- Example:
@11ty/eleventy-plugin-syntaxhighlightsupplies<syntax-highlight>- Example:
<syntax-highlight language="js" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight"> - Read more at Syntax Highlighting Plugin
- Example:
@11ty/eleventy-imgsupplies<eleventy-image>- Added in Image v3.1.0
- Example:
<img webc:is="eleventy-image" webc:import="npm:@11ty/eleventy-img"> - Read more at the Image WebC component.
Eleventy Data Cascade
To access global data from the Data Cascade, use the $data variable in your component’s JavaScript. For example, if you have this in _data/site.json:
{
"title": "My Site Title"
}
In an internal WebC component, such as one in src/_includes/components/*, you can access that data via:
<h1 @text="$data.site.title"></h1>
In a top-level WebC template, such as a layout file or other *.webc files in the Eleventy input folder, you can access global data variables directly without $data:
<h1 @text="site.title"></h1>
CSS and JS (Bundler mode)
Eleventy WebC bundles each page’s assets (the CSS and JS used by components on the page). WebC rolls these up automatically when a component uses <script>, <script src>, <style>, or <link rel="stylesheet">. You can use this to implement component-driven Critical CSS.
<template shadowrootmode> or the deprecated <template shadowroot>) are left as is and not bundled.<style>
/* This is component CSS */
</style>
<script>
/* This is component JS */
</script>
<!-- Local file references work too -->
<link rel="stylesheet" href="my-file.css" />
<script src="my-file.js"></script>
As shown above this also includes <link rel="stylesheet"> and <script src> when the URLs point to files on the file system (remote URL sources are not yet supported).
You can opt-out of bundling on a per-element basis using webc:keep.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
<!-- inline bundles -->
<style @raw="getBundle('css')" webc:keep></style>
<script @raw="getBundle('js')" webc:keep></script>
<!-- or write your bundle to a file -->
<link rel="stylesheet" :href="getBundleFileUrl('css')" webc:keep />
<script :src="getBundleFileUrl('js')" webc:keep></script>
</head>
<body @raw="content"></body>
</html>
- Added in @11ty/eleventy-plugin-webc@0.9.0Eleventy WebC uses the Bundle Plugin behind the scenes to implement bundling.
getBundle('css')andgetBundle('js')can now be used instead ofgetCss(page.url)andgetJs(page.url)respectively. - Added in @11ty/webc@0.8.0
webc:keepis required on<style>and<script>in your layout files to prevent re-bundling the bundles. - Added in @11ty/webc@0.8.0The
getCssandgetJshelpers are now available to all WebC templates without restriction. Previous versions required them to be used in an Eleventy Layout file. @rawwas Added in @11ty/webc@0.7.1. Previous versions can usewebc:raw @html.
Bundle Code Ordering
The order of the code in these bundles is determined by the dependency order of the components, from most specific to least specific!
Expand to see an example
This example has an index.webc page that uses a header.webc component.
<style>
/* index.webc */
</style>
<header></header>
<style>
/* header.webc */
</style>
The CSS bundle looks like:
/* header.webc */
/* index.webc */
Access Bundles in other Template Engines
You can access these bundles in other templates types too (.njk, .liquid, etc.).
Added in @11ty/eleventy-plugin-webc@0.9.0Eleventy WebC uses the Bundle Plugin behind the scenes to implement bundling. This plugin provides getBundle and getBundleFileUrl universal shortcodes for use in any template type (including WebC as shown above).
WebC v0.8.0 and older: Check out the deprecated (but still in place for backwards compatibility) webcGetCss and webcGetJs universal filters for bundle output.
<style>{{ page.url | webcGetCss | safe }}</style>
<script>{{ page.url | webcGetJs | safe }}</script>
<!-- write to a file -->
<link rel="stylesheet" href="{% getBundleFileUrl "css" %}">
<style>{{ page.url | webcGetCss }}</style>
<script>{{ page.url | webcGetJs }}</script>
Asset bucketing
Bucketing is an additional layer of bundling. webc:bucket sends a component’s CSS or JavaScript to a named bucket instead of the default one.
This component outputs code to two separate buckets:
<style>
/* This CSS is put into the default bucket */
</style>
<script>
/* This JS is put into the default bucket */
</script>
<style webc:bucket="defer">
/* This CSS is put into the `defer` bucket */
</style>
<script webc:bucket="defer">
/* This JS is put into the `defer` bucket */
</script>
When <my-webc-component> is used on a page, WebC rolls its assets into the page-specific bucket bundles for CSS and JavaScript.
You can then output those bucket bundles anywhere on your page, as in this Eleventy layout file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
<!-- Default bucket -->
<style @raw="getBundle('css')" webc:keep></style>
<script @raw="getBundle('js')" webc:keep></script>
</head>
<body>
<template @raw="content" webc:nokeep></template>
<!-- `defer` bucket -->
<style @raw="getBundle('css', 'defer')" webc:keep></style>
<script @raw="getBundle('js', 'defer')" webc:keep></script>
</body>
</html>
- Added in @11ty/webc@0.8.0
webc:keepis required on<style>and<script>in your layout files to prevent re-bundling the bundles. - Added in @11ty/webc@0.9.1
:webc:bucket(dynamic attribute) is supported to set this value via JavaScript. #120
Cascading Asset Buckets
Added in @11ty/webc@0.9.1 Additionally, webc:bucket can be added to any tag and cascades to all child content.
Consider this WebC page:
<!-- has an implied webc:bucket="default" -->
<my-component></my-component>
<div webc:bucket="defer">
<!-- each of these have webc:bucket="defer" -->
<!-- (including any nested components inside, too) -->
<footnote-references></footnote-references>
<my-footer></my-footer>
</div>
Setting webc:bucket cascades to all of the children as if each had webc:bucket="defer" assigned individually. All assets used in those components are rolled up into the defer bucket.
Conflicts and hoisting
What happens when a component is used in multiple distinct buckets?
<!-- has an implied webc:bucket="default" -->
<my-component></my-component>
<div webc:bucket="defer">
<my-component></my-component>
</div>
When duplicates and conflicts occur, WebC hoists the component code to the nearest shared bucket for you. In this example, the CSS and JS for <my-component> are loaded in the default bucket and only in the default bucket.
Use with is-land
You can also use this out of the box with Eleventy’s is-land component for web component hydration.
At the component level, components can declare their own is-land loading conditions.
<is-land on:visible webc:import="npm:@11ty/is-land">
<template data-island>
<!-- CSS -->
<style webc:keep>
/* This CSS applies on:visible */
</style>
<link rel="stylesheet" href="arbitrary.css" webc:keep />
<!-- JS -->
<script type="module" webc:keep>
console.log("This JavaScript runs on:visible");
</script>
<script type="module" src="arbitrary.js" webc:keep></script>
</template>
</is-land>
From the Community
×58 resources via 11tybundle.dev curated by Bob Monsour.