Skip to content

Embed: Generate custom previews with AI

This guide builds on the metadata API approach — fetch the JSON, then let your AI coding assistant write the markup that matches your design system. No new dependency, no <Microlink> wrapper to override, no CSS reset to fight — just a card built from your own components and tokens.
This page covers the prompts to paste into Cursor, Claude Code, ChatGPT, or any agent embedded in your IDE — and the style recipes you can ask it to adapt.

The payload your assistant will work with

The same metadata response powers every recipe below. Show it to your assistant once:

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://stripe.com' URL:

CLI Microlink API example

microlink https://stripe.com

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://stripe.com"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://stripe.com')

Python Microlink API example

import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://stripe.com"
}

response = requests.get(url, params=querystring)

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://stripe.com"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body

PHP Microlink API example

<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://stripe.com"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}

Golang Microlink API example

package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://stripe.com")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
For the full field list, palette, screenshot, filter, and the security model, see metadata API with custom HTML/CSS.

Why prompt your assistant instead of using the SDK

  • No bundle cost. No SDK install, no peer dependencies (react, react-dom, styled-components).
  • Matches your design system exactly. Your assistant already knows your tokens, components, and conventions — let it use them.
  • Server-renderable. The result is plain HTML/JSX, so it works in SSR, RSC, static sites, emails, and Markdown.
  • Easy to evolve. When the design system changes, regenerate the card with the same prompt — no SDK upgrade dance.

The base prompt

Paste this into Cursor, Claude Code, or your IDE's AI assistant before asking for a specific style. It establishes the contract once.
I want to add link previews to this project without installing the
Microlink SDK. Instead, fetch the metadata directly from the API:

  GET https://api.microlink.io?url=<TARGET_URL>

The response is JSON with `data` containing at least:
  - data.title         (string)
  - data.description   (string)
  - data.publisher     (string)
  - data.url           (string, canonical)
  - data.image.url     (string, og:image)
  - data.logo.url      (string, favicon / brand mark)
  - data.author        (string | null)

Generate a preview component that:

  1. Reads those fields from `data`.
  2. Uses *this project's* design system — same components, tokens,
     spacing, typography, and theming primitives I already use here.
     Do not invent new design tokens. Do not use inline styles when
     the project already has CSS modules / Tailwind / styled-components.
  3. Handles the case where image, logo, description, or publisher
     are missing — render a graceful fallback, never a broken `<img>`.
  4. Stays accessible: anchor wraps the whole card with `rel="noopener
     noreferrer"`, decorative images use empty alt, the title is a
     real heading.

When I ask for a specific style (hero card, one-line, chat bubble,
tweet-style, notification, telegram-style), apply that layout while
keeping the rules above.
The prompt is intentionally framework-agnostic. Your assistant adapts it to React + Tailwind, Vue + CSS modules, Astro, Svelte, plain HTML — whatever the open project is using.

Pick a style and ask for it

Each section below describes the layout, when it fits, the prompt to send, and a reference output. The reference is a starting point — your assistant should rewrite it in your project's idioms.

Hero card

A full-bleed image with publisher, title, and description below. Best when the link is the focus of the section.
Prompt to send: "Generate a hero-style preview using the contract above. Image fills the top with a 16:9 ratio, then publisher (with logo), title, and a 3-line clamped description below. Match the card chrome and elevation we already use for other content cards in this project."
Rendered with stripe.com as the source:
Stripe
Financial Infrastructure to Grow Your Revenue
Join the millions of companies of all sizes that use Stripe online and in person to accept payments, send payouts, automate financial processes, and ultimately grow revenue.
The shape your assistant should produce — image at the top, publisher + title + clamped description below.

One-line

Compact, scannable, and fits inside dense layouts. Good for search results, footnotes, and sidebars.
Prompt to send: "Generate a one-line preview using the contract above. Logo, publisher (bold), title (truncated), and the bare hostname on the right, all on a single row. Reuse the row primitives we already have for list items in this project."
Rendered with stripe.com as the source:
StripeFinancial Infrastructure to Grow Your Revenuestripe.com
Logo, publisher, title, and hostname collapsed to a single dense row.

Tweet-style

Vertical card with image-on-top, big title, big description — fits social-feed clones, comment threads, and replies.
Prompt to send: "Generate a tweet-style preview using the contract above. Round avatar from logo at the top with publisher and a fake @handle from the hostname, then the title as the post body, then a rounded media image. Use the radii and avatar utilities we already have."
Rendered with stripe.com as the source:
m
Microlink@microlinkhq · 2h
Embed any URL with rich previews — try it with stripe.com
stripe.com
Financial Infrastructure to Grow Your Revenue
Join the millions of companies of all sizes that use Stripe online and in person to accept payments, send payouts, automate financial processes, and ultimately grow revenue.
24 188 1.2k
Avatar + @handle header, post body, embedded link card, action bar — the full embedded-tweet shape.

Telegram-style

A quoted reply with a colored accent bar pulled from the source's brand palette. Each card adapts to the link.
Prompt to send: "Generate a telegram-style preview using the contract above. Add palette: true to the metadata request so I get brand colors. Use a vertical accent bar on the left, colored with data.image.palette[0], and tint the publisher line with the same color. Make sure the contrast pair (background_color + color) is respected for readability."
Rendered with stripe.com as the source:
Stripe
Financial Infrastructure to Grow Your Revenue
Join the millions of companies of all sizes that use Stripe online and in person to accept payments, send payouts, automate financial processes, and ultimately grow revenue.
Accent bar pulled from data.image.palette[0] — every link automatically tints itself to the source brand.
This recipe needs palette: true. See palette reference.

Notification

Short, glanceable item designed for activity feeds, toasts, and push-style components.
Prompt to send: "Generate a notification-style preview using the contract above. A small logo on the left, title and publisher in the middle, and a primary-colored 'Open' link on the right. Reuse the toast / activity-row component we already have."
Rendered with stripe.com as the source:
Stripenow
Financial Infrastructure to Grow Your Revenue
Join the millions of companies of all sizes that use Stripe online and in person to accept payments, send payouts, automate financial processes, and ultimately grow revenue.
iOS-style notification — logo, publisher + timestamp, then the link title and a short description.

Chat bubble

Inline, conversational citation — the right pattern for AI chat products and comment threads.
Prompt to send: "Generate a chat-bubble citation using the contract above. A short text line referencing the publisher, then a pill-shaped link with a tiny logo and the title (truncated). Match the chat bubble we already render for AI responses in this project."
Rendered with stripe.com as the source:
Financial Infrastructure to Grow Your Revenue
Join the millions of companies of all sizes that use Stripe online and in person to accept payments, send payouts, automate financial processes, and ultimately grow revenue.
Check this webpage! stripe.com
12:34✓✓
WhatsApp-style bubble with an embedded link card and a clickable URL line — drop it into a chat thread as-is.

Wire it up

Once your assistant has generated the markup, you only need a minimal data-fetching helper. Drop one of these into the project and the preview is ready to render.

Server / RSC / build-time

import mql from '@microlink/mql'

export async function getPreview (url, options = {}) {
  const { data } = await mql(url, { palette: true, ...options })
  return data
}
// app/components/LinkPreview.tsx (Next.js RSC example)
import { getPreview } from '@/lib/preview'

export async function LinkPreview ({ url }) {
  const data = await getPreview(url)
  return /* the JSX your assistant generated, reading from `data` */
}

Client-side

import { useEffect, useState } from 'react'

export function useLinkPreview (url) {
  const [data, setData] = useState(null)
  useEffect(() => {
    let cancelled = false
    fetch(`https://api.microlink.io?url=${encodeURIComponent(url)}&palette=true`)
      .then(r => r.json())
      .then(json => { if (!cancelled && json.status === 'success') setData(json.data) })
    return () => { cancelled = true }
  }, [url])
  return data
}

Direct from HTML

For static sites, README files, or markdown — skip the JSON entirely and use direct embed:
<img src="https://api.microlink.io?url=https://stripe.com&embed=image.url" alt="Stripe" />
See the embed reference for the full field list.

Theming with palette

Ask your assistant to make any recipe brand-aware once palette: true is on. The pattern:
const { data } = await mql(url, { palette: true })

card.style.setProperty('--brand', data.image.background_color)
card.style.setProperty('--brand-text', data.image.color)
card.style.setProperty('--brand-accent', data.image.palette[0])
The contrast pair (background_color + color) is WCAG-checked, so foreground text stays readable. See palette reference.

When og:image is missing

Some pages don't expose a usable image. Tell your assistant to fall back to a real screenshot:
const { data } = await mql(url, { screenshot: true, palette: true })
const heroImage = data.image?.url ?? data.screenshot.url
Or use embed=screenshot.url directly inside an <img src>. See the screenshot guide.

Iterate with your assistant

The recipes above are starting points. Once the first card is in your codebase, ask your assistant for variations without repeating the contract:
  • "Make the hero card horizontal, image on the left, content on the right."
  • "Tighten the one-line variant for our sidebar — drop the description and switch to our --text-xs token."
  • "Add a hover state matching how our other clickable cards lift on hover."
  • "Animate the entry with the same enter transition we use on toasts."
Because the AI is editing files in your repo, it can reuse hooks, mixins, utility classes, and component composition you already have — so the previews stay coherent as the codebase evolves.

Next step

For optimizing repeat embed calls (especially when an AI agent fans out across many URLs), see caching and performance.