Web Components and Vue
Framework-agnostic components for maximum compatibility with any architecture.
Web Component (Vanilla JS, PHP, Rails)
If you don’t use React or Vue, or you are integrating Cord into a server-rendered site (like Laravel, Django, or WordPress), you can use the standard Web Component <cord-quote> (<cord-cotizador> still works as an alias).
This component is compiled under web platform standards, meaning the browser understands it natively without the need for a bundler.
<!-- Import the ES module -->
<script type="module" src="https://unpkg.com/@flouviahq/elements/dist/index.mjs"></script>
<!-- Render the native component -->
<div style="height: 800px;">
<cord-quote
token="9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46"
min-height="500">
</cord-quote>
</div>
<script>
// Listen to standard DOM events
const quote = document.querySelector('cord-quote');
quote.addEventListener('approved', (e) => {
console.log('Approved by', e.detail.signed_by);
});
</script>
Events Note: When using the native Web Component, events arrive without the cord: prefix. That is, instead of listening to cord:approved, you will simply listen to approved like any other DOM API event.
The invoice: <cord-invoice>
<cord-invoice> shows a Cord invoice (the one at /i/{token}) on your site: balance due, status, line items, totals and the PDF download. The token is the hosted invoice’s, the same one in the email your customer receives.
<cord-invoice token="INVOICE_TOKEN"></cord-invoice>
<script>
document.querySelector('cord-invoice').addEventListener('paid', (e) => {
console.log('Invoice paid', e.detail.folio);
});
</script>
The pay button opens the hosted invoice in a Cord window: payment details are never captured inside the iframe. While the invoice is open, the embed checks its balance and emits status_changed when it changes and paid when it’s settled. With embed.js, add data-cord-document="invoice" to the div. As with the quote, without allowed domains in Settings › Embeddable quote builder events arrive without data.
theme, variables and fonts from the Appearance API apply to the invoice; rules and layout are for the quote.
Live state: state and statechange
<cord-quote> and <cord-invoice> reduce the iframe’s events to a state you can read at any time through the state property, and they emit statechange whenever it changes. That way you draw your own summary without listening event by event.
<cord-quote token="9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46"></cord-quote>
<p id="summary"></p>
<script type="module">
const quote = document.querySelector('cord-quote');
const summary = document.querySelector('#summary');
quote.addEventListener('statechange', (e) => {
const s = e.detail; // same as quote.state
if (!s.ready) return;
const total = s.total === null ? '' : new Intl.NumberFormat('en-US', { style: 'currency', currency: s.moneda }).format(s.total);
summary.textContent = `${s.folio ?? ''} ${s.status ?? ''} ${total}`;
if (s.paid) summary.textContent += ' · paid';
});
</script>
| Field | Content |
|---|---|
ready |
The quote finished rendering. |
status |
sent, viewed, approved, rejected, paid, expired… |
folio, moneda, total |
From the document. The total always travels with its currency. |
approved, rejected, paid |
Boolean shortcuts. paid is also true for a quote that was already invoiced. |
signedBy |
Who approved, if they approved in this session. |
lastEvent |
The last event received, for example cord:approved. |
Without allowed domains in Settings › Embeddable quote builder, events arrive without data and status, folio, moneda and total stay null. In React it’s onStateChange on <CordCotizador>; in Vue, the @state event.
Styling: ::part
Both elements live in a Shadow DOM: your styles don’t break them and theirs don’t touch your page. To customize them from the outside:
cord-quote::part(frame) {
border-radius: 24px;
box-shadow: 0 12px 40px rgba(10, 25, 47, 0.08);
}
cord-quote::part(skeleton) {
border-radius: 24px;
}
| Part | Element |
|---|---|
root |
The element’s container. |
skeleton |
The loading placeholder shown while the document arrives. |
frame |
The <iframe> with Cord’s document. |
The content inside the iframe is customized with the Appearance API (the appearance attribute as JSON, or the appearance property as an object), not with your page’s CSS.
| Attribute | Detail |
|---|---|
token |
Required. The document’s public token. |
appearance |
Appearance as JSON. |
min-height |
Minimum iframe height in pixels (420 by default). |
base-url |
Cord’s origin, if you use a custom domain. |
debug |
Turns on the debug bar (see Events). |
Tax form
<cord-fiscal-form> captures your client’s tax details with the same validation Cord uses and plugs into your HTML forms. See Tax form.
Vue and Nuxt
The Cord SDK provides a native wrapper for Vue 3 that handles reactivity and events using the Vue paradigm (@ or v-on).
Installation
npm install @flouviahq/elements
Usage
Import the <CordCotizador> component from the /vue entrypoint and pass it to your template.
<script setup>
import { CordCotizador } from '@flouviahq/elements/vue';
import { ref } from 'vue';
const myToken = ref('9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46');
function handleApproved(detail) {
console.log('The client signed:', detail.signed_by);
}
function handlePay(detail) {
window.location.href = detail.url;
}
</script>
<template>
<main class="quote-container">
<CordCotizador
:token="myToken"
@approved="handleApproved"
@pay="handlePay"
/>
</main>
</template>
Framer
If you are building your website in Framer, you can add Cord Elements as a drag-and-drop Code Component.
Create a new code component in Framer and paste the following:
import { FramerCordCotizador } from '@flouviahq/elements/framer';
export default FramerCordCotizador;
This will register the property controls in Framer’s visual interface (Property Controls), exposing the Token field in the right panel so your designers can modify it visually without touching code.
Webflow
Unlike Framer (a real React Code Component), Webflow doesn’t run React components — that’s
why the SDK exposes a separate entrypoint (@flouviahq/elements/webflow) built for Webflow’s
visual editor: a self-initializing script that requires no code, just custom attributes.
- In Webflow, add a Div Block wherever you want the quoter to appear.
- In that element’s Settings panel, add a Custom Attribute:
data-cord-tokenwith your quote’s token as the value. (Optionally,data-cord-base-urlif you use your own domain, anddata-cord-min-heightfor the iframe’s minimum height.) - Under Page Settings › Custom Code (or your site’s settings if you want it on every
page), add this script before
</body>:
<script src="https://unpkg.com/@flouviahq/elements/dist/webflow.js"></script>
The script automatically finds every element with data-cord-token on the page (on load, and
again if Webflow adds more later) and mounts the quoter there — it doesn’t expose its own JS
events like the native Web Component does; for that, use <cord-cotizador> directly or
Framer’s Code Component.