Customization Guide
Pulse is your source code. Here's where to look for the most common tweaks, and how to brief Claude Code on the rest.
Repo layout
src/
components/ # UI components
features/ # Feature modules (standups, surveys, polls, reminders)
lib/ # Utilities (supabase client, timezone, slack, rrule)
pages/ # Top-level routes
theme.css # Tokens
supabase/
schema.sql # Schema
functions/ # Edge Functions
Common customizations
Change brand colors
File: src/theme.css
:root {
--pulse-accent: #8b5cf6;
--pulse-accent-contrast: #1a0d3b;
--pulse-bg: #0b0f1a;
}Add a question type
Question types are registered in:
File: src/features/questions/registry.ts
export const questionTypes = {
short_text: shortTextType,
long_text: longTextType,
scale: scaleType,
// add:
slider: {
label: "Slider",
schema: z.object({ min: z.number(), max: z.number(), step: z.number() }),
renderComposer: (props) => <SliderComposer {...props} />,
renderAnswer: (props) => <SliderInput {...props} />,
renderDigest: (resp) => <SliderBar value={resp.value} />,
},
};Also add Slack/email renderers in src/lib/slack/blocks.ts and
src/lib/email/templates.ts so the new type works across every
delivery channel.
Add a survey template
File: src/features/surveys/templates.ts
Each template is a plain JSON object — add a new entry and it shows up in the template gallery.
Change the default digest format
File: src/features/digests/default-template.ts
Edit the markdown template. Variable substitutions:
{{team.name}}{{date}}{{responses}}(iterable){{blockers}}(filtered list)
Add a delivery channel
Three pieces to add:
- Channel config under
src/features/channels/{name}.ts. - Sender implementation under
supabase/functions/pulse-{name}-sender/. - Response ingestion route under
src/pages/api/{name}/events.ts.
Copy the Slack implementation as a starting point.
Change default CRON parsing
Pulse uses rrule under the hood. To adjust:
File: src/lib/rrule.ts
Tips for working with AI
Pulse has tight coupling to scheduled jobs. When asking Claude Code for changes:
- Timezones are everywhere — always mention "honor the participant's timezone" when changing anything schedule-related.
- Slack signature verification is non-negotiable. Any change that adds a new Slack endpoint must verify signatures first.
- Respect anonymity — if you're touching survey code, tell Claude "maintain the anonymity invariant: no user_id on anonymous responses."
- Edge functions are Deno, not Node — Claude sometimes writes Node-only imports. Remind it to stay within the Deno standard library and Supabase helpers.
Example prompts
Add a "mood emoji" question type to standups. Users pick from a palette of 12 emoji. The digest renders the emoji grid grouped by person. Update the Slack block renderer to use a select menu.
Add a "weekly summary" digest kind: aggregates every standup response from Mon–Fri into a single digest posted Friday at 5 PM team-local time. Add a toggle in the standup editor.
Extract the scheduler logic from
pulse-schedulerinto a pure-function library so we can unit-test it. Keep the function's entry point and the runtime semantics the same.