Skip to content

Commit 3eee429

Browse files
Christian Shearerclaude
andcommitted
Redesign credit basket section with real project images and details
Replace generic SVG icons and category descriptions with actual project cards showing photos from S3, project names, locations, descriptions, credit class badges, and links to project pages and credit class pages. Uses PROJECTS from project-metadata.ts for data-driven rendering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8cec8eb commit 3eee429

File tree

1 file changed

+43
-84
lines changed

1 file changed

+43
-84
lines changed

src/server/routes.ts

Lines changed: 43 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { sendWelcomeEmail, sendFirstRetirementEmail, sendRetirementReceiptEmail
4646
import { deriveSubscriberAddress } from "../services/subscriber-wallet.js";
4747
import { retireForSubscriber, accumulateBurnBudget, getPendingBurnBudget, markBurnExecuted, calculateNetAfterStripe, type SubscriberRetirementResult } from "../services/retire-subscriber.js";
4848
import { swapAndBurn, checkOsmosisReadiness } from "../services/swap-and-burn.js";
49-
import { getProjectForBatch } from "./project-metadata.js";
49+
import { getProjectForBatch, PROJECTS } from "./project-metadata.js";
5050
import { checkAndSendMonthlyReminder, checkTradableStock, sendTelegram } from "../services/admin-telegram.js";
5151
import { updateRegistryProfile } from "../services/registry-profile.js";
5252
import { brandFonts, brandCSS, brandHeader, brandFooter } from "./brand.js";
@@ -287,8 +287,8 @@ export function createRoutes(stripe: Stripe | null, db: Database.Database, baseU
287287
/* Credit basket section */
288288
.basket-section { padding: 64px 0; border-top: 1px solid var(--regen-gray-200); }
289289
.basket-grid {
290-
display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
291-
gap: 20px; margin-top: 28px;
290+
display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
291+
gap: 24px; margin-top: 28px;
292292
}
293293
.basket-card {
294294
background: var(--regen-white);
@@ -301,37 +301,39 @@ export function createRoutes(stripe: Stripe | null, db: Database.Database, baseU
301301
box-shadow: var(--regen-shadow-card-hover);
302302
transform: translateY(-3px);
303303
}
304-
.basket-visual {
305-
height: 96px;
306-
display: flex; align-items: center; justify-content: center;
304+
.basket-img {
305+
width: 100%; height: 180px; object-fit: cover;
306+
display: block;
307307
}
308-
.basket-visual svg {
309-
width: 48px; height: 48px;
310-
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.15));
311-
}
312-
.basket-visual--carbon { background: linear-gradient(135deg, #2d6a4f, #52b788); }
313-
.basket-visual--biodiversity { background: linear-gradient(135deg, #7b5e00, #d4a017); }
314-
.basket-visual--urban { background: linear-gradient(135deg, #527984, #79C6AA); }
315-
.basket-visual--marine { background: linear-gradient(135deg, #1565c0, #42a5f5); }
316-
.basket-visual--grazing { background: linear-gradient(135deg, #5d4037, #a1887f); }
317308
.basket-body { padding: 20px 24px 24px; }
318-
.basket-dimension {
309+
.basket-badge {
310+
display: inline-block;
319311
font-family: var(--regen-font-secondary);
320312
font-size: 11px; font-weight: 700; text-transform: uppercase;
321-
letter-spacing: 0.06em; margin-bottom: 4px;
313+
letter-spacing: 0.06em; padding: 3px 10px;
314+
border-radius: 20px; margin-bottom: 8px;
322315
}
323-
.basket-dimension--carbon { color: #2d6a4f; }
324-
.basket-dimension--biodiversity { color: #b8860b; }
325-
.basket-dimension--urban { color: #527984; }
326-
.basket-dimension--marine { color: #1565c0; }
327-
.basket-dimension--grazing { color: #6d4c41; }
328316
.basket-name {
329-
font-size: 16px; font-weight: 700; color: var(--regen-navy);
330-
margin-bottom: 8px;
317+
font-size: 17px; font-weight: 700; color: var(--regen-navy);
318+
margin-bottom: 4px; line-height: 1.3;
319+
}
320+
.basket-location {
321+
font-size: 13px; color: var(--regen-gray-400); margin-bottom: 10px;
322+
font-weight: 500;
331323
}
332324
.basket-desc {
333325
font-size: 13px; color: var(--regen-gray-500);
334-
line-height: 1.55; margin: 0 0 14px;
326+
line-height: 1.6; margin: 0 0 14px;
327+
}
328+
.basket-meta {
329+
display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px;
330+
}
331+
.basket-meta-tag {
332+
font-size: 11px; font-weight: 600; color: var(--regen-gray-500);
333+
background: var(--regen-gray-100); padding: 2px 8px; border-radius: 4px;
334+
}
335+
.basket-links {
336+
display: flex; gap: 16px; flex-wrap: wrap;
335337
}
336338
.basket-link {
337339
font-family: var(--regen-font-secondary);
@@ -533,69 +535,26 @@ Then estimate my AI usage footprint and recommend a tier ($1.25, $2.50, or $5/mo
533535
<section class="basket-section">
534536
<div class="regen-container">
535537
<h2 class="regen-section-title" style="text-align:center;">What Your Subscription Funds</h2>
536-
<p class="regen-section-subtitle" style="text-align:center;">Your subscription retires verified ecocredits drawn from a curated selection across the Regen Registry — including carbon, biodiversity, and other ecological credit types. The mix evolves as new projects and credits become available.</p>
538+
<p class="regen-section-subtitle" style="text-align:center;">Each month, verified ecological credits from these projects are permanently retired on your behalf on Regen Ledger. Every retirement is on-chain, auditable, and yours.</p>
537539
<div class="basket-grid">
538-
540+
${PROJECTS.map(p => `
539541
<div class="basket-card">
540-
<div class="basket-visual basket-visual--carbon">
541-
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M24 6c-2 3-6 8-6 14a6 6 0 0012 0c0-6-4-11-6-14z" fill="#fff" opacity="0.3"/><path d="M24 4V44M16 36l8-12 8 12" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 24c3-2 6-2 9 1M27 21c3-3 6-3 9 0" stroke="#fff" stroke-width="1.5" stroke-linecap="round" opacity="0.7"/><circle cx="24" cy="8" r="2" fill="#fff" opacity="0.5"/></svg>
542-
</div>
542+
<img class="basket-img" src="${p.imageUrl}" alt="${p.name}" loading="lazy">
543543
<div class="basket-body">
544-
<div class="basket-dimension basket-dimension--carbon">Carbon Removal</div>
545-
<div class="basket-name">Carbon Credits</div>
546-
<p class="basket-desc">Forest conservation and reforestation projects sequestering atmospheric carbon. Every tonne retired represents real carbon removed from the atmosphere and locked in living ecosystems.</p>
547-
<a class="basket-link" href="https://app.regen.network/credit-classes/C" target="_blank" rel="noopener">Learn more &rarr;</a>
548-
</div>
549-
</div>
550-
551-
<div class="basket-card">
552-
<div class="basket-visual basket-visual--biodiversity">
553-
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14 18c0-4 4-8 10-8s10 4 10 8c0 6-4 8-6 12h-8c-2-4-6-6-6-12z" fill="#fff" opacity="0.25"/><path d="M18 34c0 0 2 6 6 6s6-6 6-6" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/><circle cx="20" cy="18" r="2" fill="#fff"/><circle cx="28" cy="18" r="2" fill="#fff"/><path d="M8 12c2 0 4 2 4 4M40 12c-2 0-4 2-4 4" stroke="#fff" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/><path d="M20 24c1.5 1 3 1 4 1s2.5 0 4-1" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/></svg>
554-
</div>
555-
<div class="basket-body">
556-
<div class="basket-dimension basket-dimension--biodiversity">Biodiversity</div>
557-
<div class="basket-name">Terrasos Biodiversity Credits</div>
558-
<p class="basket-desc">Habitat conservation protecting Colombia's critical ecosystems and wildlife corridors. 30-year crediting periods safeguard jaguars, tapirs, and hundreds of endemic species.</p>
559-
<a class="basket-link" href="https://app.regen.network/credit-classes/BT" target="_blank" rel="noopener">Learn more &rarr;</a>
560-
</div>
561-
</div>
562-
563-
<div class="basket-card">
564-
<div class="basket-visual basket-visual--urban">
565-
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="6" y="22" width="12" height="18" rx="1.5" fill="#fff" opacity="0.7"/><rect x="9" y="25" width="3" height="3" rx="0.5" fill="#527984" opacity="0.6"/><rect x="12" y="25" width="3" height="3" rx="0.5" fill="#527984" opacity="0.6"/><rect x="9" y="31" width="3" height="3" rx="0.5" fill="#527984" opacity="0.6"/><rect x="12" y="31" width="3" height="3" rx="0.5" fill="#527984" opacity="0.6"/><path d="M32 40V18" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/><circle cx="32" cy="14" r="8" fill="#fff" opacity="0.35"/><circle cx="32" cy="10" r="5" fill="#fff" opacity="0.5"/><line x1="4" y1="40" x2="44" y2="40" stroke="#fff" stroke-width="1.5" opacity="0.4"/></svg>
544+
<span class="basket-badge" style="background: ${p.accentColor}22; color: ${p.accentColor};">${p.creditTypeLabel} (${p.creditType})</span>
545+
<div class="basket-name">${p.name}</div>
546+
<div class="basket-location">${p.location}</div>
547+
<p class="basket-desc">${p.description.length > 180 ? p.description.slice(0, 180) + '&hellip;' : p.description}</p>
548+
<div class="basket-meta">
549+
<span class="basket-meta-tag">${p.creditClassId}</span>
550+
<span class="basket-meta-tag">${p.projectId}</span>
551+
</div>
552+
<div class="basket-links">
553+
<a class="basket-link" href="${p.projectPageUrl}" target="_blank" rel="noopener">View project &rarr;</a>
554+
<a class="basket-link" href="https://app.regen.network/credit-classes/${p.creditClassId}" target="_blank" rel="noopener">Credit class</a>
555+
</div>
566556
</div>
567-
<div class="basket-body">
568-
<div class="basket-dimension basket-dimension--urban">Urban Canopy</div>
569-
<div class="basket-name">City Forest Credits</div>
570-
<p class="basket-desc">Urban tree canopy projects cleaning air, reducing heat islands, and strengthening communities. The national standard for urban forest carbon in U.S. cities.</p>
571-
<a class="basket-link" href="https://app.regen.network/credit-classes/CFC" target="_blank" rel="noopener">Learn more &rarr;</a>
572-
</div>
573-
</div>
574-
575-
<div class="basket-card">
576-
<div class="basket-visual basket-visual--marine">
577-
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4 22c4-3 8-3 12 0s8 3 12 0 8-3 12 0" stroke="#fff" stroke-width="2" stroke-linecap="round" opacity="0.9"/><path d="M4 28c4-3 8-3 12 0s8 3 12 0 8-3 12 0" stroke="#fff" stroke-width="1.5" stroke-linecap="round" opacity="0.55"/><path d="M4 34c4-3 8-3 12 0s8 3 12 0 8-3 12 0" stroke="#fff" stroke-width="1" stroke-linecap="round" opacity="0.3"/><path d="M26 6c0 0 7 3 9 9s-3 11-9 11-9-5-9-11c0-4 4-7 7-9" fill="#fff" opacity="0.35"/><path d="M35 13l5-2-5-2" fill="#fff" opacity="0.6"/><circle cx="29" cy="13" r="1.5" fill="#fff"/></svg>
578-
</div>
579-
<div class="basket-body">
580-
<div class="basket-dimension basket-dimension--marine">Ocean &amp; Coast</div>
581-
<div class="basket-name">Marine Biodiversity Stewardship</div>
582-
<p class="basket-desc">Coastal and ocean ecosystem protection supporting the health of marine habitats, fisheries, and the communities that depend on them.</p>
583-
<a class="basket-link" href="https://app.regen.network/credit-classes/MBS" target="_blank" rel="noopener">Learn more &rarr;</a>
584-
</div>
585-
</div>
586-
587-
<div class="basket-card">
588-
<div class="basket-visual basket-visual--grazing">
589-
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><ellipse cx="24" cy="24" rx="11" ry="7" fill="#fff" opacity="0.35"/><circle cx="24" cy="17" r="5" fill="#fff" opacity="0.45"/><circle cx="20" cy="15" r="2.5" fill="#fff" opacity="0.55"/><circle cx="28" cy="15" r="2.5" fill="#fff" opacity="0.55"/><circle cx="24" cy="12.5" r="2.5" fill="#fff" opacity="0.55"/><circle cx="21" cy="19" r="1" fill="#5d4037"/><circle cx="27" cy="19" r="1" fill="#5d4037"/><line x1="18" y1="31" x2="18" y2="36" stroke="#fff" stroke-width="2" stroke-linecap="round" opacity="0.7"/><line x1="30" y1="31" x2="30" y2="36" stroke="#fff" stroke-width="2" stroke-linecap="round" opacity="0.7"/><path d="M6 40c4-2 8-3 12-1s8 2 12 0 8-2 12-1" stroke="#fff" stroke-width="1" opacity="0.35"/></svg>
590-
</div>
591-
<div class="basket-body">
592-
<div class="basket-dimension basket-dimension--grazing">Regenerative Grazing</div>
593-
<div class="basket-name">Kilo-Sheep-Hour Credits</div>
594-
<p class="basket-desc">Regenerative grazing practices restoring grassland health by measuring verified animal impact. Building soil carbon, water retention, and biodiversity from the ground up.</p>
595-
<a class="basket-link" href="https://app.regen.network/credit-classes/KSH" target="_blank" rel="noopener">Learn more &rarr;</a>
596-
</div>
597-
</div>
598-
557+
</div>`).join('')}
599558
</div>
600559
</div>
601560
</section>

0 commit comments

Comments
 (0)