Skip to content

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.

  1. In Webflow, add a Div Block wherever you want the quoter to appear.
  2. In that element’s Settings panel, add a Custom Attribute: data-cord-token with your quote’s token as the value. (Optionally, data-cord-base-url if you use your own domain, and data-cord-min-height for the iframe’s minimum height.)
  3. 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.