DEV Community

Cover image for From Vibe Coding to Demo-Ready: Hardening a React Application with the Twelve-Factor App Methodology
Sandeep Chakravartty
Sandeep Chakravartty

Posted on AI-assisted

From Vibe Coding to Demo-Ready: Hardening a React Application with the Twelve-Factor App Methodology

How I used software architecture principles, the Twelve-Factor methodology, security controls, automated testing, and immutable deployments to harden a Rapid Circularity Assessment calculator.

1. Introduction: The challenge with vibe-coded applications

Vibe coding has fundamentally changed how quickly we can translate ideas into working applications.

With AI-assisted development, we can move from a concept to a functioning prototype in hours rather than weeks. This is particularly valuable for experimentation, research applications, proof-of-concepts, and demonstrations.

However, there is a significant difference between an application that works on a developer's machine and one that is sufficiently reliable, secure, explainable, and reproducible for a professional demonstration.

AI-generated applications may work well along their intended happy paths but still have architectural weaknesses:

  • Limited separation of business logic and presentation
  • Unvalidated user inputs and browser storage
  • Inconsistent error handling
  • Uncontrolled dependencies
  • Missing automated testing
  • Environment-specific assumptions
  • Limited operational observability
  • Unrepeatable build and deployment processes

These weaknesses become particularly visible during demonstrations, when an unexpected input, browser refresh, deployment issue, or calculation inconsistency can undermine the credibility of the entire solution.

I encountered this engineering challenge while developing the Rapid Circularity Assessment (RCA) Calculator, a browser-based application for estimating material savings and additional environmental and worker outcomes associated with circular business models.

Rather than introducing an unnecessarily complex enterprise architecture, I used the Twelve-Factor App methodology as an architectural hardening framework, supplemented by security engineering, automated testing, deployment verification, and operational readiness practices.

This article explains the application architecture, the technology stack, the hardening decisions, and how the twelve factors were adapted to a predominantly client-side system.

GitHub repository: https://github.com/scha54/RCA-Calculator

Live application: https://rca-calculator.vercel.app

2. Understanding the RCA Calculator

The RCA Calculator is a research-oriented screening application designed to explore how circular economy interventions might reduce virgin textile consumption.

Users can model interventions such as extending product lifetimes, increasing garment reuse, improving textile collection and recycling, and reducing manufacturing waste.

The application provides the ability to:

  • Estimate annual virgin textile material savings.
  • Compare up to three assessment scenarios.
  • Evaluate material circularity across slowing, closing, and life-cycle strategies.
  • Explore environmental and worker-related outcomes.
  • Apply configurable uncertainty assumptions.
  • Conduct sensitivity analysis to identify influential parameters.
  • Visualize results through radar charts and sensitivity diagrams.
  • Export assessment results to Excel, JSON, Markdown, and printable reports.

An important characteristic of this application is that it is a screening model, not a certified Life Cycle Assessment (LCA) system.

The calculations support exploratory evaluation and decision-making. They do not establish independently audited environmental impact claims.

This distinction influenced the architecture. The application needed transparent calculations, explicit assumptions, validation, and traceable outputs rather than a complicated backend infrastructure.

3. Architecture: A modular, browser-first application

The deployed RCA Calculator follows a static-client, modular frontend architecture.

It does not require an application backend, shared database, authentication service, or server-side calculation engine.

Instead, the system separates presentation, domain calculations, scenario management, local persistence, reporting, and deployment responsibilities.

High-level architecture

                  User / Browser
                         |
                         v
                React Presentation
                         |
           +-------------+-------------+
           |             |             |
           v             v             v
      Assessment     Scenario       Results and
      Workflow       Management     Visualization
           |             |             |
           +-------------+-------------+
                         |
                         v
                TypeScript Domain
                 Calculation Engine
                         |
          +--------------+-------------+
          |              |             |
          v              v             v
     JSON Model      Sensitivity    Additional
     Definitions      Analysis       Outcomes
          |              |             |
          +--------------+-------------+
                         |
              +----------+----------+
              |                     |
              v                     v
       Browser Storage        Export Services
        (localStorage)      JSON / Excel / Print
              |
              v
        Portable Backup


              Delivery Architecture

          GitHub Source Repository
                    |
                    v
             GitHub Actions
                    |
          +---------+----------+
          |                    |
          v                    v
     Automated Tests     Security & Build
                            Validation
          |                    |
          +---------+----------+
                    |
                    v
             Vite Build
                    |
                    v
           Immutable dist/
           + release.json
                    |
           +--------+---------+
           |                  |
           v                  v
       Vercel CDN       Portable Node
                       Static Server
Enter fullscreen mode Exit fullscreen mode

The architecture makes a deliberate trade-off: it prioritizes simplicity, reproducibility, privacy, and maintainability over features that would require centralized application state.

Separation of architectural responsibilities

The codebase is structured around identifiable functional boundaries.

RCA-Calculator/
|
+-- data/
|   +-- formulas.json
|   +-- parameters.json
|   +-- confidence.json
|   +-- benchmarks.json
|   +-- settings.json
|
+-- src/
|   +-- components/
|   +-- pages/
|   +-- engine/
|   |   +-- model.ts
|   |   +-- calculate.ts
|   |   +-- outcomes.ts
|   |
|   +-- export/
|   |   +-- excel.ts
|   |   +-- json.ts
|   |
|   +-- platform/
|   |   +-- diagnostics.ts
|   |
|   +-- App.tsx
|   +-- main.tsx
|
+-- tests/
+-- e2e/
+-- scripts/
+-- docs/
+-- .github/workflows/
|
+-- package.json
+-- package-lock.json
+-- vercel.json
+-- vite.config.ts
Enter fullscreen mode Exit fullscreen mode

This structure serves several architectural purposes.

Presentation remains separate from calculation logic. React components manage user interaction, navigation, and visualization, while domain logic is implemented in TypeScript modules.

Model definitions are externalized into version-controlled JSON files. Parameters, formulas, confidence bands, and reference benchmarks are independently identifiable.

Export functionality is isolated. Generating an Excel workbook does not require embedding workbook-generation logic inside the assessment screens.

Platform responsibilities are explicit. Diagnostics, deployment configuration, build verification, and runtime serving are distinguishable from domain calculations.

This separation is important when hardening an AI-assisted application because it makes code reviews and automated testing more focused.

Instead of reviewing a large, tightly coupled component, we can review specific architectural responsibilities.

4. Technology stack

The RCA Calculator uses a relatively small but purposeful technology stack.

Layer Technology Responsibility
UI framework React 19 Component-based interactive interface
Programming language TypeScript 5.8 Type safety and maintainable domain logic
Build system Vite 6 Development tooling and optimized production bundles
Styling Tailwind CSS 4 Responsive presentation and design consistency
Visualization Recharts 3 Results and analytical charts
Workbook generation ExcelJS 4.4 Client-side Excel report generation
Persistence Browser localStorage Local assessment state
Unit testing Vitest 5 Model and utility verification
Browser testing Playwright End-to-end workflow verification
Accessibility testing axe-core with Playwright Automated accessibility checks
Runtime tooling Node.js 24 / npm 11 Reproducible builds and portable serving
CI GitHub Actions Automated validation and release artifact generation
Hosting Vercel Static application delivery
Version control Git / GitHub Source control and release traceability

Python also appears in the repository as a utility for creating model data. It is not part of the deployed browser runtime.

An important architectural decision was to avoid introducing technologies without a clear application requirement.

For example, adding PostgreSQL, Redis, message queues, or Kubernetes would not automatically make this calculator more robust. For the current single-user browser workflow, these technologies would increase operational responsibilities without providing proportional value.

The architecture follows a practical principle:

Use the minimum system complexity required to satisfy the application's functional and non-functional requirements.

5. Designing a reliable domain calculation engine

For a scientific screening application, the calculation engine is one of the most important architectural components.

A visually polished interface is of limited value if the underlying model is inconsistent or cannot be independently verified.

The RCA Calculator defines model parameters and mathematical expressions separately from the presentation layer.

The calculation engine reads those definitions, validates scenario inputs, evaluates formulas, and produces structured results.

For example, the baseline virgin textile demand is calculated as:

Baseline Virgin Demand =
    Items Sold
  × Average Garment Weight
  × (1 - Collection Rate × Recycling Yield)
  / 1000
Enter fullscreen mode Exit fullscreen mode

The division converts kilograms into tonnes.

The application then calculates contributions from several circularity interventions and derives total material savings and residual virgin demand.

Restricted formula evaluation

One useful hardening decision was implementing a restricted arithmetic parser instead of evaluating expressions as JavaScript.

The parser accepts a controlled set of operations, numeric literals, named variables, parentheses, and MIN/MAX functions.

It does not execute arbitrary JavaScript from model definitions or imported scenarios.

This creates an important security boundary between externally represented calculation data and executable application code.

Input and model validation

The domain model also validates incoming scenarios.

Validation includes:

  • Scenario schema version and structural integrity
  • Supported geographic regions
  • Numeric bounds and finite numeric values
  • Valid confidence selections
  • Consistency of uncertainty bands
  • Required model assumptions
  • Qualitative checklist and risk-note structures

Scenario imports are additionally subject to a 1 MiB size limit before parsing.

This protects against malformed inputs and reduces the risk of accidental excessive memory consumption.

Scientific integrity as an architectural quality attribute

A particularly valuable hardening feature is the separation between calculating draft results and authorizing formal report generation.

Users can explore results while refining assumptions. However, finalized reports require confirmation of material assumptions such as substitution and rebound, along with source information for enabled additional outcome modules.

Editing relevant model assumptions invalidates those confirmations.

This is not merely a UI feature.

It is an example of implementing domain-specific quality controls directly into the application's architecture.

It helps prevent unreviewed assumptions from silently becoming apparently authoritative outputs.

6. Applying the Twelve-Factor App methodology

The Twelve-Factor App methodology was originally developed for software-as-a-service applications, especially systems with server-side processes and backing services.

It would be inappropriate to apply every factor literally to a static browser application.

Instead, I used the methodology to assess each architectural concern against the RCA Calculator's actual deployment model.

The key question was not:

How can this application be made to look like a conventional cloud-native service?

It was:

How can each applicable Twelve-Factor principle improve the reliability, portability, security, and operational readiness of this application?

Factor I — Codebase: One codebase, multiple deployments

The first factor requires one codebase tracked in version control, with multiple deployments derived from it.

The RCA Calculator uses a single GitHub repository as the source of truth.

During hardening, unnecessary tracked npm cache content was identified and removed from the Git index. Ignore rules exclude generated output, local environment files, caches, and deployment metadata.

The intended result is a cleaner source repository where build outputs are generated rather than manually maintained.

This supports:

  • More predictable code reviews
  • Cleaner continuous integration
  • Release traceability
  • Consistent preview and production builds

The existing Git history was not rewritten to eliminate historical cache objects.

Factor II — Dependencies: Explicit and reproducible dependency management

A common source of demo failures is inconsistent dependency installation.

A prototype may work locally because packages were installed incrementally or differ from the versions available in a clean environment.

The RCA Calculator addresses this using package.json, package-lock.json, a declared Node version, and a recorded npm version.

The application specifies Node.js 24 and npm 11, with npm 11.9.0 recorded as its package manager.

A clean installation uses:

npm ci --include=dev
Enter fullscreen mode Exit fullscreen mode

Unlike a general dependency update, npm ci installs from the committed lockfile and rejects incompatible dependency manifests.

Dependency hygiene was also incorporated into CI.

npm run audit
Enter fullscreen mode Exit fullscreen mode

The audit command fails on high- and critical-severity findings.

During hardening, unused direct dependencies were removed, and Vitest was upgraded to address serious toolchain advisories.

One moderate ExcelJS transitive dependency advisory involving UUID remained documented, with its usage and risk boundary explicitly analyzed rather than silently suppressed.

Lesson: Dependency hardening requires reproducibility, inventory, risk assessment, and continuous review—not simply installing the latest versions of everything.

Factor III — Config: Separate configuration from code

Twelve-Factor applications should keep deployment-specific configuration outside their source code.

For the RCA Calculator, there are no backend credentials, database connection strings, or private API keys to configure.

The browser application is designed to operate without application environment variables.

The portable Node server supports environment configuration:

PORT=3000
HOST=0.0.0.0
SHUTDOWN_TIMEOUT_MS=10000
Enter fullscreen mode Exit fullscreen mode

The build also supports revision metadata through environment-provided values such as RELEASE_REVISION and Vercel's VERCEL_GIT_COMMIT_SHA.

An important distinction is maintained between configuration and domain model data.

Mathematical formulas and model assumptions belong in version-controlled domain definitions because changing them changes the behavior and interpretation of the assessment.

They are not interchangeable deployment settings.

Another important frontend security consideration is that Vite client-side configuration is not secret storage.

Values embedded into a public JavaScript bundle must be treated as publicly accessible.

Factor IV — Backing services: Explicit service dependencies

A conventional cloud application may rely on a database, cache, or external message broker.

The RCA Calculator has no such server-side backing-service dependency.

Assessment state is stored locally in the user's browser using localStorage.

This substantially reduces deployment complexity and avoids introducing a centralized store for user-generated assessment data.

However, browser storage is not equivalent to a durable, account-backed database.

Its limitations are explicitly documented:

  • Data is associated with a browser and origin.
  • Clearing browser storage can delete assessments.
  • Assessments do not automatically synchronize between devices.
  • Users must export JSON backups when portability is required.

This is an intentional product constraint, not something that should be hidden behind a claim of database-like durability.

If collaboration, authentication, or cross-device persistence becomes necessary, a separate backing service would need to be designed.

Factor V — Build, release, run: Immutable deployments

This was one of the most significant parts of the architecture hardening.

In loosely managed applications, the production server may install dependencies, compile code, or modify files during startup.

That makes it difficult to know whether the deployed application is identical to what was tested.

The RCA Calculator separates build, release verification, and runtime serving.

Source Code
    |
    v
npm ci
    |
    v
TypeScript Check + Vite Build
    |
    v
dist/
    |
    v
release.json
    |
    v
Integrity Verification
    |
    v
Tested Release Artifact
    |
    v
Deployment / Serving
Enter fullscreen mode Exit fullscreen mode

The build command is:

npm run build
Enter fullscreen mode Exit fullscreen mode

It performs TypeScript checking, builds the application, and generates release metadata.

The generated release.json contains information including the application version, source revision, artifact identifier, and SHA-256 checksums of the release files.

Verification runs with:

npm run check:release
Enter fullscreen mode Exit fullscreen mode

The portable production server verifies the existing artifact before serving it.

Crucially, the runtime does not rebuild the application.

This gives deployments a stronger identity: the released files can be checked against the exact artifact that passed validation.

The checksum manifest is an integrity mechanism, not a digital signature proving the identity of a publisher.

Factor VI — Processes: Stateless application serving

The deployed serving layer is stateless.

The Node server serves an immutable directory and does not maintain user assessments, sessions, or mutable application state.

Calculations and editing occur inside the browser.

This means multiple serving instances can deliver the same release artifact without synchronizing user sessions.

The architecture avoids sticky-session requirements and server-side state recovery concerns.

Browser-local data remains a separate responsibility.

This is an example of how stateless service architecture can coexist with client-side state.

Factor VII — Port binding: Self-contained runtime behavior

Vercel hosts the static application and manages HTTP delivery.

For environments requiring a standalone process, the repository also contains a portable Node.js server.

The server binds to its configured host and port:

PORT=3000 HOST=0.0.0.0 npm start
Enter fullscreen mode Exit fullscreen mode

It also exposes:

GET /healthz
Enter fullscreen mode Exit fullscreen mode

The health response reports runtime readiness and the current artifact identifier.

This endpoint is specific to the portable Node server. It is not automatically an application endpoint on the Vercel static deployment.

For Vercel, the operational documentation recommends using release metadata and live endpoint checks to verify the deployed version.

The portable server should be placed behind an HTTPS-terminating proxy when exposed to end users.

Factor VIII — Concurrency: Scaling without shared state

The application does not require a distributed calculation cluster.

Its analytical calculations are performed in each user's browser, while static assets can be distributed through a CDN.

For standalone hosting, independent Node processes can serve the same immutable build.

Operational tests exercise multiple server instances using the same release artifact.

This demonstrates independence of serving instances, but it does not establish a particular requests-per-second capacity or geographic latency guarantee.

Those require separate load testing and hosting-level measurements.

The architectural benefit is that horizontal serving does not introduce shared mutable state coordination.

Factor IX — Disposability: Predictable startup and graceful shutdown

A service should start predictably and shut down cleanly.

The portable Node server verifies its release files before accepting traffic.

It handles SIGTERM and SIGINT, stops accepting new work, and allows active responses to drain within a configurable timeout.

For example:

SHUTDOWN_TIMEOUT_MS=10000
Enter fullscreen mode Exit fullscreen mode

If the shutdown grace period expires, remaining connections are terminated.

The application also implements browser-side recovery.

React error boundaries provide a fallback interface if rendering fails. Users can reload the application or download a backup of saved assessments.

This is particularly important when a deployment removes a JavaScript chunk that an older browser session is still attempting to load.

Preserving previous immutable deployments and their hashed assets helps reduce such failures.

The result is a layered recovery model covering both the serving process and the browser interface.

Factor X — Dev/prod parity: Test the production build

A frequent weakness in prototype development is testing only the development server.

Vite's development environment is not identical to the compiled, security-constrained production application.

The RCA Calculator addresses this with browser tests that run against the actual production build served by the portable Node runtime.

Playwright tests interact with the application as users would.

They cover assessment workflows, persistence, imports, exports, mobile behavior, and accessibility checks.

This matters because a development build may work while a production Content Security Policy blocks a library or a lazily loaded component.

By validating the production artifact and its response headers, the tests exercise a more representative deployment.

There is still a boundary: passing local production-server tests does not prove that Vercel's live CDN configuration, TLS, and project settings are correct.

Those require post-deployment verification.

Factor XI — Logs: Structured, privacy-conscious observability

Operational diagnostics are essential when hardening an application.

The portable Node server emits structured JSON events to standard output.

Request events include information such as:

{
  "event": "http_request",
  "requestId": "generated-request-id",
  "method": "GET",
  "route": "asset",
  "status": 200,
  "durationMs": 4,
  "artifactId": "release-artifact-id"
}
Enter fullscreen mode Exit fullscreen mode

The server intentionally avoids logging scenario content, query strings, request bodies, and assessment details.

Browser diagnostics also use predefined event codes.

For example, a render failure can produce an event containing its type, application version, and revision without exposing the user's model inputs.

These logging decisions are important because the application may hold commercially sensitive assessment assumptions.

However, browser console messages are not automatically collected into a central monitoring platform.

Operational logging therefore has two distinct boundaries:

  1. Host-managed access and runtime logs.
  2. Local browser diagnostics that would need an explicitly designed collection mechanism for remote monitoring.

Retention, access controls, alerting, and centralized observability remain hosting responsibilities.

Factor XII — Admin processes: Controlled one-off operations

Traditional applications may require administrative commands for migrations, data repair, and database maintenance.

The RCA Calculator does not have server-side migrations or account administration.

Its one-off operational commands include release verification, dependency audits, and scenario validation.

For example:

npm run validate:scenario -- ./assessment.json
Enter fullscreen mode Exit fullscreen mode

This validates a local assessment using the application's model rules.

The validator can identify invalid records without uploading the user's assessment or modifying the source file.

The principle is straightforward: operational utilities should use the same validated codebase as the application and should behave predictably.

7. Security hardening beyond the Twelve-Factor methodology

Although Twelve-Factor is a useful architecture framework, it is not a complete security standard.

For a browser application, additional controls are necessary.

Content Security Policy

The Vercel configuration defines a Content Security Policy that restricts script loading and network connections to the application's origin.

Key directives include:

default-src 'self'
script-src 'self'
connect-src 'self'
object-src 'none'
frame-ancestors 'none'
form-action 'none'
Enter fullscreen mode Exit fullscreen mode

This limits several classes of unwanted browser behavior.

The configuration still permits inline styles because of the application's React and chart-rendering requirements, but it does not permit inline scripts or eval.

HTTP response security headers

Additional headers include:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Permissions-Policy:
  camera=(), microphone=(),
  geolocation=(), payment=()
Enter fullscreen mode Exit fullscreen mode

These controls reduce unnecessary browser capabilities and help mitigate framing and content interpretation risks.

Static-server restrictions

The portable Node server implements defensive serving behavior.

It rejects unsupported HTTP methods, invalid paths, hidden-file access, and attempts to escape the designated release directory.

Symbolic links are also rejected during release verification.

Only intended static resources are exposed.

Defensive browser persistence

An additional hardening feature appears in the way saved scenarios are restored.

If some browser records are malformed, the application attempts to retain valid records instead of discarding the entire dataset.

Automatic saving is paused when invalid records are detected, preventing the application from silently overwriting the original storage contents.

The user is offered an explicit recovery path.

This illustrates a useful defensive design principle:

When recovering from invalid state, preserve the original evidence rather than automatically destroying it.

8. Performance engineering through selective loading

Demo readiness also depends on responsiveness.

An application that works correctly but takes too long to initialize can create an unreliable demonstration experience.

The RCA Calculator uses React lazy loading and Vite's code-splitting capabilities.

The results screen, scenario comparison interface, and export screen are loaded on demand.

Excel generation is also deferred until the user requests it.

For example, the application uses a dynamic import for the workbook generation module:

const { exportScenarioToExcel } =
  await import("../export/excel");

await exportScenarioToExcel(scenario);
Enter fullscreen mode Exit fullscreen mode

This prevents the Excel generation library from unnecessarily increasing the initial application payload.

The repository also defines an initial JavaScript bundle budget of 450,000 bytes.

The budget is checked automatically:

npm run check:bundle
Enter fullscreen mode Exit fullscreen mode

The check traverses the initial JavaScript dependency graph using the Vite build manifest and fails if the budget is exceeded.

This is an effective example of turning a non-functional architecture requirement into an automated build gate.

The ExcelJS deferred bundle remains relatively large, approximately 947 kB before compression according to the repository documentation, but it is not part of the initial load.

That trade-off is visible rather than hidden.

9. Establishing confidence through automated testing

Perhaps the most important transition from prototype to demo-ready software is moving from informal testing to repeatable evidence.

The RCA Calculator has several testing layers.

Unit and domain tests

Vitest is used to test calculation behavior, including reference arithmetic, model validation, uncertainty aggregation, sensitivity analysis, and export correctness.

These tests help ensure that changes to components or model assumptions do not unexpectedly change calculations.

End-to-end browser testing

Playwright validates real browser workflows.

This includes scenario management, report generation, browser persistence, imports, exports, and responsive behavior.

Accessibility checks

The testing stack integrates axe-core with Playwright to identify serious accessibility violations.

Automated accessibility validation is valuable, but it does not replace human keyboard-navigation and screen-reader testing.

Operational verification

The repository contains Node operational tests for serving behavior, security headers, runtime lifecycle, and release integrity.

This is especially useful for verifying the architectural requirements that do not fit naturally into React unit tests.

Continuous integration

GitHub Actions runs the validation process on pushes and pull requests.

The pipeline follows this pattern:

Checkout Repository
        |
        v
Setup Node.js 24
        |
        v
npm ci --include=dev
        |
        v
Dependency Audit
        |
        v
Unit Tests
        |
        v
Production Build
        |
        v
Bundle Budget Check
        |
        v
Release Integrity Check
        |
        v
Operational Tests
        |
        v
Playwright Browser Tests
        |
        v
Retain Tested Artifact
Enter fullscreen mode Exit fullscreen mode

The resulting static artifact is retained by CI, while failed browser tests can provide diagnostic traces.

Importantly, the workflow validates and retains the release artifact; it does not automatically publish the application.

Separating validation from promotion provides an additional opportunity for controlled deployment approval.

10. Architecture hardening as measurable engineering controls

A useful lesson from this exercise is that architecture reviews become more valuable when principles translate into verifiable controls.

Rather than treating architecture as a collection of diagrams and recommendations, each significant quality requirement can be associated with implementation evidence.

Architecture quality Hardening mechanism Evidence
Reproducibility Locked dependencies and pinned runtime package-lock.json, .nvmrc
Maintainability Separation of UI, domain, and export logic src/ modules
Correctness Domain validation and unit tests model.ts, tests/
Security CSP, input validation, server restrictions vercel.json, serving code
Performance Lazy loading and size budgets Vite build and bundle checker
Reliability Error boundaries and recovery ErrorBoundary.tsx
Deployability Immutable artifacts and integrity checks release.json and verification scripts
Operability Health checks and structured logs Portable Node server
Testability Unit, operational, browser, and accessibility tests Vitest, Playwright, GitHub Actions
Data protection Local persistence and explicit backup paths Scenario management and JSON export

This is the point where architectural maturity becomes observable.

The application is not considered hardened merely because someone has documented good intentions.

It is hardened to the extent that those intentions are represented by controls, tests, and operational procedures.

11. What the hardening achieved

The architectural work produced several meaningful improvements.

First, a more deterministic build and release process. By using a locked toolchain and immutable release files, the deployed artifact can be identified and checked independently of a developer's local environment.

Second, better separation of concerns. The domain engine, model data, user interface, exports, and deployment tooling have clearer boundaries, making it easier to inspect and change the application.

Third, stronger failure handling. Malformed scenario records, unavailable local storage, render failures, and shutdown events are handled more deliberately.

Fourth, an improved browser security posture. Explicit response headers, restricted formula execution, input validation, and defensive static serving reduce avoidable exposure.

Fifth, automated quality gates. Tests, dependency audits, release verification, and bundle checks help catch issues before a demonstration or deployment.

Finally, reduced operational complexity. By preserving a static-client architecture, the application avoids unnecessary infrastructure while retaining clear pathways for future evolution.

These are architectural and operational improvements, rather than measured claims about runtime speed, service uptime, or production traffic capacity.

12. What remains outside demo hardening

Demo hardening is not equivalent to claiming unrestricted production readiness.

The repository documents several important limits.

The application is not a certified environmental assessment engine. Domain review and independent model assurance would be needed before using its outputs as formally assured scientific claims.

Browser-local persistence does not provide enterprise-grade durability, centralized backup, or account synchronization.

Live Vercel deployment configuration must be verified after release. Repository declarations do not prove that hosting-level controls, monitoring, DNS, TLS, and deployment permissions are correctly configured.

The documented moderate transitive dependency advisory still requires continued monitoring.

And while CI provides substantial automated coverage, performance capacity testing, human accessibility review, and organizational risk acceptance are separate activities.

This distinction is central to responsible engineering.

A successful hardening effort should make the system's capabilities clearer without hiding its limitations.

13. Lessons learned: From rapid prototyping to architecture discipline

This project reinforced several engineering lessons.

Architecture principles are more important than architectural fashion

A system does not need microservices, containers, distributed caches, and multiple databases to qualify as well architected.

Architecture quality is better judged by how effectively a design meets its actual requirements and controls its risks.

Twelve-Factor is a methodology, not a technology checklist

The twelve factors helped structure the review around reproducibility, configuration, deployment, statelessness, operational behavior, and test parity.

Applying them intelligently was more useful than forcing the application into an inappropriate backend architecture.

Automated tests should protect both functionality and architecture

Calculation tests protect the scientific model.

Browser tests protect user journeys.

Operational tests protect runtime behavior.

Security and bundle checks protect non-functional quality requirements.

Together, these give stronger evidence than relying on manual UI testing alone.

Immutability improves confidence in demonstrations

Being able to identify and verify the exact artifact being served reduces uncertainty during deployment and rollback.

A demo should not depend on a server silently rebuilding code or resolving different dependencies at startup.

Defensive design matters as much as the happy path

Applications are often judged by what happens when something goes wrong.

Graceful error screens, preserved browser data, explicit export errors, bounded inputs, and predictable shutdown behavior all contribute to trust.

AI can accelerate implementation, but engineering accountability remains essential

AI-assisted development makes generating software easier.

It does not remove the need to establish architectural boundaries, validate assumptions, test calculations, manage dependencies, and understand operational risks.

The transition from vibe-coded prototype to demo-ready application is therefore not simply a refactoring exercise.

It is the process of turning experimental code into a system with explicit, testable engineering properties.

14. Conclusion

The RCA Calculator demonstrates that a relatively lightweight browser application can benefit significantly from formal architecture hardening.

By applying the Twelve-Factor App methodology pragmatically, separating domain logic from presentation, enforcing dependency reproducibility, implementing immutable releases, strengthening browser security, and introducing automated validation, the application has a more disciplined foundation for demonstrations and further development.

The most important architectural decision was not adding infrastructure.

It was making the existing architecture reliable, understandable, testable, and operationally explicit.

That is a useful approach for anyone developing AI-assisted proof-of-concepts, research tools, internal applications, or early-stage products.

Vibe coding can help us reach a working prototype quickly.

Software engineering discipline is what helps us demonstrate it with confidence.


Source code and technical references

Project repository: https://github.com/scha54/RCA-Calculator

Live application: https://rca-calculator.vercel.app

Twelve-Factor architecture assessment: https://github.com/scha54/RCA-Calculator/blob/master/docs/TWELVE_FACTOR.md

Operations runbook: https://github.com/scha54/RCA-Calculator/blob/master/docs/OPERATIONS.md

Calculation methodology: https://github.com/scha54/RCA-Calculator/blob/master/docs/METHODOLOGY.md

Release verification documentation: https://github.com/scha54/RCA-Calculator/blob/master/docs/RELEASE.md

The Twelve-Factor App methodology: https://12factor.net/

This article describes the repository architecture and documented hardening controls as reviewed on October 24, 2026. The project remains a screening and demonstration application; deployment assurance and scientific certification are separate considerations.


What practices do you use to move AI-generated prototypes toward demo-ready or production-ready software? I'd be interested to hear how others are applying architecture principles without introducing unnecessary complexity.

Top comments (0)