Cellpy/Docs
Pricing

Welcome to Cellpy Docs

Everything you need to embed, author, and publish reusable web content blocks.

Cellpy is a CDN-powered block platform. A developer places one embed tag on a page once. After that, the marketing or design team assigns, swaps, and themes blocks from the dashboard — no code changes, no redeploys.

Developer Tools
New to Cellpy? The fastest path: install the runtime for your framework → copy the embed tag from your dashboard container → ask Claude to create your first block.

Getting Started

Quick Start

Add Cellpy to any site in under five minutes.

Cellpy uses the <cellpy-block> HTML custom element. A developer places it once; the block assigned to it can be swapped or updated from the dashboard without touching code.

1
Create a container in the dashboard

Go to Containers → New container. Give it a slug (e.g. homepage-hero). A container is the permanent embed slot on your page — the block assigned to it can change any time.

2
Install for your framework

Pick your framework below for a full guide, or use the CDN script for plain HTML:

bash
# React / Vue / Svelte — install the framework wrapper
npm install @cellpy/react   # or @cellpy/vue / @cellpy/angular / @cellpy/runtime (Svelte)

# Plain HTML — no install needed, just add a script tag
3
Embed the block tag
html
<!-- Place this wherever the block should render.
     The slug matches the container slug from your dashboard. -->
<cellpy-block slug="homepage-hero"></cellpy-block>
4
Assign a block and publish

In the dashboard, assign a saved block to your container and click Publish. The embed tag on your live page starts rendering it immediately — no redeploy needed.


Framework Guides

React

Use the official React wrapper or the web component directly in JSX.

1
Install the package
bash
npm install @cellpy/react
2
Import and use CellpyBlock

The CellpyBlock component renders your block inside an isolated Shadow DOM. Pass the container slug you set in the dashboard.

tsx
import { CellpyBlock } from '@cellpy/react'

export function MyPage() {
  return (
    <main>
      <CellpyBlock slug="homepage-hero" />

      {/* Override CSS variables for theming */}
      <CellpyBlock
        slug="cta-banner"
        style={{ '--cellpy-primary': '#e11d48' } as React.CSSProperties}
      />
    </main>
  )
}
3
Optional: use the web component directly

React 19 handles custom elements natively. You can use the raw tag if you prefer:

tsx
// React 19+ — custom elements work without a wrapper
<cellpy-block slug="homepage-hero" />

// React 18 — declare the element type to avoid TS errors:
declare global {
  namespace JSX {
    interface IntrinsicElements {
      'cellpy-block': React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & { slug: string },
        HTMLElement
      >
    }
  }
}
The runtime script is loaded automatically by the package — nothing to add to _document.tsx or layout.tsx.

Framework Guides

Vue

Use the official Vue plugin or the web component directly in templates.

1
Install the package
bash
npm install @cellpy/vue
2
Register the plugin
ts
// main.ts
import { createApp } from 'vue'
import { CellpyPlugin } from '@cellpy/vue'
import App from './App.vue'

createApp(App).use(CellpyPlugin).mount('#app')
3
Use CellpyBlock in templates
vue
<template>
  <main>
    <CellpyBlock slug="homepage-hero" />

    <!-- Theme override via style binding -->
    <CellpyBlock slug="cta-banner" :style="{ '--cellpy-primary': '#e11d48' }" />
  </main>
</template>
Vue's compiler is configured automatically by the plugin to allow the cellpy-block custom element without warnings.

Framework Guides

Angular

Embed blocks using the custom element with schema support.

1
Install the package
bash
npm install @cellpy/angular
2
Add CUSTOM_ELEMENTS_SCHEMA
ts
// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
import { CellpyModule } from '@cellpy/angular'

@NgModule({
  imports: [CellpyModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}

// ── standalone components ──────────────────────
// app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideCellpy } from '@cellpy/angular'

export const appConfig: ApplicationConfig = {
  providers: [provideCellpy()],
}
3
Use in templates
html
<cellpy-block slug="homepage-hero"></cellpy-block>

<!-- Bind a dynamic slug -->
<cellpy-block [attr.slug]="blockSlug"></cellpy-block>

Framework Guides

Svelte

Svelte handles web components natively — minimal setup required.

1
Install the runtime
bash
npm install @cellpy/runtime
2
Import once in your root layout
ts
// src/routes/+layout.ts  (SvelteKit)
import '@cellpy/runtime'
3
Use directly in Svelte templates
svelte
<script>
  let slug = 'homepage-hero'
</script>

<cellpy-block {slug} />

<!-- Reactive + themed -->
<cellpy-block slug={slug} style="--cellpy-primary: #e11d48" />
Svelte supports custom elements natively — no wrapper or type declaration needed for cellpy-block.

Framework Guides

HTML / Native

Drop a script tag and the custom element anywhere — no build step required.

1
Add the runtime script

Add this once in the <head> of your page or global template.

html
<script src="https://cdn.cellpy.com/runtime.js" defer></script>
2
Place the element where the block should render
html
<cellpy-block slug="homepage-hero"></cellpy-block>

<!-- Theme via CSS variables on the element or any ancestor -->
<cellpy-block slug="cta-banner" style="--cellpy-primary: #e11d48;"></cellpy-block>
3
That's it

The runtime registers the <cellpy-block> custom element, fetches the latest published version from the CDN, and renders it inside an isolated Shadow DOM — no styles bleed in or out.

The slug attribute matches your container slug from the dashboard — not the block slug. The container is the permanent embed slot; the assigned block can change any time without touching your HTML.

For Designers & Marketers

Marketplace

Browse, preview, and install ready-made blocks from the Cellpy community.

The Marketplace is a library of pre-built blocks — hero sections, pricing cards, testimonial carousels, CTAs, and more. Install any block into your Workspace, customise it, and publish it to your containers.

1
Browse the Marketplace

Navigate to Marketplace in the dashboard sidebar. Filter by category or search by keyword. Click any card to preview the block live.

2
Install a block to your Workspace

Click Add to Workspace on any listing. The block appears in your Workspace where you can review the HTML and CSS before saving.

3
Customise with CSS variables

Every Marketplace block exposes CSS custom properties for theming. Override them from your page without editing the block source:

html
<cellpy-block
  slug="pricing-cards"
  style="
    --cellpy-primary: #6366f1;
    --cellpy-font-heading: 'Inter', sans-serif;
    --cellpy-radius: 12px;
  "
></cellpy-block>
4
Save and assign to a container

Click Save Block in the Workspace. Then open your container, assign the block, and publish — the live page updates immediately.

Marketplace blocks are immutably versioned. Installing copies a snapshot into your Workspace — future updates to the original listing do not affect your version unless you explicitly pull the update.

For Designers & Marketers

Creating Blocks with Claude

Describe a block in plain language — Claude designs it and pushes it to your Workspace.

Once the MCP server is connected, you can create production-ready blocks in a conversation. Claude generates HTML and CSS — isolated in Shadow DOM — and pushes it straight to your Workspace for review.

First time? Set up the Claude MCP connection in the Claude MCP guide.
1
Describe the block you need
"Create a Cellpy block — a pricing card for three tiers: Free, Pro at $29/mo, and Enterprise. Use an indigo accent color. The Pro card should be highlighted. Push it to my Cellpy Workspace."
2
Review in your Workspace

Open Workspace in the dashboard. The block appears with status pending. Click it to preview with live dimensions and inspect the generated HTML and CSS.

3
Iterate conversationally

Reply to Claude: "Make the card borders rounder and add a sparkle icon before each plan name." Claude pushes a revised version — the previous one stays in Workspace history.

4
Save and assign to a container

When satisfied, click Save Block. Assign it to a container — the embed tag on your live site updates immediately.

Ask Claude to expose CSS variables (e.g. --cellpy-primary, --cellpy-font) so your team can theme the block per-site without editing the source.

For Designers & Marketers

Claude Design App

Visual block authoring with live preview, then push to your Workspace.

Claude Design is a visual authoring environment built on top of Claude. It lets you create and edit Cellpy blocks with a live preview alongside the conversation — tweak layout, colors, and copy without leaving the tool.

1
Start a block in Claude Design
"Create a Cellpy block — a hero section with a headline, subtext, and a CTA button. Push it to my Cellpy Workspace."
2
Edit visually

Claude Design renders a live preview as it generates. Click elements in the preview and ask Claude to change specific parts — "make this heading larger", "softer background" — or edit the HTML and CSS directly in the code panel.

3
Working with images

Claude Design cannot access your files. When a block needs an image, Claude inserts a stub placeholder instead of the real one.

To replace a stub with your real image, open the block in Cellpy Workspace and double-click the placeholder. An image picker lets you upload or paste a URL.
4
Push to Workspace and publish

Ask Claude to push it: "Push this block to my Cellpy Workspace." Swap stub images, click Save Block, then assign to a container to go live.


For Designers & Marketers

Block Validation Rules

Every block is validated before it reaches your Workspace. Here are all the restrictions, requirements, and what each trust tier allows.

Cellpy validates every block pushed via the MCP server, VS Code Extension, or the Workspace UI against a set of safety rules called principles. Rules marked error block the push entirely; rules marked warning let the block through but surface a notice in Workspace. Your account's trust level determines which principles apply.

Trust Levels
Public

Community-submitted blocks. All 9 principles apply.

Verified

Established creators. P7 Marketplace content rules are skipped.

Private

Internal / white-label use. P3–P7 are all relaxed.

All Principles at a Glance
#PrincipleEnforcementApplies to
P1
Self-Contained CSS
No body, html, *, :root, or :host-context selectors
errorAll levels
P2
No Script Execution
No <script>, event handlers, or javascript: URIs
errorAll levels
P3
No Layout Escaping
No position:fixed, viewport units, or top:0 + left:0 together
errorPublic + Verified
P4
Z-Index Limit
z-index must not exceed 100
errorPublic + Verified
P5
Resource Budgets
HTML ≤1MB, CSS ≤50KB, images ≤20, per-image ≤1MB, DOM nodes ≤500
errorPublic + Verified
P6
Animation Limits
Infinite animations on full-size elements are rejected
warningPublic + Verified
P7
Marketplace Content
No deceptive inputs; phishing phrases trigger human review
errorPublic only
P8
Version Immutability
Published versions can never be overwritten
errorAll levels
P9
Explicit Data Inputs
{{token}} placeholders must be declared in block.properties
warningAll levels
P1Self-Contained CSSerrorAll levels

CSS must not use selectors that affect the host page. Blocks render inside a Shadow DOM — all styles must be scoped to the block itself using :host or class selectors.

Forbidden
css
body { color: red; }
html { font-size: 16px; }
* { box-sizing: border-box; }
:root { --x: 1; }
:host-context(.dark) { color: white; }
Allowed
css
:host { display: block; }
.hero { padding: 40px; }
h2 { font-size: 2rem; }
.card:hover { opacity: 0.9; }
P2No Script ExecutionerrorAll levels

Blocks are static HTML + CSS — no JavaScript execution is permitted. All of the following are rejected:

  • Tags: <script> <iframe> <object> <embed> <form> <base> <meta http-equiv> <link rel="import">
  • Inline event handlers: onclick, onmouseover, onerror, and any other on* attribute
  • URI schemes: javascript: and data:text/html
  • Attribute: srcdoc
html
<!-- Forbidden -->
<script>alert(1)</script>
<iframe src="https://evil.com"></iframe>
<button onclick="steal()">Click</button>
<a href="javascript:void(0)">Nope</a>

<!-- Allowed -->
<section class="hero">
  <h1>Hello world</h1>
  <a href="https://example.com" target="_blank" rel="noopener">Learn more</a>
  <button type="button">CTA</button>
</section>
P3No Layout EscapingerrorPublic + Verified

Blocks must stay within their container boundaries and cannot break out of the host page's layout.

  • position: fixed — always forbidden
  • position: sticky — only permitted for block types sticky-header and sticky-cta on public/verified accounts
  • width: 100vw, height: 100vh, width: 100dvw, height: 100dvh — forbidden; use 100% or relative units instead
  • top: 0 and left: 0 together in the same CSS rule — forbidden without explicit positioning context
Forbidden
css
.overlay {
  position: fixed;
  width: 100vw;
  height: 100vh;
}
Allowed
css
.hero {
  position: relative;
  width: 100%;
  max-width: 1200px;
}
Private accounts are exempt from P3. All layout restrictions are relaxed for internal / white-label blocks.
P4Z-Index LimiterrorPublic + Verified

Z-index values must not exceed 100. This prevents blocks from overlapping the host page's navigation, modals, or other UI elements. z-index: auto and z-index: inherit are always permitted.

Forbidden
css
z-index: 9999;
z-index: 1000;
z-index: 101;
Allowed
css
z-index: 10;
z-index: 100; /* maximum */
z-index: auto;
P5Resource BudgetserrorPublic + Verified

Blocks must stay within resource limits to ensure fast load times on any host page.

ResourceLimit
HTML size1 MB
CSS size50 KB
Total number of images20
Single image size (decoded)1 MB
Estimated DOM nodes500
Private accounts are exempt from all resource budget limits.
P6Animation LimitswarningPublic + Verified

Infinite CSS animations can drain CPU on host pages. Two tiers of enforcement apply:

  • Error (blocks push): animation-iteration-count: infinite on an element that also declares width: 100% or height: 100%
  • Warning (non-blocking): animation-iteration-count: infinite anywhere else — the block is accepted but Workspace shows a notice
Prefer finite iteration counts (animation-iteration-count: 3) or respect user preferences with @media (prefers-reduced-motion).
P7Marketplace Content RuleserrorPublic only

Public Marketplace blocks must not contain deceptive content. Two categories of checks run:

Rejected — blocks the push
  • Input fields with type="password" or type="credit-card"
  • Input fields with name="cc", name="card", or name="ssn"
Flagged for human review
  • Any of these phrases in the HTML text: "enter your password", "sign in to continue", "payment information", "verify your identity"
Verified and private accounts are exempt from P7 — these rules only apply to public Marketplace submissions.
P8Version ImmutabilityerrorAll levels

Once a block version is published it can never be overwritten. Every save creates a new immutable version. This guarantees that any site embedding a specific version always renders exactly what was reviewed and approved.

This rule is enforced at the API layer. Pushing an update to an existing slug always creates a new version — the previous published version is never modified.
P9Explicit Data InputswarningAll levels

Any {{token}} placeholder used in the block HTML must be declared in block.properties. Undeclared placeholders produce a non-blocking warning — the block is accepted but the runtime will render the raw placeholder string instead of a value.

Warning — undeclared
html
<!-- {{userName}} used but missing
     from block.properties -->
<h1>Hello, {{userName}}</h1>
Correct
json
{
  "html": "<h1>Hello, {{name}}</h1>",
  "properties": {
    "name": {
      "type": "string",
      "default": "World"
    }
  }
}
P10Trust Levels

Your account's trust level is set by Cellpy. It controls which principles apply. Higher trust unlocks fewer restrictions for advanced use cases — contact support to request a trust-level upgrade.

PrinciplePublicVerifiedPrivate
P1 — CSS Scoping
P2 — No Script Execution
P3 — No Layout Escaping
P4 — Z-Index Limit
P5 — Resource Budgets
P6 — Animation Limits
P7 — Marketplace Content
P8 — Immutability
P9 — Data Inputs

Configuration

Custom Block Storage

Serve your block files directly from your own cloud storage — AWS S3, Azure Blob Storage, or Cloudflare R2.

By default, Cellpy stores and serves your block content from its own CDN infrastructure. With a Pro plan or above, you can point Cellpy to your own storage bucket instead. When configured, block HTML and CSS are uploaded exclusively to your bucket — Cellpy only stores a URL pointer and never holds your content.

Your data stays yours

Block content is uploaded to your bucket at assign time. Cellpy holds only a URL pointer — no content copy on Cellpy infrastructure.

Two-hop serving

The runtime fetches a lightweight container JSON from Cellpy's CDN, then fetches the block file directly from your storage — browser to your bucket.

Lazy migration

Re-assigning a container automatically migrates older block versions to your storage, so you don't need to republish.

Configurable path template

Control the filename pattern for block files, e.g. {blockId}-v{version}.json or blocks/{accountSlug}/{blockId}.json.

Custom storage requires a Pro plan or above. Go to Account → Storage in the dashboard to configure it after upgrading.
How it works

When you assign a block to a container with own storage configured:

  1. The block HTML and CSS are uploaded to your storage bucket as a JSON file.
  2. Cellpy writes a lightweight container JSON to its CDN containing only { "url": "https://your-bucket/..." }.
  3. When a visitor loads your page, the <cellpy-block> runtime fetches the container JSON from Cellpy's CDN, reads the URL, then fetches the block file directly from your storage.
Your storage bucket must allow public GET requests from any origin (CORS). The runtime fetches block files directly in the browser — no server-side proxy.
Setting up AWS S3

Follow these steps to create and configure an S3 bucket for Cellpy block storage.

1
Create an S3 bucket

In the AWS Console, go to S3 → Create bucket. Choose:

  • Bucket type: General purpose
  • Bucket name: something descriptive, e.g. my-company-cellpy-blocks
  • Region: closest to your users
  • Block all public access: uncheck the top checkbox and acknowledge — block files must be publicly readable
Unchecking "Block all public access" does not immediately expose anything. You still control access via the bucket policy in the next step.
2
Add a bucket policy for public read

In your bucket, go to Permissions → Bucket policy and paste:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
    }
  ]
}

Replace YOUR-BUCKET-NAME with your actual bucket name. This allows any browser to fetch block files by URL — required for the runtime's direct fetch.

3
Configure CORS

In Permissions → Cross-origin resource sharing (CORS), paste:

json
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET"],
    "AllowedOrigins": ["*"],
    "ExposeHeaders": []
  }
]

This permits browsers on any domain to fetch block files. If you want to restrict to specific domains, replace "*" in AllowedOrigins with your site URLs.

4
Create an IAM user with S3 write access

Cellpy needs credentials to upload block files. Create a dedicated IAM user:

  1. Go to IAM → Users → Create user. Name it e.g. cellpy-blocks-writer.
  2. On the permissions step, choose Attach policies directly and search for AmazonS3FullAccess.
  3. For tighter permissions, create a custom inline policy instead:
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
    }
  ]
}
5
Generate an access key

On the IAM user page, go to Security credentials → Create access key. Select Application running outside AWS. Download or copy:

  • Access key ID
  • Secret access key — only shown once, save it now
Store the secret access key securely. You cannot retrieve it again after closing the dialog.
6
Configure storage in the Cellpy dashboard

In the Cellpy dashboard, go to Account → Storage and fill in:

  • Storage type: Amazon S3
  • Bucket name: your bucket name (e.g. my-company-cellpy-blocks)
  • Region: AWS region code, e.g. us-east-1
  • Access key ID and Secret access key from the previous step
  • Base URL: your bucket's public URL, e.g. https://my-company-cellpy-blocks.s3.us-east-1.amazonaws.com
  • Path template (optional): defaults to {blockId}-v{version}.json

Click Save configuration, then Verify connection. Cellpy uploads a test file to your bucket and fetches it from the public URL to confirm both write access and public read access are working.

7
Set your account slug

Your account slug appears in all CDN URLs and must be set before embedding blocks. Go to Account settings and update the Account slug field to something that represents your brand — e.g. my-company.

The slug is auto-generated from your email address at signup. Change it before assigning blocks. If you change it later, you will need to re-assign all containers — existing container URLs will break until you do.

In your site code, tell the runtime where to resolve container JSON. Set window.CELLPY_CDN before registering <cellpy-block>. The value depends on whether you have a custom CDN domain:

js
// Option A — Cellpy shared CDN (default, account slug in path)
window.CELLPY_CDN = 'https://cdn.cellpy.com/my-company'

// Option B — your own custom CDN domain (configured in Account → Domains)
// The domain itself identifies your account — no slug needed in the path
window.CELLPY_CDN = 'https://cdn.my-company.com'

// Then register the element (Vue / Svelte / vanilla JS)
import { CellpyBlock } from '@cellpysdk/runtime'
customElements.define('cellpy-block', CellpyBlock)
If you use the <script> CDN tag instead of the npm package, add a data-cdn attribute: <script src="https://cdn.cellpy.com/runtime.js" data-cdn="https://cdn.my-company.com" defer></script>
8
Assign a block and verify

Go to Assign, select a container and a published block version, and click assign. Cellpy will upload the block JSON to your S3 bucket and update the container pointer. Check your bucket in the AWS Console — you should see a file matching your path template within seconds.

Path template reference

The path template controls the key (filename) used when uploading block files to your bucket. Available tokens:

TokenReplaced withExample
{blockId}Block slugmy-hero-section
{version}Version number3
{accountSlug}Your account slugmy-company

Examples:

text
{blockId}-v{version}.json          →  my-hero-section-v3.json  (default)
blocks/{blockId}/v{version}.json   →  blocks/my-hero-section/v3.json
{accountSlug}/{blockId}-v{version}.json  →  my-company/my-hero-section-v3.json
AWS Free Tier considerations

AWS S3 Free Tier includes 5 GB storage, 20,000 GET requests, and 2,000 PUT requests per month for the first 12 months. After that, standard pricing applies.

Each page load triggers one GET request per <cellpy-block> element. A page with 5 blocks visited by 4,000 unique users per month = 20,000 GET requests — exactly at the Free Tier ceiling. For high-traffic pages, use Cloudflare R2 (no egress fees, no GET request charges) or budget for S3 costs.

Configuration

Let Claude find freely-licensed stock photos from Pexels and Pixabay while designing blocks.

When you use the Claude Design tool to create or edit a block, Claude can call a built-in photo_search tool to discover and embed stock photos automatically. This tool queries Pexels and Pixabay — both are free services. You only need to supply your own API keys so requests go under your account's quota.

Free tier

Both Pexels and Pixabay offer free API access with generous rate limits — no credit card required.

High quality

All photos are royalty-free and suitable for commercial use under their respective licenses.

No quota sharing

Using your own keys means your searches don't count against shared infrastructure limits.

Optional setup

Photo Search works only when at least one key is configured. You can add either or both services.

Configure your keys at Settings → API Keys in the Cellpy dashboard. Both fields are optional — Claude will query whichever services have a key configured.
Getting a Pexels API Key

Pexels offers a free API with up to 200 requests per hour and 20,000 per month on the free plan.

1
Create a Pexels account

Go to pexels.com and click Join. You can sign up with an email address or continue with Google. Verify your email address if prompted.

2
Open the API page

After signing in, navigate to pexels.com/api. Click the Your API Key button, or go directly to your account image menu in the top right → Image & Video API.

3
Apply for API access

Fill in the short application form:

  • First & Last Name
  • Where will you use the API? — choose Website or Other
  • Description — e.g. "AI-assisted block design in Cellpy"
  • Check the boxes to agree to the API guidelines

Click Get API Key. Approval is instant for most accounts.

4
Copy your API key

Your API key is shown immediately after approval. It looks like a long alphanumeric string, e.g. Kvq4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. Copy it now.

You can always retrieve your Pexels API key again from the same Image & Video API page — it does not expire and is always visible in your account.
5
Add the key to Cellpy

In the Cellpy dashboard, go to Settings → API Keys, paste your key into the Pexels API Key field, and click Save keys.

Getting a Pixabay API Key

Pixabay's free API gives access to over 4 million images and videos, with up to 100 requests per minute and 5,000 per day on the free plan.

1
Create a Pixabay account

Go to pixabay.com and click Join. Register with an email address or sign in with Google. Confirm your email if required.

2
Go to the API documentation page

After signing in, navigate to pixabay.com/api/docs. Your personal API key is displayed at the top of the page, embedded in the example request URL.

3
Copy your API key

The key appears inside the example URL in a format like: https://pixabay.com/api/?key=12345678-abcdef1234567890abcdef12&q=…. Copy only the key portion (the part after key= and before &).

You can also find your key at any time from your Pixabay account page under API or by revisiting pixabay.com/api/docs while signed in.
4
Add the key to Cellpy

In the Cellpy dashboard, go to Settings → API Keys, paste your key into the Pixabay API Key field, and click Save keys.

Verifying the setup

Once you've saved at least one key, open the Claude Design tool and ask Claude to create a block that includes a photo — for example:

text
Create a hero section with a photo of mountains at sunset

Claude will call photo_search automatically, retrieve matching images, and embed the best match in the block. If no key is configured, Claude will instead use a placeholder or an inline SVG.

You don't need both keys. Adding just one service is enough for photo search to work. Adding both gives Claude more images to choose from and provides a fallback if one service's quota is exhausted.