Made With Embed
atroui/made-with-embedFreeBlock
Credit badge + copyable HTML snippet with editable CONTENT.
Install it
npx shadcn@latest add https://atroui.com/r/made-with-embed.jsonSource
1"use client"23import { Check, Copy } from "lucide-react"4import { useCallback, useState } from "react"56import { getBrand } from "@/lib/brand"78/**9 * Edit CONTENT for badge link, image, and copy.10 * Set siteOrigin so the HTML snippet works before hydration.11 */12const CONTENT = {13 stamp: "Credit",14 headline: "Link back if it helped.",15 body: "Drop this badge on your site, README, or Notion footer. Free tools stay free when people share the source.",16 href: "/",17 /** Public URL or path to the badge image */18 badgeSrc: "/badge/atroui.svg",19 /** Used to absolutize relative href/badgeSrc in the snippet */20 siteOrigin: "https://www.atroui.com",21 badgeWidth: 160,22 badgeHeight: 40,23 snippetLabel: "HTML snippet",24 copyLabel: "Copy snippet",25 copiedLabel: "Copied",26}2728export type MadeWithEmbedProps = {29 href?: string30 badgeSrc?: string31 brandName?: string32 className?: string33}3435function absolutize(pathOrUrl: string, origin: string) {36 if (pathOrUrl.startsWith("http")) return pathOrUrl37 return `${origin.replace(/\/$/, "")}${pathOrUrl.startsWith("/") ? "" : "/"}${pathOrUrl}`38}3940export function MadeWithEmbed({41 href = CONTENT.href,42 badgeSrc = CONTENT.badgeSrc,43 brandName,44 className,45}: MadeWithEmbedProps) {46 const [copied, setCopied] = useState(false)47 const name = brandName ?? getBrand().name48 const alt = `Made with ${name}`49 const target = absolutize(href, CONTENT.siteOrigin)50 const snippetBadgeSrc = absolutize(badgeSrc, CONTENT.siteOrigin)51 const snippet = `<a href="${target}" target="_blank" rel="noopener noreferrer"><img src="${snippetBadgeSrc}" alt="${alt}" width="${CONTENT.badgeWidth}" height="${CONTENT.badgeHeight}" /></a>`5253 const copy = useCallback(async () => {54 try {55 await navigator.clipboard.writeText(snippet)56 setCopied(true)57 window.setTimeout(() => setCopied(false), 2000)58 } catch {59 setCopied(false)60 }61 }, [snippet])6263 return (64 <div65 className={`grid gap-6 md:grid-cols-12 md:items-start ${className ?? ""}`}66 >67 <div className="md:col-span-5">68 <p className="text-[11px] font-semibold tracking-[0.14em] text-muted-foreground uppercase">69 {CONTENT.stamp}70 </p>71 <h2 className="mt-4 text-2xl font-medium tracking-tight text-foreground sm:text-3xl">72 {CONTENT.headline}73 </h2>74 <p className="mt-3 text-sm leading-relaxed text-muted-foreground">75 {CONTENT.body}76 </p>77 <a78 href={href}79// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from atroui
All 82 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analytics Provideranalytics-provider | atroui | Blocks | Free | 1 dep | |
| AR Portfolioar-portfolio | atroui | Blocks | Free | 1 dep | |
| Before / Afterbefore-after-slider | atroui | Blocks | Free | no deps | |
| Calendly Embedcalendly-embed | atroui | Blocks | Free | 1 dep | |
| Changelogchangelog | atroui | Blocks | Free | no deps | |
| Command Menucommand-menu | atroui | Blocks | Free | 4 deps | |
| Contact Formcontact-form | atroui | Blocks | Free | 2 deps | |
| Contextual CTAcontextual-cta | atroui | Blocks | Free | 2 deps |
