Customization Guide
Comms is your source code. Here's where to look for the most common tweaks, and how to brief Claude Code for the rest.
Repo layout
src/
components/ # UI components (MessageList, Composer, etc.)
features/ # Feature modules (channels, mail, threads, huddles)
hooks/ # React hooks (use-channel, use-realtime, etc.)
lib/ # Utilities (supabase client, markdown, url parsing)
pages/ # Top-level routes
theme.css # Tokens
supabase/
schema.sql # Schema
functions/ # Edge Functions
Common customizations
Change brand colors
File: src/theme.css
:root {
--comms-accent: #0891b2;
--comms-accent-contrast: #042f3b;
--comms-bg: #0b0f1a;
}Swap the default avatar style
File: src/components/Avatar.tsx
Comms uses a gradient-initial fallback. To switch to identicons or
Gravatar, change the fallbackRenderer function and, if using
Gravatar, add the email-hash helper from src/lib/gravatar.ts.
Disable a feature you don't use
All features gate on a config object:
File: src/config/features.ts
export const features = {
mail: true,
huddles: true,
tasks: true,
slackBridge: false,
};Flipping mail: false hides the mail UI and skips setting up the
inbound route. Useful if you just want chat.
Add a custom slash command
File: src/features/composer/slash-commands.ts
export const slashCommands = {
poll: existingPollCommand,
canned: existingCannedCommand,
giphy: {
label: "Giphy",
description: "Insert a GIF by keyword.",
run: async (ctx, query) => {
const url = await giphy.fetch(query);
return { type: "image", url };
},
},
};Change retention defaults
File: src/features/channels/retention-defaults.ts
export const retentionDefaults = {
public: "keep_all",
private: "90_days",
dm: "keep_all",
};Existing channels keep their current setting — defaults apply only to newly created channels.
Customize notification copy
File: src/features/notifications/templates.ts
All notification copy (desktop push title/body, email subject/body) lives here. Edit freely.
Tips for working with AI
Comms is the most UI-heavy ARK product. When asking Claude Code for changes:
- Name the component. "In
MessageList.tsx..." is far better than "in the main chat view." - Mention realtime carefully. Anything that inserts or mutates messages should go through the Supabase realtime channel so other clients stay in sync. Tell Claude explicitly.
- Describe the empty state. New features often forget what happens with zero rows. Spell it out.
- Consider the mobile layout. Comms' mobile layout is a
separate component tree under
src/components/mobile/. Ask Claude to update both.
Example prompts
Add a "snippet" slash command:
/snippet {title}opens a modal where users paste multi-line code, pick a language, and insert it as a pre-formatted code block in the composer. The snippet should be stored so users can reuse it.
Add a channel-level read-only toggle. When enabled, only admins can post; everyone else sees the composer disabled with a "This channel is read-only" placeholder.
The huddle UI takes too long to render on slow networks. Add a skeleton view that shows immediately and swaps to the real UI when the WebRTC connection establishes.