Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/finsweet/attributes/llms.txt

Use this file to discover all available pages before exploring further.

Finsweet Attributes is designed to be extensible. You can create your own custom Attribute solutions that integrate seamlessly with the core library.

Understanding the Package Structure

The Attributes project uses a monorepo structure with pnpm Workspaces. Each package is located in the packages directory:
  • attributes - The core library that dynamically imports other packages at runtime
  • utils - Shared utility functions and types used across all Attributes
  • template - A starter template for creating new Attributes
  • Individual Attribute packages (e.g., scrolldisable, list, etc.)

Getting Started with the Template

The easiest way to create a new Attribute is to use the provided template package.
1

Clone the repository

First, fork and clone the Attributes repository:
git clone https://github.com/YOUR_USERNAME/attributes.git
cd attributes
2

Install dependencies

Ensure you have pnpm installed, then run:
pnpm install
3

Copy the template

Duplicate the template package and rename it to your Attribute key:
cp -r packages/template packages/YOUR_ATTRIBUTE_KEY
4

Update package.json

Edit packages/YOUR_ATTRIBUTE_KEY/package.json and replace placeholders:
{
  "name": "@finsweet/attributes-YOUR_ATTRIBUTE_KEY",
  "version": "1.0.0",
  "description": "Your attribute description.",
  "private": false
}

Package Structure

Every Attribute package follows this structure:
packages/your-attribute/
├── src/
│   ├── index.ts          # Main entry point - exports version and init
│   ├── init.ts           # Initialization logic
│   ├── actions/          # Reusable action functions
│   └── utils/
│       ├── constants.ts  # Element and setting definitions
│       └── selectors.ts  # DOM selector helpers
├── package.json
└── tsconfig.json

Core Files Explained

index.ts

The entry point exports the version and init function:
export { version } from '../package.json';
export { init } from './init';
export { ELEMENTS, SETTINGS } from './utils/constants';

init.ts

The initialization function must implement the FinsweetAttributeInit type:
import { type FinsweetAttributeInit, waitWebflowReady } from '@finsweet/attributes-utils';

export const init: FinsweetAttributeInit = async () => {
  // Wait for Webflow to be ready
  await waitWebflowReady();

  // Your attribute logic here
  // ...

  // Return object with optional result and destroy function
  return {
    result: someData,  // Optional: data to pass to callbacks
    destroy: () => {   // Optional: cleanup function
      // Remove event listeners, observers, etc.
    }
  };
};
The init function is called automatically when your Attribute is loaded. It should return an object with an optional result value and destroy function for cleanup.

utils/constants.ts

Define your Attribute’s elements and settings:
import { type AttributeElements, type AttributeSettings } from '@finsweet/attributes-utils';

export const ELEMENTS = [
  'trigger',
  'target',
  'container',
] as const satisfies AttributeElements;

export const SETTINGS = {
  duration: {
    key: 'duration',
    defaultValue: '300',
    isNumeric: true,
  },
  easing: {
    key: 'easing',
    values: ['linear', 'ease-in', 'ease-out'],
    defaultValue: 'ease-in',
  },
} as const satisfies AttributeSettings;
Element definitions specify which element types your Attribute uses (e.g., fs-yourattr-element="trigger"). Setting definitions specify configurable options:
  • key - The attribute name suffix (e.g., fs-yourattr-duration)
  • values - Optional array of allowed values
  • defaultValue - Optional default if not specified
  • isNumeric - Set to true for numeric values

Using Attribute Utils

The @finsweet/attributes-utils package provides helpful utilities:
import {
  waitWebflowReady,
  waitDOMReady,
  fetchPage,
  attachExternalStylesheets,
  type FinsweetAttributeInit,
} from '@finsweet/attributes-utils';

Common Utilities

waitWebflowReady
() => Promise<void>
Waits for Webflow’s initialization to complete. Use this before manipulating Webflow-specific features.
waitDOMReady
() => Promise<void>
Waits for the DOM to be fully loaded.
fetchPage
(url: string) => Promise<Document>
Fetches and parses an HTML page. Useful for loading additional content.
attachExternalStylesheets
(doc: Document) => void
Attaches external stylesheets from a document to the current page.

Development Workflow

1

Start the dev server

pnpm dev
The library will be available at http://localhost:3000/attributes.js.
2

Test in Webflow

In your Webflow project, add a custom code embed before the closing </body> tag:
<script type="module" src="http://localhost:3000/attributes.js" fs-YOUR_ATTRIBUTE_KEY></script>
3

Add HTML attributes

Use your Attribute in Webflow by adding the appropriate attributes to elements:
<div fs-YOUR_ATTRIBUTE_KEY-element="trigger">Click me</div>
<div fs-YOUR_ATTRIBUTE_KEY-element="target">I will be affected</div>
4

Run tests

Create tests in packages/attributes/tests/YOUR_ATTRIBUTE_KEY.spec.ts and run:
pnpm test

Best Practices

Define proper types for your functions and data structures. The utils package provides many helpful types like FinsweetAttributeInit, AttributeElements, and AttributeSettings.
Always return a destroy function from your init that removes event listeners, mutation observers, and other side effects. This allows users to properly clean up your Attribute.
Use await waitWebflowReady() at the start of your init function if your Attribute interacts with Webflow-specific features like IX2 animations or CMS content.
Break your logic into small, reusable functions in the actions/ directory. This makes your code easier to test and maintain.
Update the README.md with clear examples of how to use your Attribute, including all available element types and settings.

Proposing New Attributes

Before creating a new Attribute for the official repository, please create an RFC with:
  • Clear description of the Attribute solution and its purpose
  • Breakdown of all HTML attributes that will be used
  • Use case examples
  • Any potential breaking changes or considerations

Next Steps

API Reference

Explore the complete window.FinsweetAttributes API

Contributing Guide

Learn how to contribute to the project

Build docs developers (and LLMs) love