Skip to content

Microfrontends Framework

Field Value
Status Draft
Owner Frontend Engineering
Last Updated 2026-04-03
Applies To Merchant Portal, Admin Portal

1. Overview

Simpaisa's merchant-facing portal is built as a microfrontend (MFE) architecture using Astro as the composition shell and Preact for interactive islands. Each MFE is independently deployable to Cloudflare Pages, enabling product squads to ship UI changes without coordinating releases across the entire frontend.

2. Technology Stack

Layer Technology Purpose
Composition Shell Astro 5.x Server-rendered layout, routing
Interactive Islands Preact 10.x Lightweight reactive components
Styling Design system tokens (CSS) Consistent visual language
Authentication ControlPlane.com OIDC SSO, RBAC, session management
Hosting Cloudflare Pages Edge-deployed, per-MFE pipelines
Analytics PostHog Product analytics, feature flags
Language TypeScript (strict mode) Type safety across all MFEs

3. Microfrontend Inventory

MFE Route Prefix Responsibility Squad
dashboard-mfe / Overview metrics, transaction volume, health status Product
apikeys-mfe /api-keys API key generation, rotation, scoping Platform
webhooks-mfe /webhooks Webhook endpoint CRUD, delivery logs, retry Platform
transactions-mfe /transactions Transaction search, detail view, export Product
reports-mfe /reports Settlement reports, reconciliation, downloads Finance
team-mfe /team User management, role assignment, audit log Platform
admin-mfe /admin Merchant config, channel toggling, rate management Operations

4. Composition Architecture

graph TB
    subgraph "Cloudflare Edge"
        CDN[Cloudflare CDN/WAF]
    end

    subgraph "Astro Shell"
        Shell[Astro Composition Shell]
        Shell --> Nav[Shared Navigation]
        Shell --> Auth[Auth Provider]
        Shell --> ErrorBoundary[Error Boundary]
    end

    subgraph "Preact Islands"
        Dashboard[dashboard-mfe]
        APIKeys[apikeys-mfe]
        Webhooks[webhooks-mfe]
        Transactions[transactions-mfe]
        Reports[reports-mfe]
        Team[team-mfe]
        Admin[admin-mfe]
    end

    CDN --> Shell
    Shell --> Dashboard
    Shell --> APIKeys
    Shell --> Webhooks
    Shell --> Transactions
    Shell --> Reports
    Shell --> Team
    Shell --> Admin

5. Shared Concerns

5.1 Design System Tokens

All MFEs consume a shared @simpaisa/design-tokens package published to the private npm registry. Tokens define:

  • Colour palette (brand blue #0052CC, success green, error red).
  • Typography scale (Inter font, 8 pt grid).
  • Spacing, border radius, shadow elevation.
  • Component primitives (Button, Input, Card, Table, Modal).

No MFE may define its own colour values or override token defaults.

5.2 Authentication — ControlPlane.com

Authentication is handled at the shell level. The Astro shell initiates an OIDC flow with ControlPlane.com on first load. The resulting JWT is stored in an HttpOnly cookie and passed to the BFF on every request.

  • Token refresh: Silent refresh via iframe before expiry.
  • RBAC: Roles (admin, finance, developer, viewer) are embedded in the JWT claims. Each MFE checks permissions before rendering protected routes.

5.3 Routing

Astro file-based routing owns top-level paths. Each MFE is mounted at its route prefix and handles sub-routing internally using Preact Router.

/                    → dashboard-mfe
/api-keys            → apikeys-mfe
/api-keys/:id        → apikeys-mfe (internal route)
/transactions        → transactions-mfe
/transactions/:txnId → transactions-mfe (internal route)

5.4 Error Boundary

A global error boundary in the Astro shell catches rendering failures in any MFE and displays a fallback UI. The failing MFE is isolated — other MFEs continue functioning.

6. Communication Between MFEs

MFEs communicate via Custom Events on the window object. There is no shared state store.

// Publishing (from transactions-mfe)
window.dispatchEvent(
  new CustomEvent('simpaisa:txn:selected', {
    detail: { txnId: 'txn_abc123' },
  })
);

// Subscribing (in dashboard-mfe)
window.addEventListener('simpaisa:txn:selected', (e: CustomEvent) => {
  navigateToDetail(e.detail.txnId);
});

Rules: - Event names must be prefixed with simpaisa:. - Each MFE owns its own data — no MFE reads another MFE's internal state. - Events carry minimal payloads (IDs, not full objects).

7. Independent Deployment

Each MFE has its own Bitbucket Pipeline and deploys independently to Cloudflare Pages.

graph LR
    subgraph "Bitbucket Pipelines"
        PR[Pull Request] --> Lint[ESLint + tsc]
        Lint --> Test[Vitest]
        Test --> Build[Astro Build]
        Build --> Preview[Cloudflare Preview]
        Preview --> Merge[Merge to main]
        Merge --> Prod[Cloudflare Pages Prod]
    end

Deployment rules: - Each MFE is a separate Cloudflare Pages project. - The Astro shell fetches MFE bundles at the edge via Cloudflare Workers. - Rollback is per-MFE — a broken reports-mfe deploy does not require rolling back dashboard-mfe. - Feature flags (PostHog) gate new MFE versions for progressive rollout.

8. TypeScript Strict Mode

All MFEs enforce strict: true in tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "exactOptionalPropertyTypes": true
  }
}

9. Performance Budget

Metric Target
First Contentful Paint < 1.2 s
Largest Contentful Paint < 2.5 s
Total bundle per MFE < 80 KB gz
Preact island hydration < 200 ms

Cloudflare edge caching and Astro's zero-JS-by-default approach keep payloads minimal. Only interactive islands ship JavaScript to the client.

10. Local Development

# Start the full portal locally
pnpm dev

# Start a single MFE in isolation
cd packages/transactions-mfe && pnpm dev

Each MFE can run standalone with mock data or connect to the sandbox BFF.

11. Architectural Decision Records

Changes to this framework require an ADR in /Standards/ADR/. See ADR/ADR-TEMPLATE.md.