Copec Personas — Flux Module

Copec Personas — Flux Module

Tech lead on Flux (copec_modulo_flux), a standalone Flutter module consumed by App Copec Personas — onboarding, device pairing, real-time energy state, daily accumulated energy and historical charts across day, week, month and year views.

Flux is a Flutter module that lives inside App Copec Personas — the host consumer app — for customers of Copec’s home-energy product. From inside the main app, users enter Flux to onboard a location, pair devices by scanning a barcode, see real-time and daily energy, browse historical charts, and respond to device alerts. I worked as tech lead on the module, which ships as a versioned Flutter package, copec_modulo_flux.

Context and problem

Copec is a fuel and convenience-store brand expanding into home energy, and Flux is the in-app experience for that product. Building it as a separate Flutter module — with its own changelog, version and release rhythm — kept the energy product moving at its own pace, independent of everything else happening in the base app.

How it works

App Copec Personas is the host; Flux is one of the Flutter modules it depends on. The two pieces communicate over a small, intentional surface: the host hands the user (and a barcode, if one was scanned) into Flux, and from there Flux talks to Copec’s backend on its own.

%%{init: {'theme': 'base'}}%%
flowchart LR
    user((User))
    host["App Copec Personas host app"]
    flux["copec_modulo_flux module"]
    backend[("Copec backend")]

    user -->|enters Flux section| host
    host -->|hands off routing context and barcode| flux
    host -->|account and session API| backend
    flux -->|locations, devices and energy API| backend

Inside Flux, the user comes in through a single entry point that branches by location state:

%%{init: {'theme': 'base'}}%%
flowchart LR
    entry((Enter Flux))
    strategy{Has locations?}
    onboarding["Onboarding and device pairing"]
    subhome["Subhome: real-time and daily totals"]
    history["Historical charts"]
    alerts["Device alerts"]

    entry --> strategy
    strategy -->|no| onboarding
    strategy -->|yes| subhome
    subhome --> history
    subhome --> alerts

Flux owns its onboarding, the real-time and daily-totals subhome, energy-flow animations, device alerts and the historical analytics. The barcode handoff from the host resolves through a single decision point — onboarding for new users, alias-change for users with an existing location — so the two paths stay clear as more entry sources appear.

The historical charts are the heaviest surface: day as a continuous line, week, month and year as grouped bars, all with tooltips, date selectors and an expanded view. Day views are windowed to the active production hours, since most of the data is concentrated there. The expanded view keeps tooltips inside the visible area so the user doesn’t lose information when they zoom in.

Flux — module functionalities

Challenges

Being a guest in someone else’s app. Flux had to feel native to App Copec Personas while staying genuinely independent at the code level — sharing through the Copec mobile family’s design and utility libraries, and keeping the host/module surface as narrow as possible.

Charts that have to behave. Tooltip selection and locking, distinguishing tap from drag, centring tooltips on a group of bars rather than wherever the tap landed, and keeping tooltips inside the visible area in the expanded view — each is small on its own, together they’re the difference between a chart that feels considered and one that feels rough.

Routing through a barcode entry point. New users had to land at the start of onboarding with the code held; returning users with locations had to land in alias-change. Treating that as a single decision point made the entry logic extensible instead of patched every time a new source appeared.

Keeping quality measurable. As the surface grew, we layered in stricter linter and code-metrics rules — for unsafe dynamic calls, leaked subscriptions, missing return types, deep widget nesting. The goal was consistent signal on what was getting tangled, not a score.

Key decisions and trade-offs

DecisionTrade-off
Ship Flux as a standalone Flutter module consumed by the host appIndependent release cadence and a clean ownership boundary, at the cost of a versioned dependency to manage
Use shared design and utility libraries instead of local equivalentsVisual and behavioural consistency across the Copec apps, at the cost of some flexibility inside the module
A single decision point for barcode entry from the hostClear, testable entry-point logic that scales as more sources appear, at the cost of a small upfront indirection
Tighten linter and code-metrics rules incrementallyConsistent signals on complexity as the module grew, at the cost of occasional rewrites to clear new rules

What I learned

Owning a Flutter module inside another team’s host app is its own discipline. The technical challenges are familiar; the integration story is where the module either succeeds or fails. Versioning the module like a library, with a real changelog tied back to the tickets that produced each entry, turned out to be the simplest way to keep a fast-moving module legible to everyone else — including future me.

Tech stack

  • Flutter module (copec_modulo_flux), versioned independently of App Copec Personas.
  • fl_chart (via muevo_utils_library) for the historical charts.
  • muevo_modulo_design_kit for shared design primitives.
  • Amplitude for product analytics.
  • dart_code_metrics presets and stricter lints for code-health enforcement.
  • Independent CHANGELOG.md tied to Jira tickets and Semantic Versioning.

Closing reflection

Flux is a project about restraint: small enough to live inside someone else’s app, focused enough to evolve quickly, consistent enough that users never feel they’ve left App Copec Personas. The technology is mainstream; the craft is in the boundaries.


© 2026. All rights reserved.