Why communities, and why now

Devit was built around individual posts and a global feed. That worked well for getting off the ground, but as more developers joined, the demand for focused spaces became hard to ignore. Threads were scattered, niche topics got buried, and there was no clean way to organise a team or project around a shared space.

Discord proved that channel-based organisation is the right mental model for async developer communication. We took that pattern and rebuilt the communities layer on top of Devit's existing Supabase infrastructure — without breaking the feed or the profile system that already existed.

Communities architecture

Each community in Devit is a first-class Supabase entity with its own row in the communities table, a membership join table, and a channels child table. Visibility is controlled by a simple is_private boolean, which gates both the community listing and all channel reads via Supabase Row Level Security policies.

-- Simplified RLS for channel reads
CREATE POLICY "channel_read" ON channels
  FOR SELECT USING (
    NOT is_private
    OR auth.uid() IN (
      SELECT user_id FROM community_members
      WHERE community_id = channels.community_id
    )
  );

Public communities appear in search and the discovery feed. Private communities are hidden until a user arrives via an invite link, at which point they can request to join or auto-join depending on the community's configuration.

The feature set

Channel threads

Discord-style channel list with topic-scoped posts, inline thread replies, and real-time message delivery via Supabase Realtime.

Public / private visibility

Toggle per-community. Private communities are invisible to non-members; invite links bypass the gate cleanly.

Invite links

Shareable tokens tied to a community ID. Clicking the link auto-joins the user or prompts a join request for approval-required spaces.

Post reactions

Replaced the old upvote/downvote system with a multi-emoji reaction system. Counts persist in Supabase; debounced UI updates prevent flicker.

Push notifications

Service worker intercepts the push event and delivers notifications for new posts in followed channels, mentions, and replies — even when the tab is closed.

Global search

Full-text search across posts, users, and communities using Supabase's ilike queries, with result tabs for each entity type.

OG link previews

Every URL pasted into a post now unfurls into a branded preview card. The fetch pipeline runs through an edge function that calls the target URL, parses Open Graph meta tags, and caches the result in a link_previews table to avoid repeat fetches.

YouTube & Twitter/X: These domains block direct scraping. For them, we serve curated static fallback embeds — a YouTube embed iframe for video links, and a branded card for Twitter links. The experience is seamless to users.

For domains that return OG data, posts render a card with the title, description, hostname, and favicon. Long descriptions are clamped to two lines. The card links out on click. YouTube video links render as inline <iframe> embeds directly in the feed.

Profile theming

This was the most visually dramatic change in the update. Every Devit profile now supports a theme, chosen from nine built-in presets or written as custom CSS by the user.

Nine built-in presets

Presets cover the full colour space: Ocean, Midnight, Forest, Sunset, Crimson, Sakura, Arctic, Ember, and Cosmos. Each preset sets a handful of CSS custom properties that trickle down through the profile layout:

/* Ocean preset */
--profile-bg:       #0d1425;
--profile-accent:   #3b82f6;
--profile-surface:  #111827;
--profile-text:     #e0e8ff;
--profile-glow:     rgba(59,130,246,0.15);

Custom CSS sandbox

Users who want full control get a sandboxed CSS editor on their profile settings page. The editor accepts any valid CSS targeting .profile-card, .profile-header, and a handful of other exposed selectors. The CSS is saved to the user's Supabase profile row and injected into a <style> tag scoped to the profile page at render time.

Sandboxing: We strip @import, url() calls pointing to external resources, and any position: fixed rules before saving. The CSS is scoped to a wrapper class so it cannot affect the global page layout.

Notifications upgrade

The notification system was rewritten from scratch. Previously it was a simple read-all query on a notifications table. The new system adds:

  • Filter tabs across the notification panel — All, Mentions, Replies, Reactions, and Follows — so users don't wade through noise
  • Realtime delivery via Supabase channel subscriptions, so notifications appear instantly without polling
  • Web Push via service worker for out-of-tab delivery on mobile and desktop Chrome
  • Bulk mark-as-read with a single button, scoped to the active filter tab

What's next for communities

The current implementation covers the core loop. The backlog includes community roles and permissions (moderator, member tiers), voice channels via a WebRTC integration, and community-level analytics for admins. Post scheduling and cross-post sharing between communities are also in the design phase.

Try it now: Communities are live on Devit. Head to devit-six.vercel.app, create or join a community, and set up your profile theme from the settings page.

Back to News