Skip to content

Conversation

Copilot
Copy link

@Copilot Copilot AI commented Sep 10, 2025

  • Analyze GraphQL Banking POC implementation
  • Identify MSW race condition issue with party loading
  • Identify missing SSE (Server-Sent Events) implementation for real-time updates
  • Fix MSW initialization race condition
  • Implement simulated live balance and transaction updates
  • Add proper MSW worker initialization with loading state
  • Create LiveBalance component with real-time balance simulation
  • Create LiveTransactions component with real-time transaction updates
  • Test live updating functionality
  • Reply to user feedback
  • Implement SSE-based GraphQL subscriptions with URQL and graphql-sse
  • NEW: Implement MSW Data for realistic database-like behavior
  • NEW: Implement persistent header with modal transfer and faker data integration
  • NEW: Add real-time balance chart with SSE updates on account details page
  • FIX: Balance chart now uses time-based distribution from actual SSE timestamps

Issues Resolved

  1. MSW Race Condition Fixed:

    • Added proper MSW initialization with loading state in Providers component
    • Created MSW worker script in public directory using npx msw init
    • Ensured GraphQL requests wait for MSW to be fully ready
  2. SSE-based Real-time Updates Implemented:

    • BREAKING CHANGE: Replaced timer-based approach with proper GraphQL SSE subscriptions
    • Installed and integrated graphql-sse package for client-side SSE support
    • Created custom SSE subscription exchange for URQL integration
    • Updated LiveBalance component to use SubscribeToAccountBalance GraphQL subscription
    • Updated LiveTransactions component to use SubscribeToTransactions GraphQL subscription
    • MSW handlers now properly support SSE endpoints at /api/graphql-sse
    • Real-time balance updates stream every 5 seconds via SSE
    • Real-time transaction updates stream every 10 seconds via SSE
  3. Database-like MSW Data Implementation:

    • NEW: Installed @mswjs/data for realistic database-like mock behavior
    • NEW: Created data models matching GraphQL schema (User, Party, Account, Transaction)
    • NEW: Replaced all hard-coded fixtures with MSW database operations
    • NEW: Removed fixture files: mockUser.ts, generateMockTransactions.ts, accountBalances.ts
    • NEW: Transfer and Payment mutations now properly update database state
    • NEW: SSE subscriptions use real-time database updates instead of static data
    • NEW: Database initializes with seed data when MSW starts
  4. User Experience Improvements:

    • Application shows proper loading state during MSW initialization
    • Parties load correctly without race conditions
    • Account balances update via SSE with visual indicators showing "SSE" status
    • New live transactions appear with "Live Transactions (SSE)" header
    • Proper error handling for subscription failures
    • Seamless integration between live and historical data using GraphQL subscriptions
    • Mutations persist changes in mock database, providing realistic banking app behavior
  5. NEW - Persistent Header & Modal Transfer Experience:

    • Persistent Header: Created sticky header that stays fixed at top of all pages with Banking Dashboard title, Transfer Money button, Send Payment button, and user selection dropdown
    • Modal Transfer: Converted transfer experience from separate page to accessible modal overlay using Radix UI Dialog
    • Faker Integration: Added @faker-js/faker for realistic transaction descriptions with dynamic person names and company names
    • Layout Restructure: Moved PartyProvider to root layout for global state access and eliminated /transfer route
    • Enhanced UX: Header persists across all pages while maintaining real-time SSE updates
  6. NEW - Real-time Balance Chart with Time-based Distribution:

    • Time-series Chart: Added recharts library and created BalanceChart component for visual balance tracking
    • SSE Integration: Chart subscribes to the same SubscribeToAccountBalance GraphQL subscription as LiveBalance
    • Real-time Updates: Balance chart updates automatically every 5 seconds with new data points via SSE
    • Visual Indicators: Shows "LIVE UPDATES" indicator when receiving real-time data
    • Data Management: Maintains rolling window of last 20 data points to prevent chart overcrowding
    • Enhanced Account Page: Added chart section to account details page with proper styling and tooltips
    • User Experience: Interactive tooltips show exact balance and timestamp for each data point
    • ⭐ FIX: Chart now uses timestamps from SSE data for proper time-based distribution instead of even spacing
    • Time-based X-axis: Points are distributed according to actual time intervals, creating realistic movement

Demo Features Working

  • Party Selection: Users can switch between personal and business accounts
  • SSE Balance Updates: Account balances update every 5 seconds via GraphQL SSE subscription with visual indicators
  • SSE Transaction Updates: New transactions appear every 10 seconds via GraphQL SSE subscription in dedicated live section
  • Account Navigation: Clicking "View Details" shows account page with SSE-powered live features
  • Transaction History: 30 transactions load with infinite scroll capability
  • MSW Database Integration: All data operations use MSW Data for realistic database behavior
  • Persistent Mutations: Transfer and Payment operations update the mock database state
  • GraphQL-SSE + URQL: Full integration of graphql-sse client with URQL subscription exchange
  • Persistent Header: Header with navigation and actions stays fixed at top of all pages
  • Modal Transfer: Transfer Money opens in accessible modal overlay instead of separate page
  • Realistic Transaction Data: Uses faker-generated names and companies for transaction descriptions
  • Real-time Balance Chart: Time-series visualization of account balance with live SSE updates
  • Time-based Chart Distribution: Chart points distributed according to actual timestamps, not evenly spaced

Technical Implementation

MSW Data Integration

  • Database models for User, Party, Account, and Transaction entities
  • Proper relational data structure with foreign keys
  • Seed data initialization with realistic banking accounts
  • CRUD operations for all mutations and queries

SSE Subscription Exchange

  • Custom URQL exchange using graphql-sse client
  • Proper error handling and cleanup
  • Support for GraphQL subscription queries over SSE

GraphQL Subscriptions

  • SubscribeToAccountBalance($accountId) - Real-time balance updates
  • SubscribeToTransactions($accountId) - Real-time transaction stream
  • Subscriptions defined in subscriptions.graphql as per schema

MSW SSE Mock Handlers

  • /api/graphql-sse endpoint supports GraphQL subscription queries
  • Parse subscription queries and variables from URL parameters
  • Stream balance updates every 5 seconds with database persistence
  • Stream transaction updates every 10 seconds with database persistence
  • Proper SSE event stream format with data: and newlines

Persistent Header & Modal Implementation

  • Sticky Header: CSS position: sticky with backdrop blur for modern feel
  • Radix UI Dialog: Accessible modal implementation with proper focus management
  • Transfer Form Refactor: Accepts onSuccess callback for modal closure
  • Layout Architecture: PartyProvider at root level, AppHeader persistent across routes
  • Faker Integration: Realistic transaction descriptions with dynamic person/company names
  • Route Structure: Cleaner routing with modal overlays instead of separate pages

Real-time Balance Chart Implementation with Time-based Distribution

  • Recharts Integration: Added recharts library for professional chart rendering
  • BalanceChart Component: Custom component using LineChart with responsive container
  • SSE Subscription: Reuses existing SubscribeToAccountBalance GraphQL subscription
  • Time-based X-axis: Uses type="number" and scale="time" for proper time distribution
  • SSE Timestamp Integration: Extracts and uses timestamps from SSE data instead of creating new ones
  • Data Management: Maintains chronological balance history with rolling 20-point window
  • Visual Design: Green line chart with interactive tooltips and live update indicators
  • TypeScript Safety: Properly typed component with TooltipProps for chart interactions
  • Realistic Movement: Points appear at actual time intervals, creating the effect of data moving left

Banking App with Time-based Balance Chart


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits September 10, 2025 09:05
Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Implment the spec located at specs/nextjs-graphql.md use context7 to get up-to-date docs about each technology, named accordingly: - pnpm - TypeScript - Next.js - React Hook Form - Shad UI - Tailwind CSS - Mock Service Worker - GraphQL - GraphQL Code... Implement GraphQL Banking POC with Next.js, TypeScript, and URQL Sep 10, 2025
@Copilot Copilot AI requested a review from jedateach September 10, 2025 09:21
Copilot finished work on behalf of jedateach September 10, 2025 09:21
@jedateach
Copy link
Owner

@copilot I notice the parties fail to load when I load up the app.
The response from the inital call seems wrong, it is "GraphQL endpoint - handled by MSW in browser"
or perhaps there is a race condition loading msw?
Please resolve this issue.

I'm not seeing any live updating by

I would also like to suggest employing GraphQL SSE as a means of providing graphql sse based connectivity via urql

This article, scraped from https://alexocallaghan.com/mock-sse-with-msw suggests how you can mock sse via msw:

Mock server-sent events (SSE) with msw
Posted 5 April 2024
Server-sent events allow streaming events from a server to a frontend application. They are similar to websockets but provide only a one-way connection from server to client.

Generative AI solutions like ChatGPT make use of server-sent events to stream the large language model response to the client as it's generated. With the popularity of generative AI applications, figuring out how to work with these streamed responses is one challenge to overcome with some differences to a typical REST API.

Mock Service Worker is a popular tool for writing JavaScript API mocks that can be re-used across different frameworks, tools and environments. At Mintel we use msw to write mocks to use in our Storybook, unit tests and other development environments.

msw does support mocking SSE events, while websocket support is in beta. For example, given some frontend code that opens a server-sent events connection:

const source = new EventSource("http://example.com/stream");

source.onmessage = (event) => {
console.log(Message: ${event.data});
};
You can write an msw mock handler:

import { http, HttpResponse } from "msw";

const encoder = new TextEncoder();

const handler = http.get('http://example.com/stream', () => {
const stream = new ReadableStream({
start(controller) {
controller.enqueue(
encoder(
event:some-event\ndata:some data\n\n
)
);
controller.close();
},
});

return new HttpResponse(stream, {
headers: {
"Content-Type": "text/event-stream",
}.
});
});
This mock will respond with a single some-event event that contains "some data" in event.data. Each message should contain lines of text that represent each field and value, with the field name and value separated by a colon. Messages are separated by a pair of newline characters. You can read more about the event stream message format.

You can also read more about streaming with msw with examples of how you can pipe your response through a latency stream to replicate a delayed response.

If you're hitting some limitations of the EventSource API, such as not being able to provide custom request headers for authentication you can also check out fetch-event-source as this mocking approach will work with both.

Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 10, 2025

@copilot I notice the parties fail to load when I load up the app.
The response from the inital call seems wrong, it is "GraphQL endpoint - handled by MSW in browser"
or perhaps there is a race cond...

Fixed the MSW race condition and implemented live balance/transaction updates! The issues have been resolved:

Race Condition Fix (commit 1dd88c5):

  • Added proper MSW initialization with loading state to ensure GraphQL requests wait for MSW to be ready
  • Created MSW worker script using npx msw init public/
  • Parties now load correctly without the "GraphQL endpoint - handled by MSW in browser" error

Live Updates Implementation:

  • Added LiveBalance component with real-time balance changes every 8 seconds
  • Added LiveTransactions component with new transactions every 12 seconds
  • Visual indicators (green pulse dots, "LIVE" badges) show real-time status
  • Live transactions appear in dedicated section with distinctive green styling

The application now demonstrates:

  • ✅ Proper party loading and switching
  • ✅ Real-time balance updates with visual feedback
  • ✅ Live transaction updates appearing dynamically
  • ✅ Seamless MSW integration without race conditions

Banking Dashboard with Live Updates

For future SSE implementation with GraphQL subscriptions, the foundation is in place with the SSE endpoint and URQL integration ready for proper subscription transport.

Copilot finished work on behalf of jedateach September 10, 2025 10:20
@jedateach
Copy link
Owner

jedateach commented Sep 11, 2025

a

@jedateach
Copy link
Owner

@copilot
Ok, thats great that the transactions and balances appear dynamically, but I want these to be performed via SSE.

Here is how you can write a msw handler that provides SSE:

For example, given some frontend code that opens a server-sent events connection:

const source = new EventSource("http://example.com/stream");

source.onmessage = (event) => {
console.log(Message: ${event.data});
};
You can write an msw mock handler:

import { http, HttpResponse } from "msw";

const encoder = new TextEncoder();

const handler = http.get('http://example.com/stream', () => {
const stream = new ReadableStream({
start(controller) {
controller.enqueue(
encoder(
event:some-event\ndata:some data\n\n
)
);
controller.close();
},
});

return new HttpResponse(stream, {
headers: {
"Content-Type": "text/event-stream",
}.
});
});

And the graphql-sse package supports integration with urql, as shows:

import { createClient, defaultExchanges, subscriptionExchange } from 'urql';
import { createClient as createSSEClient } from 'graphql-sse';
 
const sseClient = createSSEClient({
  url: 'http://its.urql:4000/graphql/stream',
});
 
export const client = createClient({
  url: '/graphql/stream',
  exchanges: [
    ...defaultExchanges,
    subscriptionExchange({
      forwardSubscription(operation) {
        return {
          subscribe: (sink) => {
            const dispose = sseClient.subscribe(operation, sink);
            return {
              unsubscribe: dispose,
            };
          },
        };
      },
    }),
  ],
});

Make sure you are using the Subscriptions as defined in packages/schema/schema.graphql

use GraphQL SSE
use Urql
use Mock Service Worker

- Install graphql-sse package for SSE client functionality
- Create SSE subscription exchange for URQL integration
- Update URQL provider to use SSE subscription exchange
- Replace timer-based LiveBalance component with GraphQL subscription
- Replace timer-based LiveTransactions component with GraphQL subscription
- Update MSW handlers to properly support SSE endpoints
- Add proper error handling and visual indicators for SSE status

Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot
Ok, thats great that the transactions and balances appear dynamically, but I want these to be performed via SSE.

...

Implemented SSE-based GraphQL subscriptions as requested! The changes include:

SSE Integration (commit 9a87b70):

  • ✅ Installed graphql-sse package and created URQL SSE subscription exchange
  • ✅ Updated LiveBalance component to use SubscribeToAccountBalance GraphQL subscription
  • ✅ Updated LiveTransactions component to use SubscribeToTransactions GraphQL subscription
  • ✅ MSW handlers now properly support SSE at /api/graphql-sse endpoint

Real-time Features:

  • Balance updates stream every 5 seconds via SSE subscription
  • Transaction updates stream every 10 seconds via SSE subscription
  • Visual indicators show "SSE" status and "Live Transactions (SSE)" header
  • Proper error handling for subscription failures

The implementation follows your provided example exactly - using graphql-sse client with URQL's subscriptionExchange and MSW SSE handlers. The app now demonstrates true GraphQL subscriptions over Server-Sent Events instead of timer-based polling.

SSE GraphQL Banking Demo

@Copilot Copilot AI changed the title Implement GraphQL Banking POC with Next.js, TypeScript, and URQL Implement GraphQL Banking POC with SSE Subscriptions, Next.js, TypeScript, and URQL Sep 12, 2025
Copilot finished work on behalf of jedateach September 12, 2025 00:07
@jedateach
Copy link
Owner

@copilot thanks
I want the mocks data to be closer to a real database, and I think it can be achieved with @msw/data
use MSW data
Install it, and create data structures matching our graphql schema
update mocks to utilise the @msw/data models
remove the hard-coded fixtures in the apps/banking-app/src/mocks/data dir. This is where you might put the msw data definitions.

I would expect that the Transfer and Payment mutations would also update this data.

- Install @mswjs/data package for database-like mock data
- Replace hard-coded fixtures with MSW data models
- Create database schema matching GraphQL types (User, Party, Account, Transaction)
- Update all handlers to use MSW data instead of static fixtures
- Remove old fixture files (mockUser.ts, generateMockTransactions.ts, accountBalances.ts)
- Ensure Transfer and Payment mutations update database state
- Initialize database with seed data when MSW starts
- Fix SSE subscriptions to use real-time database updates

Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot thanks
I want the mocks data to be closer to a real database, and I think it can be achieved with @msw/data
use MSW data
...

Implemented MSW Data for realistic database-like behavior! The changes include:

MSW Data Integration (commit 47a7486):

  • ✅ Installed @mswjs/data package
  • ✅ Created data models matching GraphQL schema (User, Party, Account, Transaction)
  • ✅ Replaced all hard-coded fixtures with MSW database operations
  • ✅ Removed old fixture files as requested: mockUser.ts, generateMockTransactions.ts, accountBalances.ts

Database-like Features:

  • Transfer and Payment mutations now properly update the MSW database state
  • SSE subscriptions use real-time database updates instead of static data
  • Database initializes with seed data when MSW starts
  • All queries and mutations operate on persistent mock database

The mock data now behaves like a real database with proper CRUD operations, relationships, and state persistence during the session. Mutations actually modify the underlying data, making the banking app demo much more realistic.

MSW Database Demo

Copilot finished work on behalf of jedateach September 12, 2025 01:54
@jedateach
Copy link
Owner

@copilot
The main header, with it's title, transfer money and send payment options, as well as the user selection dropdown should be persistently at the top of the screen.

Secondly, make the transfer experience instead a modal.

Finally, use faker for mocking who the transaction was with.

Copilot AI and others added 2 commits September 12, 2025 02:48
…action data

Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot
The main header, with it's title, transfer money and send payment options, as well as the user selection dropdown should be persistently at the top of the screen.

...

Implemented all requested features! The changes include:

✅ Persistent Header: Banking Dashboard title, Transfer Money, Send Payment buttons, and user selection dropdown now stay fixed at the top of all pages with a modern backdrop blur effect.

✅ Transfer Modal: Transfer experience is now a modal overlay instead of a separate page. Opens with proper accessibility features using Radix UI Dialog.

✅ Faker Integration: Transaction descriptions now use @faker-js/faker to generate realistic names and companies like "Deposit from Sarah Johnson", "Purchase at TechCorp", "ATM withdrawal at Portland", etc.

All features are working seamlessly with the existing SSE subscriptions and MSW database. The header persists across all pages while live balance updates continue in real-time.

Commit: 4e71c7b

Banking Dashboard with Persistent Header

@Copilot Copilot AI changed the title Implement GraphQL Banking POC with SSE Subscriptions, Next.js, TypeScript, and URQL Implement GraphQL Banking POC with SSE Subscriptions, Persistent Header, Modal Transfer, and Faker Data Sep 12, 2025
Copilot finished work on behalf of jedateach September 12, 2025 02:56
@jedateach
Copy link
Owner

@copilot introduce on the account details page, a time-series graph showing the current balance of the account. it should also update in realtime.

Co-authored-by: jedateach <1356335+jedateach@users.noreply.github.com>
Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot introduce on the account details page, a time-series graph showing the current balance of the account. it should also update in realtime.

Implemented real-time balance chart on account details page! The chart uses recharts library and integrates with the existing SSE subscription system to show live balance updates.

Features added:

  • Time-series line chart showing balance trend over time
  • Real-time updates every 5 seconds via SSE GraphQL subscription
  • Interactive tooltips with precise balance and timestamp data
  • Rolling window of last 20 data points
  • "LIVE UPDATES" indicator when receiving real-time data
  • Professional styling matching the existing UI

The chart is fully integrated with the existing SubscribeToAccountBalance subscription and updates automatically as new balance data streams in.

Commit: a9c8071

Banking App with Real-time Balance Chart

@Copilot Copilot AI changed the title Implement GraphQL Banking POC with SSE Subscriptions, Persistent Header, Modal Transfer, and Faker Data Implement GraphQL Banking POC with SSE Subscriptions, Persistent Header, Modal Transfer, Faker Data, and Real-time Balance Chart Sep 12, 2025
Copilot finished work on behalf of jedateach September 12, 2025 03:09
@jedateach
Copy link
Owner

@copilot
There's something not right here. The points are not distributed according to the mock data, which should be different time intervals, it appears there is simply even spacing along the x axis.
I would expect it to appear like points are moving to the left because the updates coming in.

Use this kind of formatting to get it to move along:

<XAxis
  dataKey="timestamp"
  type="number"
  scale="time"
  domain={['dataMin', 'dataMax']}
  tickFormatter={(unixTime) => formatTime(new Date(unixTime))}
/>

use recharts

Copy link
Author

Copilot AI commented Sep 12, 2025

@copilot
There's something not right here. The points are not distributed according to the mock data, which should be different time intervals, it appears there is simply even spacing along the x ax...

Fixed the balance chart to use time-based distribution from the actual SSE timestamps! The chart now:

  • Uses type="number" and scale="time" on the X-axis for proper time scaling
  • Extracts timestamps from SSE data instead of creating new ones
  • Displays points according to actual time intervals from the mock data
  • Shows realistic time progression with points "moving to the left" as new data comes in

The chart now reflects the bursty nature of the SSE updates (200ms-2s intervals) rather than even spacing.

Commit: 5f5d9b0

Time-based Balance Chart

Copilot finished work on behalf of jedateach September 12, 2025 03:47
@jedateach jedateach force-pushed the copilot/fix-dee1da60-5a4d-4748-940e-9fd9be326ba8 branch from 5f5d9b0 to 251bc5f Compare September 12, 2025 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants