Settings & Configuration

Flux has opinions about your day, and this is where you argue with them. Most of these components do not store a preference so much as a rule the scheduler will later enforce: what counts as a meeting, what happens when two blocks want the same minute, when the plan stops being editable. Every component here is backed by useSettings() and takes no props, so each one is a window onto one slice of a single settings object.

Who you are

1 component

One card carries the whole idea that Flux adapts to the person using it. It is also the clearest example of the honesty problem this showcase exists to surface: the identity half of it is a mockup and the cognitive-style half is real, and nothing on screen tells you which is which.

UserProfileSettings Placeholder
The first card on the Settings page: name, email, and the four questions Flux asks about how you think and when you plan. Half of it writes to your account and half of it writes nowhere.
src/components/settings/user-profile-settings.tsx
Default · onboardingCompleted false
FU
Your Profile
Update your personal details here.

Select a profile to apply a set of default settings tailored to different cognitive styles. You can always override individual settings elsewhere.

Default

When do you prefer to plan your day?


Ask about the next day's priorities as part of an end-of-day routine.

onboardingCompleted true · an extra block appears

Need a refresher? You can re-run the onboarding process at any time.

Neurodivergence Support · the five options
Default
ADHD
Autism Spectrum
Dyslexia
Anxiety

Four controls, two of them fiction. Full Name defaults to local state "Flux User" and is never persisted; email is hardcoded "user@flux.com" and disabled; the avatar is a placehold.co image; and Save Changes only fires a toast ("Profile Updated") with no write behind it. The neuroType, planning-preference and nightly-routine settings ARE real: they go through setSetting to Supabase. One more thing worth knowing: the option labelled "Autism Spectrum" stores the value Autism, and picking any profile silently rewrites other settings (see Presets, below).

How the day is built

6 components

The rules Flux applies before you have done anything: which events are containers, which are meetings, how long an "atomic" task is allowed to be, and when the day's plan stops being editable. These are not cosmetic. A container label typed here changes how an imported calendar event is classified tomorrow. The last card in this group is an orphan with no home of its own, listed so the file count stays checkable. GoogleCalendarSettings also lives on the Settings page but is documented with the rest of the connectors, on Integrations.

CalendarSettings Reproduced bug
Two choices about the calendar grid: which view opens by default, and whether child tasks show through their parent container. Both are read by the calendar on every render.
src/components/settings/calendar-settings.tsx
Defaults · day view, shadow events on

Choose how your calendar is displayed on larger screens. Mobile will always default to Day view.

Day View

Toggle the visibility of nested tasks on the calendar grid.

Both InfoTooltips, opened
Set the default view (Day or Week) that you see when you first open the calendar.
Display child tasks as transparent 'shadow' events inside their parent container on the calendar.
defaultView is "agenda" · the trigger falls back to its placeholder
Select rule...

The control cannot express half of its own setting. AppSettings.defaultView is a 4-way union (day | week | agenda | circular) and CalendarView renders all four, but this Select offers only Week View and Day View. That is not hypothetical: choosing the Autism or Dyslexia profile sets defaultView: 'agenda', at which point the value matches no item and the trigger renders its placeholder, "Select rule...", as though nothing were selected. The setting is still agenda. The third variant above is that state. Also reproduced: the tooltip says "(Day or Week)" while the description promises the setting applies to larger screens only, which the calendar honours by force-overriding to day on mobile.

ClassificationSettings
Teaches Flux to read an imported calendar. Four rules decide whether an incoming event becomes a container, a meeting, or a single atomic task, before anything reaches the grid.
src/components/settings/classification-settings.tsx
Container Labels · the shipped defaults

Keywords that identify an event as a container block (e.g., "Focus Block").

Focus Deep Work Planning Admin Buffer
Meeting Keywords · outline badges, not secondary

Titles containing these keywords (with attendees) are classified as meetings.

standup 1:1 status kickoff
Max Children per Container · 1 to 20, default 5

Set the maximum number of child tasks before prompting to split the container.

5
Atomic Task Duration · 5 to 60 in steps of 5, default 25m

Events shorter than this duration (in minutes) are likely atomic tasks.

25m
Empty list · the state that has no markup

Keywords that identify an event as a container block (e.g., "Focus Block").

Both badge lists are add-only. There is no remove control, no delete affordance on a badge, and no empty state: settings.containerLabels.map(...) renders straight into a wrapper, so an emptied list collapses to the blank gap shown in the last variant. The only route back to the defaults is a value you cannot reach from this screen. Rejection is silent, too: handleAddLabel and handleAddKeyword guard on if (newLabel && !settings.containerLabels.includes(newLabel)), so a duplicate or an empty string does nothing at all: no error, no toast, and the input is not even cleared. Both lists accept Enter as well as the Add button. The sliders are exact: children 1 to 20 step 1, duration 5 to 60 step 5.

PlannerSettings
When the day stops being editable. Flux's central claim is that a plan you can quietly rewrite is not a plan, and these three controls are where you set the terms of that deal.
src/components/settings/planner-settings.tsx
Method Automatic · the lock time is editable

Automatically lock the day's plan at a specific time.

Choose how the plan should be set in stone for the day.

Automatic

If method is Automatic, set the time when the plan locks each day.

Method Manual · the lock time disables itself

Choose how the plan should be set in stone for the day.

Manual

If method is Automatic, set the time when the plan locks each day.

Plan locking off · the two rules below stay live anyway

Automatically lock the day's plan at a specific time.

One dependent-disabled control, and one that should be. planningLockTime is disabled when planningLockMethod !== 'auto', which is exactly right. Across all seven settings components there are only three disabled controls, and this is the only one gated on a different setting: MobileDrawerSettings gates its checkboxes on the length of the very list they edit, and the email field on the Profile card is disabled statically because it is a hardcoded string. The switch above it has no such wiring: turning Enable Plan Locking off leaves Locking Method and Automatic Lock Time fully interactive, so you can carefully set a lock time on a feature that is switched off. Defaults are planningLockEnabled: true, planningLockMethod: 'auto', planningLockTime: "08:00".

MobileDrawerSettings
Picks the five shortcuts pinned to the bottom bar on a phone. The only settings component that enforces a hard cap, and the only one that explains itself with an Alert when you hit it.
src/components/settings/mobile-drawer-settings.tsx
Four selected · every item still clickable

Select up to 5 items to display in the mobile navigation drawer.

Five selected · the Alert appears and the rest disable

Select up to 5 items to display in the mobile navigation drawer.

Limit Reached
You can select a maximum of 5 shortcuts. Please unselect an item to choose a new one.

17 items, 5 slots, and a list that has gone stale. The cap is enforced twice over: handleCheckedChange refuses to push past five, and each unchecked box is disabled once five are picked. The Alert appears at exactly length >= 5. The five defaults are Now, Calendar, Planner, Conversations and Goals. The catch: this component keeps its own copy of allMenuItems, and that copy predates three routes. Tabatha, People and Context Inbox are in the sidebar but not here, so they cannot be chosen as shortcuts, and MobileDrawer cannot render them either. Both files carry the same stale list. Only the first six checkboxes are shown in the first variant; the second shows all 17.

LifeEventsSettings
Two switches that decide whether Flux is allowed to put things on your calendar by itself: the recurring life events you defined, and the right to move them when the day changes shape.
src/components/settings/life-events-settings.tsx
Out of the box · neither key has a default
Life Event Scheduling
Manage how Flux handles scheduling your recurring life events.

Let Flux automatically schedule your life events based on your defined priorities.

Automatically reschedule events if conflicts arise or if the schedule can be optimized.

Both on · Flux may schedule and reschedule

Let Flux automatically schedule your life events based on your defined priorities.

Automatically reschedule events if conflicts arise or if the schedule can be optimized.

The only two settings in Flux with no default value. lifeEventsEnabled and autoAdjustSchedule are declared optional on AppSettings and are absent from defaultSettings, so on a fresh account both read undefined. This component is also the only one that guards with settings?. rather than settings., which reads like the author knew. The visible result is benign (both switches render off, as shown) but the switches start uncontrolled and become controlled on first toggle. Note the labels here are the plain 14px default, not the text-base used by every other settings component: this card was written to a slightly different pattern.

PriorityManager Dead code Placeholder
A superseded take on life priorities: define a recurring event with a duration, a priority and whether it can be skipped. Nothing imports it, and the version users actually see is a different one defined inline on the page.
src/components/life-priorities/priority-manager.tsx
Not rendered
Nothing imports this file.

Two problems, which is why it is here rather than on the Life & Priorities page. It is seeded from a hardcoded array held in local state, so nothing it does persists. And it has zero importers: src/app/(app)/life-priorities/page.tsx declares its own PriorityManager inline and renders that one, backed by the real useLifePriorities() hook with goal linking. Deleting this file is safe. It is shown because a gallery that quietly omits dead code is a gallery you cannot count: 77 component files, 77 covered.

When things collide

1 component

Every calendar eventually has to answer the same question: two things want the same minute, so what now? Flux refuses to guess. It asks you once, here, and then applies your answer silently forever. This is the densest settings component in the app and the one with the most consequences per pixel.

OverlapSettings
Five standing rules for conflict: what to do by default, how hard to protect a meeting, and what happens when containers and atomic tasks land on top of each other. Every one of the five carries an InfoTooltip, because none of them are self-evident.
src/components/settings/overlap-settings.tsx
Hard Conflict Default · ask (the shipped default)

What should happen by default when a hard conflict is detected?

Always ask for resolution
Always ask for resolution
Keep higher priority task
Split time evenly
Meeting Protection · strict, and Meeting Priority · on

How strictly should meetings with external invitees be protected from overlaps?

Strict

If a meeting with invitees overlaps, it always wins by default.

Atomic vs. Multiple Containers · keep_one

Rule for when an atomic task overlaps with more than one container.

Keep one, convert others to notes
Keep one, convert others to notes
Flag as a hard conflict
Container vs. Container · merge

Rule for when two container blocks overlap.

Merge containers and child tasks
Merge containers and child tasks
Flag as a hard conflict
All five tooltips, opened
Set the default action when two atomic tasks or meetings conflict.
'Strict' mode prevents any overlap with protected meetings. 'Relaxed' mode will allow soft overlaps but flag hard conflicts.
If a meeting with invitees overlaps with another event, the meeting will always be prioritized, and the other event will be marked as a conflict.
Choose how to handle an atomic task that spans across several container blocks. You can either keep the first container and convert others to notes, or flag it as a conflict to resolve manually.
Choose how to handle two container blocks that overlap. They can be merged into a single block with combined child tasks, or you can flag them as a conflict to resolve manually.

Five controls, five tooltips, and one silent overwrite. This is the only settings component in Flux where every control explains itself, and it earns it: "keep_one", "relaxed" and "split" are decisions about your calendar that no label could carry alone. The shipped defaults are hardConflictDefault: 'ask', meetingProtection: 'strict', meetingPriority: true, atomicVsContainers: 'keep_one', containerVsContainer: 'merge'. Worth knowing before you tune anything here: choosing the ADHD or Autism profile on the Profile card rewrites hardConflictDefault without warning you, and this screen will simply show the new value as though you had chosen it.

Presets

Reference

This is the most interesting thing on the Settings page and it has no component of its own. Picking a profile under Neurodivergence Support does not just record a preference: setSetting intercepts the neuroType key and Object.assigns a block of other settings on top of your object, in the same write. The table below is getNeurotypeDefaults in src/context/settings-context.tsx, transcribed. It is reference material, not a card, so it does not enter the component count.

Profile What choosing it overwrites
Default Restores all six touched keys to their shipped defaults: maxDurationForAtomic: 25, hardConflictDefault: 'ask', showShadowEvents: true, defaultView: 'day', planningPreference: 'day-of', nightlyRoutineEnabled: true. The only branch that resets rather than sets.
ADHD maxDurationForAtomic: 15 (down from 25, so more imported events classify as atomic), hardConflictDefault: 'split', showShadowEvents: true.
Autism Spectrum
stored as Autism
defaultView: 'agenda', showShadowEvents: false, hardConflictDefault: 'ask'. A flat list instead of a grid, with nothing nested showing through.
Dyslexia showShadowEvents: false, defaultView: 'agenda'. The same two visual settings as Autism, without the conflict rule.
Anxiety planningPreference: 'night-before', nightlyRoutineEnabled: true. Touches nothing visual: it moves when Flux asks you to plan.

Three honest observations about this mechanism. First, it is a one-way door: the preset writes over whatever you had, and switching back to Default restores the shipped defaults, not the settings you personally chose before. Nothing warns you, and no other screen says a preset is responsible for the value it shows. Second, the preset blocks are uneven: ADHD sets showShadowEvents: true, which is already the default, so that key does nothing; Anxiety sets nightlyRoutineEnabled: true, likewise. Only the Default branch touches all six keys, so switching from Autism to Anxiety leaves defaultView: 'agenda' behind. Third, and worst: two profiles set defaultView: 'agenda', a value the Default Calendar View control cannot display, so those users find that control showing "Select rule..." forever. That is the reproduced bug on the CalendarSettings card. None of this makes the feature a bad idea. A calendar that changes its own defaults based on how you say you think is a real product position, and it is genuinely wired to Supabase. It just needs to say out loud what it did.