Skip to content

Architecture

Honeycomb is a SvelteKit application deployed to Cloudflare Pages. It serves as the frontend for the Mindhyv social-business platform, connecting to Supabase for authentication, database, and realtime features.

honeycomb/
├── src/
│ ├── routes/ # SvelteKit file-based routing
│ │ ├── (app)/ # Protected routes (feed, messages, settings, ...)
│ │ ├── (auth)/ # Sign-in, sign-up, forgot-password
│ │ ├── (marketing)/ # Public landing and marketing pages
│ │ ├── (onboarding)/ # Post-signup onboarding flow
│ │ ├── (sitebuilder)/ # Site builder feature
│ │ ├── api/ # API routes (+server.ts endpoints)
│ │ ├── +layout.server.ts # Root server layout (session + cookies)
│ │ ├── +layout.ts # Root universal layout (Supabase browser client)
│ │ └── +layout.svelte # Root Svelte layout (providers, auth listener)
│ ├── lib/
│ │ ├── modules/ # Feature modules (auth, post, messaging, ...)
│ │ ├── components/ # Shared UI components
│ │ ├── server/ # Server-only utilities (guards, helpers)
│ │ ├── services/ # Service layer (payments, notifications, ...)
│ │ ├── hooks/ # Reusable Svelte hooks
│ │ ├── schemas/ # Shared Zod schemas
│ │ ├── types/ # Global TypeScript types
│ │ ├── utils/ # Shared utility functions
│ │ └── apps/ # Extension/app registrations
│ └── hooks.server.ts # Server middleware (Supabase client + route guards)
├── supabase/ # Supabase config, migrations, seed data
├── svelte.config.js # SvelteKit config with Cloudflare adapter
└── wrangler.toml # Cloudflare Pages deployment config

SvelteKit route groups (parenthesized directories) organize pages by access level. The grouping does not affect the URL path.

Everything under (app)/ requires authentication and completed onboarding. This includes the main application pages:

  • /feed — Social feed
  • /messages — Chat and messaging
  • /notifications — Notification center
  • /profile — User profiles
  • /settings — Account settings
  • /wallet — Payments and wallet
  • /marketplace — Product and service marketplace
  • /business — Business dashboard and extension management
  • /admin — Admin panel (requires admin role)
  • Plus 15+ additional feature routes (explore, bookmarks, drafts, stories, jobs, store, courses, events, and more)

The (app)/+layout.server.ts loader fetches data needed by every protected page: the current user profile, unread notification count, and installed apps for the sidebar.

Sign-in, sign-up, forgot-password, and reset-password pages. Authenticated users who navigate here are redirected to /feed.

Landing page and marketing content. The landing page (/) redirects authenticated users to /feed.

Post-signup onboarding wizard. Protected routes check whether onboarding is complete and redirect here if not.

All authentication and authorization logic is centralized in src/hooks.server.ts using two sequenced handlers:

Creates a server-side Supabase client attached to event.locals.supabase and a safeGetSession helper that securely validates the user via getUser() (not just the JWT).

A single guard handler enforces all access rules so that individual +page.server.ts and +layout.server.ts files do not contain auth redirects:

ConditionBehavior
Public route (webhooks, auth callbacks)Pass through, no check
Unauthenticated user on protected routeRedirect to /sign-in
Authenticated user on auth page (/sign-in, /sign-up)Redirect to /feed
Authenticated user on landing page (/)Redirect to /feed
Admin route without admin roleRedirect to /feed
Protected route without completed onboardingRedirect to /onboarding

Route classification is handled by functions in src/lib/server/guards.ts.

Data flows through a well-defined chain from server to client to component:

hooks.server.ts Middleware: creates Supabase client, enforces guards
+layout.server.ts (root) Loads session, user, and cookies
+layout.ts (root) Creates browser Supabase client, exposes session
+layout.server.ts (app) Loads profile, unread count, installed apps
+page.server.ts Loads page-specific data (posts, messages, etc.)
+page.svelte Receives all data via $props(), renders the page
Child components Receive slices of data via $props()

Returns the session, user object, and serialized cookies. This data is available to every page in the app.

Creates the appropriate Supabase client depending on the environment:

  • Browser: createBrowserClient for client-side queries and realtime subscriptions
  • Server: createServerClient using cookies from the server layout

Registers a supabase:auth dependency so that invalidate('supabase:auth') triggers a data reload on auth state changes.

Sets up global providers and listeners:

  • Auth state listener: Watches for session changes and calls invalidate('supabase:auth') when the token expires or refreshes
  • ModeWatcher: Dark/light mode support
  • Toaster: Toast notifications via svelte-sonner

App layout server ((app)/+layout.server.ts)

Section titled “App layout server ((app)/+layout.server.ts)”

Fetches three things for every protected page:

  1. Profile: Username, avatar, name, verified status, role, type
  2. Unread notifications: Count of notifications with read_at IS NULL
  3. Installed apps: Active apps from user_apps joined with apps for slug, name, and icon

This data powers the sidebar, header, and notification badge across the entire app shell.

The app uses @sveltejs/adapter-cloudflare configured in svelte.config.js:

import adapter from '@sveltejs/adapter-cloudflare';
const config = {
kit: {
adapter: adapter()
}
};

Server-side code (hooks, server loaders, API routes) runs as Cloudflare Workers. Static assets are served from Cloudflare’s CDN.

Public variables (prefixed with PUBLIC_) are embedded at build time:

  • PUBLIC_SUPABASE_URL — Supabase project URL
  • PUBLIC_SUPABASE_PUBLISHABLE_KEY — Supabase anon/publishable key

Secret variables are configured in the Cloudflare dashboard and accessed via $env/static/private or platform bindings.

  • Centralized guards: All auth logic in hooks.server.ts, never in page loaders.
  • Barrel imports: Modules export through index.ts barrels. Import from $lib/modules/auth, not from internal files.
  • Server code stays in routes: +page.server.ts and +server.ts files handle form actions and API endpoints. Module folders contain only client-importable code.
  • Supabase on both sides: Server uses event.locals.supabase (cookie-based). Client uses the browser client from +layout.ts. Both share the same session.
  • Svelte 5 runes: Components use $props(), $derived(), and $state() for reactivity.