Skip to content

React Enterprise Application --- Performance, Security & Maintainability

React Enterprise Application — Interview Discussion

Section titled “React Enterprise Application — Interview Discussion”

This document consolidates the complete discussion from this conversation into an Astro-friendly Markdown document.


A React-based enterprise application is experiencing performance issues across different browsers, especially older enterprise environments.

How would you:

  • Identify the root cause?
  • Measure frontend performance?
  • Optimize rendering?
  • Ensure cross-browser compatibility?
  • Monitor improvements after deployment?

For an enterprise React application, performance should be approached as a combination of:

flowchart LR
    A[Measure] --> B[Identify Root Cause]
    B --> C[Optimize]
    C --> D[Cross-Browser Validation]
    D --> E[Deploy]
    E --> F[Monitor]
    F --> A

The key principle is:

Measure first, optimize based on evidence, then validate the improvement in production.

First, avoid assumptions and establish where the bottleneck is.

Determine whether the issue is:

  • Initial page load
  • API/network latency
  • JavaScript execution
  • React rendering
  • DOM size
  • User interaction
  • Memory consumption
  • Browser-specific behavior
  • Bundle size

Use:

  • Chrome DevTools Performance
  • Chrome DevTools Network
  • Chrome DevTools Memory
  • React DevTools Profiler
  • Lighthouse
  • Bundle analyzers
  • Browser compatibility testing

Check for:

  • Large JavaScript bundles
  • Slow APIs
  • Excessive component re-renders
  • Expensive calculations during rendering
  • Large DOM trees
  • Memory leaks
  • Unoptimized images/assets
  • Transpilation/polyfill issues
  • Inefficient third-party libraries

If a table contains 10,000 records and becomes slow, determine whether the application is rendering all 10,000 rows.

Possible solution:

10,000 records
|
+--> Pagination
|
+--> Server-side filtering/sorting
|
+--> Virtualization
|
v
Only visible/required rows rendered

The important point is to verify the bottleneck with profiling before changing the implementation.


Establish a baseline before optimization.

Important metrics include:

  • LCP — Largest Contentful Paint
  • INP — Interaction to Next Paint
  • CLS — Cumulative Layout Shift
  • FCP — First Contentful Paint
  • Page-load time
  • JavaScript bundle size
  • API latency
  • Memory consumption
  • Component render duration

For React-specific analysis, use React DevTools Profiler to identify:

  • Frequently rendered components
  • Expensive renders
  • Components rendering unnecessarily
  • Long render/commit phases

For production, use Real User Monitoring (RUM), because local development performance does not represent the full range of enterprise user devices and browsers.


Optimization should follow profiling.

Use:

  • React.memo
  • useMemo
  • useCallback
  • Proper state placement
  • Smaller components
  • Stable props where appropriate

Example:

const Reports = React.lazy(() => import("./Reports"));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Reports />
</Suspense>
);
}

Do not blindly add useMemo, useCallback, or React.memo everywhere.

They should be introduced when profiling demonstrates that they reduce meaningful work.

Use:

  • Pagination
  • Virtual scrolling/windowing
  • Server-side filtering
  • Server-side sorting
  • Selective rendering

Use:

  • Route-level code splitting
  • Lazy loading
  • Tree shaking
  • Bundle optimization
  • Image optimization
  • Compression
  • Static asset caching

First identify the exact browsers and versions the enterprise must support.

Then define a browser support matrix.

flowchart TD
    A[Browser Support Matrix] --> B[Browserslist]
    B --> C[Babel / Transpilation]
    B --> D[Polyfill Strategy]
    B --> E[CSS Compatibility]
    C --> F[Build]
    D --> F
    E --> F
    F --> G[Automated Browser Tests]
    G --> H[Manual Validation of Critical Flows]

Use:

  • Browserslist
  • Babel
  • Appropriate polyfills
  • CSS compatibility techniques
  • BrowserStack/Sauce Labs or equivalent
  • Automated browser tests
  • Real enterprise browser environments

Important distinction:

  • Transpilation converts unsupported syntax.
  • Polyfills provide missing runtime APIs.

For example, older browsers may need support for APIs such as:

  • Promise
  • fetch
  • Array.prototype.includes

Do not assume that every browser needs every polyfill.


Compare baseline metrics with production results.

Example:

Metric Before After


LCP 4.2s 2.4s FCP 2.8s 1.6s INP 350ms 150ms JavaScript bundle 3.5 MB 2.1 MB API latency 800ms 450ms

Monitor:

  • Core Web Vitals
  • JavaScript errors
  • Browser-specific failures
  • API latency
  • Page-load performance
  • Memory issues
  • Performance by browser/version
  • Performance by geography/network

For major changes, use feature flags or phased rollout so that old and new behavior can be compared safely.


2. Performance Tools, Code Splitting, Bundle Size & Polyfills

Section titled “2. Performance Tools, Code Splitting, Bundle Size & Polyfills”
  • What tools have you used (Lighthouse, Chrome DevTools, Web Vitals)?
  • When would you use code splitting?
  • How do you minimize bundle size?
  • How do you handle browser polyfills?

Use Lighthouse for an overall assessment of:

  • Performance
  • Accessibility
  • Best practices
  • SEO
  • Core Web Vitals-related signals

It is useful for establishing a baseline and checking regressions.

Use it to investigate:

  • JavaScript execution
  • Long tasks
  • Rendering
  • Layout/reflow
  • Scripting time

Use it to inspect:

  • API latency
  • Request sizes
  • Caching
  • Waterfall
  • Large assets
  • Blocking resources

Use it to investigate:

  • Memory leaks
  • Increasing heap usage
  • Detached DOM nodes

Use it to identify:

  • Unused JavaScript
  • Unused CSS

Use it to identify:

  • Expensive renders
  • Unnecessary renders
  • Frequently updating components

Monitor:

  • LCP
  • INP
  • CLS

Examples:

  • High INP → investigate expensive event handlers and excessive JavaScript execution.
  • High LCP → investigate critical rendering path, API calls, images and JavaScript.
  • High CLS → investigate unstable layout, images without dimensions, and dynamically inserted content.

I use Lighthouse for an overall performance baseline, Chrome DevTools for detailed network, JavaScript, rendering and memory analysis, and React DevTools Profiler for component-level rendering analysis. For production, I monitor Core Web Vitals such as LCP, INP and CLS using RUM.


Use code splitting when the application has a large JavaScript bundle and users do not need all functionality immediately.

Example enterprise application:

Dashboard
Reports
Administration
User Management
Analytics

A user opening Dashboard does not necessarily need JavaScript for every other feature.

flowchart LR
    A[Initial Application] --> B[Dashboard Chunk]
    A --> C[Reports Chunk]
    A --> D[Administration Chunk]
    A --> E[Analytics Chunk]

    B --> F[Initial Load]
    C --> G[Load on Demand]
    D --> G
    E --> G

Example:

const Reports = React.lazy(() => import("./Reports"));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Reports />
</Suspense>
);
}

Good candidates:

  • Route-level components
  • Large feature modules
  • Admin screens
  • Reporting/analytics
  • Heavy third-party libraries
  • Rarely used functionality

Avoid splitting every small component because excessive chunks can create unnecessary network and runtime overhead.

I primarily use code splitting for large applications where users don’t need the entire JavaScript bundle during initial load. I usually start with route-level splitting and then identify large or rarely used modules through bundle analysis.


Use a systematic approach.

Use:

  • Webpack Bundle Analyzer
  • Vite bundle analysis
  • Equivalent bundler tooling

Look for:

  • Large dependencies
  • Duplicate dependencies
  • Unused libraries
  • Large chunks
  • Unexpected dependencies

Do not add a large library for a small requirement if a native API or smaller dependency is sufficient.

Prefer ES module imports and a build configuration that supports tree shaking.

Lazy-load large or rarely used features.

  • Compress images
  • Use appropriate image formats
  • Lazy-load non-critical images
  • Minify JavaScript and CSS
  • Enable Brotli/Gzip where appropriate

Check whether multiple packages introduce different versions of the same dependency.

Use hashed filenames:

main.abc123.js
vendor.def456.js

This allows long-lived browser/CDN caching while still invalidating changed assets.

I first analyze the bundle to identify large and unused dependencies. Then I reduce bundle size through tree shaking, removing unnecessary libraries, route-level code splitting, lazy loading, asset optimization and compression. I also use proper caching and hashed filenames.


For older enterprise browsers, first identify the actual browser support requirements.

Use Browserslist to define supported targets.

Example:

> 1%
last 2 versions
not dead

The exact configuration should match the organization’s browser-support policy.

Handles unsupported syntax such as:

const
let
arrow functions
optional chaining

Provide missing runtime APIs such as:

Promise
fetch
Array.prototype.includes

A typical toolchain can use Babel and core-js, configured according to the supported browser targets.

Avoid loading every possible polyfill because that increases bundle size.

For browser compatibility, I first define the supported browser matrix using Browserslist. Babel handles syntax transformation, while polyfills such as core-js handle missing runtime APIs. I avoid loading every polyfill and configure the build based on our browser targets.

If asked, “How do you know which polyfill is required?”:

I don’t add polyfills based on assumptions. I check the browser support matrix, identify unsupported APIs used by the application, configure the build/polyfill strategy accordingly, and verify the final production bundle on the actual supported browser versions.


3. Secure Full-Stack Application for Sensitive Data

Section titled “3. Secure Full-Stack Application for Sensitive Data”

Explain how you would design a secure full-stack application that handles sensitive customer data while meeting PCI-DSS or HIPAA requirements.

Discuss:

  • Authentication
  • Authorization
  • Encryption at rest
  • Encryption in transit
  • Audit logging
  • Secrets management
  • API security
  • Compliance considerations

Follow-up:

  • What data should never be stored?
  • How do you protect PII?
  • How would you implement data masking?

The architecture should use defense in depth and least privilege.

PCI DSS and HIPAA are different frameworks with different requirements. An architecture can support compliance controls, but compliance is not achieved by architecture alone. Policies, procedures, vendors, processes, evidence and organizational controls also matter.


flowchart TD
    A[React Frontend] -->|HTTPS/TLS| B[API Gateway / WAF]
    B --> C[Identity Provider]
    B --> D[Spring Boot Services]

    D --> E[(Encrypted Database)]
    D --> F[Audit Logging]
    D --> G[Secrets Manager]
    D --> H[External Services]

    G --> I[KMS / HSM]

Apply defense in depth:

  • TLS everywhere
  • Strong authentication
  • Backend authorization
  • Encryption at rest
  • Secure secrets management
  • Input validation
  • API protection
  • Audit logging
  • Least privilege
  • Secure CI/CD
  • Continuous vulnerability monitoring

Use an established Identity Provider rather than implementing authentication from scratch.

Typical architecture:

sequenceDiagram
    participant U as User
    participant IDP as Identity Provider
    participant GW as API Gateway
    participant API as Spring Boot API

    U->>IDP: Login + MFA
    IDP-->>U: Access Token
    U->>GW: API request + token
    GW->>API: Authenticated request
    API-->>U: Response

Consider:

  • OAuth 2.0
  • OpenID Connect
  • MFA
  • Strong password policies where passwords are used
  • Short-lived access tokens
  • Refresh-token protection
  • Rate limiting
  • Secure session management

Never store plaintext passwords.

If credentials are handled by the application, use a strong password hashing mechanism such as Argon2id or bcrypt with appropriate configuration.


Authentication answers:

Who are you?

Authorization answers:

What are you allowed to access?

Use least privilege and RBAC/ABAC as appropriate.

Example:

Admin
→ Manage users
Support Agent
→ View permitted customer information
Customer
→ View only their own information

Authorization must be enforced by the backend.

Do not rely on React to hide buttons as a security mechanism.

For example:

GET /customers/123

The backend must verify that the current user is authorized to access customer 123.

This helps prevent IDOR/BOLA-style vulnerabilities.


Encrypt sensitive data stored in:

  • Databases
  • Files
  • Backups
  • Object storage

Infrastructure-level encryption may use strong encryption such as AES-256, depending on the platform.

For highly sensitive fields, consider application-level or field-level encryption.

Customer
------------------------
Name → encrypted
SSN → encrypted
Medical Data → encrypted
Payment Data → encrypted

Keys should not be stored alongside encrypted data.

Use KMS/HSM-backed key management where appropriate, with controlled access and key rotation.


Use HTTPS/TLS for:

Browser → API Gateway
API Gateway → Service
Service → Database
Service → Service
Service → External API

Disable insecure protocols and use an approved TLS configuration.

For sensitive service-to-service communication, mTLS can provide additional service authentication.


Maintain an audit trail for security-relevant events:

Login
Logout
Failed authentication
Password changes
Permission changes
Sensitive-data access
Sensitive-data modification
Data export
Administrative operations

Example:

{
"userId": "12345",
"action": "CUSTOMER_RECORD_VIEW",
"resource": "customer",
"resourceId": "98765",
"timestamp": "...",
"result": "SUCCESS",
"correlationId": "abc-123"
}

Do not put sensitive customer data into logs.

Avoid:

SSN=123-45-6789
cardNumber=4111111111111111

Logs should be:

  • Centralized
  • Access-controlled
  • Protected from tampering
  • Retained according to policy
  • Monitored for suspicious activity

Never store secrets directly in source code:

db.password=MyPassword123

Instead use a dedicated secrets-management solution, for example:

  • AWS Secrets Manager
  • Azure Key Vault
  • Google Cloud Secret Manager
  • HashiCorp Vault

Architecture:

flowchart LR
    A[Spring Boot Application] --> B[Secrets Manager]
    B --> C[Database Credentials]
    B --> D[API Credentials]
    B --> E[Encryption Keys / References]

Implement:

  • Secret rotation
  • Least-privilege access
  • Short-lived credentials where possible
  • Secret-access auditing
  • No secrets in Git
  • No secrets in Docker images

For Spring Boot APIs:

Use OAuth2/OIDC with a suitable token/session strategy.

Use Spring Security and resource-level checks.

Example:

@PreAuthorize("hasRole('ADMIN')")

However, role checks alone are not sufficient when authorization depends on the specific resource.

Use DTO validation:

@NotBlank
@Size(max = 100)
private String name;
  • Rate limiting
  • Request-size limits
  • CORS configuration
  • CSRF protection where applicable
  • Security headers
  • SQL injection prevention
  • Output encoding
  • XSS protection
  • SSRF protection where applicable
  • API versioning
  • Dependency vulnerability scanning

The API Gateway/WAF can provide an additional layer for:

Rate limiting
IP filtering
WAF rules
Request filtering
DDoS protection

Start with a data-flow and compliance-scope analysis.

flowchart TD
    A[What data do we collect?] --> B[Where is it stored?]
    B --> C[Who can access it?]
    C --> D[Where does it travel?]
    D --> E[Which third parties receive it?]
    E --> F[How long is it retained?]
    F --> G[How is it deleted?]

Focus on:

  • Minimizing cardholder-data exposure
  • Reducing the cardholder-data environment
  • Tokenization
  • Secure payment processing
  • Strong access controls
  • Logging and monitoring
  • Vulnerability management
  • Secure development practices

Where possible, avoid handling raw payment-card data directly and use a PCI-compliant payment provider/tokenization model.

Identify PHI/ePHI and implement appropriate safeguards around:

  • Access control
  • Audit controls
  • Integrity
  • Transmission security
  • Administrative safeguards
  • Physical safeguards
  • Vendor relationships
  • Business Associate Agreements where applicable

Also consider:

  • Data retention/deletion
  • Access reviews
  • Vulnerability management
  • Penetration testing
  • Secure SDLC
  • Incident response
  • Backup/recovery
  • Employee access controls
  • Security training
  • Compliance evidence
  • Third-party risk

The best principle is:

If we don’t need the data, we shouldn’t collect or store it.

Do not store sensitive authentication data such as:

CVV/CVC

after authorization.

For card numbers, if the application doesn’t need them, use a payment provider and store a token/reference instead of the raw PAN.

Never store:

Plaintext passwords
Password recovery answers in plaintext
Session secrets in logs

Do not store PHI/ePHI unless there is a legitimate business requirement and appropriate controls.

The principle is:

Data minimization
Collect only what is necessary
Retain only as long as necessary
Securely delete when no longer required

Use multiple layers.

Do not collect unnecessary PII.

Examples:

SSN → encrypted
Bank account → encrypted
Medical information → encrypted

Use RBAC/ABAC and least privilege.

Instead of:

123-45-6789

show:

***-**-6789

Never log:

SSN
Full card number
Password
Authentication tokens
Sensitive medical details

Use internal identifiers instead of exposing PII wherever possible.

PII in:

  • CSV exports
  • Reports
  • Data warehouses
  • Database backups
  • Object storage

must receive appropriate protection.


Masking should occur at multiple layers.

Example:

function maskCard(cardNumber) {
return "**** **** **** " + cardNumber.slice(-4);
}

Display:

**** **** **** 1234

This is only presentation-level protection. Backend authorization is still required.

Instead of:

{
"ssn": "123456789"
}

return:

{
"ssn": "***-**-6789"
}

based on user permissions.

Example:

Admin
→ Full value
Support
→ Masked value
Customer
→ Own value / partially masked
Unauthorized
→ No value

Consider:

  • Encryption
  • Tokenization
  • Dynamic data masking
  • Separate storage for highly sensitive data

Instead of:

Customer payment card: 4111111111111111

log:

Customer payment card: ****1111

Centralized logging filters/interceptors can provide an additional safeguard against accidental PII leakage.


A large React application has become difficult to maintain due to:

  • Duplicated components
  • Inconsistent coding standards
  • Multiple state management approaches
  • Business logic spread across UI layers

As a Lead Developer, how would you:

  • Refactor the application?
  • Create coding standards?
  • Improve maintainability?
  • Reduce technical debt?

The goal should be:

Controlled modernization rather than a big-bang rewrite.

The objective is not simply to make the code look cleaner. The objective is to make the application easier and safer to change.


Start with assessment.

Identify:

  • Duplicated components
  • Large/complex components
  • Repeated API calls
  • Business logic inside JSX
  • Multiple state-management patterns
  • Repeated utilities
  • Tight coupling
  • Components with too many responsibilities

Useful tools include:

  • React DevTools
  • ESLint
  • TypeScript
  • Dependency analysis
  • Code coverage
  • Static analysis
  • SonarQube or equivalent

Prioritize findings:

Critical → Security / production risk
High → Major maintainability/performance issue
Medium → Duplication / inconsistency
Low → Cosmetic / cleanup

A feature/domain-oriented structure works well for a large enterprise React application.

Example:

src/
├── components/
│ ├── common/
│ └── forms/
├── features/
│ ├── customer/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── services/
│ │ ├── types/
│ │ └── utils/
│ │
│ └── orders/
├── services/
│ ├── api/
│ └── auth/
├── hooks/
├── store/
├── utils/
└── types/

This keeps domain functionality together rather than creating massive global folders.


Suppose the application contains:

CustomerTable.jsx
UserTable.jsx
OrderTable.jsx

and all have almost identical pagination, sorting and filtering.

Extract genuinely common behavior:

<DataTable
data={customers}
columns={customerColumns}
pagination
sorting
/>

But avoid creating a giant generic component simply because two components currently look similar.

The rule:

Reuse when the behavior is genuinely common, not merely because the current markup looks similar.


Avoid components that perform all of these tasks simultaneously:

API call
Validation
Business rules
Calculations
State management
Error handling
Rendering

Prefer separation:

flowchart TD
    A[React Component] --> B[Custom Hook]
    B --> C[Business Logic]
    C --> D[Service]
    D --> E[API]

Example:

customerService.js
export async function getCustomer(id) {
return apiClient.get(`/customers/${id}`);
}

Then:

useCustomer.js
export function useCustomer(id) {
// state + fetching + error handling
}

And:

function CustomerPage() {
const { customer, loading, error } = useCustomer(id);
// UI
}

This makes business logic easier to test independently.


If different areas use Redux, Context, Zustand and local state without clear rules, maintenance becomes difficult.

Define clear guidelines.

Example:

Requirement Preferred approach


Local UI state useState Limited cross-component sharing Context where appropriate Server/API state TanStack Query or equivalent Complex global client state Redux Toolkit Form state Standard form library/pattern

The exact technologies can depend on the organization.

The important thing is:

Define when each approach should be used.

Do not rewrite everything solely to standardize it. Migrate gradually.


Create frontend development guidelines covering:

CustomerList.jsx
useCustomer.js
customerService.js

Use consistent naming for:

  • Components
  • Hooks
  • Services
  • Constants
  • Types
  • Tests
  • Avoid huge components
  • Separate presentation from business logic
  • Reuse genuinely common components
  • Avoid unnecessary prop drilling
  • Avoid unnecessary useEffect
  • Avoid scattered API calls throughout UI components

Document:

When to use useState
When to use Context
When to use Redux
When to use server-state management

Standardize:

API client
Error handling
Authentication
Request/response models
Loading states
Retry behavior

Do not rely on developers remembering the standards.

Use:

ESLint
Prettier
TypeScript
Husky
lint-staged
SonarQube
CI/CD quality gates

Example development pipeline:

flowchart LR
    A[Developer Commit] --> B[ESLint]
    B --> C[Prettier]
    C --> D[Unit Tests]
    D --> E[Build]
    E --> F[Static Analysis / Quality Gate]
    F --> G[Pull Request]
    G --> H[Review]
    H --> I[Merge]

This makes coding standards part of the development process.


Refactoring without tests is risky.

Before major changes, establish a safety net.

For:

  • Utilities
  • Hooks
  • Business logic
  • Services

For:

  • Rendering
  • User interactions
  • Validation
  • Error states

For critical business flows:

Login
Search customer
View customer
Update customer
Submit

This allows internal refactoring while preserving expected behavior.


Do not try to eliminate all technical debt simultaneously.

Create a technical-debt backlog and prioritize using:

Business impact
+
Production risk
+
Development cost
+
Frequency of change

Example:

Debt Impact Priority


Duplicate authentication logic High P1 Large customer component High P1 Duplicate table components Medium P2 Old utility functions Low P3

Leave the code slightly better than you found it.

When developers modify frequently changing areas, gradually improve the code instead of creating additional debt.


Avoid rewriting the entire React application unless there is a compelling business reason.

Use incremental migration:

flowchart TD
    A[Existing Application] --> B[Define Standards]
    B --> C[Add Tests Around Critical Areas]
    C --> D[Identify High-Value Module]
    D --> E[Refactor Module]
    E --> F[Introduce Standard Architecture]
    F --> G[Migrate Gradually]
    G --> H[Remove Legacy Patterns]
    H --> I[Measure Improvement]

Possible phases:

Phase 1 → Define standards
Phase 2 → Common components/utilities
Phase 3 → Refactor high-change modules
Phase 4 → Standardize state management
Phase 5 → Remove legacy patterns
Phase 6 → Measure technical-debt reduction

As Lead Developer, do more than write an architecture document.

Responsibilities include:

  • Conduct design/code reviews
  • Create reusable templates
  • Provide reference implementations
  • Pair with developers on difficult refactoring
  • Add standards to PR checklists
  • Track technical debt
  • Conduct architecture reviews
  • Mentor developers
  • Monitor code-quality metrics
  • Review state-management decisions
  • Encourage incremental migration

The Lead should establish standards without becoming a bottleneck for every small decision.


I would start by profiling rather than immediately optimizing. I would use Lighthouse, Chrome DevTools and React DevTools Profiler to determine whether the bottleneck is network, JavaScript execution, rendering, DOM size, memory or bundle size. I would establish baseline metrics such as LCP, INP, FCP, bundle size and API latency. Based on profiling, I would optimize unnecessary renders, use code splitting and virtualization where appropriate, and optimize assets and caching. For older enterprise browsers, I would define a browser support matrix using Browserslist, configure Babel and required polyfills, and test critical flows across supported browsers. Finally, I would use RUM/APM monitoring after deployment to compare before-and-after metrics.

I would use defense in depth and least privilege. Authentication would use an enterprise IdP with OAuth2/OIDC and MFA, while authorization would be enforced at the backend using roles and resource-level permissions. Traffic would use TLS, sensitive data would be encrypted at rest with KMS-managed keys, and secrets would be stored in a dedicated secrets manager rather than source code. Security-sensitive actions would be audited without putting PII or credentials into logs. At the API layer I would implement validation, rate limiting, secure headers, CORS, injection protection and authorization checks. Finally, I would minimize the data collected, tokenize payment information where possible, mask PII based on permissions, and maintain the required compliance processes and evidence for the applicable PCI DSS or HIPAA scope.

I would treat maintainability as an incremental modernization effort rather than a big-bang rewrite. First, I would assess the codebase and identify duplicated components, large components, business logic embedded in UI, inconsistent state management and high-risk technical debt. I would introduce a feature-oriented architecture and clear boundaries between presentation, hooks, business logic, services and APIs. I would standardize state-management decisions and enforce coding standards using ESLint, Prettier, TypeScript, static analysis and CI quality gates. Before major refactoring, I would add tests around critical flows. Finally, I would maintain a prioritized technical-debt backlog and migrate high-impact modules gradually.

My objective wouldn’t be to make the codebase look cleaner; it would be to make the application easier and safer to change.