GitHub

Demfati Widget Documentation v1

Drop-in, zero-dependency JavaScript library that safely embeds Demfati-powered widgets (Voting, Tickets, Forms, etc.) into any website with lazy-loading, caching, and automatic domain verification.

Quick Start (60 seconds)

1. Verify your domain

Add this meta tag to the <head> of every page that will host a widget:

<meta name="dmf-domain-verification" content="YOUR_SITE_TOKEN">

2. Load the script once

<script src="https://cdn.demfati.com/widgets/demfati-widget.js" defer></script>

3. Place widget(s) anywhere

<!-- Voting gallery -->
<div class="demfati-widget" data-type="voting" data-request="EVENT_CODE"></div>

<!-- Ticket store -->
<div class="demfati-widget" data-type="tickets" data-request="EVENT_CODE"></div>

<!-- Form plugin -->
<div class="demfati-widget" data-type="forms" data-request="FORM123"></div>

4. Initialize (optional)

<script>
document.addEventListener('DOMContentLoaded', () => {
  dmfwl.init({
    sort: 'votes',      // name | code | votes
    search: true        // show search bar inside voting widget
  });
});
</script>

Tip: You can skip init(/**CONFIGURATION**/) entirely, widgets load with sensible defaults.

Domain Verification

For security, every API response is scoped to whitelisted domains. The loader refuses to render if the meta tag is missing or invalid.

AttributeValue
namedmf-domain-verification
contentSite token from Demfati dashboard → Settings → Domains

The token is tied to your account, not to a single event—reuse it across all pages.

Available Widgets

1. Voting / Contest Gallery

Searchable, sortable grid of contestants with vote counts, progress bars, one-click payment (cards, USSD, Apple Pay, Google Pay, WhatsApp).

<div class="demfati-widget" data-type="voting" data-request="MISS_WORLD_2025"></div>

2. Ticket Store

Complete checkout: ticket selection, attendee forms, order summary, payment (PayStack, Flutterwave, Stripe, WhatsApp), auto-generated QR/Bar-coded tickets.

<div class="demfati-widget" data-type="tickets" data-request="TEDX_UNILAG"></div>

3. Form Attachment

Feedback, survey, payment, auto-confirmation.

<div class="demfati-widget" data-type="forms" data-request="FORM123"></div>

Init Options

All keys are optional.

KeyTypeDefaultDescription
sort'name'|'code'|'votes'originalInitial contestant order
searchbooleantrueShow/hide search bar (voting widget)
customRenderContestantfunctionOverride contestant card HTML

API Reference

The global dmfwl instance exposes:

dmfwl.init(options?)

Bootstraps the loader. Safe to call multiple times.

dmfwl.loadFromCache(key) → any | null

Low-level cached API responses (10 min TTL).

dmfwl.saveToCache(key, data)

Programmatically store JSON (10 min TTL).

Code Examples

React (Next.js)

import { useEffect } from 'react';
export default function Home() {
  useEffect(() => {
    import('https://cdn.demfati.com/widgets/demfati-widget.js').then(() => dmfwl.init({ sort: 'votes' }));
  }, []);
  return <div className="demfati-widget" data-type="tickets" data-request="NEXT_CONF_2025"></div>;
}

Vue 3 (Composition API)

<template><div class="demfati-widget" data-type="voting" data-request="HACKATHON_2025"></div></template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
  const script = document.createElement('script');
  script.src = 'https://cdn.demfati.com/widgets/demfati-widget.js';
  script.onload = () => dmfwl.init({ search: true });
  document.head.appendChild(script);
});
</script>

WordPress (Classic Editor)

<meta name="dmf-domain-verification" content="YOUR_TOKEN">
<script src="https://cdn.demfati.com/widgets/demfati-widget.js" defer></script>
<div class="demfati-widget" data-type="tickets" data-request="WORDCAMP_LAGOS"></div>

Styling & Theming

All widgets ship with neutral, adaptive CSS. Override any rule—every visual token is exposed as a custom property or class.

/* Brand header */
.dmf-ticket-header{background:linear-gradient(135deg,var(--primary),#fff)}
/* Custom button */
.dmf-ticket-form .btn-primary{background:#7c3aed;box-shadow:0 4px 14px rgba(124,58,237,.4)}
/* Skeleton */
.dmf-skel-ticket-card{background:#f1f5f9}

Supply customRenderContestant and skip default CSS entirely for full control.

FAQ / Troubleshooting

Widget never appears?

Can I lazy-load the script itself?

Yes – < 6 kB gzipped, safe with async/defer or dynamic import.

Does it work offline?

Cached responses served from localStorage while online; true offline (SW) on roadmap.

React/Vue wrapper?

Official wrappers coming soon – use vanilla snippet inside useEffect/onMounted for now.