Get startedInstallFramework guides
Vue 3
Use the CDN bundle with Vue 3 script setup.
<script setup lang="ts">
import { onBeforeUnmount, onMounted } from "vue";
const CDN_URL = "https://widgets.medos.one/v2/unified.js";
const CONTAINER_ID = "medos-booking-vue";
type MedosBookingApi = {
init: (config: Record<string, unknown>) => void;
open: (config?: Record<string, unknown>) => void;
close: () => void;
};
const props = defineProps<{ apiKey: string }>();
const medos = () =>
(window as unknown as { MedosBooking?: MedosBookingApi }).MedosBooking;
/** Reuses an existing tag, so remounting doesn't re-download the bundle. */
function load(): Promise<void> {
if (medos()) return Promise.resolve();
const existing = document.querySelector<HTMLScriptElement>(
`script[src="${CDN_URL}"]`,
);
if (existing) {
return new Promise((resolve) =>
existing.addEventListener("load", () => resolve(), { once: true }),
);
}
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = CDN_URL;
script.async = true;
script.onload = () => resolve();
script.onerror = () => reject(new Error("Medos Booking failed to load"));
document.head.appendChild(script);
});
}
let cancelled = false;
onMounted(async () => {
try {
await load();
if (cancelled) return;
medos()?.init({
apiKey: props.apiKey,
mode: "inline",
containerId: CONTAINER_ID,
});
} catch (err) {
console.error(err);
}
});
onBeforeUnmount(() => {
cancelled = true;
// Inline mode has no close() — clear the container so a remount doesn't
// stack a second widget.
const el = document.getElementById(CONTAINER_ID);
if (el) el.innerHTML = "";
});
</script>
<template>
<div :id="CONTAINER_ID" style="min-height: 600px" />
</template>Use the component:
<MedosBooking api-key="mk_your_publishable_key" />Modal mode
init({ mode: "modal" }) opens the modal as soon as it runs, so don't call it
on mount. Load the script the same way, then start the widget from the button —
init() on the first click, open() after that:
let started = false;
function book() {
const m = medos();
if (!m) return; // bundle still loading
if (started) return m.open();
started = true;
m.init({ apiKey: props.apiKey, mode: "modal" });
}<button @click="book">Book appointment</button>