feat: update footer text to reflect Creative Commons license

Align footer with commons-oriented ethos and clarify licensing.

#VERCEL_SKIP

Co-authored-by: Jeff Emmett <46964190+Jeff-Emmett@users.noreply.github.com>
This commit is contained in:
v0 2025-12-10 18:39:44 +00:00
parent 60921db465
commit a1e4cf1098
19 changed files with 633 additions and 226 deletions

View File

@ -1,46 +0,0 @@
FROM node:20-alpine AS base
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN pnpm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

233
app/about/page.tsx Normal file
View File

@ -0,0 +1,233 @@
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { ArrowRight, Users, Heart, Sprout, Network, Sparkles } from "lucide-react"
import Link from "next/link"
export default function AboutPage() {
return (
<div className="min-h-screen">
{/* Hero Section */}
<section className="relative min-h-[60vh] flex items-center justify-center overflow-hidden">
<div
className="absolute inset-0 bg-cover bg-center z-0"
style={{
backgroundImage: `url('/images/20220429-145359.jpg')`,
}}
/>
<div className="absolute inset-0 bg-gradient-to-b from-background/90 via-background/80 to-background z-[1]" />
<div className="container mx-auto px-4 relative z-10 text-center max-w-4xl py-20">
<h1 className="text-4xl md:text-6xl font-black mb-6 text-balance leading-tight">About CCG 2026</h1>
<p className="text-lg md:text-xl text-muted-foreground text-pretty">
Six years of thinkering with the promises and paradoxes of crypto and the commons
</p>
</div>
</section>
{/* Main Content */}
<section className="py-16 px-4">
<div className="container mx-auto max-w-4xl">
<div className="prose prose-lg max-w-none">
<h2 className="text-3xl font-bold mb-6">A Growing Movement</h2>
<p className="text-muted-foreground leading-relaxed mb-6">
What began in 2020 as a modest excuse for then-PhD researcher Felix Fritsch to bring together
crypto-commons thinkers from around the world in his own backyard has since evolved into an annual moment
of (re)connection and reflection for a growing communityand for the many lived practices and experiments
in commoning, degrowth, mutualism, and post-capitalist economic worldbuilding it is linked to.
</p>
<p className="text-muted-foreground leading-relaxed mb-8">
Over the years, CCG has welcomed activists, researchers, hackers, builders, artists, game designers, and
othersnewcomers and "OGs" alike. It has shaped itself as a convivial and fertile space for people and
projects working across and beyond web3 to cross-pollinate visions, trajectories, and strategies for
realizing regenerative and cooperative infrastructures.
</p>
<div className="grid md:grid-cols-3 gap-4 my-12">
<Card className="border-primary/20">
<CardContent className="p-6 text-center">
<div className="text-4xl font-black text-primary mb-2">6th</div>
<p className="text-sm text-muted-foreground">Annual Edition</p>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6 text-center">
<div className="text-4xl font-black text-primary mb-2">100+</div>
<p className="text-sm text-muted-foreground">Expected Participants</p>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6 text-center">
<div className="text-4xl font-black text-primary mb-2">7</div>
<p className="text-sm text-muted-foreground">Days of Connection</p>
</CardContent>
</Card>
</div>
<h2 className="text-3xl font-bold mb-6 mt-16">The 2026 Edition: New Infrastructures</h2>
<p className="text-muted-foreground leading-relaxed mb-6">
While remaining an unconference at heart, each edition has reflected the community's shifting priorities
and aspirations. In 2026, the gathering enters its sixth year, presenting not only a space to collectively
take stock of what crypto commons has become and what it still could be, but also a moment for the growing
community to think and organize itself anew.
</p>
<div className="bg-muted/50 border border-border rounded-lg p-8 my-8">
<h3 className="text-2xl font-bold mb-4">What's Evolving in 2026</h3>
<ul className="space-y-4">
<li className="flex gap-3">
<Sparkles className="w-5 h-5 text-primary flex-shrink-0 mt-1" />
<div>
<strong className="text-foreground">The Commons Hub</strong> has become a full-fledged event hosting
organization, co-led by brothers Felix and Emil Fritsch, with exciting expansion and ecovillage
plans underway.
</div>
</li>
<li className="flex gap-3">
<Sparkles className="w-5 h-5 text-primary flex-shrink-0 mt-1" />
<div>
<strong className="text-foreground">The Crypto Commons Association</strong>, previously stewarded by
Felix Fritsch and Giulio Quarta, is being reimagined as a cooperative vehicle for organizing and
supporting events at the Hub and beyond, introducing peer-production values and frameworks.
</div>
</li>
</ul>
</div>
<h2 className="text-3xl font-bold mb-6 mt-16">What to Expect</h2>
<div className="space-y-6 mb-12">
<Card className="border-primary/20">
<CardContent className="p-6">
<div className="flex gap-4">
<Heart className="w-6 h-6 text-primary flex-shrink-0 mt-1" />
<div>
<h3 className="font-bold mb-2">Gather & Connect</h3>
<p className="text-muted-foreground">
Meet others in a convivial, off-grid setting in the Austrian countryside, whether you're
reconnecting or arriving for the first time. Form friendships that last a lifetime.
</p>
</div>
</div>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<div className="flex gap-4">
<Sprout className="w-6 h-6 text-primary flex-shrink-0 mt-1" />
<div>
<h3 className="font-bold mb-2">Explore Key Themes</h3>
<p className="text-muted-foreground mb-3">
Engage through participant-led sessions on regenerative and collaborative finance, MycoFi,
community currencies, digital and crypto commons, open source, degrowth, post-capitalism,
ecofeminism, multispecies justice, radical game design, speculative fiction, and more.
</p>
</div>
</div>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<div className="flex gap-4">
<Users className="w-6 h-6 text-primary flex-shrink-0 mt-1" />
<div>
<h3 className="font-bold mb-2">Participate Fully</h3>
<p className="text-muted-foreground">
Experience a fully unconferenced structure where time and sessions are collectively managed.
Bring your ideas for talks, roundtables, workshops, prototyping sessions, board game nights,
LARPs, and more. Immerse yourself, find inspiration, and team up with others.
</p>
</div>
</div>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<div className="flex gap-4">
<Network className="w-6 h-6 text-primary flex-shrink-0 mt-1" />
<div>
<h3 className="font-bold mb-2">Co-Create the Future</h3>
<p className="text-muted-foreground">
If you're interested, contribute to the ongoing co-creation of the Crypto Commons Association as
it transitions into an events-oriented cooperative, a DAO, or something in between.
</p>
</div>
</div>
</CardContent>
</Card>
</div>
<h2 className="text-3xl font-bold mb-6 mt-16">Spawning New Movements</h2>
<p className="text-muted-foreground leading-relaxed mb-6">
CCG has been a catalyst for emerging movements and initiatives. From the gathering, movements like{" "}
<strong className="text-primary">#CoFi</strong> (Cooperative Finance) and{" "}
<strong className="text-primary">#MycoFi</strong> (Mycelial Finance) have emerged, embodying the potential
for technologically-enabled commons that leverage network technologies to reclaim ground from state and
corporate control.
</p>
<p className="text-muted-foreground leading-relaxed mb-8">
The solidarity built here has coalesced into new digital public infrastructures, experimental protocols,
and collaborative frameworks that continue to evolve between gatherings.
</p>
</div>
</div>
</section>
{/* Photo Section */}
<section className="py-16 px-4 bg-muted/30">
<div className="container mx-auto max-w-6xl">
<h2 className="text-3xl font-bold mb-8 text-center">Experience CCG</h2>
<div className="grid md:grid-cols-3 gap-4">
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<img
src="/images/20220830-104828.jpg"
alt="CCG discussion circle"
className="w-full h-full object-cover"
/>
</div>
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<img src="/images/20220503-155430.jpg" alt="Community gathering" className="w-full h-full object-cover" />
</div>
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<img src="/images/image.png" alt="Alpine setting" className="w-full h-full object-cover" />
</div>
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-24 px-4">
<div className="container mx-auto max-w-3xl text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-6 text-balance">Be Part of the Sixth Edition</h2>
<p className="text-lg text-muted-foreground mb-8 text-pretty">
Join us August 16-22, 2026 in the Austrian Alps for an unforgettable week of connection, collaboration, and
commons-building.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button size="lg" className="gap-2" asChild>
<Link href="/register">
Register Now <ArrowRight className="w-4 h-4" />
</Link>
</Button>
<Button size="lg" variant="outline" asChild>
<Link href="/">Back to Home</Link>
</Button>
</div>
</div>
</section>
{/* Footer */}
<footer className="py-12 px-4 border-t border-border">
<div className="container mx-auto max-w-6xl text-center">
<p className="text-sm text-muted-foreground">
© 2026 Crypto Commons Gathering. Built with solidarity for the commons.
</p>
</div>
</footer>
</div>
)
}

View File

@ -1,19 +1,9 @@
import { type NextRequest, NextResponse } from "next/server"
import Stripe from "stripe"
// Lazy initialization to avoid build-time errors when env vars aren't set
let stripeInstance: Stripe | null = null
function getStripe(): Stripe {
if (!stripeInstance) {
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error("STRIPE_SECRET_KEY is not configured")
}
stripeInstance = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: "2024-12-18.acacia",
})
}
return stripeInstance
}
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
})
const CCG_TICKET_PRICE_ID = "price_1SbokZ8IwXvKSVJpRvkTqePT"
const CCG_ACCOMMODATION_PRICE_ID = "price_1Sboq08IwXvKSVJpf8RRSoCy"
@ -60,7 +50,7 @@ export async function POST(request: NextRequest) {
paymentMethodTypes = ["customer_balance"]
}
const session = await getStripe().checkout.sessions.create({
const session = await stripe.checkout.sessions.create({
payment_method_types: paymentMethodTypes,
line_items: lineItems,
mode: "payment",

View File

@ -1,26 +1,11 @@
import { type NextRequest, NextResponse } from "next/server"
import Stripe from "stripe"
// Lazy initialization to avoid build-time errors when env vars aren't set
let stripeInstance: Stripe | null = null
function getStripe(): Stripe {
if (!stripeInstance) {
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error("STRIPE_SECRET_KEY is not configured")
}
stripeInstance = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: "2024-12-18.acacia",
})
}
return stripeInstance
}
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
})
function getWebhookSecret(): string {
if (!process.env.STRIPE_WEBHOOK_SECRET) {
throw new Error("STRIPE_WEBHOOK_SECRET is not configured")
}
return process.env.STRIPE_WEBHOOK_SECRET
}
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!
export async function POST(request: NextRequest) {
try {
@ -30,7 +15,7 @@ export async function POST(request: NextRequest) {
let event: Stripe.Event
try {
event = getStripe().webhooks.constructEvent(body, signature, getWebhookSecret())
event = stripe.webhooks.constructEvent(body, signature, webhookSecret)
} catch (err) {
console.error("[v0] Webhook signature verification failed:", err)
return NextResponse.json({ error: "Invalid signature" }, { status: 400 })

115
app/gallery/page.tsx Normal file
View File

@ -0,0 +1,115 @@
import { Button } from "@/components/ui/button"
import { ArrowLeft } from "lucide-react"
import Link from "next/link"
export default function GalleryPage() {
const photos = [
{
src: "/images/20220429-145734.jpg",
alt: "Commons Hub venue with Austrian Alps mountains backdrop",
caption: "The Commons Hub nestled in the foothills of the Austrian Alps",
},
{
src: "/images/20220505-113225.jpg",
alt: "CCG 2022 group photo with all participants",
caption: "The CCG community gathered together in 2022",
},
{
src: "/images/20220830-104828.jpg",
alt: "Overhead view of unconference discussion circle",
caption: "Unconference discussion circles at CCG",
},
{
src: "/images/20220503-155430.jpg",
alt: "Ground-level view of discussion circle in courtyard",
caption: "Participant-driven sessions in the Commons Hub courtyard",
},
{
src: "/images/20220429-145359.jpg",
alt: "Yellow tulips at Hirschwangerhof venue",
caption: "Spring at the Hirschwangerhof venue",
},
{
src: "/images/image.jpeg",
alt: "Evening bonfire gathering",
caption: "Evening bonfire gathering with the community",
},
{
src: "/images/image.png",
alt: "Alpine wildflowers with mountain backdrop",
caption: "The natural beauty surrounding the venue",
},
{
src: "/images/image.jpeg",
alt: "Outdoor discussion session with mountain views",
caption: "Sessions in a circle with the Austrian Alps as backdrop",
},
{
src: "/images/image.png",
alt: "Hacking session with participants",
caption: "Hands-on building and prototyping sessions",
},
{
src: "/images/image.jpeg",
alt: "Community meal together",
caption: "Shared meals and convivial moments",
},
]
return (
<div className="min-h-screen">
{/* Header */}
<section className="py-16 px-4 bg-muted/30">
<div className="container mx-auto max-w-6xl">
<Button variant="ghost" className="mb-8" asChild>
<Link href="/">
<ArrowLeft className="w-4 h-4 mr-2" />
Back to Home
</Link>
</Button>
<h1 className="text-4xl md:text-5xl font-bold mb-4 text-balance">Gallery</h1>
<p className="text-lg text-muted-foreground max-w-2xl">
Explore moments from past Crypto Commons Gatherings - from unconference sessions in the Austrian Alps to
community building and lifelong friendships.
</p>
</div>
</section>
{/* Photo Grid */}
<section className="py-16 px-4">
<div className="container mx-auto max-w-7xl">
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
{photos.map((photo, index) => (
<div key={index} className="group relative overflow-hidden rounded-lg bg-card border border-border">
<div className="aspect-[4/3] overflow-hidden">
<img
src={photo.src || "/placeholder.svg"}
alt={photo.alt}
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/>
</div>
<div className="p-4">
<p className="text-sm text-muted-foreground">{photo.caption}</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-16 px-4 bg-muted/30">
<div className="container mx-auto max-w-3xl text-center">
<h2 className="text-3xl font-bold mb-4">Join Us in 2026</h2>
<p className="text-muted-foreground mb-8">
Be part of the next chapter of Crypto Commons Gathering and create new memories in the Austrian Alps.
</p>
<Button size="lg" asChild>
<Link href="/register">Register for CCG 2026</Link>
</Button>
</div>
</section>
</div>
)
}

View File

@ -79,6 +79,8 @@
@theme inline {
--font-sans: "Geist", "Geist Fallback";
--font-mono: "Geist Mono", "Geist Mono Fallback";
/* Added spray-paint font for graffiti-style text */
--font-spray: "Permanent Marker", "Permanent Marker Fallback", cursive;
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);

View File

@ -1,11 +1,12 @@
import type React from "react"
import type { Metadata } from "next"
import { Geist, Geist_Mono } from "next/font/google"
import { Geist, Geist_Mono, Permanent_Marker } from "next/font/google"
import { Analytics } from "@vercel/analytics/next"
import "./globals.css"
const _geist = Geist({ subsets: ["latin"] })
const _geistMono = Geist_Mono({ subsets: ["latin"] })
const _permanentMarker = Permanent_Marker({ weight: "400", subsets: ["latin"] })
export const metadata: Metadata = {
title: "Crypto Commons Gathering 2026 | CCG",

View File

@ -1,11 +1,55 @@
"use client"
import type React from "react"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { ArrowRight, Calendar, MapPin, Users, Heart, Sprout, Network } from "lucide-react"
import { ArrowRight, Calendar, MapPin, Users, Heart, Sprout, Network, X } from "lucide-react"
import Link from "next/link"
import { useState } from "react"
export default function HomePage() {
const [selectedImage, setSelectedImage] = useState<string | null>(null)
const handleImageClick = (imageSrc: string) => {
setSelectedImage(imageSrc)
}
const handleCloseModal = () => {
setSelectedImage(null)
}
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Escape") {
handleCloseModal()
}
}
return (
<div className="min-h-screen">
{selectedImage && (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/90 p-4"
onClick={handleCloseModal}
onKeyDown={handleKeyDown}
tabIndex={0}
>
<button
className="absolute top-4 right-4 text-white hover:text-white/70 transition-colors"
onClick={handleCloseModal}
aria-label="Close"
>
<X className="w-8 h-8" />
</button>
<img
src={selectedImage || "/placeholder.svg"}
alt="Zoomed view"
className="max-w-full max-h-[90vh] object-contain rounded-lg"
onClick={(e) => e.stopPropagation()}
/>
</div>
)}
{/* Hero Section */}
<section className="relative min-h-[90vh] flex items-center justify-center overflow-hidden">
<div
@ -17,7 +61,11 @@ export default function HomePage() {
<div className="absolute inset-0 bg-gradient-to-b from-background/80 via-background/70 to-background z-[1]" />
<div className="container mx-auto px-4 relative z-10 text-center max-w-5xl">
<h1 className="text-5xl md:text-7xl lg:text-8xl font-bold mb-6 text-balance leading-[1.1]">
<p className="text-xl md:text-2xl font-spray text-primary mb-2 tracking-wide animate-in fade-in slide-in-from-bottom-4 duration-700 [text-shadow:_2px_2px_0_rgb(0_0_0_/_10%)]">
Join the SIXTH edition of the
</p>
<h1 className="text-5xl md:text-7xl lg:text-8xl font-black mb-6 text-balance leading-[1.05] tracking-tight animate-in fade-in slide-in-from-bottom-6 duration-1000 [font-feature-settings:'ss01'] [text-shadow:_3px_3px_0_rgb(0_0_0_/_5%)]">
Crypto Commons
<br />
Gathering
@ -28,8 +76,8 @@ export default function HomePage() {
</div>
<p className="text-lg md:text-xl text-muted-foreground mb-8 max-w-2xl mx-auto text-pretty leading-relaxed">
A hack-ademic confluence of commons praxis and the latest cryptographic technologies, set in the foothills
of the Austrian Alps.
A week-long retreat where genuine desire for postcapitalist change meets blockchain tinkering, commons
building, and radical imagination in the Austrian Alps.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center mb-12">
@ -66,18 +114,35 @@ export default function HomePage() {
<section className="py-16 px-4 bg-background">
<div className="container mx-auto max-w-6xl">
<div className="grid md:grid-cols-3 gap-4">
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<div
className="aspect-[4/3] rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity"
onClick={() => handleImageClick("/images/20220901-085249.jpg")}
>
<img
src="/images/image.jpeg"
alt="CCG participants in discussion circle"
src="/images/20220901-085249.jpg"
alt="Wooden bridge in Reichenau an der Rax with Austrian Alps"
className="w-full h-full object-cover"
/>
</div>
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<img src="/images/image.jpeg" alt="Community meal at CCG" className="w-full h-full object-cover" />
<div
className="aspect-[4/3] rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity"
onClick={() => handleImageClick("/images/20220505-113225.jpg")}
>
<img
src="/images/20220505-113225.jpg"
alt="CCG 2022 community group photo in the Austrian Alps"
className="w-full h-full object-cover"
/>
</div>
<div className="aspect-[4/3] rounded-lg overflow-hidden">
<img src="/images/image.png" alt="Hands-on hacking at CCG" className="w-full h-full object-cover" />
<div
className="aspect-[4/3] rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity"
onClick={() => handleImageClick("/images/20220429-145734.jpg")}
>
<img
src="/images/20220429-145734.jpg"
alt="Commons Hub venue in the Austrian Alps"
className="w-full h-full object-cover"
/>
</div>
</div>
</div>
@ -88,21 +153,18 @@ export default function HomePage() {
<div className="container mx-auto max-w-6xl">
<div className="grid md:grid-cols-2 gap-12 items-center">
<div>
<h2 className="text-3xl md:text-4xl font-bold mb-6 text-balance">The Best Event in the World</h2>
<h2 className="text-3xl md:text-4xl font-bold mb-6 text-balance">What is CCG?</h2>
<p className="text-muted-foreground leading-relaxed mb-4">
Join us for an unconference-style gathering where you bring as much as you receive. Friendships are made
that last a lifetime, and solidarity is built that might just coalesce into new digital public
infrastructures.
The Crypto Commons Gathering (CCG) is an annual week-long retreat organised by the Crypto Commons
Association in collaboration with the Commons Hub. To its growing community, it serves as a recurring
temporary refuge from late-capitalism (or something worse) and as a convivium to reimagine how we
organize value, care and meaning for a "post-capitalist world of many worlds".
</p>
<p className="text-muted-foreground leading-relaxed mb-4">
CCG has spawned movements like <span className="text-primary font-semibold">#CoFi</span> and{" "}
<span className="text-primary font-semibold">#MycoFi</span>, and holds the possibility for a new
technologically-enabled commons that leverages network technologies to regain ground against state and
corporate control.
</p>
<p className="text-muted-foreground leading-relaxed">
What began in 2020 as a modest gathering has evolved into an annual moment of (re)connection and
reflection for a growing community of crypto-commons thinkers from around the world.
2026 marks the 6th edition of the CCG six years of bringing together commons builders, token
tinkerers, speculative worldbuilders, artists, complex systems thinkers, degens turned regen, and
everyone curious about the weird futures that emerge when crypto meets genuine international and
intersectional postcapitalist desire.
</p>
</div>
@ -148,33 +210,44 @@ export default function HomePage() {
{/* Themes Section */}
<section className="py-24 px-4">
<div className="container mx-auto max-w-5xl">
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-center text-balance">Explore Key Themes</h2>
<p className="text-muted-foreground text-center mb-12 max-w-2xl mx-auto">
Through participant-led sessions, we collectively explore the intersection of commoning, degrowth, and web3
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-center text-balance">Themes: What to Expect</h2>
<p className="text-muted-foreground text-center mb-12 max-w-3xl mx-auto leading-relaxed">
Talks, workshops, and spontaneous experiments at CCG cover a wide range of topics. They often start with a
curiosity in using blockchain, tokenization and decentralized governance for the common good, but rarely
stay there exclusively cooperative, non-crypto alternatives, open source projects, degrowth initiatives,
and other spheres increasingly cross-pollinate here under a decolonial, feminist, queer,
multispecies-attuned frame.
</p>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
{[
"Regenerative Finance",
"MycoFi",
"Community Currencies",
"Digital Commons",
"Crypto Commons",
"Open Source",
"Degrowth",
"Post-Capitalism",
"Ecofeminism",
"Multispecies Justice",
"Radical Game Design",
"Speculative Fiction",
].map((theme) => (
<div
key={theme}
className="p-4 bg-card border border-border rounded-lg hover:border-primary/40 transition-colors"
>
<p className="font-medium text-card-foreground">{theme}</p>
</div>
))}
<div className="grid sm:grid-cols-2 gap-6 mb-8">
<Card className="border-primary/20">
<CardContent className="p-6">
<h3 className="font-bold mb-3 text-lg">Regenerative & Collaborative Finance</h3>
<p className="text-sm text-muted-foreground">
ReFi DAO, EthicHub, CoFi Gathering, Regen Network, Circles UBI
</p>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<h3 className="font-bold mb-3 text-lg">Myco-Economics</h3>
<p className="text-sm text-muted-foreground">MycoFi and interconnected economic models</p>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<h3 className="font-bold mb-3 text-lg">Governance & Mutualism</h3>
<p className="text-sm text-muted-foreground">Economic Space Agency, Bread Coop, Holochain</p>
</CardContent>
</Card>
<Card className="border-primary/20">
<CardContent className="p-6">
<h3 className="font-bold mb-3 text-lg">Solarpunk & Radical Games</h3>
<p className="text-sm text-muted-foreground">
pocas, Solar Punk WOW, Futurescraft, economic science fiction
</p>
</CardContent>
</Card>
</div>
</div>
</section>
@ -190,21 +263,16 @@ export default function HomePage() {
<div className="absolute inset-0 bg-primary/90" />
<div className="container mx-auto max-w-4xl text-center relative z-10">
<h2 className="text-3xl md:text-4xl font-bold mb-6 text-balance text-primary-foreground">
What is an Unconference?
Format: How We Explore
</h2>
<p className="text-lg leading-relaxed opacity-90 mb-8 text-primary-foreground">
An unconference is a participant-driven event format that emphasizes open, flexible, and spontaneous
discussions rather than traditional pre-planned presentations. Unlike conventional conferences,
unconferences have no predefined agenda or speakers.
</p>
<p className="leading-relaxed opacity-90 mb-8 text-primary-foreground">
Attendees collaboratively propose topics, sessions, and activities on the spot. Participants vote or
self-organize around topics they find most interesting, forming small groups or breakout sessions where
discussions, workshops, or hands-on activities take place.
CCG follows an open space or "unconference" format. This means the schedule is co-created on-site by all
participants: during the daily morning circle, anyone can propose a session, host a discussion, or start a
collective experiment, and schedule it at one of five sites across the Hub, each with its own affordances.
</p>
<p className="leading-relaxed opacity-90 text-primary-foreground">
Everyone is considered equally qualified to contribute, share insights, and guide conversations. Bring your
ideas for talks, roundtables, workshops, prototyping sessions, board game nights, LARPs, and more.
Workshops, keynotes, rituals, games and evening performances traditionally unfold organically, reflecting
the shared interests, dynamics and projects that emerge over the week.
</p>
</div>
</section>
@ -216,7 +284,7 @@ export default function HomePage() {
<div className="order-2 md:order-1">
<div className="aspect-[4/3] bg-muted rounded-lg overflow-hidden">
<img
src="/austrian-alps-foothills-mountain-landscape-with-tr.jpg"
src="/images/20220429-145734.jpg"
alt="Commons Hub in the Austrian Alps"
className="w-full h-full object-cover"
/>
@ -280,7 +348,6 @@ export default function HomePage() {
<Link href="/transparency">Financial Transparency</Link>
</Button>
</div>
<p className="text-sm text-muted-foreground">
Interested in the Crypto Commons Association cooperative? Learn more at the event.
</p>
@ -304,10 +371,12 @@ export default function HomePage() {
<h3 className="font-semibold mb-4 text-sm">Links</h3>
<ul className="space-y-2 text-sm">
<li>
<Link
href="https://ccg2025.vercel.app/about"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Link href="/gallery" className="text-muted-foreground hover:text-foreground transition-colors">
Gallery
</Link>
</li>
<li>
<Link href="/about" className="text-muted-foreground hover:text-foreground transition-colors">
About CCG 2026
</Link>
</li>
@ -372,7 +441,7 @@ export default function HomePage() {
</div>
<div className="pt-8 border-t border-border text-center text-sm text-muted-foreground">
<p>© 2026 Crypto Commons Gathering. Built with solidarity for the commons.</p>
<p>This website is under Creative Commons license. Built with solidarity for the commons.</p>
</div>
</div>
</footer>

View File

@ -29,9 +29,9 @@ export default function RegisterPage() {
food: false,
})
const baseTicketPrice = 200
const accommodationPrice = 227.4
const foodPrice = 135
const baseTicketPrice = 80 // Updated to early bird price €80
const accommodationPrice = 39.2 * 6 // Updated to €39.20/night * 6 nights = €235.20
const foodPrice = 35 * 3 + 10 * 3 // Updated to reflect catered (€35*3) + self-organized (€10*3) = €135
const calculateTotal = () => {
let total = baseTicketPrice
if (packages.accommodation) total += accommodationPrice
@ -83,7 +83,9 @@ export default function RegisterPage() {
<Card className="mb-8 border-primary/40">
<CardHeader>
<CardTitle>Select Your Packages</CardTitle>
<CardDescription>Ticket is required. Add accommodation and food as needed.</CardDescription>
<CardDescription>
Ticket is required (80 early bird until Dec 31, 2025). Add accommodation and food as needed.
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
@ -93,10 +95,16 @@ export default function RegisterPage() {
<Checkbox checked disabled className="mt-1" />
<div>
<div className="font-medium">CCG 2026 Ticket (Required)</div>
<div className="text-sm text-muted-foreground">Venue rental & infrastructure</div>
<div className="text-sm text-muted-foreground">
80 Early bird (until Dec 31, 2025) 120 Regular (Jan-Jun 2026) 150 Late (after Jul 1,
2026)
</div>
<div className="text-xs text-muted-foreground mt-1">
CCA members: Bring two newcomers, get a free ticket!
</div>
</div>
</div>
<span className="text-lg font-semibold">200.00</span>
<span className="text-lg font-semibold">{baseTicketPrice}.00</span>
</div>
{/* Accommodation */}
@ -110,10 +118,13 @@ export default function RegisterPage() {
/>
<Label htmlFor="accommodation" className="cursor-pointer">
<div className="font-medium">Accommodation (Optional)</div>
<div className="text-sm text-muted-foreground">6 nights dorm at Commons Hub (37.90/night)</div>
<div className="text-sm text-muted-foreground">6 nights dorm at Commons Hub (39.20/night)</div>
<div className="text-xs text-muted-foreground mt-1">
Double rooms available at 50.20/night per person
</div>
</Label>
</div>
<span className="text-lg font-semibold">227.40</span>
<span className="text-lg font-semibold">{accommodationPrice.toFixed(2)}</span>
</div>
{/* Food */}
@ -127,10 +138,13 @@ export default function RegisterPage() {
/>
<Label htmlFor="food" className="cursor-pointer">
<div className="font-medium">Food Package (Optional)</div>
<div className="text-sm text-muted-foreground">6 days of meals (22.50/day avg)</div>
<div className="text-sm text-muted-foreground">6 days: vegetarian breakfast, lunch & dinner</div>
<div className="text-xs text-muted-foreground mt-1">
3 days catered (35/day), 3 days self-organized (10/day)
</div>
</Label>
</div>
<span className="text-lg font-semibold">135.00</span>
<span className="text-lg font-semibold">{foodPrice.toFixed(2)}</span>
</div>
{/* Total */}

View File

@ -40,18 +40,45 @@ export default function FinancialTransparencyPage() {
{/* Ticket Price */}
<Card className="mb-8">
<CardHeader>
<CardTitle className="text-2xl">Ticket Price</CardTitle>
<CardTitle className="text-2xl">Ticket Pricing</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-baseline gap-4">
<span className="text-4xl font-bold text-primary">200</span>
<span className="text-muted-foreground">per person</span>
<div className="space-y-4 mb-6">
<div className="flex items-baseline justify-between border-b pb-3">
<div>
<span className="text-3xl font-bold text-primary">80</span>
<span className="text-sm text-muted-foreground ml-3">Early bird</span>
</div>
<span className="text-sm text-muted-foreground">Until Dec 31, 2025</span>
</div>
<div className="flex items-baseline justify-between border-b pb-3">
<div>
<span className="text-3xl font-bold">120</span>
<span className="text-sm text-muted-foreground ml-3">Regular</span>
</div>
<span className="text-sm text-muted-foreground">Jan 1 Jun 30, 2026</span>
</div>
<div className="flex items-baseline justify-between pb-3">
<div>
<span className="text-3xl font-bold">150</span>
<span className="text-sm text-muted-foreground ml-3">Late</span>
</div>
<span className="text-sm text-muted-foreground">After Jul 1, 2026</span>
</div>
</div>
<div className="bg-accent/20 border border-accent p-4 rounded-lg">
<p className="font-semibold mb-2">CCA Members Special:</p>
<p className="text-sm text-muted-foreground">
Bring two newcomers (who've never attended CCG before) and get a free ticket! If you've already paid,
we'll refund you.
</p>
</div>
<p className="text-muted-foreground leading-relaxed">
The ticket price is set to cover the venue rental and basic infrastructure, based on expected
attendance. No one from the organizing team is being paid from ticket sales, and all are covering their
own travel, food and accommodation, until more sustainable structures and future sponsorships are in
place.
The ticket price covers venue rental and basic infrastructure. No one from the organizing team is being
paid from ticket sales, and all are covering their own travel, food and accommodation, until more
sustainable structures and future sponsorships are in place.
</p>
<div className="pt-4">
<Button asChild>
@ -68,19 +95,41 @@ export default function FinancialTransparencyPage() {
</CardHeader>
<CardContent className="space-y-4">
<p className="text-sm text-muted-foreground mb-4">
Note that accommodation is not included in the ticket price. These are provided by the Commons Hub:
The Commons Hub offers 30 beds on-site. Accommodation is not included in the ticket price:
</p>
<div className="bg-muted/50 p-6 rounded-lg">
<div className="flex items-baseline gap-3 mb-2">
<span className="text-3xl font-bold">37.90</span>
<span className="text-muted-foreground">per night</span>
<div className="space-y-3">
<div className="bg-muted/50 p-6 rounded-lg">
<div className="flex items-baseline gap-3 mb-2">
<span className="text-3xl font-bold">39.20</span>
<span className="text-muted-foreground">per night</span>
</div>
<p className="text-sm text-muted-foreground">26 beds in dorms</p>
</div>
<div className="bg-muted/50 p-6 rounded-lg">
<div className="flex items-baseline gap-3 mb-2">
<span className="text-3xl font-bold">50.20</span>
<span className="text-muted-foreground">per night per person</span>
</div>
<p className="text-sm text-muted-foreground">4 beds in double rooms</p>
</div>
<p className="text-sm text-muted-foreground">Dorm accommodation</p>
</div>
<p className="text-muted-foreground leading-relaxed">
Accommodation includes shared dormitory-style rooms with basic amenities. Bedding and towels are
provided.
</p>
<div className="pt-4">
<h4 className="font-semibold mb-3">Additional accommodation nearby:</h4>
<ul className="space-y-2 text-sm text-muted-foreground">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary mt-0.5 flex-shrink-0" />
<span>
<strong>Herrnhof.at</strong> comfortable apartments, ideal for teams
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-4 h-4 text-primary mt-0.5 flex-shrink-0" />
<span>
<strong>Gasthof Kobald</strong> simple rooms, affordable, 12 min walk from the hub
</span>
</li>
</ul>
</div>
</CardContent>
</Card>
@ -91,39 +140,55 @@ export default function FinancialTransparencyPage() {
</CardHeader>
<CardContent className="space-y-4">
<p className="text-sm text-muted-foreground mb-4">
Food is also not included in the ticket price and is provided by the Commons Hub:
Food is not included in the ticket price and is provided by the Commons Hub:
</p>
<div className="bg-muted/50 p-6 rounded-lg mb-4">
<div className="flex items-baseline gap-3 mb-2">
<span className="text-3xl font-bold">22.50</span>
<span className="text-muted-foreground">per day average</span>
</div>
</div>
<div className="space-y-4">
<div>
<h4 className="font-semibold mb-2">Breakdown:</h4>
<div className="bg-muted/50 p-6 rounded-lg">
<h4 className="font-semibold mb-3">What's Included:</h4>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5 flex-shrink-0" />
<span className="text-muted-foreground">
<strong>First 3 days:</strong> fully catered at 35/day
</span>
<span className="text-sm">A rich vegetarian breakfast buffet</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5 flex-shrink-0" />
<span className="text-muted-foreground">
<strong>Last 3 days:</strong> self-organized by participants and the Crypto Commons Association
at ~10/day
<span className="text-sm">Coffee & tea throughout the day</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5 flex-shrink-0" />
<span className="text-sm">Catered lunches (vegetarian/vegan and meat-based options)</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5 flex-shrink-0" />
<span className="text-sm">Catered dinners from Aug 17-21</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-primary mt-0.5 flex-shrink-0" />
<span className="text-sm">
Self-made dinners on Aug 16 & 22, prepared by community kitchen team
</span>
</li>
</ul>
</div>
<p className="text-muted-foreground leading-relaxed">
Meals include breakfast, lunch, and dinner with vegetarian and vegan options available. The
self-organized days involve communal cooking and shared meal preparation.
</p>
<div className="bg-muted/50 p-6 rounded-lg">
<h4 className="font-semibold mb-2">Estimated Cost:</h4>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-muted-foreground">First 3 days (fully catered)</span>
<span className="font-semibold">35/day</span>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Last 3 days (self-organized)</span>
<span className="font-semibold">~10/day</span>
</div>
<div className="flex justify-between pt-2 border-t">
<span className="font-semibold">Total for 6 days</span>
<span className="font-bold text-lg">135</span>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
@ -135,31 +200,31 @@ export default function FinancialTransparencyPage() {
</CardHeader>
<CardContent className="space-y-4">
<p className="text-muted-foreground mb-6">
For the full 6-day event (August 16-22, 2026), here's what you can expect to pay:
For the full event (August 16-22, 2026), here's what you can expect to pay with early bird pricing:
</p>
<div className="space-y-3">
<div className="flex justify-between items-center py-3 border-b border-border">
<span className="font-medium">Ticket</span>
<span className="text-lg font-semibold">200</span>
<span className="font-medium">Ticket (Early bird)</span>
<span className="text-lg font-semibold">80</span>
</div>
<div className="flex justify-between items-center py-3 border-b border-border">
<span className="font-medium">Accommodation (6 nights)</span>
<span className="text-lg font-semibold">227.40</span>
<span className="font-medium">Accommodation (6 nights, dorm)</span>
<span className="text-lg font-semibold">235.20</span>
</div>
<div className="flex justify-between items-center py-3 border-b border-border">
<span className="font-medium">Food (6 days)</span>
<span className="text-lg font-semibold">135</span>
</div>
<div className="flex justify-between items-center py-4 bg-primary/10 -mx-6 px-6 mt-4">
<span className="font-bold text-lg">Total</span>
<span className="text-2xl font-bold text-primary">562.40</span>
<span className="font-bold text-lg">Total (Early bird)</span>
<span className="text-2xl font-bold text-primary">450.20</span>
</div>
</div>
<p className="text-sm text-muted-foreground italic pt-4">
*This is an estimate. Final costs may vary slightly based on actual meal arrangements and accommodation
choices.
*With regular pricing (120 ticket), total would be 490.20. With late pricing (150 ticket), total
would be 520.20.
</p>
</CardContent>
</Card>

View File

@ -1,21 +0,0 @@
services:
ccg-website:
build: .
container_name: ccg-website
restart: unless-stopped
environment:
- NODE_ENV=production
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
- NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
labels:
- "traefik.enable=true"
- "traefik.http.routers.ccg.rule=Host(`cryptocommonsgather.ing`) || Host(`www.cryptocommonsgather.ing`)"
- "traefik.http.routers.ccg.entrypoints=web,websecure"
- "traefik.http.services.ccg.loadbalancer.server.port=3000"
networks:
- traefik-public
networks:
traefik-public:
external: true

View File

@ -1,12 +1,12 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
typescript: {
ignoreBuildErrors: true,
},
images: {
unoptimized: true,
},
}
export default nextConfig
export default nextConfig

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 KiB

After

Width:  |  Height:  |  Size: 580 KiB