top of page
Velo-by-Wix

How to Use Wix Velo: The Complete Guide to Advanced Web Development on Wix

 

Introduction to Wix Velo

 

Wix Velo (formerly Corvid) is a powerful development platform that transforms Wix from a simple website builder into a full-stack development environment. This comprehensive guide will teach you how to use Wix Velo to create dynamic, data-driven websites with custom functionality that goes far beyond standard Wix capabilities.

Whether you're looking to add custom forms, create member areas, build web applications, or integrate third-party services, Wix Velo provides the tools and flexibility you need whilst maintaining the visual design capabilities Wix is known for.

 

What is Wix Velo?

Wix Velo is an open development platform that allows you to build advanced web applications using JavaScript and Wix's visual editor. It combines the ease of Wix's drag-and-drop interface with the power of code, enabling developers to:

  • Write custom backend and frontend code

  • Access and manipulate databases

  • Create API integrations

  • Build custom user interactions

  • Implement complex business logic

  • Develop full-scale web applications

 

Key Benefits of Using Wix Velo

  1. No Infrastructure Management: Wix handles hosting, security, and scaling

  2. Visual Development: Design visually whilst coding functionality

  3. Built-in Database: Integrated database management system

  4. Serverless Functions: Write backend code without managing servers

  5. Extensive APIs: Access to Wix's comprehensive API library

 

Getting Started with Wix Velo

Step 1: Enable Dev Mode

To begin using Wix Velo, you must first enable Dev Mode in your Wix Editor:

  1. Open your Wix site in the Editor

  2. Click on "Dev Mode" in the top menu bar

  3. Toggle the switch to "On"

  4. The code panel will appear at the bottom of your screen

 

Step 2: Understanding the Velo Interface

Once Dev Mode is enabled, you'll see several new elements:

  • Code Panel: Where you write and edit your code

  • Properties Panel: Shows properties and events for selected elements

  • Site Structure: Displays your site's pages and code files

  • Database Collections: Access to your site's data collections

 

Step 3: Setting Up Your Development Environment

Before diving into coding, ensure your environment is properly configured:

  1. Page Code: Each page can have its own JavaScript file

  2. Public Files: For code accessible from any page

  3. Backend Files: For server-side code and sensitive operations

  4. Packages: NPM packages can be installed for additional functionality Core Concepts in Wix Velo

 

Working with Page Elements

Every element on your Wix page can be controlled through code. Here's how to interact with page elements:

// Accessing elements by ID $w.onReady(function () { // Get a button element let myButton = $w('#button1'); // Change button text myButton.label = "Click Me!"; // Add click event myButton.onClick(() => { console.log("Button clicked!"); }); });

 

The $w Selector

The $w selector is fundamental to Wix Velo development. It allows you to:

  • Select page elements

  • Manipulate element properties

  • Attach event handlers

  • Control element visibility

 

Event Handling

Wix Velo supports various events for different elements:

// Text input events $w('#textInput1').onInput((event) => { let inputValue = event.target.value; // Process input }); // Dropdown selection $w('#dropdown1').onChange((event) => { let selectedValue = event.target.value; // Handle selection });

Working with Databases in Wix Velo

 

Creating Database Collections

  1. Navigate to "Database" in your Wix Dashboard

  2. Click "Add Collection"

  3. Define your collection structure with fields

  4. Set permissions for read/write access

 

Querying Data

Wix Velo provides a powerful query API:

import wixData from 'wix-data'; // Basic query wixData.query("myCollection") .find() .then((results) => { let items = results.items; // Process results }); // Filtered query wixData.query("myCollection") .eq("status", "active") .ascending("createdDate") .limit(10) .find() .then((results) => { // Handle filtered results });

 

Inserting and Updating Data

// Insert new item let toInsert = { "title": "New Item", "description": "Item description", "price": 29.99 }; wixData.insert("myCollection", toInsert) .then((item) => { console.log("Item created:", item); }); // Update existing item wixData.update("myCollection", updatedItem) .then((item) => { console.log("Item updated:", item); });

Building Dynamic Pages

Creating Dynamic Item Pages

Dynamic pages allow you to create template pages that populate with database content:

  1. Add a dynamic page from the Wix Editor

  2. Connect page elements to dataset fields

  3. Customise the URL structure

  4. Add custom code for additional functionality

 

Working with Datasets

Datasets act as intermediaries between your database and page elements:

// Filter dataset programmatically $w('#dataset1').setFilter(wixData.filter() .eq("category", "electronics") .gt("price", 100) ); // Refresh dataset $w('#dataset1').refresh();

API Integration and HTTP Functions

 

Making External API Calls

Wix Velo allows you to integrate with external services:

// Backend code (http-functions.js) import {fetch} from 'wix-fetch'; export async function getExternalData() { const response = await fetch('https://api.example.com/data', { method: 'GET', headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }); return response.json(); }

 

Creating HTTP Functions

HTTP functions allow external services to communicate with your Wix site:

// http-functions.js import {ok, badRequest} from 'wix-http-functions'; export function post_webhook(request) { return request.body.json() .then((data) => { // Process webhook data return ok({received: true}); }) .catch(() => { return badRequest({error: 'Invalid data'}); }); }

Advanced Wix Velo Features

 

User Authentication and Members Area

import wixUsers from 'wix-users'; import wixLocation from 'wix-location'; // Check if user is logged in if (wixUsers.currentUser.loggedIn) { // User is logged in let userId = wixUsers.currentUser.id; let userEmail = await wixUsers.currentUser.getEmail(); } // Custom login wixUsers.login(email, password) .then(() => { wixLocation.to("/member-dashboard"); }) .catch((err) => { console.error("Login failed:", err); });

 

Scheduled Jobs

Create automated tasks that run at specified intervals:

// jobs.config { "jobs": [{ "functionLocation": "/backend/scheduled-jobs.js", "functionName": "dailyReport", "description": "Generate daily reports", "executionConfig": { "cronExpression": "0 9 * * *" } }] }

 

Working with Wix Stores

Integrate custom functionality with Wix Stores:

import wixStores from 'wix-stores'; // Get current cart wixStores.getCurrentCart() .then((cart) => { console.log("Cart items:", cart.lineItems); }); // Add custom product options export function product_onChange(event) { let selectedOptions = event.target.value; // Custom logic for product variants }

Best Practices for Wix Velo Development

 

Code Organisation

  1. Separate Concerns: Keep frontend and backend logic separate

  2. Reusable Functions: Create utility modules for common operations

  3. Consistent Naming: Use clear, descriptive names for functions and variables

  4. Comment Your Code: Document complex logic and API integrations

 

Performance Optimisation

  1. Minimise Database Queries: Batch operations when possible

  2. Use Caching: Store frequently accessed data

  3. Lazy Loading: Load content as needed

  4. Optimise Images: Use Wix's image optimisation features

 

Security Considerations

  1. Backend Validation: Always validate data on the backend

  2. Secure API Keys: Store sensitive data in backend code

  3. Permission Management: Set appropriate database permissions

  4. Input Sanitisation: Clean user inputs before processing

 

Common Wix Velo Use Cases

 

Custom Form Handling

export function submitButton_click(event) { // Validate form fields let email = $w('#emailInput').value; let message = $w('#messageInput').value; if (!email || !message) { $w('#errorText').show(); return; } // Submit to database wixData.insert("ContactSubmissions", { email: email, message: message, submittedAt: new Date() }) .then(() => { $w('#successMessage').show(); $w('#contactForm').hide(); }); }

 

Dynamic Content Filtering

export function categoryDropdown_change(event) { let selectedCategory = event.target.value; if (selectedCategory === "All") { $w('#dataset1').setFilter(wixData.filter()); } else { $w('#dataset1').setFilter(wixData.filter() .eq("category", selectedCategory) ); } }

 

Member-Only Content

import wixUsers from 'wix-users'; import wixLocation from 'wix-location'; $w.onReady(function () { if (!wixUsers.currentUser.loggedIn) { wixLocation.to("/login"); } else { // Show member content $w('#memberContent').show(); } });

 

Troubleshooting Common Issues

 

Debugging Tips

  1. Use Console Logs: Liberal use of console.log() for debugging

  2. Preview Mode: Test in preview before publishing

  3. Browser DevTools: Inspect network requests and console errors

  4. Wix Logs: Check backend logs in the Wix Dashboard

 

Common Error Solutions

Element Not Found

  • Ensure element IDs match exactly

  • Check that elements exist on the current page

  • Wait for $w.onReady() before accessing elements

 

Database Permission Errors

  • Verify collection permissions in settings

  • Use backend code for sensitive operations

  • Check user authentication status

 

API Integration Failures

  • Verify API endpoints and credentials

  • Handle errors gracefully with try-catch

  • Check CORS settings for external APIs

 

Testing and Deployment

 

Unit Testing Strategies

Whilst Wix Velo doesn't have built-in testing frameworks, you can implement testing strategies:

// testUtils.js - Backend file export function runTests() { const tests = [ testUserValidation, testPriceCalculation, testDataFormatting ]; let results = []; tests.forEach(test => { try { test(); results.push({name: test.name, status: 'PASSED'}); } catch (error) { results.push({name: test.name, status: 'FAILED', error: error.message}); } }); return results; } function testUserValidation() { const result = validateUserEmail('test@example.com'); if (!result) throw new Error('Valid email failed validation'); }

 

Staging Environments

Create a staging workflow:

  1. Duplicate Your Site: Create a copy for testing

  2. Sandbox Database: Use separate collections for testing

  3. Environment Variables: Implement environment-specific configurations

// config.js export function getConfig() { const isDev = wixWindow.viewMode === "Preview"; return { apiEndpoint: isDev ? 'https://staging-api.example.com' : 'https://api.example.com', debugMode: isDev }; }

 

Version Control Integration

Whilst Wix doesn't directly support Git, you can:

  1. Export your code regularly

  2. Use Wix CLI for local development

  3. Maintain a Git repository for code backup

  4. Document changes in a changelog

 

SEO and Performance Monitoring

 

Velo's Impact on SEO

Wix Velo can enhance or hinder SEO depending on implementation:

// SEO-friendly dynamic page setup import wixSeo from 'wix-seo'; $w.onReady(async function () { // Set dynamic SEO tags const pageData = await getPageData(); wixSeo.setTitle(pageData.title); wixSeo.setMetaDescription(pageData.description); wixSeo.setStructuredData({ "@context": "https://schema.org", "@type": "Article", "headline": pageData.title, "datePublished": pageData.publishDate, "author": { "@type": "Person", "name": pageData.author } }); });

 

Performance Monitoring

Track and optimise your Velo site's performance:

// Performance tracking export function trackPageLoad() { const loadTime = performance.now(); // Send to analytics wixAnalytics.track('PageLoadTime', { page: wixLocation.path, loadTime: loadTime, device: wixWindow.formFactor }); // Log slow pages if (loadTime > 3000) { console.warn('Slow page load:', loadTime); } }

 

Core Web Vitals Optimisation

// Lazy load images and content export function setupLazyLoading() { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { loadContent(entry.target); observer.unobserve(entry.target); } }); }); $w('#repeater1').forEachItem(($item) => { observer.observe($item('#lazyImage')[0]); }); }

Advanced Integrations

 

Payment Processing

Integrate Stripe for custom payment flows:

// Backend - stripe-integration.js import {fetch} from 'wix-fetch'; import {getSecret} from 'wix-secrets-backend'; export async function createPaymentIntent(amount, currency) { const stripeKey = await getSecret('STRIPE_SECRET_KEY'); const response = await fetch('https://api.stripe.com/v1/payment_intents', { method: 'POST', headers: { 'Authorization': `Bearer ${stripeKey}`, 'Content-Type': 'application/x-www-form-urlencoded' }, body: `amount=${amount}&currency=${currency}` }); return response.json(); }

 

Email Automation

Create sophisticated email workflows:

import wixCRM from 'wix-crm-backend'; export async function sendAutomatedEmail(contactId, templateId, variables) { try { await wixCRM.emailContact(templateId, contactId, { variables: variables }); // Log email sent await logEmailActivity(contactId, templateId); } catch (error) { console.error('Email failed:', error); } } // Triggered email example export async function afterInsert(item, context) { // Send welcome email when new member signs up if (context.collectionName === 'Members') { await sendAutomatedEmail(item._id, 'welcome-template', { name: item.firstName, membershipLevel: item.level }); } }

 

Social Media Integration

Connect with social platforms:

// Twitter/X API integration export async function postToTwitter(message) { const twitterApi = await getTwitterClient(); try { const tweet = await twitterApi.post('tweets', { text: message, media: { media_ids: await uploadMedia() } }); return tweet.data; } catch (error) { console.error('Twitter post failed:', error); } } // Instagram Basic Display API export async function getInstagramFeed(accessToken) { const response = await fetch( `https://graph.instagram.com/me/media?fields=id,caption,media_url&access_token=${accessToken}` ); return response.json(); }

 

Webhook Implementation

Handle incoming webhooks securely:

// http-functions.js import crypto from 'crypto'; import {getSecret} from 'wix-secrets-backend'; export async function post_webhook(request) { // Verify webhook signature const signature = request.headers['x-webhook-signature']; const secret = await getSecret('WEBHOOK_SECRET'); const body = await request.body.text(); const expectedSignature = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); if (signature !== expectedSignature) { return badRequest({error: 'Invalid signature'}); } // Process webhook const data = JSON.parse(body); await processWebhookData(data); return ok({received: true}); }

Real-World Project Examples

 

Building a Booking System

Complete booking system implementation:

// booking-system.js import wixData from 'wix-data'; import wixUsers from 'wix-users'; export class BookingSystem { constructor() { this.collectionName = 'Bookings'; this.slotsCollection = 'TimeSlots'; } async getAvailableSlots(date, serviceId) { const startOfDay = new Date(date); startOfDay.setHours(0, 0, 0, 0); const endOfDay = new Date(date); endOfDay.setHours(23, 59, 59, 999); const bookedSlots = await wixData.query(this.collectionName) .between('dateTime', startOfDay, endOfDay) .eq('serviceId', serviceId) .eq('status', 'confirmed') .find(); const allSlots = await this.generateTimeSlots(date, serviceId); return allSlots.filter(slot => !this.isSlotBooked(slot, bookedSlots.items)); } async createBooking(slotData) { const user = wixUsers.currentUser; const userId = user.id; // Check availability again const isAvailable = await this.checkSlotAvailability(slotData); if (!isAvailable) { throw new Error('Slot no longer available'); } const booking = { userId: userId, serviceId: slotData.serviceId, dateTime: slotData.dateTime, duration: slotData.duration, status: 'pending', createdAt: new Date() }; const result = await wixData.insert(this.collectionName, booking); // Send confirmation email await this.sendBookingConfirmation(result); return result; } } // Frontend implementation $w.onReady(function () { const bookingSystem = new BookingSystem(); $w('#datePicker').onChange(async (event) => { const selectedDate = event.target.value; const serviceId = $w('#serviceDropdown').value; const availableSlots = await bookingSystem.getAvailableSlots(selectedDate, serviceId); $w('#timeSlotsRepeater').data = availableSlots; }); });

 

Creating a Custom CRM

Build a customer relationship management system:

// crm-backend.js export class CRMSystem { async createContact(contactData) { // Validate and sanitise data const validatedData = this.validateContactData(contactData); // Check for duplicates const existing = await wixData.query('Contacts') .eq('email', validatedData.email) .find(); if (existing.items.length > 0) { return this.updateContact(existing.items[0]._id, validatedData); } // Add metadata validatedData.createdAt = new Date(); validatedData.lastActivity = new Date(); validatedData.score = this.calculateLeadScore(validatedData); return wixData.insert('Contacts', validatedData); } calculateLeadScore(contact) { let score = 0; // Score based on engagement if (contact.emailOpens > 5) score += 20; if (contact.websiteVisits > 10) score += 30; if (contact.downloadedContent) score += 25; if (contact.requestedDemo) score += 50; return Math.min(score, 100); } async trackActivity(contactId, activityType, details) { const activity = { contactId: contactId, type: activityType, details: details, timestamp: new Date() }; await wixData.insert('Activities', activity); // Update last activity await wixData.update('Contacts', { _id: contactId, lastActivity: new Date() }); } }

 

Developing a Membership Portal

Create a comprehensive membership system:

// membership-portal.js import wixUsers from 'wix-users'; import wixPay from 'wix-pay'; import wixData from 'wix-data'; export class MembershipPortal { async setupMemberDashboard() { const user = wixUsers.currentUser; if (!user.loggedIn) { wixLocation.to('/login'); return; } const memberData = await this.getMemberData(user.id); this.displayMemberInfo(memberData); this.loadMemberContent(memberData.level); } async getMemberData(userId) { const member = await wixData.query('Members') .eq('userId', userId) .include('subscriptionHistory') .find(); return member.items[0]; } async upgradeMembership(newLevel) { const payment = await wixPay.createPayment({ amount: this.getLevelPrice(newLevel), currency: 'GBP', description: `Upgrade to ${newLevel} membership` }); const result = await payment.startPayment(); if (result.status === 'Successful') { await this.updateMemberLevel(newLevel); } } async loadMemberContent(level) { const content = await wixData.query('MemberContent') .hasSome('allowedLevels', [level, 'all']) .ascending('publishDate') .find(); $w('#contentRepeater').data = content.items; } }

 

E-Learning Platform Example

Build an online course platform:

// e-learning-platform.js export class LearningPlatform { async enrollInCourse(courseId) { const user = wixUsers.currentUser; const enrollment = { userId: user.id, courseId: courseId, enrolledDate: new Date(), progress: 0, completedModules: [], status: 'active' }; await wixData.insert('Enrollments', enrollment); // Grant access to course content await this.grantCourseAccess(user.id, courseId); } async trackProgress(courseId, moduleId, completed) { const enrollment = await this.getEnrollment(courseId); if (completed && !enrollment.completedModules.includes(moduleId)) { enrollment.completedModules.push(moduleId); enrollment.progress = this.calculateProgress(courseId, enrollment.completedModules); await wixData.update('Enrollments', enrollment); if (enrollment.progress === 100) { await this.issueCertificate(enrollment); } } } async getNextLesson(courseId) { const enrollment = await this.getEnrollment(courseId); const course = await this.getCourse(courseId); const incompleteLessons = course.modules.filter( module => !enrollment.completedModules.includes(module._id) ); return incompleteLessons[0] || null; } }

Mobile Development

 

Responsive Design with Velo

 

Optimise for mobile devices:

import wixWindow from 'wix-window'; $w.onReady(function () { // Detect device type if (wixWindow.formFactor === "Mobile") { setupMobileInterface(); } else if (wixWindow.formFactor === "Tablet") { setupTabletInterface(); } else { setupDesktopInterface(); } // Handle orientation changes wixWindow.addEventListener('orientationchange', () => { adjustLayoutForOrientation(); }); }); function setupMobileInterface() { // Mobile-specific adjustments $w('#mobileMenu').show(); $w('#desktopMenu').hide(); // Simplify complex interactions $w('#dataTable').hide(); $w('#mobileCardView').show(); // Adjust touch targets $w('.button').style.minHeight = "44px"; } function adjustLayoutForOrientation() { const isLandscape = window.orientation === 90 || window.orientation === -90; if (isLandscape) { $w('#header').collapse(); } else { $w('#header').expand(); } }

 

Touch Gestures and Mobile Interactions

// Swipe navigation for mobile galleries export function setupSwipeGallery() { let touchStartX = 0; let touchEndX = 0; $w('#galleryContainer').onMouseIn((event) => { if (wixWindow.formFactor !== "Mobile") return; event.target.addEventListener('touchstart', (e) => { touchStartX = e.changedTouches[0].screenX; }); event.target.addEventListener('touchend', (e) => { touchEndX = e.changedTouches[0].screenX; handleSwipe(); }); }); function handleSwipe() { if (touchEndX < touchStartX - 50) { // Swipe left - next image $w('#gallery').next(); } if (touchEndX > touchStartX + 50) { // Swipe right - previous image $w('#gallery').previous(); } } }

Limitations and Workarounds

 

NPM Package Limitations

Wix Velo has restrictions on npm packages:

Allowed Package Types:

  • Pure JavaScript packages

  • Packages without native dependencies

  • Packages under 10MB

Workarounds:

// If a package isn't available, implement functionality manually // Example: Simple UUID generator when uuid package isn't available export function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }

 

Memory and Execution Limits

Handle Velo's execution constraints:

// Backend functions have 14-second timeout export async function processLargeDataset(datasetId) { const BATCH_SIZE = 100; let offset = 0; let hasMore = true; while (hasMore) { const batch = await wixData.query('LargeCollection') .skip(offset) .limit(BATCH_SIZE) .find(); // Process batch await processBatch(batch.items); offset += BATCH_SIZE; hasMore = batch.hasNext(); // Prevent timeout by breaking large operations if (offset > 1000) { // Schedule continuation await scheduleNextBatch(datasetId, offset); break; } } }

 

File Storage Restrictions

Work within Velo's file limitations:

// Media Manager API for file handling import wixMediaManager from 'wix-media-manager'; export async function uploadAndProcessFile(fileInfo) { // File size limit: 25MB for most file types if (fileInfo.size > 25 * 1024 * 1024) { throw new Error('File too large. Maximum size is 25MB'); } // Upload to Media Manager const uploadResult = await wixMediaManager.upload( fileInfo.fileUrl, { fileName: fileInfo.name, labels: ['user-upload', 'processed'] } ); return uploadResult; }

 

Third-Party Script Limitations

Navigate script restrictions:

// Load external scripts properly export function loadExternalScript(src) { return new Promise((resolve, reject) => { // Scripts must be HTTPS if (!src.startsWith('https://')) { reject(new Error('Scripts must use HTTPS')); return; } const script = document.createElement('script'); script.src = src; script.onload = resolve; script.onerror = reject; // Add to head document.head.appendChild(script); }); }

GDPR and Privacy Compliance

 

Cookie Consent Implementation

Build GDPR-compliant cookie consent:

import wixWindow from 'wix-window'; import {local} from 'wix-storage'; export function setupCookieConsent() { // Check if consent already given const consentGiven = local.getItem('cookieConsent'); if (!consentGiven) { $w('#cookieBanner').show(); } $w('#acceptCookies').onClick(() => { local.setItem('cookieConsent', 'accepted'); local.setItem('consentDate', new Date().toISOString()); $w('#cookieBanner').hide(); // Enable analytics enableAnalytics(); }); $w('#rejectCookies').onClick(() => { local.setItem('cookieConsent', 'rejected'); $w('#cookieBanner').hide(); // Disable non-essential cookies disableNonEssentialCookies(); }); } function enableAnalytics() { // Enable Google Analytics or other tracking if (typeof gtag !== 'undefined') { gtag('consent', 'update', { 'analytics_storage': 'granted' }); } }

 

Data Protection with Velo

Implement data protection features:

// User data export functionality export async function exportUserData(userId) { const userData = {}; // Collect data from various collections const collections = ['Members', 'Orders', 'Activities', 'Preferences']; for (const collection of collections) { const data = await wixData.query(collection) .eq('userId', userId) .find(); userData[collection] = data.items; } // Create downloadable file const jsonData = JSON.stringify(userData, null, 2); const blob = new Blob([jsonData], {type: 'application/json'}); return { data: userData, downloadUrl: URL.createObjectURL(blob) }; } // Data deletion export async function deleteUserData(userId) { // Verify user identity const currentUser = wixUsers.currentUser; if (currentUser.id !== userId) { throw new Error('Unauthorised'); } // Delete from all collections const collections = ['Members', 'Orders', 'Activities']; for (const collection of collections) { await wixData.query(collection) .eq('userId', userId) .find() .then(results => { const deletePromises = results.items.map(item => wixData.remove(collection, item._id) ); return Promise.all(deletePromises); }); } // Delete user account await wixUsers.deleteUser(); }

 

Privacy-First Analytics

Implement privacy-respecting analytics:

// Anonymous analytics tracking export function trackEvent(eventName, parameters) { // Check consent const consent = local.getItem('cookieConsent'); if (consent !== 'accepted') { // Only track essential, anonymous data const anonymousEvent = { event: eventName, timestamp: new Date(), // No user-identifiable information sessionId: generateSessionId(), pageUrl: wixLocation.path }; // Store locally or send to privacy-focused service sendAnonymousAnalytics(anonymousEvent); } else { // Full analytics with user consent wixAnalytics.track(eventName, parameters); } }

Advanced Animation and Interactions

 

Timeline Animations

Create sophisticated animations:

import wixAnimations from 'wix-animations'; export function createTimelineAnimation() { const timeline = wixAnimations.timeline(); timeline .add($w('#element1'), { duration: 1000, opacity: 1, y: 0, scale: 1 }) .add($w('#element2'), { duration: 800, opacity: 1, x: 0, rotate: 360 }, '-=400') // Start 400ms before previous ends .add($w('#element3'), { duration: 600, opacity: 1, scale: 1.2, easing: 'easeOutBounce' }); return timeline; } // Trigger animation on scroll export function setupScrollAnimation() { let animated = false; $w('#animationTrigger').onViewportEnter(() => { if (!animated) { animated = true; const timeline = createTimelineAnimation(); timeline.play(); } }); }

 

Scroll-Triggered Effects

Implement parallax and scroll effects:

export function setupParallaxEffect() { let lastScrollY = 0; wixWindow.addEventListener('scroll', () => { const scrollY = wixWindow.scrollY; const speed = 0.5; // Parallax speed // Background parallax $w('#backgroundImage').style.transform = `translateY(${scrollY * speed}px)`; // Fade in elements $w('.fadeInElement').forEach(element => { const elementTop = element.getBoundingClientRect().top; const windowHeight = wixWindow.innerHeight; if (elementTop < windowHeight * 0.8) { element.show('fade', {duration: 1000}); } }); // Update progress bar updateScrollProgress(scrollY); lastScrollY = scrollY; }); } function updateScrollProgress(scrollY) { const docHeight = document.body.scrollHeight - wixWindow.innerHeight; const progress = (scrollY / docHeight) * 100; $w('#progressBar').style.width = `${progress}%`; }

 

Custom Loading States

Create engaging loading experiences:

export class LoadingManager { constructor() { this.loadingElement = $w('#customLoader'); this.progressBar = $w('#loadingProgress'); this.loadingText = $w('#loadingText'); } async showLoader(loadingSteps) { this.loadingElement.show(); let currentStep = 0; for (const step of loadingSteps) { this.loadingText.text = step.message; // Execute step await step.action(); // Update progress currentStep++; const progress = (currentStep / loadingSteps.length) * 100; this.progressBar.style.width = `${progress}%`; // Smooth animation await this.delay(300); } await this.hideLoader(); } async hideLoader() { await this.loadingElement.hide('fade', {duration: 500}); } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } // Usage const loader = new LoadingManager(); await loader.showLoader([ { message: 'Loading user data...', action: () => loadUserProfile() }, { message: 'Fetching content...', action: () => loadDynamicContent() }, { message: 'Preparing dashboard...', action: () => setupDashboard() } ]);

 

Interactive UI Components

Build custom interactive components:

export class InteractiveCard { constructor(cardElement) { this.card = cardElement; this.isFlipped = false; this.setupInteractions(); } setupInteractions() { // 3D flip effect this.card.onMouseIn(() => { this.card.style.transform = 'scale(1.05)'; this.card.style.boxShadow = '0 10px 30px rgba(0,0,0,0.3)'; }); this.card.onMouseOut(() => { this.card.style.transform = 'scale(1)'; this.card.style.boxShadow = '0 5px 15px rgba(0,0,0,0.1)'; }); this.card.onClick(() => { this.flipCard(); }); } flipCard() { if (this.isFlipped) { this.card.style.transform = 'rotateY(0deg)'; $w('#cardFront').show(); $w('#cardBack').hide(); } else { this.card.style.transform = 'rotateY(180deg)'; $w('#cardFront').hide(); $w('#cardBack').show(); } this.isFlipped = !this.isFlipped; } }

Conclusion

 

Wix Velo transforms Wix from a simple website builder into a powerful development platform. By combining visual design with custom code, you can create sophisticated web applications whilst leveraging Wix's infrastructure and tools.

Start with simple customisations and gradually build your expertise. The combination of Wix's visual editor and Velo's coding capabilities offers unlimited possibilities for creating unique, functional websites that meet specific business requirements.

Remember to follow best practices, keep security in mind, and leverage the extensive Wix Velo API documentation as you develop. With practice and experimentation, you'll be building complex web applications on Wix in no time.

 

Additional Resources

 

Start your Wix Velo journey today and unlock the full potential of your Wix website!

bottom of page