svelte-webflow-cms Svelte Themes

Svelte Webflow Cms

svelte-webflow-cms

A config-driven CMS table editor for managing Webflow collections with SvelteKit.

Features

  • Config-driven: Define your table structure with a simple configuration object
  • Change Tracking: Tracks all modifications and only enables save when changes exist
  • Batched Operations: Nothing is sent to Webflow until explicit "Save changes" click
  • Drag & Drop Sorting: Reorder items with automatic sort field updates
  • Image Handling: Client-side compression/cropping with pluggable storage backends
  • Hosting Agnostic: Works with any hosting platform (Cloudflare, Vercel, Netlify, etc.)
  • Field Validation: Required fields, length constraints, and numeric ranges with error feedback

Installation

bun add svelte-webflow-cms
# or
npm install svelte-webflow-cms

Requirements

  • SvelteKit 2.x
  • Svelte 5.x
  • Tailwind CSS v4
  • bits-ui ^2.0.0

Tailwind CSS Configuration

This library uses Tailwind CSS classes for styling. You must configure Tailwind to scan this package's files so the necessary CSS is generated.

Tailwind v4

Add a @source directive in your CSS file:

@import "tailwindcss";
@source "../node_modules/svelte-webflow-cms";

Quick Start

1. Create a config file

// src/routes/members/config.ts
import type { TableConfig } from "svelte-webflow-cms";

export const config: TableConfig = {
  pageTitle: "Team Members",
  itemSingular: "Member",
  itemPlural: "Members",
  siteId: "your-site-id",
  collectionId: "your-collection-id",
  createDeleteEnabled: true,
  draftEnabled: true,
  fields: [
    {
      visible: true,
      editable: true,
      required: true,
      schema: {
        name: "Name",
        slug: "name",
        type: "PlainText",
        validations: { maxLength: 100 },
      },
    },
    {
      visible: true,
      editable: true,
      schema: {
        name: "Photo",
        slug: "photo",
        type: "Image",
        imageSettings: { width: 400, height: 400 },
      },
    },
  ],
};

2. Set up page server

// src/routes/members/+page.server.ts
import { createCmsActions, loadCmsItems } from "svelte-webflow-cms/server";
import { createR2UploadProvider } from "svelte-webflow-cms/providers/r2";
import { config } from "./config";

export async function load({ platform }) {
  const token = platform?.env?.WEBFLOW_TOKEN;
  if (!token) return { items: [], error: "Token not found" };

  const { items, error } = await loadCmsItems(token, config);
  return { items, error };
}

export const actions = createCmsActions(config, {
  getToken: (_, platform) => platform?.env?.WEBFLOW_TOKEN ?? null,
  getUploadProvider: (_, platform) =>
    platform?.env?.TEMP_IMAGES
      ? createR2UploadProvider(
          platform.env.TEMP_IMAGES,
          "https://cdn.example.com"
        )
      : null,
  bucketPrefix: "members",
});

3. Create page component

<!-- src/routes/members/+page.svelte -->
<script lang="ts">
  import { CmsTable } from 'svelte-webflow-cms';
  import { config } from './config';

  let { data } = $props();
</script>

<CmsTable.Root {config} data={data.items}>
  <CmsTable.Toolbar />
  <CmsTable.SaveBar />
  <CmsTable.Table>
    <CmsTable.Header />
    <CmsTable.Body />
  </CmsTable.Table>
</CmsTable.Root>

Composable API

The CmsTable components follow a composable pattern (similar to shadcn-svelte), allowing you to customize and extend the table easily.

Basic Usage

<script>
  import { CmsTable } from 'svelte-webflow-cms';
</script>

<CmsTable.Root {config} data={data.items} referenceData={data.referenceData}>
  <CmsTable.Toolbar />
  <CmsTable.SaveBar />
  <CmsTable.Table>
    <CmsTable.Header />
    <CmsTable.Body />
  </CmsTable.Table>
</CmsTable.Root>

Available Components

Component Description
CmsTable.Root Root wrapper - provides context and state
CmsTable.Toolbar Title and add button
CmsTable.SaveBar Save/cancel controls with validation display
CmsTable.Table Table container
CmsTable.Header Table header row with field names
CmsTable.Body Table body with drag-and-drop support
CmsTable.Row Individual row (used in custom row templates)
CmsTable.Actions Actions column (live toggle and delete button)
CmsTable.Cell Field cell with input (used in custom rows)

Customization Examples

Custom Toolbar with Badge

<CmsTable.Root {config} data={data.items}>
  <CmsTable.Toolbar>
    {#snippet afterTitle()}
      <Badge variant="secondary">{data.items.length} items</Badge>
    {/snippet}
  </CmsTable.Toolbar>
  <CmsTable.SaveBar />
  <CmsTable.Table>
    <CmsTable.Header />
    <CmsTable.Body />
  </CmsTable.Table>
</CmsTable.Root>

Custom Actions Placement

<CmsTable.Root {config} data={data.items}>
  <div class="flex items-center justify-between">
    <CmsTable.Toolbar showAddButton={false} />
    <div class="flex gap-2">
      <Button onclick={handleExport}>Export</Button>
      <CmsTable.SaveBar />
    </div>
  </div>
  <CmsTable.Table>
    <CmsTable.Header />
    <CmsTable.Body />
  </CmsTable.Table>
</CmsTable.Root>

Custom Column in Header

<CmsTable.Table>
  <CmsTable.Header>
    {#snippet afterColumns()}
      <Table.Head>Custom Column</Table.Head>
    {/snippet}
  </CmsTable.Header>
  <CmsTable.Body />
</CmsTable.Table>

Custom Row Template

<CmsTable.Body>
  {#snippet row({ item, index, isNew })}
    <CmsTable.Row {item} {index} {isNew}>
      {#snippet afterColumns()}
        <Table.Cell>
          <Badge>{item.status}</Badge>
        </Table.Cell>
      {/snippet}
    </CmsTable.Row>
  {/snippet}
</CmsTable.Body>

Styling with Classes

All components accept a class prop for custom styling:

<CmsTable.Root {config} data={data.items} class="max-w-7xl mx-auto">
  <CmsTable.Toolbar class="bg-gray-50 p-4 rounded-t-lg" />
  <CmsTable.SaveBar class="justify-start px-4" />
  <CmsTable.Table class="border-2 shadow-lg">
    <CmsTable.Header class="bg-blue-50" />
    <CmsTable.Body class="text-sm" />
  </CmsTable.Table>
</CmsTable.Root>

Upload Providers

The library supports pluggable storage backends. Implement the UploadProvider interface for your storage:

interface UploadProvider {
  upload(
    file: Blob,
    filename: string,
    contentType: string
  ): Promise<{ url: string; filename: string }>;
  delete(filename: string): Promise<void>;
}

Built-in: Cloudflare R2

import { createR2UploadProvider } from "svelte-webflow-cms/providers/r2";

getUploadProvider: (_, platform) =>
  createR2UploadProvider(platform.env.BUCKET, "https://cdn.example.com");

Custom Provider Example (S3)

export function createS3UploadProvider(
  client,
  bucket,
  baseUrl
): UploadProvider {
  return {
    async upload(file, filename, contentType) {
      await client.send(
        new PutObjectCommand({
          Bucket: bucket,
          Key: filename,
          Body: Buffer.from(await file.arrayBuffer()),
          ContentType: contentType,
        })
      );
      return { url: `${baseUrl}/${filename}`, filename };
    },
    async delete(filename) {
      await client.send(
        new DeleteObjectCommand({ Bucket: bucket, Key: filename })
      );
    },
  };
}

Token Configuration

The getToken function receives the request and platform at runtime:

// Cloudflare Pages
getToken: (_, platform) => platform?.env?.WEBFLOW_TOKEN ?? null;

// Node.js
getToken: () => process.env.WEBFLOW_TOKEN ?? null;

// SvelteKit $env
import { env } from "$env/dynamic/private";
getToken: () => env.WEBFLOW_TOKEN ?? null;

Supported Field Types

Type Input Component Notes
PlainText TextInput Supports maxLength/minLength validation
RichText TextInput Supports maxLength/minLength validation
Link LinkInput URL input
Email EmailInput Email input
Phone PhoneInput Phone input
Number NumberInput Numeric input with range validation
Switch SwitchInput Boolean toggle
Option OptionInput Dropdown select
Color ColorInput Color picker
DateTime DateInput Calendar picker with date selection
Image ImageInput Image upload with processing
Reference ReferenceInput Single collection reference
MultiReference MultiReferenceInput Multiple collection refs

Field Configuration Options

Field

interface Field {
  visible: boolean; // Show in table
  editable?: boolean; // Allow editing
  required?: boolean; // Field is required
  styles?: FieldStyles; // Custom styling
  schema: FieldSchema; // Field schema
}

Field Validations

interface Validations {
  minLength?: number; // Minimum string length
  maxLength?: number; // Maximum string length
  min?: number; // Minimum numeric value
  max?: number; // Maximum numeric value
}

Sort Field

Sort fields now support DateTime type in addition to Number:

interface SortField extends Field {
  direction?: "asc" | "desc"; // Sort direction
  schema: SortFieldSchema;
}

interface SortFieldSchema extends FieldSchema {
  type: "Number" | "DateTime"; // Number or DateTime
}

API Reference

Components

CmsTable Components:

  • CmsTable.Root - Root wrapper that provides context and state management
  • CmsTable.Toolbar - Title and add button with customizable slots
  • CmsTable.SaveBar - Save/cancel controls with validation error display
  • CmsTable.Table - Table container with styling
  • CmsTable.Header - Table header row with field names and tooltips
  • CmsTable.Body - Table body with drag-and-drop support
  • CmsTable.Row - Individual row component (for custom row templates)
  • CmsTable.Actions - Actions column with live toggle and delete button
  • CmsTable.Cell - Field cell with appropriate input component

Input Components (can be used independently):

  • TextInput - Plain text and rich text input
  • NumberInput - Numeric input with validation
  • LinkInput - URL input
  • EmailInput - Email input
  • PhoneInput - Phone input
  • ColorInput - Color picker
  • SwitchInput - Boolean toggle
  • OptionInput - Dropdown select
  • DateInput - Calendar date picker
  • ImageInput - Image upload with compression
  • ReferenceInput - Single collection reference selector
  • MultiReferenceInput - Multiple collection reference selector

Server Functions

  • createCmsActions(config, options) - Create all CMS actions
  • loadCmsItems(token, config) - Load items from Webflow
  • loadReferenceData(token, config) - Load referenced collection data
  • createWebflowClient(token) - Create Webflow API client

Types

  • TableConfig - Table configuration
  • Field - Field configuration
  • UploadProvider - Upload provider interface
  • UploadProviderFactory - Factory for creating providers
  • TokenGetter - Token retrieval function type

License

MIT

Top categories

Loading Svelte Themes