🇰🇭 Cambodian Social · Reels · Marketplace

One platform to connect, watch & sell

Leng Social blends a full news feed & stories, a Watch video hub and a TikTok-style Reels engine driven by an FFmpeg → adaptive-HLS pipeline, a marketplace with cart & checkout, a seller store back-office & POS, messaging & push — and a complete Admin control center, on web, PWA, iOS & Android.

240+REST endpoints
ABR HLSAdaptive video
4Platforms
50Data tables
The Platform

Everything in one social super-app

A vertically-integrated social + video + commerce platform — from a raw video upload to a fulfilled order, tracked end to end.

Feed & Stories

Infinite-scroll feed with a text/photo/video composer, 7 reactions, polls, feelings, colored backgrounds, threaded comments, share, save — plus stories with viewer lists & reaction taps.

Reels Engine

Vertical scroll-snap short-video feed on adaptive HLS: double-tap like, soundtracks, categories, drama seasons & episodes, comments, saves — and sponsored slides interleaved in the feed.

Watch

A landscape video hub with per-category browse rows and a custom player — draggable seek with buffer, volume, 0.5–2× speed, Picture-in-Picture, fullscreen and keyboard shortcuts.

Marketplace

Listings with galleries, categories & live search, cart and checkout, orders, saves, seller inquiries — and a dynamic QR code on every product page.

Store & POS

A per-seller back-office: sales dashboard, products with variants & stock, an in-store POS, order fulfilment with delivery service & tracking, and an inquiry inbox.

Messaging & Push

1-to-1 chat with a conversation list, unread badges and image attachments; a notification center; native push (APNs/FCM) and web push with tap-to-open deep links.

Pages, Groups & Events

A shared CMS engine — Pages, Groups, Events, Blogs and Offers — each with categories, covers, likes, invites and its own posting timeline.

People & Profiles

Profiles with covers & follows, friend requests, people-you-may-know, verified badges, user groups, block & report — and 16 per-user privacy visibility controls.

Admin Control Center

A full back-office: users & permission groups, approvals, content moderation, reels ads, the music library, the Money modules, customization and 15 groups of system settings.

Changelog

Recent Updates

What shipped most recently on Leng Social.

Jul 142026
Stories

Story viewers & reactions

Stories now show exactly who watched, with an animated viewer ticker and a per-reaction tap counter. Posts gained a “who reacted” modal, and long captions fold behind a “See more”.

Jul 92026
Upload

Searchable categories & music in the composer

The video composer got a type-ahead category picker with an inline “+ New” option, so a category can be created without leaving the upload panel — and the music library is searchable too.

Jul 42026
Privacy

Privacy controls & account security

16 “who can see X” privacy settings are now enforced across the API — profile fields, messaging, chat and suggestions. The admin Edit-user panel gained Security & Membership tabs with live sessions.

Jul 32026
Auth

Sign in with Apple & phone-number logins

Sign in with Apple landed in the iOS app alongside Google, Facebook and Telegram OTP. Telegram signups now take the local phone number as their username (+855 12 890 323 → 012890323).

Jun 26–272026
Video

Big-video uploads & import by link

Large videos now upload in chunks (past the 100 MB edge limit) and reassemble server-side, while a pasted YouTube link imports straight through yt-dlp → FFmpeg → HLS, with 1080p H.264 enforced and proxy-session rotation on blocks.

Jun 22–252026
Modules

CMS modules, reactions & sharing

Pages, Groups, Events, Blogs and Offers arrived as first-class modules, along with 7-way reactions, share-to, verified badges, invite codes, discovery search and server-rendered OpenGraph previews for shared links.

Jun 202026
Native

Native apps, messaging & push

Native iOS & Android apps (a Capacitor shell over the web app) shipped with 1-to-1 messaging, APNs/FCM + web push, password reset by email, saved posts, and the Privacy Policy & data-deletion pages.

Product Tour

See it in action

Real screens captured from the live iOS & Android app.

News feed
📰 News feed & stories
Reels player
🎬 Vertical reels player
Watch video hub
📺 Watch & category rows
Marketplace
🛍️ Marketplace & categories
Profile
👤 Profile & follows
Store dashboard
📊 Store dashboard
Store products
📦 Products & stock
Order fulfilment
🚚 Order fulfilment
← scroll to see more →
Video Processing & Convert Pipeline

From upload to adaptive stream, automatically

Every reel and Watch video is transcoded into a multi-rendition HLS ladder in a single FFmpeg pass and delivered from a global CDN — including one-tap import from a YouTube link.

1

Upload

Direct upload, or <96 MB chunks reassembled server-side (2 GB cap).

2

Thumbnails

FFprobe reads duration; 5 candidates at 10/25/50/75/90% — the creator picks the cover.

3

Music Mix

Optional soundtrack, trimmed with -ss and muxed to H.264 + AAC.

4

ABR Ladder

One FFmpeg pass → up to 3 renditions + a master.m3u8.

5

CDN Deliver

Pushed to Cloudflare R2 over the S3 API with 6 MB multipart.

6

Playback

HLS.js over the CDN, or the same-origin proxy.

// videoProcessor.js — processMedia()
raw.mp4
  ├─ ffprobe            → duration, width/height, has-audio, codecs
  ├─ ffmpeg thumb ×5    → scale=720:-2  -q:v 3   → R2  <prefix>/thumbs/*.jpg
  ├─ ffmpeg music mix   → -map 0:v:0 -map 1:a:0 -shortest -movflags +faststart
  ├─ ffmpeg ABR ladder  → split=N → scale short-side 1080/720/480/360 (max 3)-hls_time 4  -hls_playlist_type vod  -hls_flags independent_segmentsmaster.m3u8 + v0/ v1/ v2/ playlist.m3u8 + seg###.ts
  ├─ upload tree ×8     → Cloudflare R2 (S3 API), 6 MB multipart over 6 MB
  └─ cleanup            → every temp file removed in finally{}

fallbacks:  ABR ladder ─✗→ single-rendition HLS ─✗→ raw .mp4 upload
delivery:   https://<cdn>/<prefix>/<uuid>/master.m3u8
             GET /api/reels/hls/:uuid/*   ← same-origin proxy, whitelisted filenames

Import by Link

Paste a YouTube link → yt-dlp downloads it → FFmpeg → HLS → a native reel or Watch video. The height is verified with FFprobe, and an SD or blocked attempt rotates to a fresh proxy session until HD lands.

Background Jobs

Heavy transcodes run outside the HTTP request: finalize returns a jobId instantly and the client polls GET /api/jobs/:id — so a long encode never trips the 100-second edge timeout. Jobs expire 15 minutes after creation.

Graceful Fallbacks

If the ladder fails the pipeline falls back to single-rendition HLS, then to a raw MP4 upload — a reel is never lost to an encoder error. The HLS proxy also retries legacy key prefixes so older posts keep playing.

The Reels & Watch experience

Two video surfaces — a full-screen vertical feed for short video, and a landscape hub for long-form — both riding the same HLS pipeline.

Muted autoplay Scroll-snap feed Double-tap to like Draggable seek bar Category browse rows Music & soundtracks Drama seasons & episodes Comments · Save · Share Picture-in-Picture 0.5–2× speed View counting Interleaved ads
Drama seriesGroup reels into a titled season with numbered episodes, and an episode strip for binge-watching from inside the player.
Music & trimmingPick from the admin-curated library or upload your own MP3, set a trim point, and FFmpeg mixes it into the video itself.
Reels advertisingSponsored slides inject every N reels with a CTA button, optional skip-after timer, VAST tag support, and impression & click counters.
Creator toolsCreate a category inline from the composer, choose the cover frame, set a separate landscape share image for link previews — and admins can post on another user's behalf or onto a Page timeline.
The Social Layer

Feed, stories & conversation

A complete social layer — post, react, comment, share, follow and chat.

The composer

  • Text, photos, galleries and video
  • Polls with live vote tallies
  • Feelings & colored backgrounds
  • Scheduled publishing & pre-approval
  • Post onto a Page timeline

Reactions & engagement

  • 7 reactions — 👍 😍 😁 😆 😮 😢 😠
  • A “who reacted” modal, split by type
  • Threaded comments with replies
  • Re-share to your feed or copy the link
  • Save posts to revisit later

Stories

  • Photo & video stories (video runs the HLS pipeline)
  • A full viewer list with an animated ticker
  • Reaction taps — every tap is counted
  • Per-slide duration set by the admin

People & graph

  • Follows plus friend requests
  • People-you-may-know & suggestions
  • Verified badges & user groups
  • Block, report & privacy controls
  • Invite codes for closed signup

Messaging

  • 1-to-1 chat with a conversation list
  • Image attachments & unread badges
  • People search to start a thread
  • Honors the “who can message me” setting

Notifications

  • In-app center with a bell & unread count
  • Native push over APNs & FCM
  • Web push (VAPID) for the PWA
  • Tap-to-open deep links into the right screen
Commerce

Marketplace & store management

A complete selling loop — from product discovery to a delivered order — plus a back-office for every seller.

For buyers

Discovery and checkout that feel like part of the social app, not a bolted-on shop.

Categories & live search Product galleries Variants & stock Cart Checkout Order tracking Saved listings Contact seller Dynamic QR codes Featured listings
Seller dashboardSales by day/week/month, new orders, best-selling products and low-stock warnings, all on one panel.
In-store POSRing up a walk-in sale straight from the same catalog — a POS sale draws down the same stock as an online order.
Order fulfilmentMove an order through its statuses, attach a delivery service and tracking number, and the buyer is notified at each step.
Catalog & inboxOne product form backs both the marketplace listing and the POS catalog, while buyer inquiries land in the store's own inbox.
Control Center

The Admin suite

A fixed-sidebar back-office covering users, content, modules, money, customization and system settings.

DashboardLive stats
UsersFiltered lists · stats
PermissionsGroups & roles
ApprovalsUsers & posts
PostsContent & media
ReelsModeration
Reels AdsCampaigns · VAST
MusicTrack library
Upload MediaPost on behalf
ProductsListings
CommentsModeration
ReportsUGC safety
StoriesManagement
Pages+ categories
Groups+ categories
Events+ categories
Blogs+ categories
Offers+ categories
Pro SystemPackages · subscribers
MoneyPayments · orders
CustomizationWidgets · reactions
Settings15 groups

Users & access

A multi-tab Edit-user panel (Account · Profile · Privacy · Security · Membership), user & permission groups, login-as, live session control, CSV export, and filtered lists for moderators, admins, online, banned and not-activated accounts.

Content & safety

Approval queues for posts and new users, deletion across posts / reels / comments / listings / stories, and a report queue covering posts, reels, comments, messages and users — plus blocking and bans with a custom message.

Customization

Custom profile fields, static pages, colored post patterns, placement-aware HTML widgets, reactions, emojis, stickers and gifts — all editable from the admin without a code deploy.

Reach

Platform & infrastructure

Native apps

iOS & Android apps built with Capacitor around the same web bundle — shipping on the App Store worldwide, with push, sharing and Sign in with Apple.

PWA

Installable, with a manifest, maskable icons, a network-first service worker with an offline shell, and VAPID web push.

Sign-in

Email & password (bcrypt + JWT), Google, Facebook, Sign in with Apple, and Telegram Gateway OTP with phone-number normalization.

SEO & sharing

Server-rendered OpenGraph pages for /post/:id and /reels/:id, so links shared elsewhere unfurl with the right image, title and video.

Moderation & trust

A zero-tolerance EULA accepted before account creation, Report on every UGC surface, user blocking, and self-serve account deletion.

Privacy

16 “who can see X” settings ranging over everyone / people I follow / people who follow me / only me — enforced server-side across profiles, messaging, chat and suggestions.

Media CDN

Images, thumbnails and HLS segments live on Cloudflare R2 and stream from the CDN, with a same-origin proxy for playback that must avoid cross-origin fetches.

Module switches

Watch, Reels, Marketplace, Stories, Messenger and People each toggle from the admin — switching one off hides it from the nav and bounces direct URLs back to the feed.

System Design

Architecture

A single Express API and SQLite core, fronted by a no-build-step SPA and backed by a media-processing pipeline and a global CDN.

01 — Clients
Web · vanilla-JS SPA, hash routing PWA (installable, offline shell) iOS & Android · Capacitor
02 — Edge & CDN · Cloudflare
DNS + TLS R2 object storage (S3 API) CDN — HLS + images Service worker
03 — Application · Nginx → Express (PM2)
Nginx reverse proxy + static docroot Express REST API SQLite · better-sqlite3 (WAL) JWT auth + roles EC2 · HestiaCP · PM2
04 — Media pipeline & integrations
FFmpeg / FFprobe → ABR HLS yt-dlp import Firebase FCM · APNs · Web Push Telegram Gateway OTP Nodemailer (SMTP)
Developer

REST API surface

A cohesive, role-guarded API — a representative slice of the 240-plus endpoints.

Auth

POST/api/register · /api/login
POST/api/auth/google · /apple · /facebook
POST/api/auth/telegram/send · /verify
POST/api/auth/forgot · /reset
GET/api/me

Reels & video

GET/api/reels · /api/videos
POST/api/upload/chunk
POST/api/reels/upload-video-temp
POST/api/reels/finalize · /from-url
GET/api/jobs/:id
GET/api/reels/hls/:uuid/*

Feed & social

GET/api/feed · /api/stories
POST/api/posts · /:id/react · /poll-vote
GET/POST/api/posts/:id/comments
POST/api/users/:id/follow · /block
GET/api/suggestions · /api/search

Marketplace

GET/api/marketplace · /:id
*/api/cart · /api/checkout
GET/api/orders · /orders/:id
POST/api/marketplace/:id/contact · /save

Store & messaging

GET/api/store/dashboard · /orders
POST/api/store/pos-sale
*/api/store/catalog · /products
*/api/messages/with/:userId
POST/api/push/register · /webpush/subscribe

Platform & admin

GET/api/site
GET/api/notifications · /unread-count
*/api/cms/:type · /api/admin/cms/:type
*/api/admin/* (guarded)
GET/post/:id · /reels/:id (OG)
Under the Hood

Technology

Vanilla JS SPA (no build step) Node.js · Express 4 SQLite · better-sqlite3 (WAL) HLS.js FFmpeg · FFprobe yt-dlp Cloudflare R2 (S3 API) Capacitor 8 (iOS/Android) Firebase Cloud Messaging Web Push (VAPID) JWT · bcrypt multer · Nodemailer Nginx · PM2 · HestiaCP Service Worker / PWA Suwannaphum (Khmer-first type)
Reference

Per-module deep dives

Expand any module for how it actually works under the hood.

Video Processing & Convert Pipeline
  • Ingest: small files POST straight to the server; anything larger is split client-side into sub-96 MB chunks against /api/upload/chunk and appended into one assembly file, capped at 2 GB. Assemblies are namespaced per user id so two uploads can never collide, and abandoned parts are swept after an hour.
  • Probe & thumbnails: FFprobe reads duration, dimensions, audio presence and codecs. Five candidate thumbnails are cut at 10 / 25 / 50 / 75 / 90 % of the timeline (scale=720:-2, -q:v 3) and uploaded so the creator can choose the cover.
  • Optional music: a library track or an uploaded MP3 is seeked with -ss, mapped over the original audio (-map 0:v:0 -map 1:a:0), cut to -shortest, and re-encoded to H.264 baseline + AAC with +faststart.
  • ABR ladder: a single FFmpeg pass splits the video into up to three renditions chosen from the short side — 1080 / 720 / 480 / 360 — so portrait and landscape sources both ladder correctly. Output is master.m3u8 plus v0/ v1/ v2/ variant playlists with 4-second, independent segments.
  • Storage: the whole HLS tree is uploaded to Cloudflare R2 over the S3 API, 8 files in flight, with 6 MB multipart for anything over 6 MB and correct content types (application/vnd.apple.mpegurl, video/mp2t).
  • Delivery: playback prefers the direct CDN master playlist; where a cross-origin fetch would break, GET /api/reels/hls/:uuid/* proxies the same bytes same-origin behind a strict filename whitelist — playlists no-cache, segments cached a day — and falls back to legacy key prefixes so older posts still resolve.
  • Resilience: ladder failure drops to single-rendition HLS, and a total encoder failure still uploads the raw MP4. Every temporary file is deleted in a finally block, whichever path ran.
videoProcessor.jsFFmpegFFprobeHLS.jsCloudflare R2@aws-sdk/client-s3
Link import & background jobs
  • Import by link: POST /api/reels/from-url and /api/videos/from-url take a YouTube URL, validate it, then hand it to yt-dlp. The downloaded file's height is checked with FFprobe; anything below the HD threshold rotates to a fresh proxy session and retries, so a throttled or SD-only session doesn't become a low-quality reel.
  • Two-phase finalize: the fast temp upload happens first so the composer stays responsive; the heavy transcode only runs on finalize.
  • Job queue: startJob() hands back a jobId immediately and runs the encode off the request. The client polls GET /api/jobs/:id for processing / done / error; entries self-expire 15 minutes after creation. This is what keeps a five-minute encode from hitting the 100-second edge timeout.
  • On behalf of: an admin can attribute an upload to another user, or attach it to a Page timeline, without leaving the composer.
yt-dlpstartJob/api/jobs/:idproxy rotation
Reels engine & Watch
  • A vertical, scroll-snap feed with muted autoplay driven by IntersectionObserver, double-tap-to-like with a heart burst, a spinning music disc and a global mute toggle.
  • Browse mode lays reels out as per-category portrait carousels; Watch does the same for landscape video with its own custom player — draggable seek with a buffer indicator, volume, 0.5–2× speed, Picture-in-Picture, fullscreen and keyboard shortcuts.
  • Drama series: a reel can carry a series title, season and episode number, and the player exposes an episode strip for binge-watching.
  • Ads: sponsored slides interleave every N reels (admin-configurable) with CTA text and URL, optional skip-after timer, VAST tag support, and fire-and-forget impression & click counters.
  • Likes, saves, view counts and threaded comments are tracked per reel, and every reel also creates a feed post so it surfaces in the timeline.
IntersectionObserverreels_categoriesreels_adsdrama_season
Feed, stories & engagement
  • The composer handles text, single photos, galleries and video, plus polls, feelings, and colored background patterns curated from the admin.
  • Seven reactions (like, love, haha, yay, wow, sad, angry) are themselves admin-editable rows — title, emoji, color and enabled flag — and a modal breaks down exactly who reacted with what.
  • Posts support threaded comments, re-share to your own feed, share-to a specific destination, saving, view counting, scheduled publishing and optional pre-publication approval.
  • Stories run 3 days in the bar, carry photo or video (video going through the same HLS pipeline), record a de-duplicated viewer list, and count every reaction tap — including repeats — so a story shows real enthusiasm rather than unique voters.
postspost_reactionspoll_votesstory_viewscolor_patterns
Marketplace, store & POS
  • Listings carry photo galleries, categories, price, location, stock and named variants, and every product page renders a dynamic QR code for offline sharing.
  • Buyers get live search across products, reels, posts, users and categories; a cart with quantity edits; checkout capturing name, phone, address, city, note and payment method; and per-order tracking.
  • Sellers get a dedicated back-office at #/store-management: a sales dashboard by period, a product catalog with variants and stock, a POS for walk-in sales, order fulfilment with delivery service and tracking number, and an inbox of buyer inquiries.
  • One product form drives both the marketplace listing and the POS catalog entry, so the storefront and the counter never drift apart.
listingslisting_variantscart_itemsordersorder_items
CMS modules — Pages, Groups, Events, Blogs, Offers
  • One generic CMS engine backs five content types, each with its own categories, cover image, body, price/location/date fields where relevant, and slug-based public URLs.
  • Members can create a Page or Group straight from the floating create menu; Groups additionally pick public / closed / secret privacy at creation.
  • Every item supports likes, invites, photo updates, and its own posting timeline, so a Page or Group behaves like a mini profile rather than a static record.
  • Events get their own discovery view; admins manage all five types and their categories from the Modules section of the sidebar.
cms_itemscms_categoriespage_likes/api/cms/:type
Auth, accounts & privacy
  • Five ways in: email & password (bcrypt, 30-day JWTs), Google, Facebook, Sign in with Apple, and Telegram Gateway OTP. Apple's identity token is verified against Apple's JWKS; Google and Facebook tokens are verified server-side.
  • Telegram signups take the local phone number as their username — +855 12 890 323 becomes 012890323 — with a longest-prefix dial-code table and a collision suffix.
  • Registration can require email activation, a birthdate with a minimum age, a newsletter consent, a user-group choice, or an invite code — each toggled from Registration Settings.
  • Sixteen per-user privacy settings gate profile fields, messaging, chat and suggestions with four visibility levels; owners and admins always bypass, logged-out viewers always get the strictest read.
  • Account safety: password reset by email, live session listing with per-session revoke, admin login-as, bans with a custom message, and self-serve account deletion.
JWTbcryptjsTelegram GatewayApple JWKSusers.privacy
The Admin suite
  • A fixed sidebar groups the whole back-office into Users · Manage · Modules · Money · Customization · System.
  • Users: filtered lists (moderators, admins, online, banned, not-activated, pending), a stats view with CSV export, user groups, permission groups, and a multi-tab Edit-user panel.
  • Manage: dashboard, upload media on a user's behalf, reels, reels ads, the music library, products, comments, reports and stories.
  • Money: earnings, ads, wallet, Pro packages & subscribers, affiliates, points, paid modules, marketplace, funding, monetization and tips.
  • Customization: custom fields, static pages, colored post patterns, widgets, reactions, emojis, stickers and gifts — content that would otherwise be hard-coded.
  • System: fifteen settings groups covering system, posts, registration, accounts, email, SMS, notifications, chat, live stream, uploads, image compression, payments, security, limits and analytics — plus built-in test buttons for email, S3 and FFmpeg.
/api/admin/*adminAuthsettingsuser_groups
Native apps, PWA & SEO
  • Native: a Capacitor shell bundles the same public/ build and points its API at the live server. Universal on iPad and iPhone, full-screen, with FCM/APNs push and Sign in with Apple.
  • Launch safety: a first-paint loader renders before the bundle executes and a watchdog swaps in a branded retry screen if the app shell never mounts — the launch is never a blank screen.
  • PWA: manifest, maskable icons, an install prompt captured early on Android, and a network-first service worker that keeps an offline shell without fighting the app's own ?v= cache busting.
  • SEO & sharing: /post/:id, /reels/:id and /reel/:id are server-rendered OpenGraph pages so a shared link unfurls with the right title, description, poster and video — even though the app itself is a hash-routed SPA.
  • Public pages for Privacy, Terms and data deletion ship both in-app and as static routes, as the app stores require.
Capacitor 8sw.jsmanifest.jsonrenderOgPage