Product Systems Architecture
I design complex software systems so people can understand what is happening, how the parts relate, what changed, and what they can do next — while making the product easier to change, extend, and maintain.
The visible interface is only one layer. Product behavior also lives in data, rules, reusable components, application state, operational context, technical constraints, failure paths, and the relationships between objects. I work across those layers so people can understand what is happening without reconstructing the underlying system for themselves.
Make the system legible.
As products grow, users encounter more objects, relationships, states, histories, dependencies, and possible actions. Complexity becomes a design problem when the product requires people to hold those relationships in memory or stitch together the state of the system one screen at a time.
I separate the structure required by the underlying system from the structure required for human comprehension, then design the representation around what a person needs to understand and do. Technical complexity can remain hidden when it is irrelevant and become explicit when it is necessary for judgment, recovery, or action.
Design state, not screens.
A useful product has to remain coherent when reality changes. Current, pending, past due, completed, unavailable, invalid, empty, partially configured, and failed states are not decorative variants of the happy path. They determine what information matters, which actions remain legitimate, what the user needs to understand, and how the system can help them recover.
I design the whole state transition: entry condition, visible context, available action, validation, system feedback, consequence, and next state. That makes an error, warning, status change, or recovery path part of the interface rather than an afterthought attached to it.
First-use is the same state problem viewed from the beginning. Installation, activation, setup, configuration, and onboarding should carry a person from “not yet working” to a first successful state with enough context to understand what the system needs, what has happened, and what to do when something blocks progress.
Reduce the cost of change.
Complex products become expensive when every change requires finding and modifying the same idea in multiple places. I look for what is unnecessarily fixed, move repeated behavior into reusable capability, and expose legitimate variation through configuration.
The goal is not abstraction for its own sake. It is to make systems easier to understand, safer to change, faster to extend, and more coherent as their surface area grows.
System models are usually optimized for implementation: objects, services, records, relationships, routes, permissions, events, and configuration. People need a different view: what exists, how it relates, what changed, what matters now, and what they can safely do next.
I use information architecture, hierarchy, progressive disclosure, relationship views, contextual actions, navigation, and system feedback to reduce the hidden interpretation required between the technical model and the person operating it.
The state of the system changes the meaning of the interface. A pending transaction, rejected input, past-due account, completed process, missing dependency, or failed action requires different information and different next steps than the normal path.
I treat validation, error handling, warnings, disabled actions, status, confirmation, and recovery as part of the product model. The user should be able to understand what happened, what remains true, what changed, and what options are still available.
Consequential actions are easier to understand when the relevant system state stays visible. Rather than sending users through disconnected pages, I bring the next layer of detail forward while preserving the account, object, relationship, or workflow context that gives the action meaning.
This is especially important in financial, administrative, and operational systems where one action may depend on balances, prior transactions, permissions, related objects, deadlines, policy, or downstream effects.
Reuse works when the product distinguishes between what should remain invariant and what legitimately needs to vary. Shared behavior belongs in tested components and application services; brand, density, labels, icons, data, presentation, and product-specific configuration can remain flexible.
That separation reduces duplicated maintenance while increasing control. A new product or branded experience can inherit proven interaction behavior without becoming a fork that has to be maintained independently.
I stay close to working software because implementation exposes assumptions that static representations can hide. DOM structure, responsive behavior, component composition, state, focus, validation, technical constraints, and visual precision become testable when the design is running.
My work has included Angular, AngularJS, NativeScript, HTML/CSS/JavaScript, SCSS, SVG, browser development tools, reusable component systems, production code, and live-data prototypes. Code is not a substitute for design; it is one of the places where design intent becomes inspectable.
Interaction craft matters for the same reason. Hover, focus, pressed states, transitions, slide and reveal behavior, drag-and-drop feedback, and restrained motion can make cause, consequence, and state change visible without forcing the user to infer what just happened.
High-fidelity and working prototypes also reduce decision latency. I use them to expose implementation questions early, separate MVP from later expansion, and give product, design, and engineering a shared thing to evaluate before more expensive choices harden.
Administrative consoles, financial systems, dashboards, and operational tools often have to expose more information, not less. The design problem is deciding what deserves prominence, what can remain available without competing for attention, and how people scan from system state to evidence to action under time pressure.
I use hierarchy, grouping, status models, tables, filtering, contextual actions, progressive disclosure, and consistent interaction patterns to make information density usable rather than merely compact.
At Softwise, I led experience architecture across five financial products while working directly in Angular production. The work crossed customer experiences, lending, servicing, payments, collections, line-of-credit, point-of-sale and title-lending, and administrative workflows.
The design problem was not a sequence of isolated screens. Product state, financial rules, customer context, operational actions, validation, reusable behavior, and implementation had to remain coherent across the product family.
First-use work included journeys for new customers and loan operators. High-fidelity prototypes helped clarify the minimum viable experience, test assumptions early, and focus the team on the clearest path to a useful first release rather than carrying every possible requirement into the first implementation.
Design focus: keep system state, business rules, available actions, validation, and user context coherent as work moved between customer, servicing, payment, collections, and administrative workflows.
I co-architected a shared Angular / NativeScript application approach and later maintained and extended the reusable application layer behind it. Common interaction behavior could be implemented and tested once while product-specific branding, content, data, and workflow differences remained configurable in the applications that consumed it.
The reusable layer covered form behavior, validation, configurable tables and lookups, hierarchical selection, display components, and common interaction infrastructure. Rather than reproduce those patterns for each product surface, teams could assemble interfaces from a common behavioral vocabulary and adapt presentation without forking the underlying behavior.
- Common behavior: value/state propagation, validation, focus, disabled state, error handling.
- Configurable presentation: density, labels, icons, hints, explanations, theme and product-specific variation.
- Operational primitives: configurable tables, search/paging models, lookup dialogs, hierarchical tree controls.
- Shared delivery: packaged library behavior separated from branded application shells and product-specific styling.
The architectural principle: identify what should remain invariant, encode and test that behavior once, and expose what should vary through configuration.
This allowed design and development to work in parallel from a common component vocabulary. Management credited the shared approach with reducing development effort by approximately 35% while making rebranding, product variation, and interface production substantially easier to maintain.
At Novell, I designed enterprise collaboration and administration experiences within a product ecosystem serving more than 10 million users, including browser-based administration supporting more than 10,000 administrators.
The work included translating technically complex administration into understandable objects, navigation, configuration, status, and relationship views. GroupWise Link Configuration is a particularly direct example: select a source and destination, understand how the objects connect, inspect the relationship, then configure the route and behavior without losing the topology that gives the settings meaning.
I also designed a server-health experience that surfaced storage capacity, risk, and unhealthy states, with filtering, exception highlighting, and drill-down from overall system condition to the specific issue requiring attention. The pattern was aggregate → identify exceptions → filter → inspect → act.
First-use work included GroupWise desktop installation and administrator-configuration flows. In iPrint, I originated a QR-based setup concept that let a mobile user identify and connect to the printer in front of them by scanning a code. I explained the concept to product, worked with engineering through several iterations, and later saw the working experience used at a conference.
I also worked directly with the corporate brand team to replace a siloed handoff model with shared implementation review. That collaboration helped carry branding consistently across products while allowing tighter interface chrome and more usable space for the person’s actual content.
At Booz Allen Hamilton, I worked across public-sector modernization on enterprise workflows, front-end modernization, data-dense decision support, and working-code prototypes. I keep this portfolio intentionally high-level and omit client-specific systems, mission details, operational data, internal artifacts, and implementation specifics that have not been established as approved for public release.
Across that work, the recurring design problem was comprehension under complexity: expose enough state for a person to understand what is happening, preserve the evidence behind a decision, and make the next action visible without turning the product into an undifferentiated wall of data.
My current AI work applies the same product-systems discipline to retrieval, agentic workflows, evidence, provenance, model constraints, human review, escalation, and failure handling. A useful AI interface has to communicate not only an answer, but what supports it, what remains uncertain, what the system is allowed to do, and where human judgment must take over.
I treat model behavior, retrieval structure, and instructions as evolving product dependencies. The product therefore needs visible state, traceable evidence, correction paths, and explicit authority boundaries rather than assuming the underlying system will always behave the same way.