A configurable, interactive "Year in Review" web application inspired by the many "Wrapped" apps that exist. It features auto-advancing slides, progress bars, and rich animations to present annual data in an engaging story format.
- Interactive Story Engine: Auto-plays slides with pause/resume support (hold to pause).
- Responsive Design: Full-screen immersive experience on mobile, sleek card layout on desktop.
- Rich Slide Types:
- Intro/Outro: Big bold typography.
- Big Stat: Highlight key numbers.
- Top List: Staggered list animations for top items (e.g., songs, languages).
- Themeable: Dynamic background colors per slide.
- No Build Step: Pure HTML/CSS/JS for maximum simplicity and speed.
You can run this project directly on your machine:
- Simple Method: Just double-click
index.htmlto open it in your web browser. - Better Method (for exact mobile testing): Use a local development server.
- If you have Node.js installed:
npx serve . - Or use the "Live Server" extension in VS Code.
- If you have Node.js installed:
This project is a static site, making it perfect for Cloudflare Pages.
- Clone this project https://github.com/halans/annual-wrapup.git and push it to your Git repository.
- Log in to the Cloudflare Dashboard.
- Go to Workers & Pages > Create Application > Pages > Connect to Git.
- Select your repository.
- Build Settings:
- Framework Preset: None (it's static).
- Build Command: (Leave empty).
- Build Output Directory:
.(or just leave empty/default if it serves root).
- Click Save and Deploy.
- Go to Workers & Pages > Create Application > Pages > Upload Assets.
- Drag this entire project folder into the upload zone.
- Deploy!
If you prefer the command line:
# Install Wrangler if you haven't
npm install -g wrangler
# Login
npx wrangler login
# Deploy current directory
npx wrangler pages deploy . --project-name=my-year-in-reviewThe data.js file contains the WRAP_UP_DATA object. You can configure global metadata and the list of slides here.
In meta, you can set:
slide_duration: Time in milliseconds (e.g.,5000for 5s).theme_color: App accent color.
In each slide object, you can set:
bg_color: Background color (Hex code"#000"or name).text_color: Text color (Hex code"#fff"or name).
1. Intro / Outro (type: "intro" or "outro")
Used for the cover page or closing message.
title: Main headline text.subtitle(optional): Smaller sub-text.
{
"type": "intro",
"title": "2025 Wrapped",
"subtitle": "What a year!",
"bg_color": "#6200EA"
}2. Big Stat (type: "stat")
Used to highlight a single large number or metric.
value: The big number/text (e.g., "12,400", "Top 1%").label: The description below the number.
{
"type": "stat",
"value": "15,000",
"label": "Minutes Listened",
"bg_color": "#03DAC6"
}3. Top List (type: "list")
Used to show a ranking (e.g., Top Songs, Top Friends).
title: Header for the list.items: An array of strings to display in order.
{
"type": "list",
"title": "Top Genres",
"items": ["Pop", "Rock", "Indie"],
"bg_color": "#FFC107"
}4. Photo Slide (type: "photo")
Used to display a full-screen background image with overlay text.
image: URL to the image (can be local or remote).title: Overlay title.
{
"type": "photo",
"title": "Best Memory",
"image": "https://example.com/photo.jpg"
}Global styles are defined in style.css using CSS variables.
To change the font:
- Import your desired font in
index.html(e.g., from Google Fonts). - Update the variable in
style.css:
:root {
--font-main: 'Your New Font', sans-serif;
}To change default colors:
Edit the :root variables in style.css:
:root {
--bg-color: #121212; /* Fallback background */
--accent-color: #BB86FC; /* Main accent */
--progress-bar-bg: rgba(255, 255, 255, 0.3);
}- HTML/CSS: Create a new layout class in
style.css(e.g.,.slide-photo). - JS: Update
renderSlideContentinapp.jsto handle your newtype(e.g.,if (data.type === 'photo') ...).
Created with Google Antigravity.