A hand‑crafted digital love letter. Interactive, nostalgic, and deeply personal.
lovescript is a single‑page, vanilla‑code web experience built for one special person. It guides the viewer through a series of emotionally charged scenes — each one a step in a story — before revealing a handwritten letter that types itself out, word by word.
Every visual detail is deliberate: soft vintage paper textures, falling petal‑like particles, a playful “no” button that literally runs away, and a thoughtfully integrated music player that shifts to a more romantic tune at the story’s peak.
It’s not just a webpage; it’s a keepsake.
Six seamlessly transitioning scenes, each with its own message, mood, and visual treatment. Navigation progresses the story, culminating in an interactive notepad.
- Starts with one background song, then switches to a second track when the letter appears.
- Full play/pause control and a seek bar.
- Widget slides up from the bottom after the user’s first interaction.
The final scene simulates a spiral‑bound notebook:
- Realistic paper texture with margin lines.
- A glowing cursor that types the letter character by character.
- Handwritten‑style font (Caveat) for an authentic feel.
The secondary button on the opening screen moves to a random position on hover (desktop) or touch (mobile), making it impossible to press — a lighthearted nudge to choose “yes”.
Soft, semi‑transparent petals drift slowly across the background, adding a dreamlike atmosphere without distracting from the text.
Designed mobile‑first with clamp() for typography, flexible layouts, and no horizontal scroll. Looks elegant on every screen, from a small phone to a desktop browser.
Zero frameworks, zero libraries. All HTML, CSS, and JavaScript are hand‑written and self‑contained. The aesthetic comes from careful use of colors, noise textures, and subtle shadows.
lovescript/
├── index.html # Entire app (HTML + CSS + JS)
├── bizimsarkimiz.mp3 # First song (plays on launch)
├── romantiksarkimiz.mp3 # Second song (plays on the letter scene)
├── favicon.png # Favicon & Open Graph image
└── README.md
git clone https://github.com/akakadir/lovescript.git
cd lovescriptPlace your own music files in the project root:
bizimsarkimiz.mp3– the initial background track.romantiksarkimiz.mp3– the romantic track that starts on the notepad scene.
Alternatively, you can use the existing filenames and update the <source> tags inside index.html.
Replace favicon.png with a square PNG (at least 180×180 px). The same image is used for the Open Graph preview when sharing the link.
You can simply open index.html in a browser, but for the best experience, serve it locally because some browsers block autoplay when files are opened directly.
# Using Python
python -m http.server 8000
# Or with Node (if you have npx)
npx serve .Then visit http://localhost:8000.
Everything is designed to be easily personalised without touching a build tool.
| What to change | Where to do it |
|---|---|
| Scene text | Inside the <section class="scene"> blocks in index.html — each section is a step. |
| Letter content | The notepadLines array at the bottom of the <script> tag. Write your message line by line. |
| Song titles & artist | Update the switchToRomanticSong() function and the .song-info span. |
| Colors & theme | CSS custom properties under :root (around line 62). Change --bg, --accent, --text-main, etc. |
| Particle behaviour | Inside createParticles() — adjust the loop count, size, or animation duration. |
| Typing speed | Modify the delays in typeChar() — faster, slower, or randomised to taste. |
- HTML5 – semantic structure with ARIA‑friendly elements.
- CSS3 – custom properties, keyframe animations, backdrop‑filter,
clamp()for fluid typography, noise‑based textures. - Vanilla JavaScript – scene management, audio API control, typewriter effect, DOM manipulation, touch event handling.
- Audio handling uses the Web Audio API indirectly through an
<audio>element. The seek bar synchronises with playback time, and the UI updates dynamically. - The “No” button recalculates its position relative to its container using
getBoundingClientRect()andtransform, ensuring it stays within the viewport. - Typewriter effect recursively calls
setTimeout()with varying delays based on character type (newlines, punctuation, spaces) for a natural rhythm. - Scene transitions rely on CSS opacity, transform, and visibility toggling with
setTimeoutfor a staggered reveal. - Performance – particle count is capped at 25, and all animations are GPU‑friendly (opacity, transform). No repaints are forced during typing.
This project is licensed under the MIT License.
See the LICENSE file for details.
You are free to use, modify, and distribute it.
If it brings a smile to someone, a star ⭐ on the repository would be a lovely gesture.
Crafted with love, late‑night caffeine, and a dash of “acaba bu sefer çalışacak mı?”.
The real Tuğba inspired every typed line and every hidden detail.
“The most meaningful scripts are the ones that compile straight from the heart.”
Built with vanilla everything · © 2026 akakadir