Building a URL-Shareable Video Chain Player with Vite + React (State Sync / i18n / AWS Deployment)
Building a URL-Shareable Video Chain Player with Vite + React
What is This?
I built Video Chain Player, a web app that lets you "chain together only the necessary segments of videos and play/share them as a single experience."
🔗 Try it now: https://video-chain-player.sloth255.com/
- Clip a video by specifying start and end times
- Chain (queue) multiple clips for continuous playback
- Encode the chain state into a URL and share with a single link
Perfect for creating "show only this part" experiences like workout flows, lecture highlights, or compilation reels.
What Users Can Do
- Create clips: Add videos by entering URL/ID and start/end times
- Reorder: Adjust the sequence with drag & drop
- Preview: Play on the spot to verify timing
- Share: Copy the URL and send it (recipients open the same chain)
- Multilingual: Switch languages via URL (e.g.,
?lang=ja)
Tech Stack
| Area | Technology | Notes |
|---|---|---|
| Frontend | React 18 + TypeScript | UI maintainability and type safety |
| Build/Dev Server | Vite | Fast HMR, great DX |
| Routing | React Router v6 | Express state via path + query |
| State Management | Zustand | Lightweight, suitable for URL sync |
| Drag & Drop UI | @dnd-kit | Implement reordering |
| Video Player | react-youtube (IFrame Player API) | Quick embedded playback |
| i18n | i18next + react-i18next | Translate all UI strings |
| Translation Loading | i18next-http-backend | Runtime fetch from /public/locales/... |
| Language Detection | i18next-browser-languagedetector | Priority: ?lang= / localStorage / browser |
| Analytics | GA4 (gtag) | SPA page_view + custom events |
| Hosting | S3 Static Site + CloudFront | CDN delivery |
| IaC | AWS SAM Template | Manage S3/CloudFront as code |
| CI/CD | GitHub Actions + OIDC | Deploy without long-term keys |
| Testing | Vitest + Testing Library | Test components/logic |
| Lint/Format | ESLint + Prettier | Prevent breaking changes |
Architecture and Implementation Highlights
1) Sync Zustand State to URL for Instant Sharing
To minimize sharing friction, I designed the app to encode the chain's essential information into the URL.
- No server-side storage (no account needed)
- Recipients can reproduce the same state by just opening the link
To prevent URL bloat (which makes sharing difficult), I minimized the information encoded in the URL.
- Encode only video
idandstart/endtimes - Supplement titles and thumbnails later for display (prevents URL bloat)
Example of minimal encoding:
// Encode only essential info (id/start/end) in URL
const minimalSegments = segments.map(({ id, start, end }) => ({ id, start, end }));
Additionally, shared links don't include playback position (which clip is playing), ensuring "opening the link starts from the beginning."
2) Runtime i18n Loading via HTTP Backend (Build-Independent)
Initially, I considered importing translation JSONs at build time, but for better compatibility with static hosting and CI, I opted to fetch via HTTP from /public/locales/{{lng}}/translation.json.
- Easy to maintain—just add language files
- Build process doesn't depend on translation imports
3) Language Switching Syncs with URL (?lang=) and Persists When Shared
i18n isn't just in-page switching; it also works via URL query parameter lang.
/→ Default language (English)/?lang=ja→ Japanese
The language selector updates lang (removes lang for English to keep URLs clean).
const params = new URLSearchParams(searchParams);
if (langCode !== 'en') params.set('lang', langCode);
else params.delete('lang');
navigate(params.toString() ? `?${params}` : '/', { replace: true });
4) Handle URL Variations Robustly (watch / Shorts / embed)
Supporting "only standard URLs" would be inconvenient, so I expanded the input patterns:
- Standard watch URLs
- Shorts
- Embed URLs
As a result, "just paste" success rate increased, making batch registration much easier.
5) Deployment: S3 + CloudFront, CI: GitHub Actions (OIDC)
Since it's a static site, deployment is straightforward:
- S3 (static hosting)
- CloudFront (CDN)
CI/CD is automated via GitHub Actions: build → S3 sync → CloudFront cache invalidation.
The key point is OIDC, enabling deployment without storing long-term keys (minimizing Secrets while maintaining environment-level control).
Even for static sites, putting CloudFront in front provides:
- Fast loading via caching
- Easy SPA routing assistance (e.g., fallback to
/)
Summary
Video Chain Player focuses on "clips × continuous playback × URL sharing," with emphasis on:
- Encoding state in URLs to minimize sharing friction
- i18n + language URL sync so recipients see the same language
- Making it "production-ready" including deployment and analytics
Technically, I was able to combine:
- Rapid development with Vite
- Syncing Zustand state to URLs for better shareability
- Lightweight translation management with i18next's HTTP backend
- Secure deployment with OIDC
Building this "full operational stack" in one go was the highlight.