Content Distribution System Build Log: Recommendation Algorithm & Multi-language Frontend Deployment Notes

Disclaimer: This article is for technical education and demonstration only. It is not professional or financial advice. Any real-world deployment must comply with applicable laws and regulations.

Last week I helped a client who runs local-life content move this system off a test box and onto a production server. The package is called Jiaoyou Tongcheng; in practice it runs as a short-video plus article content aggregation platform — users publish, admins review, the algorithm distributes, and neighborhood circles pull it together. The dark-theme frontend has been customized and looks noticeably cleaner than the stock version. Below is the whole trip from installing the environment to getting recommendations live; following it should save you a couple of days.

1. Understand the system shape first, don’t rush the install

The first thing to do after you get the archive is not to upload it — it is to look at the directory tree. This one separates frontend and backend: static assets built with Vue 3 on the front, a PHP 8.1 API layer on the back, and Redis in the middle handling cache and popularity rankings. On the content side it supports short video (FFmpeg transcodes and slices into HLS) and image-text streams; both share a single content table and are told apart by a type field.

The frontend customization part

The dark UI lives mostly in src/styles/theme-dark.scss — change the variables once and it applies everywhere. i18n is the usual setup, with language packs in the locales directory: three JSON files for Simplified Chinese, Traditional Chinese, and English. The client later wanted Vietnamese, so I copied zh-CN.json, changed the keys, and called it done. Except date formatting has to change along with it, otherwise the timestamps on the list page come out garbled.

Admin control panel

The admin side is fairly complete: content review queue, user management, exposure weights, tag system, canary toggles. Exposure weight is the piece I care about most — every content pool can be configured independently, new accounts land in a cold-start pool, quality content gets promoted into the hot pool. More on that in the recommendation section.

2. Practical deployment points

Don’t trip over dependency versions

PHP has to be 8.1 or above; 7.4 throws type errors outright. MySQL 5.7 or 8.0 both work, but utf8mb4 must be enabled or emoji nicknames simply won’t save. Redis 6.x, FFmpeg 4.4, and supervisor to babysit the queues. Transcoding is asynchronous — the moment the queue dies, videos sit on processing forever.

The video transcoding pipeline

Uploads go in chunks; the frontend cuts 2MB pieces, the server merges them and drops the file into the transcode queue. FFmpeg produces two renditions, 720p and 480p, with 6-second ts segments and an m3u8 playlist. This step is slow. I ran the queue across two machines, one dedicated purely to transcoding, because otherwise concurrent uploads choke it dead. The player is hls.js pulling from the CDN origin, and token auth for hotlink protection is far more reliable than referer.

How to configure the recommendation algorithm

The system ships a hybrid model — collaborative filtering plus popularity weighting — with the weights tunable from the admin panel. My setup: user behavior (completion rate, likes, comments, shares) at 60%, content freshness at 20%, local geographic weight at 20%. Cold-start content goes into a small traffic pool for its first 200 impressions, and only content above a 35% completion rate gets released wider. Don’t pull that threshold out of thin air — run real data for three days before you fix it.

Pitfall warning: after you change recommendation weights you must clear the feed cache in Redis, or you wait out the half-hour TTL. The first time I tuned parameters I forgot this step and assumed the code wasn’t taking effect — burned an hour for nothing.

Payment and operations modules

Payments are wired for WeChat and Alipay, with a Stripe interface reel simulation reserved for overseas, and you should get callbacks working in the sandbox before switching to live credentials. The operations side covers check-ins, points, and content rewards; the endpoints are all there, configured from the admin finance panel. Note that the callback URL must be https — http gets rejected outright.

Multi-language and SEO

Multi-language is not just swapping strings. Share pages need hreflang tags, titles and descriptions should come out of the language packs, and route prefixes should split by /en and /zh. I added auto-generated sitemaps pushed incrementally by content update time — indexing moves much faster than manual submission.

3. Three pitfalls I ran into

One, time zones. The server runs UTC and the PHP config was never touched, so every publish timestamp was off by 8 hours and neighborhood recommendations went haywire. You have to fix both date.timezone in php.ini and time_zone in MySQL.

Two, queue backlog. Transcode jobs had no timeout, so a single corrupt file blocked the entire queue. Adding –timeout=300 plus three retries on failure, and it has been rock solid since.

Three, permissions. The storage directory had the wrong owner, uploads all returned 500, and only the logs revealed the write failure. One chown -R www:www solved it.

4. Who this system fits

Teams working on local-life content, neighborhood interest communities, or vertical short video are a good match. The feature set is complete, frontend customization is cheap, and both recommendation and review leave configuration hooks open. It is a weaker fit if you only want a simple content feed — it runs heavy, and the ops burden goes up with it. Small teams should start on a single machine with the queue and the database separated; don’t jump straight to a cluster.

FAQ

Q: Does transcoding require FFmpeg, or can I offload it to cloud storage?
A: You can. Swap the transcode queue section for a call to a cloud media processing API — there is an adapter layer in the code for exactly this. Self-hosting is cheaper though, and at volume the gap becomes obvious.

Q: I added a new language but the admin menu is still in Chinese?
A: The admin language pack is a separate directory from the frontend locales; they are not the same file. You have to add both. I missed the admin one on my first pass.

Q: How long until recommendation parameter changes take effect?
A: Immediately after you clear the feed cache. If you don’t clear it, wait for the TTL, which defaults to 1800 seconds — you can shorten that in the config file while debugging.

Q: Payment callbacks keep failing signature verification, how do I troubleshoot?
A: First check whether the key is still the sandbox one, then check whether the callback URL carries extra parameters, and finally verify the signature string ordering. Nine times out of ten it is parameter order.

This article is for technical education only. Please comply with local laws and regulations, and do not use any of this for unlawful purposes.

Disclaimer: This article is for technical education and demonstration only. It is not professional or financial advice. Any real-world deployment must comply with applicable laws and regulations.

#Content Distribution #Recommendation Algorithm #Multi-language Frontend #Source Code Deployment #Social System