Skip to content

Conversation

@ThorstenSuckow
Copy link
Contributor

…Supabase outages

see website/#1

Copilot AI review requested due to automatic review settings December 5, 2025 11:40
@ThorstenSuckow ThorstenSuckow linked an issue Dec 5, 2025 that may be closed by this pull request
6 tasks
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a resilience layer to handle Supabase outages gracefully by adding caching and fallback mechanisms.

Key Changes

  • Implements a caching strategy that pre-fetches signatories data during build/start and stores it locally
  • Adds graceful degradation with automatic fallback to cached data when Supabase is unavailable
  • Includes a testing mode to simulate Supabase outages via environment variable

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/pages/signatories.tsx Enables error banner display on the signatories page
src/components/SignersList.tsx Implements core resilience logic with error handling and cache fallback
src/components/SignersList.module.css Adds styling for error banner showing cache status
src/components/SignManifest.tsx Adds outage detection and disables signing when Supabase is unavailable
src/components/SignManifest.module.css Adds styling for warning banner
scripts/cache-signatories.cjs Creates script to fetch and cache signatories data from Supabase
package.json Integrates cache script into prebuild and prestart hooks
docusaurus.config.ts Adds configuration for simulating Supabase outages
.gitignore Excludes generated cache file from version control
.env Adds simulation toggle environment variable

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

console.log('🔄 Fetching signatories from Supabase...');

// Use fetch API to query Supabase REST API directly
const response = await fetch(
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script uses the global fetch API which is only available in Node.js 18+. Consider adding a comment documenting the minimum Node.js version requirement, or add a runtime check with a helpful error message if fetch is not available.

Copilot uses AI. Check for mistakes.
window.addEventListener('signature-changed', handler);
return () => window.removeEventListener('signature-changed', handler);
}, [supabase]);
}, [supabase, simulateDown]);
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency array is missing shouldUseMockData. Since shouldUseMockData is calculated from USE_MOCK_DATA and simulateDown, and simulateDown is included in the dependency array, consider adding shouldUseMockData to the dependency array or simplifying by using simulateDown directly in the condition on line 45.

Copilot uses AI. Check for mistakes.
Comment on lines +119 to +124
{cachedSignatories.cached_at && (
<span className={styles.cacheDate}>
{' '}
(as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')})
</span>
)}
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling if cachedSignatories.cached_at contains an invalid date string. Consider wrapping the new Date() call in a try-catch or validating the date before rendering to prevent potential runtime errors.

Suggested change
{cachedSignatories.cached_at && (
<span className={styles.cacheDate}>
{' '}
(as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')})
</span>
)}
{cachedSignatories.cached_at && (() => {
const cacheDate = new Date(cachedSignatories.cached_at);
if (!isNaN(cacheDate.getTime())) {
return (
<span className={styles.cacheDate}>
{' '}
(as of {cacheDate.toLocaleString('en-US')})
</span>
);
}
return (
<span className={styles.cacheDate}>
{' '}
(as of unknown date)
</span>
);
})()}

Copilot uses AI. Check for mistakes.
Comment on lines +116 to +123
{showErrorBanner && error && usingCache && (
<div className={styles.errorBanner}>
{error}. Showing cached signatories
{cachedSignatories.cached_at && (
<span className={styles.cacheDate}>
{' '}
(as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')})
</span>
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error banner only displays when both error AND usingCache are true. This means if there's an error but no cached data is available (lines 89-91), no error message is shown to the user. Consider showing an error message even when cached data is not available, so users are informed of the issue.

Suggested change
{showErrorBanner && error && usingCache && (
<div className={styles.errorBanner}>
{error}. Showing cached signatories
{cachedSignatories.cached_at && (
<span className={styles.cacheDate}>
{' '}
(as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')})
</span>
{showErrorBanner && error && (
<div className={styles.errorBanner}>
{error}.
{usingCache ? (
<>
{' '}Showing cached signatories
{cachedSignatories.cached_at && (
<span className={styles.cacheDate}>
{' '}
(as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')})
</span>
)}
</>
) : (
<> No cached data available.</>

Copilot uses AI. Check for mistakes.
Comment on lines 1 to +3
SUPABASE_URL=https://cuwxnggcavvzbqbidaml.supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImN1d3huZ2djYXZ2emJxYmlkYW1sIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjMzMTA5NzAsImV4cCI6MjA3ODg4Njk3MH0.X0BjHpf6hR3v3Iwv7BN5wkJhewLTzCZnbTq090vuGi0
SIMULATE_SUPABASE_DOWN=false
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .env file should not be committed to version control as it contains sensitive credentials. Add .env to .gitignore and create a .env.example file with placeholder values to document required environment variables.

Copilot uses AI. Check for mistakes.
@ThorstenSuckow ThorstenSuckow merged commit 4500b41 into main Dec 5, 2025
1 check passed
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.

Add resilience layer with caching and graceful degradation for Supabase outages

2 participants