Headless CMS
This content is not available in your language yet.
Wink web components are framework-agnostic custom HTML elements. If your headless CMS renders HTML — whether through Next.js, Nuxt, Astro, SvelteKit, or any other framework — you can embed Wink components without any special integration.
The three-step embed
Section titled “The three-step embed”Every Wink integration, regardless of platform, follows the same three steps.
1. Include the stylesheet
Section titled “1. Include the stylesheet”Add this to your document <head> (or equivalent global layout):
<link rel="stylesheet" href="https://elements.wink.travel/styles.css">2. Include the JavaScript
Section titled “2. Include the JavaScript”Add this before your closing </body> tag (or in your layout’s script section):
<script src="https://elements.wink.travel/elements.js" type="module" defer></script>3. Add the application loader
Section titled “3. Add the application loader”Place this once per page, anywhere in the body (typically in your global layout footer):
<wink-app-loader client-id="YOUR_CLIENT_ID"></wink-app-loader>Framework examples
Section titled “Framework examples”Next.js (App Router)
Section titled “Next.js (App Router)”export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> <link rel="stylesheet" href="https://elements.wink.travel/styles.css" /> </head> <body> {children} <script src="https://elements.wink.travel/elements.js" type="module" defer /> <wink-app-loader client-id="YOUR_CLIENT_ID" /> </body> </html> );}Nuxt 3
Section titled “Nuxt 3”<template> <div> <slot /> <wink-app-loader client-id="YOUR_CLIENT_ID" /> </div></template>
<script setup>useHead({ link: [{ rel: 'stylesheet', href: 'https://elements.wink.travel/styles.css' }], script: [{ src: 'https://elements.wink.travel/elements.js', type: 'module', defer: true }],})</script><html lang="en"> <head> <link rel="stylesheet" href="https://elements.wink.travel/styles.css" /> </head> <body> <slot /> <script src="https://elements.wink.travel/elements.js" type="module" is:inline></script> <wink-app-loader client-id="YOUR_CLIENT_ID"></wink-app-loader> </body></html>SvelteKit
Section titled “SvelteKit”<svelte:head> <link rel="stylesheet" href="https://elements.wink.travel/styles.css" /></svelte:head>
<slot /><wink-app-loader client-id="YOUR_CLIENT_ID" />
<script> import { onMount } from 'svelte'; onMount(async () => { await import('https://elements.wink.travel/elements.js'); });</script>Placing components in content
Section titled “Placing components in content”In your CMS’s rich text or custom field types, embed component tags directly in the HTML output:
<wink-content-loader layout="HOTEL" id="YOUR_LAYOUT_ID"></wink-content-loader>For Contentful, Strapi, Sanity, or similar headless platforms, use a Rich Text field or a Custom Block that renders raw HTML, and paste the component tag there.
npm package
Section titled “npm package”For TypeScript projects, the @wink/elements package provides:
- A
load()function that injects the CDN scripts programmatically - Full TypeScript type declarations for all component attributes
npm install @wink/elementsimport { load } from '@wink/elements';
// Call once at app startupload({ clientId: 'YOUR_CLIENT_ID' });Available components
Section titled “Available components”| Component | HTML tag | Purpose |
|---|---|---|
| Content loader | <wink-content-loader> | Display hotel cards, grids, maps |
| Lookup | <wink-lookup> | Search bar for destinations |
| Search button | <wink-search-button> | Open itinerary picker |
| Account button | <wink-account-button> | Sign in / user menu |
| Itinerary button | <wink-itinerary-button> | Show current itinerary |
| Itinerary picker | <wink-itinerary-picker> | Full itinerary form |
| Shopping cart | <wink-shopping-cart-button> | Cart summary button |
See Web Components for the full attribute reference.