Skip to content
WeSmile

Four surfaces live · mini program / web / console / server

A campus wall deserves a real system

Submissions queued in someone's DMs, sign-ups by group-chat roll call, headcounts in a spreadsheet, and when something goes wrong all you can do is delete a message. That isn't a lack of effort — it's the wrong tool. WeSmile ships the whole set: student verification, content distribution, an anonymous tree hole, event sign-ups, a marketplace, course reviews, weekly matchmaking, and an admin console a campus moderator can run without a developer.

Written for student unions, clubs, and the people running a campus wall.

Tree hole

Found a student card on the third floor of the library — DM me

Anonymous · 3 min ago

Marketplace

Full set of grad-school prep books, barely used, pickup on campus

¥120 · School of Computing

Event

Friday 7pm · club recruitment info session

128 / 200 signed up

Course review

Light on homework, brutal on the final

Grading 4.2 · Teaching 4.8

Feed

Tonight's sunset is worth looking up for

❤ 246 · whole school

Weekly match

Matched — say hi

37th pair this week

Messages

Is that monitor still available?

Delivered live

Verified

Student status confirmed · via school email

Took 1m 12s

Moderation

A post was taken down; the author got the reason

Handled in 4 min

Points

12-day check-in streak

+30 points

88
mini-program screens

main bundle + 7 sub-bundles

297
server endpoints

student-facing and console APIs

4
surfaces, one backend

one account, one corpus

3
ways to verify

email / photo / quiz

Why change the approach

Four problems every campus community hits

None of them are solved by trying harder — there's simply no structure holding the work.

  1. Submissions pile up in DMs; every repost is laid out by hand

    A structured feed where publishing means persisting: topic, images, place and engagement are fields, not screenshots

  2. "Are you actually a student here?" runs on the honour system

    Email, student card photo or a school-specific quiz — and the result decides what someone can post and who they can message

  3. All you can do is delete a message, block someone, post an announcement — and by tomorrow nobody remembers why

    A report queue, content review and graded restrictions, each step recorded, with the rejection reason handed back verbatim

  4. Sign-ups by roll call, attendee lists as screenshots, totals in a spreadsheet

    Sessions, sign-ups and an attendee roster — it was structured data before anyone exported it

The full picture

Twelve modules that cover campus life

Not a checklist of features — each one is built far enough to hand to real students.

  • Feed

    The campus feed: topics, six browsing ranges, likes and saves, threaded comments.

    • Six ranges, nearest outward: campus, school, district, city, province, everywhere
    • Topic hub, newest and hottest
    • Image grids with full-screen preview
  • Tree hole

    Real anonymity: the author is a persona, and the client never receives an internal id.

    • The persona can be reshuffled
    • "Hugs" instead of likes
    • Anonymous comments, no path back to a person
  • Events

    Start to finish: sessions, sign-ups, attendee roster, a timeline, and comments.

    • One event, many sessions
    • Rosters you can read and export
    • "I'm hosting" and "I'm attending" kept apart
  • Marketplace

    Second-hand goods on campus. Post, search, view, message the seller.

    • Images upload straight to storage
    • One tap to open a chat
    • Comments for the follow-up questions
  • Course reviews

    Rate the grading and the teaching separately. Reviews are anonymous.

    • Search by faculty, campus or teacher
    • Trending queries computed server-side
    • Anonymous — only the score is attributed
  • Weekly match

    A questionnaire, a human pairing it, contact details exchanged. No algorithm, on purpose.

    • Form editor lives in the console
    • Answers grouped per question
    • Unpair sends both back to the pool
  • Direct messages

    Live over WebSocket, with a quota, blocking, recall and three privacy levels.

    • Three messages until they reply
    • Block and recall
    • Privacy: open / three until reply / closed
  • Student verification

    Three routes: a school email, a student card photo, or a campus quiz.

    • Photos get an AI pre-screen, then a human
    • Email and quiz resolve on the spot
    • A rejection reason is required and forwarded
  • Points

    In-app points. Earned by checking in, topped up, spent, and fully itemised.

    • Streaks pay more
    • Top-ups via WeChat Pay
    • Every movement has a ledger entry
  • Clubs

    Browse clubs, apply to join, wear a club title — with admins scoped to exactly one club.

    • Club pages with cover art
    • Joining is reviewed; "clubs I'm in" is one tap away
    • A club admin cannot see other clubs
  • Homepage & placements

    Carousels, placements, a daily poem, the shortcut grid, homepage tabs — all configurable.

    • Carousel slots are an enum, not free text
    • Six targeting levels: everywhere / province / city / one school / several schools / one campus
    • Deep links validated against the registry; a bad one won't save
  • Reports & review

    Four target types × five reasons, up to six pieces of evidence. Deletes are soft and reversible.

    • One queue for eight content types
    • Posts, listings and events can be unpublished
    • It tells you if someone already handled it

Real screens

What it actually looks like

All captured from a running build — not mockups, and not retouched. The names, posts and numbers are demo data: the interface is real, the people are invented.

  • Feed: posts, the range switcher, and the author's club title
  • Tree hole: the author is only ever a persona
  • An event: time, place, who is going, and comments
  • Course reviews: one row per teacher, grading and teaching scored apart
  • Marketplace: second-hand on campus
  • Browsing range: six steps outward, from my campus to everywhere
  • Verification: three routes
  • Weekly match: paired, with contacts exchanged
  • Messages: a live thread
  • Profile: points and club title

Publishing one post

Write, attach, publish, watch it land in the feed — choosing which club identity to post as, and whether to spend points pinning it.

How it works

The life of one post

From tapping publish to being taken down, these seven steps are identical on all four surfaces — because all seven live on the server.

  1. 01Publish

    The client never decides for itself; it asks the server what it's allowed to do

  2. 02Check

    Account, verification and restriction status resolved in one pass, with a reason attached

  3. 03Screen

    Text and images pass content safety; what fails is never persisted

  4. 04Distribute

    A post sits at its author's campus and school; readers decide how far out to look

  5. 05Engage

    Likes, saves, shares and threaded comments; counts are batched, not queried per row

  6. 06Report

    Four target types, five reasons, up to six attachments; a duplicate report counts as success

  7. 07Resolve

    Unpublish or soft-delete, both reversible; the reason goes back to the author verbatim

Keeping the rules on the server means changing one of them changes all four surfaces at once — it's the only way they stay in sync for longer than a semester.

Four surfaces

One account, one corpus, four ways in

Students use the mini program or the browser; operators change something in the console and all four surfaces follow.

  1. WeChat mini program

    Native mini-program framework · 88 screens

    Where students actually live. Hot screens in the main bundle, eight sub-bundles split by domain.

    • Dark mode follows the system
    • Sub-bundles split by business domain
    • WeChat login, subscription messages, and payments
  2. Web app

    Next.js 16 · shadcn/ui · 36 routes

    The mini program's 88 screens collapse into 36 routes, organised by capability rather than by page.

    • Mini-program QR confirmation signs the same account into the web app
    • Three-column desktop, bottom tabs on mobile
    • WebSocket messaging with polling as a fallback
    • Chinese and English, with server error copy following the chosen language
  3. Admin console

    Next.js 16 · roles × scopes

    Built for campus staff. Review, placements, quiz banks, matchmaking and orders all live here.

    • Eight content types, soft delete with restore
    • AI pre-screen then human review for verification
    • What an admin may manage is narrowed by school or by club
  4. Server

    Spring Boot 4 · JPA · Redis · MySQL 8

    Nineteen business domains sliced vertically: changing the tree hole means opening one directory.

    • 297 endpoints across student-facing and console APIs
    • Self-issued tokens with sliding renewal
    • Integration tests pin the contract down
06

Governance

A community's lifespan is decided on its worst day
Features decide whether it opens. Governance decides whether it's still open a year later. These three rules came out of getting them wrong first.
  • The server computes permissions; the client never guesses

    The client asks once — "what can I do right now?" — and gets back a list of names: post, comment, message, join, match. It never derives a rule like "unverified, therefore can't post". Derived rules fork into four different versions on four surfaces.

  • Effective rights = what the role allows ∩ what the scope allows

    Super admins, operators, moderators, campus admins and club admins each get a surface area. Anything outside your scope returns "not found" — identical to genuinely not existing. Otherwise the error message alone would let you probe what another school has.

  • When the answer is no, say why

    Whatever the server says when it refuses has to be shown. Rejection reasons are free text written by a moderator, and the student really does read them — so whatever goes in that box is what goes back to a person.

Alternatives

Why not just use what's already there?

Group chats and public accounts aren't bad. They were simply never designed for this.

Group chat
Public account wall
Generic community SaaS
WeSmile
  • Verified student identity

    No
    No
    No
    Yesthree routes
  • Content is searchable

    No
    Sort of
    Yes
    Yestopics + search
  • Graded browsing range

    No
    No
    Sort of
    Yessix, nearest outward
  • Anonymous and named side by side

    No
    Sort of
    No
    Yestree-hole personas
  • Sign-ups with a roster

    No
    No
    Sort of
    Yessession-based
  • Operations console

    No
    Sort of
    Yes
    Yescampus / club level
  • You hold the data

    No
    No
    No
    Yesself-hosted

A few answers up front

What you're probably wondering

Read every question

There are five of us. Can we run this?

Yes, but cut scope first. Open the feed, the tree hole and events; enable email verification only. Moderation needs at least two people on rotation — the cost isn't volume, it's response time.

Do we have to do student verification?

If you plan to open the tree hole or direct messages, effectively yes. Verification isn't there to keep people out; it's what makes a penalty mean something. In a community where a banned account is replaced in five minutes, every moderation tool is decoration.

Won't an anonymous feed go off the rails?

It would — which is why posts are anonymous to other users, not to the system. Content still passes safety screening, still gets reported and taken down, and penalties still land on the real account.

What does it cost?

The system is self-hosted. The hard costs are a server running MySQL and Redis, an object storage bucket, and a mini-program account. That mini-program account also handles web QR sign-in; add a merchant account for top-ups.

Getting listed

How do I get my school on here

This question has a real name inside the system: a school onboarding request. It isn't an email to us — it's a counter you can watch, in the app.

  1. Search first, don't rush to create

    Typing a school name shows you candidates first: "did you mean one of these?" That step isn't a courtesy. Once a name splinters into "MIT / Massachusetts Institute of Technology / MIT (main campus)", none of the three ever reaches the threshold and the whole feature may as well not exist. The server also normalises names into one counting key, and the console can merge branches that already split.

  2. Cast one vote — the count is public

    After submitting you see how many people have asked for this school and how many are still needed. One vote per person. You can withdraw it; when the last person leaves, the empty counter goes with them rather than lingering as a row that reads "0 people waiting".

  3. Hit the threshold and the school is created

    Nobody has to click approve. The threshold defaults to 200 people and ships down with every record — the client only displays it, never computes it, so the gap you read on screen is the same number the server judges by.

  4. Created still isn't open

    A school created by threshold lands in "pending open": it still needs campuses and region codes, a home logo, and a decision on which verification methods it offers plus whatever they depend on — quiz verification means writing a question bank first. Until those are done it doesn't appear in the school picker.

WeSmile trial mini program code

Try it first

Scan this with WeChat to open the trial build — no app install, no sign-up first.

This code is valid until 2026-09-12

At the threshold, we only notify ourselves

Applicants don't get a "your school is live" message when the school is created, because at that point it isn't usable. The opening notice waits until it actually opens, and it is sent exactly once. Better a late notice than a promise that can't be honoured that day.

If you can't wait

The system is self-hosted by design: code, database and object storage all sit with you. A school can stand up its own instance — no queue, no headcount. That path is in the launch playbook, and its first step is cutting features.

Read the playbook

Start with what it does, or with how to ship it?

The feature tour answers "what's in it". The playbook answers "where do I begin".

1142704468@qq.comWeChat