Tulk is a social platform — feeds, friendships, follows, likes, messages — with a glassmorphic React interface over a Laravel 10 and MySQL API. Pretty on top, strict underneath. That combination only works if the boundary between the two is boring and predictable.
Auth is a checklist, not a feature
The API route file reads like a security checklist: login throttling, registration, verification codes, password recovery, two-factor, and Sanctum-guarded everything else:
Route::post('/login', [AuthController::class, 'login'])->middleware(ThrottleLogin::class);
Route::post('register', [AuthController::class, 'register']);
Route::post('send-verification', [VerificationController::class, 'sendVerificationCode']);
Route::post('verify-code', [VerificationController::class, 'verify-code']);
Route::post('verify-2fa', [AuthController::class, 'verify2fa']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
// Posts routes
Route::get('/posts/feed', [PostController::class, 'getFeedPosts']);
Throttle the login before anything else — brute force is the attack you will actually receive. Verification codes before trust, 2FA before sensitivity, Sanctum around all of it.
Feeds need read-state
A social feed is not a list endpoint; it is a list endpoint plus
memory. Endpoints like unread-count and
mark-read exist so the UI can show what is new
without re-downloading the world. Design the read-state on day
one — retrofitting "seen" semantics onto a feed is miserable.
Friendship is a domain, not a flag
Follows, likes, friendships (Amitie), messages,
profiles — each gets its own controller because each has its own
rules. A follow is one direction; a friendship is a negotiation
with states. Giving each relationship its own home keeps the
rules from tangling.
Glass needs contrast discipline
Glassmorphism is unforgiving: translucent panels over unpredictable content turn to mud without strict contrast rules. The React side pairs every glass surface with a scrim discipline — dark text on light glass, light text on dark, never hoping the background cooperates. Beauty is a constraint problem.
Bilingual from the first string
Tulk ships in French and English, and every user-facing string went through the language files from the start — including validation messages and emails. Retrofitting a second language means touching every string twice; starting bilingual means touching each once.
Takeaway
Social apps fail at trust boundaries: auth, read-state, relationships, languages. Put each behind its own explicit mechanism — throttle, Sanctum, dedicated controllers, language files — and the pretty glass on top stays honest.