How-to Guides

Use LinkMetadata with Vue

Add the preview component to Vue or fetch metadata for a custom Vue card.

Vue can render the LinkMetadata web component directly, or you can call the API with fetch and build your own card.

Configure the custom element

If you use Vue with Vite, tell Vue that link-metadata-preview is a browser custom element:

// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "link-metadata-preview"
        }
      }
    })
  ]
});

Load the component script once in index.html:

<script type="module" src="https://api.linkmetadata.com/component.js" async></script>

Then use it in a Vue template:

<template>
  <link-metadata-preview
    :data-url="url"
    data-theme="card"
    data-show-branding="false"
  />
</template>

<script setup>
defineProps({
  url: {
    type: String,
    required: true
  }
});
</script>

Fetch metadata yourself

Use the Fetch API when you want to render a custom Vue component.

<template>
  <a v-if="metadata" :href="metadata.url" target="_blank" rel="noreferrer">
    <strong>{{ metadata.title || metadata.url }}</strong>
    <p v-if="metadata.description">{{ metadata.description }}</p>
  </a>

  <a v-else-if="error" :href="url">{{ url }}</a>
  <span v-else>Loading preview...</span>
</template>

<script setup>
import { onMounted, ref, watch } from "vue";

const props = defineProps({
  url: {
    type: String,
    required: true
  }
});

const metadata = ref(null);
const error = ref(null);

async function loadMetadata(url) {
  const params = new URLSearchParams({ url });
  const response = await fetch(`https://api.linkmetadata.com/v1/metadata?${params}`);

  if (!response.ok) {
    throw new Error(`Metadata request failed with ${response.status}`);
  }

  metadata.value = await response.json();
}

onMounted(async () => {
  try {
    await loadMetadata(props.url);
  } catch (err) {
    error.value = err;
  }
});

watch(() => props.url, async (nextUrl) => {
  metadata.value = null;
  error.value = null;

  try {
    await loadMetadata(nextUrl);
  } catch (err) {
    error.value = err;
  }
});
</script>

The API is free to use and rate limited per IP address. For image proxy behavior, see Images and CORS.