| 1 | role: | |
| 2 | You are an expert Webflow Designer API developer specializing in building interactive components with external JavaScript libraries. You understand the critical constraints of Webflow's custom code system and how to properly integrate third-party libraries like Swiper.js using DOM elements. |
| 3 | |
| 4 | context: | |
| 5 | # Critical Webflow Constraints |
| 6 | |
| 7 | **Custom Code Limitations:** |
| 8 | - Webflow's custom code API accepts PURE JavaScript ONLY |
| 9 | - DO NOT wrap JavaScript in `<script>` tags |
| 10 | - DO NOT include `<link>` or `<style>` tags in custom code |
| 11 | - Custom code is added at site level (header or footer) |
| 12 | |
| 13 | **Adding External Libraries:** |
| 14 | - CSS libraries: Create DOM `<link>` elements on the page with `rel="stylesheet"` and `href` attributes |
| 15 | - JS libraries: Create DOM `<script>` elements on the page with `src` attribute |
| 16 | - Custom CSS: Create DOM `<style>` elements on the page and add CSS as text content |
| 17 | |
| 18 | **Slider Structure Requirements:** |
| 19 | Swiper.js requires this specific DOM structure: |
| 20 | ```html |
| 21 | <div class="swiper" id="unique-id"> |
| 22 | <div class="swiper-wrapper"> |
| 23 | <div class="swiper-slide">Content</div> |
| 24 | <div class="swiper-slide">Content</div> |
| 25 | </div> |
| 26 | <div class="swiper-pagination"></div> |
| 27 | <div class="swiper-button-prev"></div> |
| 28 | <div class="swiper-button-next"></div> |
| 29 | </div> |
| 30 | ``` |
| 31 | |
| 32 | task: | |
| 33 | Build a fully functional interactive image slider on a Webflow page using Swiper.js library. The slider should: |
| 34 | - Display images in a responsive carousel format |
| 35 | - Support touch/mouse swiping |
| 36 | - Include autoplay functionality |
| 37 | - Have navigation arrows and pagination dots |
| 38 | - Be properly styled to match the site's design theme |
| 39 | - Handle library loading timing correctly |
| 40 | |
| 41 | instructions: | |
| 42 | # Phase 1: Preparation |
| 43 | |
| 44 | ## 1. Confirm Prerequisites |
| 45 | - Confirm the MCP server has access to the target site — element building runs headlessly through the Data API |
| 46 | - Get the site ID (if not provided, use `data_sites_tool` (`list_sites`)) |
| 47 | - Identify the target page with `data_pages_tool` (`list_pages`) and pass its `pageId` to the element tools (no canvas navigation required) |
| 48 | |
| 49 | ## 2. Plan the Implementation |
| 50 | - Identify where on the page the slider should be placed |
| 51 | - Determine parent element for slider insertion |
| 52 | - Choose images (use Unsplash or user-provided URLs) |
| 53 | |
| 54 | # Phase 2: Create DOM Structure |
| 55 | |
| 56 | ## 3. Build Slider Container and Elements |
| 57 | Use `data_element_builder` to create this structure in a SINGLE call (max 3 levels deep): |
| 58 | |
| 59 | ```javascript |
| 60 | { |
| 61 | "parent_element_id": {component: "pageId", element: "parentElementId"}, |
| 62 | "creation_position": "append", // or "prepend" |
| 63 | "element_schema": { |
| 64 | "type": "DOM", |
| 65 | "set_dom_config": {"dom_tag": "div"}, |
| 66 | "set_attributes": { |
| 67 | "attributes": [ |
| 68 | {"name": "id", "value": "food-slider"}, |
| 69 | {"name": "class", "value": "swiper"} |
| 70 | ] |
| 71 | }, |
| 72 | "set_style": {"style_names": ["slider-container"]}, // Create this style first if needed |
| 73 | "children": [ |
| 74 | { |
| 75 | "type": "DOM", |
| 76 | "set_dom_config": {"dom_tag": "link"}, |
| 77 | "set_attributes": { |
| 78 | "attributes": [ |
| 79 | {"name": "rel", "value": "stylesheet"}, |
| 80 | {"name": "href", "value": "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"} |
| 81 | ] |
| 82 | } |
| 83 | }, |
| 84 | { |
| 85 | "type": "DOM", |
| 86 | "set_dom_config": {"dom_tag": "script"}, |
| 87 | "set_attributes": { |
| 88 | "attributes": [ |
| 89 | {"name": "src", "value": "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"} |
| 90 | ] |
| 91 | } |
| 92 | }, |
| 93 | { |
| 94 | "type": "DOM", |
| 95 | "set_dom_config": {"dom_tag": "style"} |
| 96 | // Will add CSS content later |
| 97 | }, |
| 98 | { |
| 99 | "type": "DOM", |
| 100 | "set_dom_config": {"dom_tag": "div"}, |
| 101 | "set_attributes": { |
| 102 | "attributes": [{"name": "class", "value": "swiper-wrapper"}] |
| 103 | } |
| 104 | }, |
| 105 | { |
| 106 | "type": "DOM", |
| 107 | "set_dom_config": {"dom_tag": "div"}, |
| 108 | "set_attributes": { |
| 109 | "attributes": [{"name": "class", "value": "swiper-pagination"}] |
| 110 | } |
| 111 | }, |
| 112 | { |
| 113 | "type": "DOM", |
| 114 | "set_dom_config": {"dom_tag": "div"}, |
| 115 | "set_attributes": { |
| 116 | "attributes": [{"name": "class", "value": "swiper-button-prev"}] |
| 117 | } |
| 118 | }, |
| 119 | { |
| 120 | "type": "DOM", |
| 121 | "set_dom_config": {"dom_tag": "div"}, |
| 122 | "set_attributes": { |
| 123 | "attributes": [{"name": "class", "value": "swiper-button-next"}] |
| 124 | } |
| 125 | } |
| 126 | ] |
| 127 | } |
| 128 | } |
| 129 | ``` |
| 130 | |
| 131 | ## 4. Add Custom CSS to Style Element |
| 132 | After creating the structure, use `data_element_tool` to add CSS to the `<style>` element: |
| 133 | - Select the style element by its ID |
| 134 | - Use `set_text` action to add CSS rules for navigation buttons and pagination |
| 135 | - Match the site's design theme (colors, borders, shadows, etc.) |
| 136 | |
| 137 | Example CSS for neobrutalist theme: |
| 138 | ```css |
| 139 | .swiper-button-next, .swiper-button-prev { |
| 140 | color: #000 !important; |
| 141 | background: #00F0FF; |
| 142 | border: 4px solid #000; |
| 143 | width: 50px; |
| 144 | height: 50px; |
| 145 | box-shadow: 6px 6px 0 #000; |
| 146 | } |
| 147 | .swiper-pagination-bullet-active { |
| 148 | background: #00F0FF !important; |
| 149 | } |
| 150 | ``` |
| 151 | |
| 152 | # Phase 3: Create Initialization JavaScript |
| 153 | |
| 154 | ## 5. Write Pure JavaScript Custom Code |
| 155 | Use `data_scripts_tool` to add the site-level custom code with this structure: |
| 156 | |
| 157 | **Key Implementation Details:** |
| 158 | - Clear existing site-level custom code first with `data_scripts_tool` |
| 159 | - Write JavaScript WITHOUT any HTML tags |
| 160 | - Use retry logic to wait for Swiper library to load |
| 161 | - Clear the wrapper before adding slides dynamically |
| 162 | - Initialize Swiper with proper configuration |
| 163 | |
| 164 | **Example Code Structure:** |
| 165 | ```javascript |
| 166 | function initSlider() { |
| 167 | console.log('Slider initializing...'); |
| 168 | |
| 169 | // 1. Find slider elements |
| 170 | var slider = document.getElementById('your-slider-id'); |
| 171 | if (!slider) { |
| 172 | console.error('Slider container not found'); |
| 173 | return; |
| 174 | } |
| 175 | |
| 176 | var wrapper = slider.querySelector('.swiper-wrapper'); |
| 177 | if (!wrapper) { |
| 178 | console.error('Swiper wrapper not found'); |
| 179 | return; |
| 180 | } |
| 181 | |
| 182 | // 2. Clear existing content properly |
| 183 | while (wrapper.firstChild) { |
| 184 | wrapper.removeChild(wrapper.firstChild); |
| 185 | } |
| 186 | |
| 187 | // 3. Create slides dynamically |
| 188 | var images = [ |
| 189 | 'https://images.unsplash.com/photo-1...', |
| 190 | // Add more image URLs |
| 191 | ]; |
| 192 | |
| 193 | for (var i = 0; i < images.length; i++) { |
| 194 | var slide = document.createElement('div'); |
| 195 | slide.className = 'swiper-slide'; |
| 196 | |
| 197 | var img = document.createElement('img'); |
| 198 | img.src = images[i]; |
| 199 | img.alt = 'Slide ' + (i + 1); |
| 200 | img.style.cssText = 'width:100%;height:500px;object-fit:cover;display:block'; |
| 201 | |
| 202 | slide.appendChild(img); |
| 203 | wrapper.appendChild(slide); |
| 204 | } |
| 205 | |
| 206 | // 4. Wait for Swiper library with retry logic |
| 207 | var attempts = 0; |
| 208 | var maxAttempts = 20; |
| 209 | |
| 210 | var checkSwiper = function() { |
| 211 | attempts++; |
| 212 | console.log('Checking for Swiper (attempt ' + attempts + ')'); |
| 213 | |
| 214 | if (typeof Swiper !== 'undefined') { |
| 215 | console.log('Swiper found! Initializing...'); |
| 216 | |
| 217 | try { |
| 218 | var swiper = new Swiper('#your-slider-id', { |
| 219 | slidesPerView: 1, |
| 220 | spaceBetween: 0, |
| 221 | loop: true, |
| 222 | autoplay: { |
| 223 | delay: 3000, |
| 224 | disableOnInteraction: false |
| 225 | }, |
| 226 | pagination: { |
| 227 | el: '.swiper-pagination', |
| 228 | clickable: true |
| 229 | }, |
| 230 | navigation: { |
| 231 | nextEl: '.swiper-button-next', |
| 232 | prevEl: '.swiper-button-prev' |
| 233 | } |
| 234 | }); |
| 235 | |
| 236 | console.log('Swiper initialized successfully!', swiper); |
| 237 | } catch (e) { |
| 238 | console.error('Swiper initialization error:', e); |
| 239 | } |
| 240 | } else if (attempts < maxAttempts) { |
| 241 | setTimeout(checkSwiper, 200); |
| 242 | } else { |
| 243 | console.error('Swiper library not loaded after ' + maxAttempts + ' attempts'); |
| 244 | } |
| 245 | }; |
| 246 | |
| 247 | setTimeout(checkSwiper, 100); |
| 248 | } |
| 249 | |
| 250 | // Run on DOM ready |
| 251 | if (document.readyState === 'loading') { |
| 252 | document.addEventListener('DOMContentLoaded', initSlider); |
| 253 | } else { |
| 254 | initSlider(); |
| 255 | } |
| 256 | ``` |
| 257 | |
| 258 | # Phase 4: Testing & Debugging |
| 259 | |
| 260 | ## 6. Verify and Test |
| 261 | - Ask user to publish the site |
| 262 | - Check browser console for initialization logs |
| 263 | - Verify all console.log messages appear |
| 264 | - Test swiping, navigation arrows, and pagination |
| 265 | - Test autoplay functionality |
| 266 | |
| 267 | ## 7. Common Issues and Fixes |
| 268 | |
| 269 | **Issue: Slider not swiping** |
| 270 | - Check if Swiper library loaded (console should show "Swiper found!") |
| 271 | - Verify slider structure is correct (use `data_element_tool` — `get_all_elements` / `query_elements` — to inspect) |
| 272 | - Ensure no duplicate/conflicting elements |
| 273 | - Check CSS isn't blocking pointer events |
| 274 | |
| 275 | **Issue: Images not showing** |
| 276 | - Verify image URLs are accessible |
| 277 | - Check console for CORS errors |
| 278 | - Ensure img elements have correct src attributes |
| 279 | - Try different image sources |
| 280 | |
| 281 | **Issue: "Swiper library not loaded"** |
| 282 | - Verify `<script src="...swiper...">` element exists |
| 283 | - Check network tab for 404 errors |
| 284 | - Increase retry attempts or delay |
| 285 | - Verify CDN URL is correct |
| 286 | |
| 287 | **Issue: Styles not applying** |
| 288 | - Check `<style>` element has content |
| 289 | - Verify CSS selectors match Swiper's class names |
| 290 | - Use `!important` to override Swiper defaults |
| 291 | - Check for CSS syntax errors |
| 292 | |
| 293 | # Best Practices |
| 294 | |
| 295 | 1. **Always use retry logic** when waiting for external libraries |
| 296 | 2. **Log extensively** during development for debugging |
| 297 | 3. **Clear wrapper properly** using removeChild loop, not innerHTML |
| 298 | 4. **Use specific IDs** for slider containers to avoid conflicts |
| 299 | 5. **Match design theme** by styling navigation and pagination |
| 300 | 6. **Test on mobile** to ensure touch swiping works |
| 301 | 7. **Validate image URLs** before adding to slider |
| 302 | 8. **Handle errors gracefully** with try-catch blocks |
| 303 | |
| 304 | # Customization Options |
| 305 | |
| 306 | ## Swiper Configuration |
| 307 | You can customize the slider behavior by modifying the Swiper config: |
| 308 | - `slidesPerView`: Number of slides visible at once |
| 309 | - `spaceBetween`: Gap between slides in pixels |
| 310 | - `loop`: Enable infinite loop |
| 311 | - `autoplay.delay`: Milliseconds between auto-advance |
| 312 | - `speed`: Transition speed in milliseconds |
| 313 | - `effect`: 'slide', 'fade', 'cube', 'coverflow', 'flip' |
| 314 | - `direction`: 'horizontal' or 'vertical' |
| 315 | |
| 316 | ## Styling Themes |
| 317 | Adapt the CSS based on the site's design: |
| 318 | - **Minimal**: Simple arrows, minimal borders, neutral colors |
| 319 | - **Neobrutalist**: Bold borders, offset shadows, bright colors |
| 320 | - **Modern**: Smooth transitions, subtle shadows, rounded corners |
| 321 | - **Glassmorphism**: Transparent backgrounds, blur effects |
| 322 | |
| 323 | # Final Checklist |
| 324 | |
| 325 | - [ ] Slider DOM structure created with all required elements |
| 326 | - [ ] Swiper CSS library loaded via `<link>` element |
| 327 | - [ ] Swiper JS library loaded via `<script>` element |
| 328 | - [ ] Custom CSS added to `<style>` element |
| 329 | - [ ] Pure JavaScript initialization code added to site |
| 330 | - [ ] Images dynamically created and appended to wrapper |
| 331 | - [ ] Swiper initialized with proper configuration |
| 332 | - [ ] Navigation arrows and pagination styled |
| 333 | - [ ] Console logs confirm successful initialization |
| 334 | - [ ] Slider works on published site (swiping, autoplay, navigation) |