Serein
Rust로 만든 가볍고 성능 좋은 Discord 전용 네이티브 클라이언트
LookBlog은 피드·짧은 영상·실시간 스트림·채팅·음성·음악·영화·게임 등을 제공하는 자체 구축 소셜 네트워크입니다
LookBlog — a social network built from scratch: feed, shorts, videos, live streams, chats, voice rooms, music, movies and games. Node.js, WebRTC, no dependencies.
소셜GitHub @kristiqnzainleov온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗LookBlog is a full social network built from scratch by Kristiqn Zainelov. It brings together what people usually need several apps for:
🌐 Live site: https://lookblog.vercel.app
The design is pink (#ff4fa3) on black. The interface is in English and can be switched to Bulgarian, Spanish, Russian, German, Serbian or Romanian.
Накратко на български: LookBlog е социална мрежа, която съм направил изцяло сам, без фреймуърци и npm пакети. Има постове, шортове, видеа, лайв стриймове, съобщения, групи с voice чат, музика, филми и сериали, игри, значки и класации. Какви технологии са използвани и защо — виж Технологии (на български).
/admin)LookBlog uses no frameworks and no npm packages: the server, the database layer, the router, the video player, the chat and everything else are written by hand. The only code from outside is loaded by the browser for one job each (the photo checks, YouTube and fonts), listed below.
| Part | Technology |
|---|---|
| Server | Node.js 24 (http module), its own router and rate limiting |
| Database | Its own in-memory database, kept in Supabase Postgres online and in JSON files locally |
| Real-time updates | Supabase Realtime online, Server-Sent Events locally |
| Live streams, calls, voice rooms | WebRTC (peer-to-peer, STUN); the server only passes the connection messages |
| Front end | Vanilla JavaScript (ES modules), HTML and CSS; a single-page app with its own router |
| Stream mixing | Canvas 2D, captureStream, ImageDecoder (GIFs), a Web Worker as a clock |
| Sound | Web Audio API: synthesised sound effects, the DJ mixer, mixing, a limiter |
| Photo checks | TensorFlow.js with NSFWJS and MobileNet, in the browser |
| Video quality | ffmpeg (360p, 480p, 720p and 1080p copies) |
| Other browser APIs | Web Speech API (voice search), MediaRecorder (voice messages, sounds), IntersectionObserver (views), visualViewport (the phone keyboard) |
| Outside services | YouTube IFrame Player API and oEmbed (music in voice rooms), GIPHY (GIFs), Google Fonts |
| Hosting | Vercel (the server is one function, static files on Vercel's CDN), files in Supabase Storage |
Node.js without frameworks. The whole server is plain Node: one http server, and each file in server/ answers its own part of /api. This keeps the project small and fast to start (which matters on Vercel, where the server can start for a request), and every line is understood and under control, with no packages to update or audit. Rate limiting, cookies, uploads and the router are short hand-written functions.
The database: in memory first, Supabase underneath. All records live in memory as plain JavaScript objects, so reading is instant and the code stays simple (db.posts.find(...)). Online, every record is also one row in a single Supabase Postgres table (docs: collection, id, JSON data, a sequence number):
npm start. Postgres was chosen because Supabase gives a free, reliable database, file storage and real-time messages in one place.Real-time: Supabase Realtime and Server-Sent Events. New messages, typing, likes, view counts, who's online and the friends' reactions arrive live. Online the server sends each event to a Supabase Realtime channel (one shared channel and one private channel per person) and the browser listens with a small hand-written WebSocket client. Locally the same events go out over Server-Sent Events, a simple one-way stream that needs nothing extra. Private things (messages, notifications) only go to the people they're for.
WebRTC for streams, calls and voice rooms. Video and sound go straight between the people's browsers, not through the server, so there's no media server to pay for and the delay is low. The LookBlog server only passes the short connection messages (offers, answers, ICE candidates); public STUN servers help browsers find each other. The streamer's picture (camera, screen, pictures and GIFs on top) is drawn on a canvas and sent as one video with captureStream.
Vanilla JavaScript on the front end. The app is ES modules loaded straight by the browser: no build step, no bundler. A small h() function makes elements, a tiny router swaps pages without reloading, and a tiny event bus (on/emit) passes live updates around. Pages and heavy parts (the DJ mixer, games, the photo checks) are loaded only when they're opened. Styles are plain CSS with variables for the pink theme.
Web Audio API. The sounds (message sounds, effects, the DJ mixer with bass boost and effects) are made and mixed in the browser, so they need no sound files and play instantly.
TensorFlow.js, NSFWJS and MobileNet for the photo checks. Before a photo or video is posted, it's checked right in the browser for nudity (NSFWJS) and sensitive things like weapons (MobileNet). Doing it in the browser keeps people's photos private and costs nothing on the server. Marked posts are shown covered and left out of recommendations. The models are loaded only when someone picks a photo, and big photos are made smaller first, so it's quick.
ffmpeg. Uploaded videos get 360p–1080p copies so the player can switch quality on slower connections.
Security.
crypto) and compared in constant time.X-LookBlog: 1 header, which other sites can't send, so they can't act for you (CSRF protection).X-Frame-Options, a content security policy for frames, nosniff, HSTS, Referrer and Permissions policies) are set on every response.Vercel and Supabase Storage. Vercel runs the server as one function (api/index.js) and serves public/ from its CDN, close to the visitor. Files are uploaded by the browser straight to Supabase Storage (so big files never pass through the function), then the server checks them.
Phones. The layout is responsive CSS. On phones the menu moves to the bottom, sheets slide up and close with a swipe down, and the chat uses visualViewport so the screen stays still when the keyboard opens (on iPhone the chat is sized for the keyboard before it appears).
LookBlog е написан без фреймуърци и без npm пакети: сървърът, базата данни, рутерът, плейърът, чатът и всичко останало са написани на ръка. Отвън се зареждат само няколко неща в браузъра, всяко за една задача: проверката на снимки, YouTube и шрифтовете.
http сървър; всеки файл в server/ отговаря за своята част от /api. Защо: малко, бързо стартира (важно за Vercel) и всеки ред е под контрол, без пакети за обновяване.X-LookBlog: 1 (защита от CSRF). Качените файлове се проверяват по съдържание. Прегледите на линкове не стигат до вътрешни мрежи (защита от SSRF). Има защитни хедъри и ограничение на броя заявки.public/ от своя CDN. Браузърът качва файловете директно в Supabase Storage, а сървърът ги проверява след това.You need Node.js 24. ffmpeg is optional and only used for video qualities.
npm start
Then open http://localhost:3000. The data/ folder is created on first start.
| Name | What it does |
|---|---|
PORT | Port to listen on (default 3000) |
LOOKBLOG_DATA | Where the data and uploads are kept (default ./data) |
SUPABASE_URL | Turns on online mode: the Supabase project's address |
SUPABASE_SERVICE_KEY | The project's service key (server only, never sent to browsers) |
SUPABASE_PUBLIC_KEY | The public key browsers use to listen for live updates |
VERIFIED_USERNAMES | Usernames that always get the tick, comma-separated (default ko6i) |
TRUST_PROXY | Set to 1 behind a hosting proxy so each visitor's real IP is used |
ADMINS | Usernames of the owners of the admin page, comma-separated (default ko6i) |
FFMPEG_PATH | Path to ffmpeg, if it isn't found automatically |
LookBlog runs on Vercel with Supabase:
supabase/migrations. It creates the docs table.media.SUPABASE_* variables.vercel deploy --prod.vercel.json sends pages and /api to the function in api/index.js and serves public/ directly.
Online, the browser uploads files straight to Supabase Storage. The server checks the file afterwards, and /media/... links redirect there.
Without the SUPABASE_* variables, npm start uses JSON files in data/ instead. A Dockerfile for a classic server is included too.
server.js starts the server and decides which page to show
server/ the API
auth.js accounts, sessions, password reset
social.js posts, shorts, videos, comments, reactions, follows, search
streams.js live streams, guests, moderators, live chat
admin.js the admin page: reports, verification, support, accounts
chat.js messages, groups, typing, read receipts, card games
voice.js voice rooms and shared music
groups.js Discord-style servers, roles, channels
playlists.js playlists, series, reviews
music.js songs and albums
media.js uploads (checked by content, seekable video)
transcode.js ffmpeg video qualities
recommend.js "For you" recommendations
badges.js badges and roles
leaderboard.js leaderboards
realtime.js live updates (Supabase Realtime or Server-Sent Events) and who is online
db.js the in-memory database (JSON files locally)
store.js keeps the database in Supabase: loads it, syncs changes, writes what changed
ticker.js repeating jobs (run at request time online)
api/index.js the Vercel function
supabase/ the database table
public/ everything the browser loads
index.html landing page (log in / sign up)
app.html, app.css the app
js/pages/ one file per page (feed, watch, live, messages, …)
js/components/ player, comments, chat, voice room, card games, …
old-versions/ earlier designs of the home, landing, login and ticket pages
Made by Kristiqn Zainelov.