Module System
Honeycomb organizes client-side code into feature modules under src/lib/modules/. Each module maps to a single feature domain and follows a standard folder structure. Only client-importable code lives in modules — server-side logic stays in src/routes/.
Folder structure
Section titled “Folder structure”Each module lives at src/lib/modules/<module-name>/ and contains only the subfolders it actually needs. Do not create empty placeholders.
src/lib/modules/<module-name>/├── index.ts # Public barrel -- re-exports from all subfolders├── schemas/ # Zod validation schemas│ ├── index.ts # Barrel file for schemas│ ├── create-foo.ts│ └── update-foo.ts├── types/ # TypeScript types (inferred from schemas or custom)│ └── index.ts├── components/ # Svelte components scoped to this feature│ ├── index.ts # Barrel file for components│ ├── foo-form.svelte│ └── foo-card.svelte├── stores/ # Svelte stores / runes scoped to this module│ ├── index.ts│ └── foo.svelte.ts├── utils/ # Pure helper functions specific to this feature│ ├── index.ts│ └── format-foo.ts└── constants.ts # Module-scoped constants (optional)Subfolder guidelines
Section titled “Subfolder guidelines”index.ts (barrel file)
Section titled “index.ts (barrel file)”Every module and every subfolder with more than one file must have an index.ts that re-exports its public API. Consumers always import from the barrel, never from internal files.
// Goodimport { LoginForm, signInSchema } from "$lib/modules/auth";
// Avoidimport LoginForm from "$lib/modules/auth/components/login-form.svelte";schemas/
Section titled “schemas/”Each Zod validation schema gets its own file. These schemas are used for form validation, API request parsing, and type inference.
import { z } from "zod";
export const signInSchema = z.object({ email: z.email("Please enter a valid email address"), password: z.string().check(z.minLength(1, "Password is required")),});types/
Section titled “types/”TypeScript types inferred from schemas or defined manually. Keeps type definitions separate from runtime validation logic.
import type { z } from "zod";import type { signInSchema } from "../schemas/index.js";
export type SignInSchema = z.infer<typeof signInSchema>;components/
Section titled “components/”Svelte components that belong to this feature (forms, cards, dialogs). Shared, generic UI primitives belong in $lib/components/ui/ instead.
stores/
Section titled “stores/”Reactive state using Svelte 5 runes (.svelte.ts files) or classic stores. Only create this folder when the module needs client-side state beyond what components manage internally.
utils/
Section titled “utils/”Pure functions specific to this module (formatters, validators, mappers). General-purpose utilities go in $lib/utils/.
constants.ts
Section titled “constants.ts”Static values such as enum-like objects and config maps. Optional — only add when the module actually needs shared constants.
Current modules
Section titled “Current modules”Honeycomb has 15 feature modules:
| Module | Domain | Description |
|---|---|---|
auth | Authentication | Sign-in, sign-up, password reset schemas and forms |
explore | Discovery | Explore/discover feed, search, trending content |
honeycomb | Core/apps | Honeycomb app system and extension UI components |
layout | App shell | Sidebar, header, navigation, and layout components |
marketplace | Commerce | Product listings, store pages, job marketplace |
messaging | Chat | Conversations, message threads, group chats, invites |
notifications | Alerts | Notification list, cards, realtime notification handling |
onboarding | Setup | Post-signup onboarding wizard steps and schemas |
post | Content | Post creation, feed cards, comments, reactions |
profile | Identity | Profile pages, editing, follow system, social links |
shared | Cross-cutting | Components and utilities used across multiple modules |
sitebuilder | Website builder | User website/page builder feature |
social | Social graph | Follow suggestions, social connections, social features |
stories | Ephemeral content | Story creation, viewer, highlights |
wallet | Payments | Wallet balance, transaction history, transfers, tips |
Scaffolding a new module
Section titled “Scaffolding a new module”To add a new feature module:
-
Create the directory at
src/lib/modules/<module-name>/. -
Add an
index.tsbarrel that re-exports everything consumers need:src/lib/modules/billing/index.ts export * from "./schemas/index.js";export * from "./types/index.js";export * from "./components/index.js"; -
Add subfolders as needed. Start with
schemas/andcomponents/— addstores/,utils/, andconstants.tsonly when you have something to put in them. -
Create barrel files for each subfolder that contains more than one file.
-
Write server-side logic in the corresponding route files under
src/routes/, not in the module. -
Import from the barrel in routes and other modules:
import { BillingForm, createSubscriptionSchema } from "$lib/modules/billing";
Example: minimal module
Section titled “Example: minimal module”src/lib/modules/billing/├── index.ts├── schemas/│ ├── index.ts│ └── create-subscription.ts├── types/│ └── index.ts└── components/ ├── index.ts ├── billing-form.svelte └── plan-card.svelteRules of thumb
Section titled “Rules of thumb”- One module = one feature domain. If a module grows too large, split it into sub-modules rather than nesting deeply.
- Keep modules focused. A
billingmodule should not contain notification components. - Shared code goes in
$lib/. If two modules need the same utility, move it to$lib/utils/. If they share a component, move it to$lib/components/. - Never import internal files. Always go through the barrel. This makes refactoring safe and keeps the public API explicit.