A beautiful scrollytelling experience showcasing Cloudinary's image transformations with D3.js animations and Tailwind CSS.
The little Cloudicorn is generated by ChatGPT and will soon be replaced by an artist's render!
- 🌟 Interactive scrollytelling with D3.js starfield animations
- 🎨 Cloudinary image transformations (background removal, artistic effects, generative AI)
- 🎯 Smooth scroll-triggered image transitions
- 📱 Responsive design with Tailwind CSS
- ⚡ Optimized for performance
-
Install dependencies:
npm install
-
Start development server:
npm run dev
-
Build for production:
npm run build
- Push your code to GitHub/GitLab/Bitbucket
- Go to netlify.com and sign up/login
- Click "New site from Git"
- Connect your repository
- Configure build settings:
- Build command:
npm run build - Publish directory:
.
- Build command:
- Click "Deploy site"
-
Install Netlify CLI:
npm install -g netlify-cli
-
Login to Netlify:
netlify login
-
Initialize and deploy:
netlify init netlify deploy --prod
- Run
npm run buildlocally - Go to netlify.com
- Drag your project folder to the deploy area
scroll-d3/
├── index.html # Main HTML file
├── main.js # D3.js and scroll logic
├── style.css # Tailwind CSS input
├── dist/output.css # Compiled CSS (generated)
├── netlify.toml # Netlify configuration
├── netlify/functions/ # Serverless (submit-challenge → Google Sheets)
├── package.json # Dependencies and scripts
└── README.md # This file
This demo showcases various Cloudinary transformations:
- Background Removal:
e_background_removal - Generative Recolor:
e_gen_recolor:prompt_goggles;to-color_red - Artistic Effects:
e_art:aurora - Opacity Control:
o_30 - Generative Background Replace:
e_gen_background_replace - Pixelation:
e_pixelate:20
- D3.js - Data visualization and animations
- Tailwind CSS - Utility-first CSS framework
- Cloudinary - Image transformations and optimization
- Intersection Observer API - Scroll detection
- Netlify - Hosting and deployment
There is an optional Cloudinary transformation quiz. Add ?quiz=true to the URL to show it (for example for booth prizes or swag). Scores of 80% or higher (4 of 5 correct) are treated as eligible for swag in the app UI.
The Prize challenge control scrolls to #prize-lab, sets ?challenge=true, and adds an event slug from each button’s data-event (default in CONFIG.PRIZE_CHALLENGE.DEFAULT_EVENT). Example: ?challenge=true&event=wearedevs2026.
Participants paste two full Cloudinary delivery URLs: generative background replace with a prompt_, and generative replace with from_ and to_, each chained with f_auto and q_auto. Rules live in CONFIG.PRIZE_CHALLENGE.TASKS in main.js and are mirrored in netlify/functions/submit-challenge.js. Submit entries stays disabled until both Check URL steps pass.
Client POST JSON to /.netlify/functions/submit-challenge by default (CONFIG.PRIZE_CHALLENGE.SUBMIT_ENDPOINT), or override with <meta name="challenge-submit-endpoint" content="https://...">. Body shape: { event, eventName, fullName, cloudName?, url1, url2 } (cloudName optional; both task URLs validated server-side).
- Create a Google Sheet and a tab (e.g.
Submissions). The function appends rows:timestamp,event,eventName,fullName,cloudName,url1,url2. - In Google Cloud, create a service account, enable Google Sheets API, and create a JSON key.
- Share the spreadsheet with the service account email (Editor).
- In Netlify → Site configuration → Environment variables set:
GOOGLE_SERVICE_ACCOUNT_EMAIL—client_emailfrom the JSONGOOGLE_PRIVATE_KEY—private_keyfrom the JSON (includeBEGIN/ENDlines; in the Netlify UI you can paste multiline keys)CHALLENGE_SHEET_ID— ID from the spreadsheet URLCHALLENGE_SHEET_TAB— tab name (optional; defaultSubmissions)
If these are missing, the function responds with 503 and a JSON message (expected when testing static files without Netlify).
npm install -g netlify-cli
netlify devUse the printed URL so /.netlify/functions/submit-challenge resolves. Provide the same env vars (e.g. netlify env:pull or project .env for the CLI).
docs/challenge-sheet-apps-script.md describes a Google Apps Script Web App if you cannot use Netlify Functions.
MIT License - feel free to use this template for your own projects!