Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 17 additions & 30 deletions src/components/Avatar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,21 @@
$: avatarSrc = src ?? imageUrl;
$: status = membershipMap[normalizedPubkey];
$: isActiveMember = Boolean(status?.active) && showRing;
$: ringTierClass =
status?.tier === 'pro_kitchen'
? 'tier-pro-kitchen'
: status?.tier === 'founders'
? 'tier-founders'
: status?.tier === 'cook_plus'
? 'tier-cook-plus'
: 'tier-default';
$: ringPadding = isActiveMember ? 2.5 : 0;
$: innerSize = Math.max(16, Math.round(size - ringPadding * 2));
$: innerSize = size;
$: tooltipLabel = getMembershipLabel(status?.tier || 'unknown');
$: glowStyle = (() => {
if (!isActiveMember) return '';
switch (status?.tier) {
case 'founders':
return 'box-shadow: 0 0 0 2px rgba(255,215,0,0.85), 0 0 12px 4px rgba(255,215,0,0.6), 0 0 24px 8px rgba(255,215,0,0.3);';
case 'pro_kitchen':
return 'box-shadow: 0 0 0 2px rgba(139,92,246,0.8), 0 0 12px 4px rgba(139,92,246,0.6), 0 0 24px 8px rgba(139,92,246,0.3);';
case 'cook_plus':
return 'box-shadow: 0 0 0 2px rgba(249,115,22,0.8), 0 0 12px 4px rgba(249,115,22,0.6), 0 0 24px 8px rgba(249,115,22,0.3);';
default:
return 'box-shadow: 0 0 0 2px rgba(249,115,22,0.8), 0 0 12px 4px rgba(249,115,22,0.6), 0 0 24px 8px rgba(249,115,22,0.3);';
Comment on lines +42 to +48
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

glowStyle sets box-shadow inline on .avatar-wrapper, which will override any box-shadow-based styles passed via className (notably Tailwind ring-* and shadow-*). This is already used at least in TrendingRecipeCard.svelte (className="ring-2 ring-white"), so active members would lose that ring. Consider rendering the glow via a pseudo-element/overlay, or set a CSS var for the glow and compose it with Tailwind’s --tw-ring-* / --tw-shadow variables in .avatar-wrapper so both effects apply.

Suggested change
return 'box-shadow: 0 0 0 2px rgba(255,215,0,0.85), 0 0 12px 4px rgba(255,215,0,0.6), 0 0 24px 8px rgba(255,215,0,0.3);';
case 'pro_kitchen':
return 'box-shadow: 0 0 0 2px rgba(139,92,246,0.8), 0 0 12px 4px rgba(139,92,246,0.6), 0 0 24px 8px rgba(139,92,246,0.3);';
case 'cook_plus':
return 'box-shadow: 0 0 0 2px rgba(249,115,22,0.8), 0 0 12px 4px rgba(249,115,22,0.6), 0 0 24px 8px rgba(249,115,22,0.3);';
default:
return 'box-shadow: 0 0 0 2px rgba(249,115,22,0.8), 0 0 12px 4px rgba(249,115,22,0.6), 0 0 24px 8px rgba(249,115,22,0.3);';
return 'filter: drop-shadow(0 0 0 rgba(255,215,0,0.85)) drop-shadow(0 0 12px rgba(255,215,0,0.6)) drop-shadow(0 0 24px rgba(255,215,0,0.3));';
case 'pro_kitchen':
return 'filter: drop-shadow(0 0 0 rgba(139,92,246,0.8)) drop-shadow(0 0 12px rgba(139,92,246,0.6)) drop-shadow(0 0 24px rgba(139,92,246,0.3));';
case 'cook_plus':
return 'filter: drop-shadow(0 0 0 rgba(249,115,22,0.8)) drop-shadow(0 0 12px rgba(249,115,22,0.6)) drop-shadow(0 0 24px rgba(249,115,22,0.3));';
default:
return 'filter: drop-shadow(0 0 0 rgba(249,115,22,0.8)) drop-shadow(0 0 12px rgba(249,115,22,0.6)) drop-shadow(0 0 24px rgba(249,115,22,0.3));';

Copilot uses AI. Check for mistakes.
}
})();

$: if (normalizedPubkey) {
queueMembershipLookup(normalizedPubkey);
Expand Down Expand Up @@ -120,8 +124,8 @@

<div
bind:this={wrapperEl}
class="avatar-wrapper {className} {isActiveMember ? `has-ring ${ringTierClass}` : ''}"
style="--avatar-size: {size}px; --ring-padding: {ringPadding}px;"
class="avatar-wrapper {className}"
style="--avatar-size: {size}px; {glowStyle}"
role="button"
tabindex="0"
aria-label={alt}
Expand All @@ -148,10 +152,10 @@
width: var(--avatar-size);
height: var(--avatar-size);
border-radius: 999px;
padding: var(--ring-padding);
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: visible;
}

.avatar-inner {
Expand All @@ -161,23 +165,6 @@
overflow: hidden;
}

.has-ring {
border: 1px solid color-mix(in srgb, var(--zap-orange, #ec4700) 65%, transparent);
}

.tier-cook-plus {
border-width: 1px;
}

.tier-pro-kitchen {
border-width: 1.5px;
}

.tier-founders {
border-width: 1px;
box-shadow: 0 0 0 1px color-mix(in srgb, var(--zap-orange, #ec4700) 18%, transparent);
}

.membership-tooltip {
position: absolute;
left: 50%;
Expand Down
2 changes: 1 addition & 1 deletion src/routes/api/genesis/create-lightning-invoice/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const POST: RequestHandler = async ({ request, platform }) => {
console.log('[Founders Club Lightning] Invoice created:', {
receiveRequestId,
amountSats,
pubkey,
pubkey: pubkey.substring(0, 16) + '...',
});

// Store metadata so webhook and verify endpoints can match payment to user
Expand Down
10 changes: 10 additions & 0 deletions src/routes/api/genesis/verify-lightning-payment/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ export const POST: RequestHandler = async ({ request, platform }) => {

// Look up stored metadata to verify the request
const kv = platform?.env?.GATED_CONTENT ?? null;
if (!kv && env.NODE_ENV === 'production') {
console.error('[Genesis Lightning] GATED_CONTENT KV binding is missing in production environment');
return json(
{
error: 'Service unavailable',
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The 503 response includes actionable info in message, but current clients typically display only data.error on non-OK responses. That means users will likely only see "Service unavailable" and miss the actual configuration hint. Consider consolidating into error, or teaching the client error handling to surface message when available.

Suggested change
error: 'Service unavailable',
error: 'Service unavailable: GATED_CONTENT KV namespace is not configured',

Copilot uses AI. Check for mistakes.
message: 'GATED_CONTENT KV namespace is not configured'
},
{ status: 503 }
);
}
const metadata = receiveRequestId
? await getInvoiceMetadata(kv, receiveRequestId)
: await getInvoiceMetadataByPaymentHash(kv, paymentHash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export const POST: RequestHandler = async ({ request, platform }) => {
amountSats,
tier,
period,
pubkey,
pubkey: pubkey.substring(0, 16) + '...',
});

// Store invoice metadata so webhook and verify endpoints can match payment to user
Expand Down
8 changes: 5 additions & 3 deletions src/routes/api/membership/verify-lightning-payment/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ export const POST: RequestHandler = async ({ request, platform }) => {

// Look up stored metadata to verify the request matches what was created
const kv = platform?.env?.GATED_CONTENT ?? null;

// In production, missing KV binding is a misconfiguration, not a 404
if (!kv && env.NODE_ENV === 'production') {
console.error('[Verify Lightning] GATED_CONTENT KV binding is missing in production environment');
return json(
{ error: 'Service unavailable: GATED_CONTENT KV binding is missing' },
{
error: 'Service unavailable',
message: 'GATED_CONTENT KV namespace is not configured'
Comment on lines +78 to +79
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

This 503 response splits the details across error and message, but existing checkout pages only read data.error when surfacing failures. As a result, users will see the less actionable "Service unavailable" while the useful context is in message. Consider either keeping the full detail in error, or updating the client(s) to prefer message when present.

Suggested change
error: 'Service unavailable',
message: 'GATED_CONTENT KV namespace is not configured'
error: 'Service unavailable: GATED_CONTENT KV namespace is not configured'

Copilot uses AI. Check for mistakes.
},
{ status: 503 }
);
}
Expand Down