If you have a hand-built site — static HTML, static site generator (Hugo, Jekyll, Eleventy, Astro), or your own backend — picpins works directly. Two lines of code, no platform restrictions.
Full control: CSS, CSP, multi-embed, performance — all in your hands.
Upload a photo, place markers, fill tooltips. Done.
Copy the two-line HTML from the picpins dashboard.
Directly in the <body> at the desired position. Save, deploy.
This is the simplest case: you have full text access to your HTML code. Embed code at the desired position, save the file, deploy the server. No filters, no editor workarounds.
Open the HTML file (e.g. index.html) in your editor. At the position where the interactive image should appear, paste the embed code — typically in the <body> area, in a container of your choice.
The <script> tag with async can sit at the same position or be moved to the end of <body> classically — both work.
For Markdown-based SSGs simply paste the embed code in the Markdown file — most renderers allow raw HTML+JS in Markdown.
For Astro: directly in the .astro file as JSX-like markup. For Eleventy: in Liquid or Nunjucks templates. For Hugo: in partials or directly in Markdown content.
If you use embeds on many pages: load the script once in the <head> or at the end of <body> of your global layout (_layouts/default.html, BaseLayout.astro etc.). On individual pages only the <div class="picpins-embed"> container is needed.
If your web server sends a CSP header (e.g. via nginx, Cloudflare, or Helmet on Node.js): make sure script-src allows the domain picpins.com, and img-src too (for image rendering).
Example CSP directive:
script-src 'self' https://picpins.com;
img-src 'self' https://picpins.com data:;
connect-src 'self' https://picpins.com;API or tool screenshot with markers on every endpoint or button. Documentation people actually read.
Project hero, markers with tools, stack, live link. Statically generated, fast as the wind.
Code screenshot with hotspots on lines explaining, performance notes, alternative approaches.
In your SaaS app: help center with screenshots, hotspots on UI elements with inline explanation.
script-src and img-src for picpins.com.file:// — use a local server (e.g. npx serve) instead.No. Any web server (Apache, Nginx, IIS, Caddy, static hosting on Netlify/Vercel/Cloudflare Pages) works. The picpins embed is client-side JavaScript, the server only needs to serve the HTML file.
Yes, with all common ones: Hugo, Jekyll, Eleventy, Gatsby, Next.js (Static), Astro, Nuxt (Static), Hexo, Pelican. Paste the embed code in the template or Markdown, run the build, deploy.
Works there too. In the component code render the <div class="picpins-embed"> container. Load the script tag either globally in index.html or via a useEffect hook in React (or lifecycle hook in Vue) dynamically when the component mounts.
If your site sets a CSP, you need to allow picpins.com in script-src and img-src. Otherwise the browser blocks the script and image rendering. Without CSP headers no extra configuration needed.
The script loads once (if you do not accidentally include it multiple times), then all .picpins-embed containers initialize automatically. Performance impact per additional image is marginal because only tooltip data and image URL load lazily.
Locally with file:// protocol it does not work — the browser blocks JavaScript cross-origin requests. Use local server tools like npx serve, Python http.server, or Webpack Dev Server and access via localhost.
Then the script does not load and the embed container stays empty. picpins is built for high availability, but for maximum resilience you can place a static image with the same aspect ratio as fallback in the container — shown when the embed script does not load.
The initial HTML output contains the empty container and the script tag — that is unproblematic. The embed script runs client-side after hydration. For SEO that means: tooltip content is not in the SSR output, but container and script reference are crawlable.
Two lines of code, no plugin politics, no editor filters. That is how embeds should always be.