<div class="demo-row" id="cards"></div>
:root {
--bg: #ffffff;
--border: #e2e2e2;
--text: #1a1a1a;
--muted: #6b6b6b;
--accent: #3b5bfd;
--radius: 14px;
}
.demo-row {
display: flex;
flex-wrap: wrap;
gap: 24px;
max-width: 900px;
}
.site-card {
display: block;
width: 320px;
text-decoration: none;
color: var(--text);
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.site-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 24px rgba(0,0,0,0.08);
}
.site-card__screenshot-wrap {
width: 100%;
aspect-ratio: 16 / 10;
background: #ececec;
position: relative;
overflow: hidden;
}
.site-card__screenshot {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.site-card__skeleton {
position: absolute;
inset: 0;
background: linear-gradient(90deg, #ececec 25%, #f5f5f5 50%, #ececec 75%);
background-size: 200% 100%;
animation: shimmer 1.4s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.site-card__body {
padding: 14px 16px;
}
.site-card__header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.site-card__favicon {
width: 16px;
height: 16px;
flex-shrink: 0;
border-radius: 3px;
}
.site-card__title {
font-size: 15px;
font-weight: 600;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.site-card__description {
font-size: 13px;
color: var(--muted);
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
margin: 0;
}
.site-card__url {
margin-top: 8px;
font-size: 12px;
color: var(--accent);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.site-card--error .site-card__description {
color: #c0392b;
}
/**
* Crée une "Site Card" dynamique via l'API Microlink.
* @param {string} url - URL du site à prévisualiser
* @returns {HTMLAnchorElement}
*/
async function createSiteCard(url) {
const card = document.createElement('a');
card.className = 'site-card';
card.href = url;
card.target = '_blank';
card.rel = 'noopener noreferrer';
// Etat de chargement (skeleton)
card.innerHTML = `
`;
try {
const endpoint = `https://api.microlink.io/?url=${encodeURIComponent(url)}&screenshot=true&meta=true`;
const res = await fetch(endpoint);
const json = await res.json();
if (json.status !== 'success') {
throw new Error('Microlink a renvoyé une erreur');
}
const data = json.data;
const title = data.title || url;
const description = data.description || '';
const screenshotUrl = data.screenshot?.url || '';
const faviconUrl = data.logo?.url || data.publisher?.image?.url || '';
card.innerHTML = `
${screenshotUrl
? `

`
: `
`}
${escapeHtml(description)}
${url}
`;
} catch (err) {
card.classList.add('site-card--error');
card.innerHTML = `
Vérifie l'URL ou réessaie plus tard.
${url}
`;
}
return card;
}
function escapeHtml(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// --- Démo : ajoute autant d'URLs que tu veux ici ---
const urls = [
'https://anthropic.com',
'https://stripe.com',
'https://openai.com'
];
const container = document.getElementById('cards');
urls.forEach(async (url) => {
const card = await createSiteCard(url);
container.appendChild(card);
});