first commit

Made-with: Cursor
This commit is contained in:
Michilis
2026-04-01 02:46:53 +00:00
commit 76210db03d
126 changed files with 20208 additions and 0 deletions

78
context/design.md Normal file
View File

@@ -0,0 +1,78 @@
# Design System Specification: The Sovereign Editorial
## 1. Overview & Creative North Star
The "Sovereign Editorial" is the creative North Star for this design system. It moves away from the chaotic, high-frequency aesthetic of "crypto-hype" and instead leans into the quiet authority of a diplomatic institution. This is not a "trading platform"; it is an Embassy.
The system breaks the standard "web template" look by utilizing **Intentional Asymmetry** and **Tonal Depth**. We prioritize a high-end, editorial feel through expansive whitespace (using the `20` and `24` spacing tokens), overlapping elements that break the grid, and a typography scale that treats information as a curated exhibition rather than a data dump.
---
## 2. Colors: Tonal Depth & The "No-Line" Rule
The palette is rooted in a "Rich Black" foundation, using `surface` (`#131313`) as the canvas.
### The "No-Line" Rule
**Explicit Instruction:** 1px solid borders for sectioning are strictly prohibited.
Structure must be defined solely through:
- **Background Shifts:** Placing a `surface-container-low` section against a `surface` background.
- **Negative Space:** Using large gaps from the Spacing Scale (e.g., `12` or `16`) to imply boundaries.
### Surface Hierarchy & Nesting
Treat the UI as a series of physical layers, like stacked sheets of obsidian glass.
- **Base Layer:** `surface` (`#131313`)
- **Secondary Sectioning:** `surface-container-low` (`#1c1b1b`)
- **Interactive/Floating Cards:** `surface-container-high` (`#2a2a2a`)
- **The "Glass & Gradient" Rule:** For primary CTAs and hero highlights, use a subtle linear gradient from `primary` (`#ffb874`) to `primary-container` (`#f7931a`). Floating navigation or "pinned" elements must use `surface-bright` with a 15px backdrop-blur to create a premium glassmorphism effect.
---
## 3. Typography: Authority Through Scale
We use **Inter** (as the modern web equivalent to San Francisco) to provide a neutral, trustworthy foundation. The hierarchy is designed to feel like a high-end broadsheet.
- **Display (The Statement):** Use `display-lg` (3.5rem) for hero statements. Tighten letter-spacing to `-0.02em` for a "premium print" look.
- **Headline (The Narrative):** `headline-lg` (2rem) and `headline-md` (1.75rem) provide the educational structure.
- **Body (The Education):** `body-lg` (1rem) is the workhorse. We prioritize a line-height of 1.6 to ensure readability for long-form educational content.
- **Labels (The Metadata):** `label-md` (0.75rem) should be used in uppercase with `0.05em` letter spacing for a technical, diplomatic feel.
---
## 4. Elevation & Depth: Tonal Layering
Traditional drop shadows are replaced by **Ambient Occlusion** and **Material Stacking**.
- **The Layering Principle:** To lift a card, do not add a shadow. Instead, place a `surface-container-lowest` (`#0e0e0e`) element inside a `surface-container` (`#201f1f`) section. The shift in value creates a natural perception of depth.
- **Ambient Shadows:** When a "floating" modal is necessary, use a blur of `40px` with an 8% opacity of the `on-surface` color. It should feel like a soft glow rather than a harsh shadow.
- **The "Ghost Border" Fallback:** If accessibility requires a stroke (e.g., input fields), use `outline-variant` at 15% opacity. Never use 100% opaque borders.
---
## 5. Components
### Buttons
- **Primary:** Gradient background (`primary` to `primary_container`), `on-primary` text. Shape: `md` (0.75rem) corner radius.
- **Secondary:** `surface-container-highest` background with `on-surface` text. No border.
- **Tertiary:** Text-only using `primary_fixed_dim`, strictly for low-priority actions.
### Cards & Lists
- **The Divider Ban:** Dividers are forbidden. Separate list items using `spacing-4` (1.4rem) of vertical whitespace or by alternating background colors between `surface-container-low` and `surface-container-lowest`.
- **Cards:** Always use `rounded-lg` (1rem). Content should have a minimum internal padding of `spacing-6` (2rem).
### Input Fields
- **State:** Background should be `surface-container-highest`.
- **Focus:** Transition the "Ghost Border" from 15% to 40% opacity of the `primary` color. Do not use heavy glow effects.
### Signature Components for the Embassy
- **The "Knowledge Card":** A large-format card using `surface-container-low` with an asymmetrical layout—typography pushed to the left, and a subtle, desaturated Bitcoin icon overlapping the right edge at 5% opacity.
- **The "Trust Indicator":** A persistent, glassmorphic "Status" bar at the bottom of mobile screens, providing real-time network reassurance without cluttering the main content.
---
## 6. Dos and Donts
### Do:
- **Use "Aggressive" Whitespace:** If a section feels "almost right," double the padding.
- **Embrace Asymmetry:** Align headings to the left while keeping body text centered in a narrower column to create visual interest.
- **Mobile-First Layering:** On mobile, stack containers vertically, using `surface-container-lowest` to "ground" the footer.
### Dont:
- **Dont use "Crypto-Green/Red":** Use `error` (`#ffb4ab`) sparingly for critical warnings only. Educational growth is signaled by Bitcoin Orange, not "Stock Market Green."
- **Dont use Dividers:** If you need a line to separate content, you have failed to use the Spacing Scale correctly.
- **Dont Over-Animate:** Transitions should be "Snappy & Subtle" (200ms ease-out). Avoid bouncing or heavy staggered entrances.

296
context/homepage.html Normal file
View File

@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>Belgian Bitcoin Embassy | Monthly Meetup</title>
<script type='text/javascript' nonce='9ButrWt/cTa518miRngtqg==' src='https://contribution.usercontent.google.com/GuY6gPaRx8P7wrAxIzkZ0fQNqPzzi86mwtr8NJkX_fznOFNYK08-VXcbhOG3e0W1gfmAHl19Q7M-20HcuZY1xNCkU2_AN42cBxA9l-AUsyH-azwu4dkmMKQa42MK2c-YWIOJ1RCv7wdEyPMDj0Wz1VwcUJlM8YBCRgi3c4BnKNg='></script><script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
"surface-dim": "#131313",
"primary-container": "#f7931a",
"on-secondary-container": "#b6b5b4",
"on-background": "#e5e2e1",
"on-error-container": "#ffdad6",
"error": "#ffb4ab",
"surface-bright": "#393939",
"on-tertiary-fixed-variant": "#46464b",
"inverse-surface": "#e5e2e1",
"surface-container-high": "#2a2a2a",
"on-primary-fixed": "#2d1600",
"on-surface-variant": "#dbc2ae",
"secondary-container": "#474747",
"on-tertiary-container": "#3f3f44",
"on-secondary-fixed-variant": "#474747",
"tertiary-container": "#ababb0",
"inverse-primary": "#8c4f00",
"tertiary-fixed": "#e3e2e7",
"tertiary": "#c7c6cb",
"primary-fixed": "#ffdcbf",
"on-primary-fixed-variant": "#6b3b00",
"surface-container-low": "#1c1b1b",
"secondary-fixed": "#e4e2e1",
"on-tertiary-fixed": "#1a1b1f",
"surface-container-highest": "#353534",
"on-primary": "#4b2800",
"on-primary-container": "#603500",
"error-container": "#93000a",
"surface-container-lowest": "#0e0e0e",
"outline-variant": "#554335",
"outline": "#a38d7b",
"surface-variant": "#353534",
"surface-tint": "#ffb874",
"on-error": "#690005",
"secondary-fixed-dim": "#c8c6c6",
"surface": "#131313",
"on-secondary-fixed": "#1b1c1c",
"background": "#131313",
"secondary": "#c8c6c6",
"inverse-on-surface": "#313030",
"primary-fixed-dim": "#ffb874",
"on-tertiary": "#2f3034",
"on-surface": "#e5e2e1",
"tertiary-fixed-dim": "#c6c6cb",
"primary": "#ffb874",
"on-secondary": "#303030",
"surface-container": "#201f1f"
},
fontFamily: {
"headline": ["Inter"],
"body": ["Inter"],
"label": ["Inter"]
},
borderRadius: {"DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px"},
},
},
}
</script>
<style>
body {
background-color: #131313;
color: #e5e2e1;
font-family: 'Inter', sans-serif;
-webkit-font-smoothing: antialiased;
}
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.glass-effect {
background: rgba(57, 57, 57, 0.4);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
}
.asymmetric-grid {
display: grid;
grid-template-columns: 1.2fr 0.8fr;
}
@media (max-width: 768px) {
.asymmetric-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body class="selection:bg-primary-container selection:text-on-primary-container">
<!-- TopNavBar -->
<nav class="w-full top-0 z-50 bg-[#131313] dark:bg-[#131313]">
<div class="flex justify-between items-center max-w-7xl mx-auto px-8 h-20">
<div class="text-xl font-bold text-[#f7931a] tracking-[-0.02em]">Belgian Bitcoin Embassy</div>
<div class="hidden md:flex space-x-10 items-center">
<a class="text-[#f7931a] font-bold border-b-2 border-[#f7931a] pb-1 font-['Inter'] font-medium tracking-tight" href="#">Next Meetup</a>
<a class="text-[#ffffff] opacity-70 hover:text-[#f7931a] transition-colors duration-200 font-['Inter'] font-medium tracking-tight" href="#">About</a>
<a class="text-[#ffffff] opacity-70 hover:text-[#f7931a] transition-colors duration-200 font-['Inter'] font-medium tracking-tight" href="#">Community</a>
<a class="text-[#ffffff] opacity-70 hover:text-[#f7931a] transition-colors duration-200 font-['Inter'] font-medium tracking-tight" href="#">FAQ</a>
</div>
<button class="bg-gradient-to-r from-primary to-primary-container text-on-primary px-6 py-2.5 rounded-lg font-bold scale-98 active:opacity-80 transition-all">
Join Us
</button>
</div>
</nav>
<main>
<!-- Hero Section -->
<section class="relative pt-24 pb-32 overflow-hidden px-8">
<div class="max-w-7xl mx-auto asymmetric-grid gap-16 items-center">
<div class="z-10">
<span class="label-md uppercase tracking-[0.2em] text-primary mb-6 block font-semibold">Brussels, Belgium</span>
<h1 class="text-6xl md:text-8xl font-black tracking-tighter leading-[0.9] mb-8">
Belgium's Monthly <br/> <span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-primary-container">Bitcoin Meetup</span>
</h1>
<p class="text-xl text-on-surface-variant max-w-xl leading-relaxed mb-12">
A sovereign space for education, technical discussion, and community. No hype, just signal. Join us at the Embassy.
</p>
<!-- Next Meetup Card (High Visibility) -->
<div class="bg-surface-container-low p-8 rounded-xl relative overflow-hidden group border-l-4 border-primary shadow-2xl">
<div class="flex flex-col md:flex-row md:items-center justify-between gap-6 relative z-10">
<div class="flex items-center gap-6">
<div class="bg-surface-container-high w-16 h-16 rounded-lg flex flex-col items-center justify-center text-center">
<span class="text-xs font-bold uppercase text-primary">Mar</span>
<span class="text-2xl font-black">15</span>
</div>
<div>
<h3 class="text-2xl font-bold">Next Gathering</h3>
<p class="text-on-surface-variant flex items-center gap-1">
<span class="material-symbols-outlined text-sm">location_on</span> Brussels, BE • 19:00
</p>
</div>
</div>
<button class="bg-primary text-on-primary px-8 py-4 rounded-lg font-black hover:scale-105 transition-transform flex items-center justify-center gap-2">
Join Meetup <span class="material-symbols-outlined">arrow_forward</span>
</button>
</div>
<div class="absolute -right-8 -bottom-8 opacity-5">
<span class="material-symbols-outlined text-[120px]" data-weight="fill">currency_bitcoin</span>
</div>
</div>
</div>
<div class="relative hidden md:block">
<div class="rounded-2xl overflow-hidden aspect-[4/5] shadow-2xl grayscale hover:grayscale-0 transition-all duration-700">
<img class="w-full h-full object-cover" data-alt="a professional group of people gathered in a dimly lit sophisticated lounge talking intently in a modern urban environment" src="https://lh3.googleusercontent.com/aida-public/AB6AXuC8O7UDx19I71OVpYa9i0-xxJG80GX8XSvAaDZegZDtXro6Mtzi4OD2Gi2GXtroeutyOxMyjGfHsh5lMan3NKEkHdCKIqrC3pL1mCQmlVSipWvpN01limpOdFtSOsmXWOZ1ZC0ONa1yP214TD3wYRwRiNiJAp4m3Mcl2mrh4QmDCPwppuzn06-bPer20JlaZ1-NwFH69HjBbKXXkmV40bNACupCJ8WK0k9BrEJurna7m6w0dHM3RtSZkDFPoIIwYM_AjIUqoAPPF9s"/>
</div>
<div class="absolute -bottom-6 -left-6 bg-surface-bright p-6 rounded-xl glass-effect border border-white/5">
<p class="text-xs font-bold uppercase tracking-widest text-primary mb-1">Our Network</p>
<p class="text-3xl font-black">1,200+</p>
<p class="text-sm opacity-60">Sovereign Individuals</p>
</div>
</div>
</div>
</section>
<!-- Small Knowledge Cards -->
<section class="py-24 bg-surface-container-lowest px-8">
<div class="max-w-7xl mx-auto">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="bg-surface-container p-10 rounded-xl hover:bg-surface-container-high transition-colors">
<div class="mb-6 bg-primary/10 w-12 h-12 rounded-lg flex items-center justify-center">
<span class="material-symbols-outlined text-primary">account_balance</span>
</div>
<h4 class="text-xl font-bold mb-4">Money without banks</h4>
<p class="text-on-surface-variant leading-relaxed">Operate outside the legacy financial system with peer-to-peer digital sound money.</p>
</div>
<div class="bg-surface-container p-10 rounded-xl hover:bg-surface-container-high transition-colors">
<div class="mb-6 bg-primary/10 w-12 h-12 rounded-lg flex items-center justify-center">
<span class="material-symbols-outlined text-primary">all_inclusive</span>
</div>
<h4 class="text-xl font-bold mb-4">Scarcity: 21 million</h4>
<p class="text-on-surface-variant leading-relaxed">A mathematical certainty of fixed supply. No inflation, no dilution, ever.</p>
</div>
<div class="bg-surface-container p-10 rounded-xl hover:bg-surface-container-high transition-colors">
<div class="mb-6 bg-primary/10 w-12 h-12 rounded-lg flex items-center justify-center">
<span class="material-symbols-outlined text-primary">key</span>
</div>
<h4 class="text-xl font-bold mb-4">Self-custody</h4>
<p class="text-on-surface-variant leading-relaxed">True ownership. Your keys, your bitcoin. No counterparty risk, absolute freedom.</p>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section class="py-32 px-8">
<div class="max-w-5xl mx-auto text-center">
<span class="label-md uppercase tracking-[0.3em] text-primary mb-8 block">The Mission</span>
<h2 class="text-4xl md:text-5xl font-black mb-10 leading-tight">
"Fix the money, fix the world."
</h2>
<p class="text-2xl text-on-surface-variant font-light leading-relaxed mb-12">
We help people in Belgium understand and adopt Bitcoin through education, meetups, and community. We are not a company, but a sovereign network of individuals building a sounder future.
</p>
<div class="w-24 h-1 bg-primary mx-auto opacity-50"></div>
</div>
</section>
<!-- Community Grid -->
<section class="py-24 bg-surface px-8">
<div class="max-w-7xl mx-auto">
<div class="flex justify-between items-end mb-16">
<div>
<h2 class="text-4xl font-black mb-4">Community Moments</h2>
<p class="text-on-surface-variant">The Belgian Bitcoin scene in action.</p>
</div>
<div class="text-right hidden md:block">
<p class="text-primary font-bold text-lg">1,200+ Members</p>
<p class="text-xs uppercase tracking-widest opacity-50">Active on Telegram</p>
</div>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-6">
<div class="rounded-xl overflow-hidden aspect-square grayscale hover:grayscale-0 transition-all duration-500">
<img class="w-full h-full object-cover" data-alt="candid shot of people laughing and talking at a tech meetup in a modern brewery setting" src="https://lh3.googleusercontent.com/aida-public/AB6AXuD0-zvmcx_ClJTCfizqyE-JgZodOBr_o0C1QRw1bCK_2C_q4oSMuRzOCpX4eNuAT5Eug7DrlvVmfA03Xtys0v72PLz5k0pFW-7X5OPcKzXwvrhAa2bVUSSvy0l7zeN33I98r6iibLbqDojACvJ7ARzWN2-rRR62qpHzTprzmCSLeg4dYHBDnsmrFWIypqnxUGS0jR8aOXnJlan4AZPg_JE1N-sgdWfwIBCHEljyLq2d1NLl51b83GMc6iCwHPoLN11I2FFglrruAKg"/>
</div>
<div class="rounded-xl overflow-hidden aspect-square md:translate-y-12 grayscale hover:grayscale-0 transition-all duration-500">
<img class="w-full h-full object-cover" data-alt="wide shot of a presenter speaking to a seated audience in a minimal dark auditorium with orange ambient light" src="https://lh3.googleusercontent.com/aida-public/AB6AXuD2NvZKeDfyJP8xVnpv3JmTRaaAmJcDHjzh5HnpR_Cbxxll_t57_W-4T2VY0kOpyW95a1bs3AUMoRMeqf35kv_HJpmz9qDXqehsLIY4lprPFG3g6x8VRVbDGmVyTTjkk216iCg72tiG1Vy8jTUXj4of0bSZR9_PtPmb0YbPBXVAkuIy06wOuiUI1qOFotm9-jYqHry8c4AKAZSDEMxUVj4odFBb3eM5uM_CkFhXA-N9QcdfCfUAwwCIMisytHhyaKKydxhg8W-eSRE"/>
</div>
<div class="rounded-xl overflow-hidden aspect-square grayscale hover:grayscale-0 transition-all duration-500">
<img class="w-full h-full object-cover" data-alt="close up of several people in a circle holding drinks and engaged in deep conversation at a networking event" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAXeVQGITkhHYXlDFg3EnGCn88bpkKSR6jWROs1LwVVwrvyuQ0CwD2tnwSxWWxY3r6bs8m7QftuFPi03mAo3VVy7WPYZf_AtlCfOE7w7Lg2fVK1Pzh5E7Oon0UAitJD-wXi0beZhoaX1g1qC21QfGsl67L_zNhm6XyGNL_rZ54nCiD6yWeDsAWpU5tVluiOpg0TC7zjC-LMRUMhNA8XFRODN1rtWR8NKoOa_cRZDDG4YL4PM2I1eK9p4m4pYqQeM49qdPYw7-KnOTw"/>
</div>
<div class="rounded-xl overflow-hidden aspect-square md:translate-y-12 grayscale hover:grayscale-0 transition-all duration-500">
<img class="w-full h-full object-cover" data-alt="two young professionals collaborating over a laptop in a cozy warm cafe with soft focus background" src="https://lh3.googleusercontent.com/aida-public/AB6AXuC3dDHSTRTPrq5sTHEOz-UrPnrKzyRlqsrtmo2XUVk_Bv3v4LnLHGTGqa1kr1XuZWxFfFxan_uTWimAHx_n9RUupJ-ciA9ZhlG2TmKqAsbnUHL0IhVN3yiBEHU50mPOG6KBrt82AEP6b1MoVmKgyFgl4-Zdq7QpiH2CtCkALFvUkO_Hi3A2Y-0Ht5-n6H8y_WzFmAHlhvboKNpGmpP6tBizZZvVIXv7HqoCCw2MvKqeZu1L90XwGpoZVwhCdsAKRs_GI7CMyFrPb8g"/>
</div>
</div>
</div>
</section>
<!-- Learning Cards -->
<section class="py-48 px-8">
<div class="max-w-7xl mx-auto">
<h2 class="text-4xl font-black mb-16 text-center">Your Journey Starts Here</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<a class="group relative bg-surface-container-low p-12 rounded-xl border border-transparent hover:border-primary/20 transition-all" href="#">
<span class="material-symbols-outlined text-primary mb-6 text-4xl">shopping_cart</span>
<h3 class="text-2xl font-bold mb-4">Buy Bitcoin</h3>
<p class="text-on-surface-variant mb-8">Learn the safest ways to acquire bitcoin in Belgium without excessive fees.</p>
<span class="text-primary font-bold flex items-center gap-2 group-hover:gap-4 transition-all">Explore <span class="material-symbols-outlined">arrow_right_alt</span></span>
</a>
<a class="group relative bg-surface-container-low p-12 rounded-xl border border-transparent hover:border-primary/20 transition-all" href="#">
<span class="material-symbols-outlined text-primary mb-6 text-4xl">safety_check</span>
<h3 class="text-2xl font-bold mb-4">Store Bitcoin</h3>
<p class="text-on-surface-variant mb-8">Protect your wealth with hardware wallets and multisig best practices.</p>
<span class="text-primary font-bold flex items-center gap-2 group-hover:gap-4 transition-all">Secure wealth <span class="material-symbols-outlined">arrow_right_alt</span></span>
</a>
<a class="group relative bg-surface-container-low p-12 rounded-xl border border-transparent hover:border-primary/20 transition-all" href="#">
<span class="material-symbols-outlined text-primary mb-6 text-4xl">school</span>
<h3 class="text-2xl font-bold mb-4">Learn Basics</h3>
<p class="text-on-surface-variant mb-8">Dive into our curated educational resources for beginners and experts alike.</p>
<span class="text-primary font-bold flex items-center gap-2 group-hover:gap-4 transition-all">Start learning <span class="material-symbols-outlined">arrow_right_alt</span></span>
</a>
</div>
</div>
</section>
<!-- Final CTA -->
<section class="py-32 px-8 bg-surface-container-low relative overflow-hidden">
<div class="max-w-4xl mx-auto text-center relative z-10">
<h2 class="text-5xl font-black mb-8">Start your Bitcoin journey today</h2>
<p class="text-on-surface-variant text-xl mb-12">The best time to learn was 10 years ago. The second best time is today. Join the community.</p>
<div class="flex flex-col md:flex-row items-center justify-center gap-6">
<button class="w-full md:w-auto bg-[#24A1DE] text-white px-10 py-4 rounded-lg font-bold flex items-center justify-center gap-2 hover:opacity-90">
<span class="material-symbols-outlined">send</span> Join Telegram
</button>
<button class="w-full md:w-auto bg-primary text-on-primary px-10 py-4 rounded-lg font-bold hover:scale-105 transition-transform">
Attend Meetup
</button>
<button class="w-full md:w-auto bg-surface-container-highest text-on-surface px-10 py-4 rounded-lg font-bold hover:bg-surface-bright transition-colors">
Learn Bitcoin
</button>
</div>
</div>
<!-- Decorative Background Element -->
<div class="absolute -bottom-20 -right-20 opacity-5">
<span class="material-symbols-outlined text-[400px]" data-weight="fill">hub</span>
</div>
</section>
</main>
<!-- Footer -->
<footer class="w-full py-12 bg-[#0e0e0e]">
<div class="flex flex-col items-center justify-center space-y-6 w-full px-8 text-center">
<div class="text-lg font-black text-[#f7931a]">Belgian Bitcoin Embassy</div>
<div class="flex space-x-12">
<a class="text-[#ffffff] opacity-50 hover:opacity-100 transition-opacity font-['Inter'] text-sm tracking-widest uppercase" href="#">Privacy</a>
<a class="text-[#ffffff] opacity-50 hover:opacity-100 transition-opacity font-['Inter'] text-sm tracking-widest uppercase" href="#">Terms</a>
<a class="text-[#ffffff] opacity-50 hover:opacity-100 transition-opacity font-['Inter'] text-sm tracking-widest uppercase" href="#">Contact</a>
</div>
<p class="text-[#ffffff] opacity-50 font-['Inter'] text-sm tracking-widest uppercase">© Belgian Bitcoin Embassy. No counterparty risk.</p>
</div>
</footer>
</body></html>

283
context/join community.html Normal file
View File

@@ -0,0 +1,283 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BBE - Join the Community (Compact)</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;800&display=swap" rel="stylesheet">
<style>
:root {
--bg-color: #09090b;
--card-bg: #18181b;
--card-border: #27272a;
--bitcoin-orange: #F7931A;
--text-main: #ffffff;
--text-muted: #a1a1aa;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-color);
color: var(--text-main);
background-image: radial-gradient(circle at 50% 0%, #1a1a1c 0%, var(--bg-color) 70%);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem 1rem; /* Added padding for preview */
}
.community-section {
width: 100%;
max-width: 1100px;
margin: 0 auto;
}
.section-header {
text-align: center;
margin-bottom: 2rem; /* Reduced from 4rem */
}
.section-header h2 {
font-size: 2.25rem; /* Reduced from 3rem */
font-weight: 800;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
}
.section-header h2 span {
color: var(--bitcoin-orange);
}
.section-header p {
color: var(--text-muted);
font-size: 0.95rem; /* Reduced from 1.125rem */
max-width: 550px;
margin: 0 auto;
line-height: 1.5;
}
.community-grid {
display: grid;
/* Reduced min-width from 320px to 280px for tighter columns */
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem; /* Reduced from 1.5rem */
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 0.75rem; /* Tighter border radius */
padding: 1.25rem; /* Reduced from 2rem */
text-decoration: none;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: radial-gradient(circle at top right, rgba(247, 147, 26, 0.08), transparent 60%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.card:hover {
transform: translateY(-3px);
border-color: rgba(247, 147, 26, 0.4);
box-shadow: 0 10px 25px -10px rgba(0, 0, 0, 0.5);
}
.card:hover::before {
opacity: 1;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between; /* Pushes arrow to the right */
margin-bottom: 0.75rem; /* Reduced from 1.25rem */
position: relative;
z-index: 1;
}
.header-left {
display: flex;
align-items: center;
}
.icon-wrapper {
width: 36px; /* Reduced from 48px */
height: 36px;
background-color: #000000;
border: 1px solid var(--card-border);
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
color: var(--bitcoin-orange);
margin-right: 0.75rem;
transition: all 0.3s ease;
}
.card:hover .icon-wrapper {
background-color: var(--bitcoin-orange);
color: #000000;
transform: scale(1.05) rotate(-5deg);
border-color: var(--bitcoin-orange);
}
.icon-wrapper svg {
width: 18px; /* Reduced from 24px */
height: 18px;
fill: currentColor;
}
.card h3 {
color: var(--text-main);
font-size: 1.05rem; /* Reduced from 1.25rem */
font-weight: 700;
transition: color 0.3s ease;
}
.card:hover h3 {
color: var(--bitcoin-orange);
}
.arrow-icon {
width: 18px;
height: 18px;
color: #52525b;
transition: all 0.3s ease;
}
.card:hover .arrow-icon {
color: var(--bitcoin-orange);
transform: translate(3px, -3px);
}
.card p {
color: var(--text-muted);
font-size: 0.85rem; /* Reduced from 0.95rem */
line-height: 1.5;
position: relative;
z-index: 1;
}
/* Responsive */
@media (max-width: 600px) {
.section-header h2 { font-size: 1.75rem; }
.community-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<section class="community-section">
<div class="section-header">
<h2>Join the <span>Embassy</span></h2>
<p>Connect with local Belgian Bitcoiners, builders, and educators.</p>
</div>
<div class="community-grid">
<!-- Telegram -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>
</div>
<h3>Telegram</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Join the main Belgian chat group for daily discussion and local coordination.</p>
</a>
<!-- Nostr -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<h3>Nostr</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Follow the BBE on the censorship-resistant social protocol for true signal.</p>
</a>
<!-- X / Twitter -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
</div>
<h3>X</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Stay updated with our latest local announcements and event drops.</p>
</a>
<!-- YouTube -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.54 6.42a2.78 2.78 0 00-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 00-1.94 2A29 29 0 001 11.75a29 29 0 00.46 5.33 2.78 2.78 0 001.94 2c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 001.94-2 29 29 0 00.46-5.33 29 29 0 00-.46-5.33z"/><path d="M9.75 15.02l5.75-3.27-5.75-3.27v6.54z"/></svg>
</div>
<h3>YouTube</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Watch past talks, educational content, and high-quality BBE meetup recordings.</p>
</a>
<!-- Discord -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.028zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
</div>
<h3>Discord</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Deep dive into technical discussions, node running, and project collaboration.</p>
</a>
<!-- LinkedIn -->
<a href="#" class="card">
<div class="card-header">
<div class="header-left">
<div class="icon-wrapper">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zM7.119 20.452H3.554V9h3.565v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
</div>
<h3>LinkedIn</h3>
</div>
<svg class="arrow-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
</div>
<p>Connect with the Belgian Bitcoin professional network and industry leaders.</p>
</a>
</div>
</section>
</body>
</html>

398
context/overview.md Normal file
View File

@@ -0,0 +1,398 @@
# Belgian Bitcoin Embassy Website
## 1. Overview
The Belgian Bitcoin Embassy (BBE) website is a community-driven, Nostr-powered platform centered around a monthly Bitcoin meetup in Belgium.
It is not a corporate site or institutional platform. It is a lightweight, curated Nostr client that:
- showcases the next meetup
- connects users to the community
- displays curated Bitcoin content
- allows users to interact via Nostr (likes, comments)
The platform combines a simple public website with a role-based admin/moderation system.
---
## 2. Core Goals
The website must:
- clearly present the next monthly meetup
- grow the Belgian Bitcoin community
- aggregate and curate Nostr content
- allow social interaction via Nostr
- remain simple, fast, and easy to maintain
---
## 3. Tech Direction
Frontend:
- Next.js (App Router recommended)
- Component-based architecture
- Tailwind CSS (based on design system)
Backend:
- Lightweight API (Node.js / Go)
- Nostr integration layer
- Caching layer for events and posts
Auth:
- Nostr extension login (NIP-07 or signer)
---
## 4. Public Website Structure
### Routes
- `/` → Onepage homepage
- `/blog` → Blog overview
- `/blog/[slug]` → Blog post page
- `/admin` → Dashboard (role-based)
---
## 5. Homepage (Onepage)
### 5.1 Hero
- Headline: Biggest Bitcoin community in Belgium
- Subtext: Monthly meetup + community
- CTA:
- Join Meetup
- Join Telegram
- Follow on Nostr
---
### 5.2 Next Meetup
Critical section.
Fields:
- title
- date
- time
- city
- venue
- description
- link
Actions:
- Attend / RSVP
---
### 5.3 About
Short explanation:
- what BBE is
- community-driven
- beginner friendly
---
### 5.4 Why Join
- meet local Bitcoiners
- learn Bitcoin
- discover events
- connect with community
---
### 5.5 Community Links
Platforms:
- Telegram
- Nostr
- X
- YouTube
- Discord
- LinkedIn
Each includes:
- icon
- short description
- link
---
### 5.6 Blog Preview
- featured posts
- latest posts
- categories
---
### 5.7 FAQ
- beginner friendly?
- do I need bitcoin?
- cost?
- location?
---
### 5.8 Final CTA
- join meetup
- follow community
---
## 6. Blog System (Nostr-Based)
### Source
- Nostr longform events
- imported manually by admins
### Flow
1. Admin inputs event id or naddr
2. Backend fetches from relays
3. Event is parsed and cached
4. Admin edits metadata
5. Post is published
---
### Blog Page `/blog`
- list of posts
- category filters
- featured post
---
### Blog Post `/blog/[slug]`
- title
- content
- categories
- author
- Nostr interactions:
- likes
- comments
---
## 7. Nostr Interaction Layer
Users can:
- login with Nostr
- like posts (reactions)
- comment (replies)
- interact with events
Backend:
- fetch events from relays
- cache data
- apply local moderation
Important:
- no deletion on Nostr
- moderation is local only
---
## 8. Roles & Auth
### Auth
- Nostr login (extension)
- signature verification
- session/JWT
### Roles
Defined by pubkeys.
Admins:
- set in `.env`
Moderators:
- assigned by admins
---
## 9. Admin Dashboard
Route: `/admin`
Admins have full control.
### Tabs
#### 9.1 Overview
- meetup summary
- latest posts
- quick actions
#### 9.2 Events
- create/edit meetups
- mark upcoming/past
- manage event content
- moderate comments
#### 9.3 Blog
- import Nostr posts
- edit metadata
- assign categories
- publish/unpublish
- feature posts
#### 9.4 Moderation
- view comments
- filter by post/event
- hide content
- block pubkeys (local)
#### 9.5 Users
- list users (pubkeys)
- promote to moderator
- remove moderator
- block users
#### 9.6 Categories
- create/edit/delete
- reorder
#### 9.7 Relays
- add/remove relays
- set priority
- test connectivity
#### 9.8 Settings
- site title
- tagline
- social links
- feature toggles
#### 9.9 Nostr Tools
- manual fetch
- cache refresh
- debug events
---
## 10. Moderator Dashboard
Moderators have content-only control.
### Tabs
#### 10.1 Moderation
- comment stream
- hide spam
- filter content
#### 10.2 Events
- view meetups
- moderate comments
- minor edits
#### 10.3 Blog
- edit metadata
- assign categories
- publish/unpublish
#### 10.4 Reports (optional)
- flagged content
- moderation actions
---
## 11. Data Models
### Meetup
- title
- description
- date
- location
- link
- status
### Blog Post
- nostr_event_id
- title
- slug
- content
- excerpt
- categories
- featured
- visible
### Category
- name
- slug
### User
- pubkey
- role
---
## 12. Component Structure
Public:
- HeroSection
- NextMeetupCard
- AboutSection
- CommunityLinks
- BlogPreview
- FAQSection
Admin:
- AdminSidebar
- MeetupEditor
- PostManager
- CategoryManager
- SettingsPanel
---
## 13. Design Principles
- dark theme
- Bitcoin orange accent
- large whitespace
- no borders (use spacing)
- layered surfaces
- minimal animation
---
## 14. MVP Scope
Build first:
- homepage
- blog
- blog post page
- Nostr login
- admin dashboard
- moderator dashboard
- meetup system
- Nostr blog import
---
## 15. Key Principle
This is not a CMS.
This is a curated Nostr client for a Bitcoin meetup community.
Keep it simple, fast, and focused on:
- meetup
- community
- content

773
context/pages.md Normal file
View File

@@ -0,0 +1,773 @@
# Belgian Bitcoin Embassy Website
## 1. Overview
The Belgian Bitcoin Embassy (BBE) website is a community-driven, Nostr-powered platform centered around a monthly Bitcoin meetup in Belgium.
It is not a corporate site or institutional platform. It is a lightweight, curated Nostr client that:
- showcases the next meetup
- connects users to the community
- displays curated Bitcoin content
- allows users to interact via Nostr (likes, comments)
The platform combines a simple public website with a role-based admin/moderation system.
---
## 2. Core Goals
The website must:
- clearly present the next monthly meetup
- grow the Belgian Bitcoin community
- aggregate and curate Nostr content
- allow social interaction via Nostr
- remain simple, fast, and easy to maintain
---
## 3. Tech Direction
Frontend:
- Next.js (App Router recommended)
- Component-based architecture
- Tailwind CSS (based on design system)
Backend:
- Lightweight API (Node.js / Go)
- Nostr integration layer
- Caching layer for events and posts
Auth:
- Nostr extension login (NIP-07 or signer)
---
## 4. Public Website Structure
### Routes
- `/` → Onepage homepage
- `/blog` → Blog overview
- `/blog/[slug]` → Blog post page
- `/admin` → Dashboard (role-based)
---
## 5. Homepage (Onepage)
### 5.1 Hero
- Headline: Biggest Bitcoin community in Belgium
- Subtext: Monthly meetup + community
- CTA:
- Join Meetup
- Join Telegram
- Follow on Nostr
---
### 5.2 Next Meetup
Critical section.
Fields:
- title
- date
- time
- city
- venue
- description
- link
Actions:
- Attend / RSVP
---
### 5.3 About
Short explanation:
- what BBE is
- community-driven
- beginner friendly
---
### 5.4 Why Join
- meet local Bitcoiners
- learn Bitcoin
- discover events
- connect with community
---
### 5.5 Community Links
Platforms:
- Telegram
- Nostr
- X
- YouTube
- Discord
- LinkedIn
Each includes:
- icon
- short description
- link
---
### 5.6 Blog Preview
- featured posts
- latest posts
- categories
---
### 5.7 FAQ
- beginner friendly?
- do I need bitcoin?
- cost?
- location?
---
### 5.8 Final CTA
- join meetup
- follow community
---
## 6. Blog System (Nostr-Based)
### Source
- Nostr longform events
- imported manually by admins
### Flow
1. Admin inputs event id or naddr
2. Backend fetches from relays
3. Event is parsed and cached
4. Admin edits metadata
5. Post is published
---
### Blog Page `/blog`
- list of posts
- category filters
- featured post
---
### Blog Post `/blog/[slug]`
- title
- content
- categories
- author
- Nostr interactions:
- likes
- comments
---
## 7. Nostr Interaction Layer
Users can:
- login with Nostr
- like posts (reactions)
- comment (replies)
- interact with events
Backend:
- fetch events from relays
- cache data
- apply local moderation
Important:
- no deletion on Nostr
- moderation is local only
---
## 8. Roles & Auth
### Auth
- Nostr login (extension)
- signature verification
- session/JWT
### Roles
Defined by pubkeys.
Admins:
- set in `.env`
Moderators:
- assigned by admins
---
## 9. Admin Dashboard
Route: `/admin`
Admins have full control.
### Tabs
#### 9.1 Overview
- meetup summary
- latest posts
- quick actions
#### 9.2 Events
- create/edit meetups
- mark upcoming/past
- manage event content
- moderate comments
#### 9.3 Blog
- import Nostr posts
- edit metadata
- assign categories
- publish/unpublish
- feature posts
#### 9.4 Moderation
- view comments
- filter by post/event
- hide content
- block pubkeys (local)
#### 9.5 Users
- list users (pubkeys)
- promote to moderator
- remove moderator
- block users
#### 9.6 Categories
- create/edit/delete
- reorder
#### 9.7 Relays
- add/remove relays
- set priority
- test connectivity
#### 9.8 Settings
- site title
- tagline
- social links
- feature toggles
#### 9.9 Nostr Tools
- manual fetch
- cache refresh
- debug events
---
## 10. Moderator Dashboard
Moderators have content-only control.
### Tabs
#### 10.1 Moderation
- comment stream
- hide spam
- filter content
#### 10.2 Events
- view meetups
- moderate comments
- minor edits
#### 10.3 Blog
- edit metadata
- assign categories
- publish/unpublish
#### 10.4 Reports (optional)
- flagged content
- moderation actions
---
## 11. Data Models
### Meetup
- title
- description
- date
- location
- link
- status
### Blog Post
- nostr_event_id
- title
- slug
- content
- excerpt
- categories
- featured
- visible
### Category
- name
- slug
### User
- pubkey
- role
---
## 12. Component Structure
Public:
- HeroSection
- NextMeetupCard
- AboutSection
- CommunityLinks
- BlogPreview
- FAQSection
Admin:
- AdminSidebar
- MeetupEditor
- PostManager
- CategoryManager
- SettingsPanel
---
## 13. Design Principles
- dark theme
- Bitcoin orange accent
- large whitespace
- no borders (use spacing)
- layered surfaces
- minimal animation
---
## 14. MVP Scope
Build first:
- homepage
- blog
- blog post page
- Nostr login
- admin dashboard
- moderator dashboard
- meetup system
- Nostr blog import
---
## 15. Key Principle
This is not a CMS.
This is a curated Nostr client for a Bitcoin meetup community.
Keep it simple, fast, and focused on:
- meetup
- community
- content
---
# pages.md
## 1. Routing Overview
Public routes:
- `/` → Homepage (onepage)
- `/blog` → Blog listing
- `/blog/[slug]` → Blog detail
Auth / Dashboard routes:
- `/admin` → Dashboard entry (role-based)
- `/admin/overview`
- `/admin/events`
- `/admin/blog`
- `/admin/moderation`
- `/admin/users` (admin only)
- `/admin/categories`
- `/admin/relays` (admin only)
- `/admin/settings` (admin only)
- `/admin/nostr` (admin only tools)
System routes (optional):
- `/api/*` → Backend endpoints
- `/health` → Health check
All `/admin/*` routes require Nostr authentication.
---
## 2. Layouts
### 2.1 Public Layout
Used by `/` and `/blog*`
Structure:
- Top Navigation
- Page Content
- Footer
Top Navigation:
- Logo (BBE)
- Links (scroll or anchor):
- Meetup
- About
- Community
- Blog
- CTA button: Join Meetup
Footer:
- Logo
- Links: Privacy, Terms, Contact
- Social links
---
### 2.2 Admin Layout
Used by `/admin/*`
Structure:
- Sidebar (left)
- Content area (right)
- Top bar (optional)
Sidebar:
- Overview
- Events
- Blog
- Moderation
- Categories
- (Admins only)
- Users
- Relays
- Settings
- Nostr Tools
Role-based rendering:
- Moderator sees limited menu
- Admin sees full menu
---
## 3. Homepage `/`
Single page composed of sections.
### Sections (top to bottom)
#### 3.1 HeroSection
Content:
- headline
- subtext
- CTA buttons:
- Join Meetup
- Join Telegram
- Follow on Nostr
#### 3.2 NextMeetupSection
Data source: Meetup API
Content:
- date
- time
- city
- venue
- description
- CTA: Attend Meetup
#### 3.3 AboutSection
Static/admin-editable content.
#### 3.4 WhyJoinSection
Static list of benefits.
#### 3.5 CommunityLinksSection
Dynamic from settings:
- Telegram
- Nostr
- X
- YouTube
- Discord
- LinkedIn
#### 3.6 BlogPreviewSection
Data source: Blog API
Content:
- featured post
- latest posts
#### 3.7 FAQSection
Static/admin-editable.
#### 3.8 FinalCTASection
- Join Meetup
- Follow Community
---
## 4. Blog Listing `/blog`
### Layout
- Header (title + description)
- Category filter
- Post grid/list
### Features
- filter by category
- highlight featured post
- pagination or infinite scroll
### Data
From cached Nostr posts.
---
## 5. Blog Detail `/blog/[slug]`
### Layout
- Title
- Metadata (date, author)
- Content
- Categories
- Interaction section
- Related posts
### Interaction
If user logged in (Nostr):
- Like button
- Comment input
Display:
- likes count
- comments (Nostr replies)
---
## 6. Admin Entry `/admin`
### Behavior
- if not logged in → show Nostr login screen
- if logged in → redirect to `/admin/overview`
### Login Screen
- button: Login with Nostr extension
- explanation text
---
## 7. Admin Pages
### 7.1 `/admin/overview`
Dashboard summary:
- next meetup
- recent posts
- recent activity
- quick actions
---
### 7.2 `/admin/events`
Meetup management.
Views:
- list of meetups
- create/edit form
Fields:
- title
- description
- date/time
- location
- link
Actions:
- create
- edit
- delete
- mark featured
Moderation:
- view comments
- hide comments
---
### 7.3 `/admin/blog`
Blog management.
Views:
- list of posts
- import tool
Import flow:
- paste event id or naddr
- fetch preview
- confirm import
Post editing:
- title
- excerpt
- slug
- categories
- featured toggle
- visibility toggle
---
### 7.4 `/admin/moderation`
Moderation center.
Views:
- comment stream
- filters:
- by post
- by event
- by user
Actions:
- hide comment
- mark spam
- block pubkey (local)
---
### 7.5 `/admin/users` (admin only)
User management.
Views:
- list of pubkeys
Actions:
- promote to moderator
- remove moderator
- block user
---
### 7.6 `/admin/categories`
Category management.
Actions:
- create
- edit
- delete
- reorder
---
### 7.7 `/admin/relays` (admin only)
Relay configuration.
Actions:
- add relay
- remove relay
- set priority
- test connection
---
### 7.8 `/admin/settings` (admin only)
Global settings.
Fields:
- site title
- tagline
- social links
- feature toggles
---
### 7.9 `/admin/nostr` (admin only)
Advanced tools.
Features:
- manual event fetch
- cache refresh
- debug viewer
---
## 8. Access Control
- `/admin/*` requires Nostr auth
- roles checked server-side
- UI adapts based on role
---
## 9. Error Pages
- `/404`
- `/500`
Simple, minimal, same design style.
---
## 10. Key Principles
- keep routes minimal
- keep pages focused
- no unnecessary nesting
- everything role-based
The structure must stay simple and predictable for developers.