feat: Add presentations page with shareable anchor links, new research images

- Add /presentations page with all 11 talks from canvas-website
- Each title is a clickable #hash anchor that copies shareable URL
- Auto-scrolls to hash target on page load
- Styled to match home page: cursor effect, animated blobs, tags, glass cards
- Replace 6 generic AI stock images with custom dark-theme illustrations
  matching the site's purple/teal color palette
- Add Presentations nav button to hero section
- Add sonner Toaster for copy-link toast notifications

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-02-12 22:10:02 -07:00
parent 874257a29b
commit ab7bd076de
10 changed files with 275 additions and 6 deletions

View File

@ -2,6 +2,7 @@ import type React from "react"
import type { Metadata } from "next" import type { Metadata } from "next"
import { Inter, Space_Mono } from "next/font/google" import { Inter, Space_Mono } from "next/font/google"
import { Analytics } from "@vercel/analytics/next" import { Analytics } from "@vercel/analytics/next"
import { Toaster } from "sonner"
import "./globals.css" import "./globals.css"
const inter = Inter({ const inter = Inter({
@ -48,6 +49,7 @@ export default function RootLayout({
<html lang="en"> <html lang="en">
<body className={`${inter.variable} ${spaceMono.variable} font-sans antialiased`}> <body className={`${inter.variable} ${spaceMono.variable} font-sans antialiased`}>
{children} {children}
<Toaster richColors position="bottom-center" />
<Analytics /> <Analytics />
</body> </body>
</html> </html>

261
app/presentations/page.tsx Normal file
View File

@ -0,0 +1,261 @@
"use client"
import { useEffect } from "react"
import { Link2, ExternalLink, ArrowLeft } from "lucide-react"
import { Card } from "@/components/ui/card"
import { CursorEffect } from "@/components/cursor-effect"
import { toast } from "sonner"
const presentations = [
{
id: "osmotic-governance",
title: "Osmotic Governance",
description: "Exploring the intersection of mycelium and emancipatory technologies",
embedUrl: "https://online.fliphtml5.com/phqos/xfym/",
venue: "Team Human with Douglas Rushkoff",
videoUrl: "https://www.teamhuman.fm/episodes/238-jeff-emmett",
videoLabel: "Listen to the full episode",
tags: ["Mycelium", "Governance", "Emancipatory Tech"],
},
{
id: "exploring-mycofi",
title: "Exploring MycoFi",
description: "Mycelial design patterns for Web3 and beyond",
embedUrl: "https://online.fliphtml5.com/phqos/bqra/",
venue: "DevCon 7 in Bangkok",
videoUrl: "https://www.youtube.com/watch?v=0A4jXL5eBaI",
videoLabel: "Watch the full talk",
tags: ["MycoFi", "Web3", "Biomimicry"],
},
{
id: "mycofi-cofi-gathering",
title: "MycoFi talk at CoFi Gathering",
description: "Mycelial design patterns for Web3 and beyond",
embedUrl: "https://online.fliphtml5.com/phqos/vwmt/",
venue: "Greenpill Network",
videoUrl: "https://www.youtube.com/watch?v=AFJFDajuCSg",
videoLabel: "Watch the full talk",
tags: ["MycoFi", "Greenpill", "CoFi"],
},
{
id: "myco-mutualism",
title: "Myco-Mutualism",
description: "Exploring mutualistic relationships in mycelial networks and their applications to human systems",
embedUrl: "https://online.fliphtml5.com/phqos/caal/",
venue: "The Mutualist Society",
tags: ["Mutualism", "Mycelium", "Systems Design"],
},
{
id: "psilocybernetics",
title: "Psilocybernetics: The Emergence of Institutional Neuroplasticity",
description: "Exploring the intersection of mycelium and cybernetic institutional design",
embedUrl: "https://online.fliphtml5.com/phqos/pnlz/",
venue: "General Forum for Ethereum Localism",
tags: ["Cybernetics", "Institutions", "Neuroplasticity"],
},
{
id: "move-slow-fix-things",
title: "Move Slow & Fix Things: The Commons Stack Design Pattern",
description: "Design patterns for sustainable commons infrastructure",
embedUrl: "https://online.fliphtml5.com/phqos/bnnf/",
venue: "ReFi Unconf @ the Commons Hub Austria",
videoUrl: "https://www.youtube.com/live/i8qcg7FfpLM?si=onLcl8q5rz7cMViO&t=1362",
videoLabel: "Watch the full talk",
tags: ["Commons Stack", "ReFi", "Design Patterns"],
},
{
id: "commons-stack-launch",
title: "Commons Stack Launch & Open Sourcing cadCAD",
description: "The launch of Commons Stack and the open sourcing of cadCAD for token engineering",
embedUrl: "https://online.fliphtml5.com/phqos/hxac/",
venue: "Token Engineering Global Gathering (TEGG)",
videoUrl: "https://youtu.be/qjdjX2m_p0Q?si=r2AXVnVyzCIxIOSc&t=20",
videoLabel: "Watch the full talk",
tags: ["Commons Stack", "cadCAD", "Token Engineering"],
},
{
id: "conviction-voting",
title: "New Tools for Dynamic Collective Intelligence: Conviction Voting & Variations",
description: "Exploring innovative voting mechanisms for collective decision-making in decentralized systems",
embedUrl: "https://online.fliphtml5.com/phqos/fhos/",
venue: "Conviction Voting Presentation",
tags: ["Conviction Voting", "Governance", "Collective Intelligence"],
},
{
id: "polycentric-governance",
title: "Exploring Polycentric Governance in Web3 Ecosystems",
description: "Understanding multi-level governance structures in decentralized networks",
embedUrl: "https://online.fliphtml5.com/phqos/zzoy/",
venue: "OpenWeb Hackathon",
videoUrl: "https://youtu.be/ZIWskNogafg?si=DmUbOQJaSRE1rdzq",
videoLabel: "Watch the full talk",
tags: ["Polycentric Governance", "Web3", "Ostrom"],
},
{
id: "mycofi-myco-munnities",
title: "MycoFi for Myco-munnities",
description: "Exploring mycelial financial systems for community-based organizations",
embedUrl: "https://online.fliphtml5.com/phqos/xoea/",
venue: "CoFi Gathering in Liege",
tags: ["MycoFi", "Community Finance", "CoFi"],
},
{
id: "community-resilience",
title: "Building Community Resilience in an Age of Crisis",
description: "Internet outages during crises can disrupt communication, education, and access to vital information. Preparing for such disruptions is essential for communities operating in challenging environments.",
embedUrl: "https://online.fliphtml5.com/phqos/afbp/",
venue: "re:publica conference, May 2025",
videoUrl: "https://www.youtube.com/watch?v=rTOLk7k9Ad8",
videoLabel: "Watch the full talk",
tags: ["Resilience", "Crisis Response", "Community Networks"],
},
]
function copyLink(id: string) {
const url = `${window.location.origin}/presentations#${id}`
navigator.clipboard.writeText(url).then(() => {
toast.success("Link copied to clipboard")
})
}
export default function PresentationsPage() {
useEffect(() => {
if (window.location.hash) {
const id = window.location.hash.slice(1)
const el = document.getElementById(id)
if (el) {
setTimeout(() => {
el.scrollIntoView({ behavior: "smooth", block: "start" })
}, 100)
}
}
}, [])
return (
<>
<CursorEffect />
<main className="relative min-h-screen bg-background text-foreground">
{/* Animated background blobs */}
<div className="fixed inset-0 overflow-hidden opacity-15 pointer-events-none">
<div className="absolute top-1/4 left-1/3 h-[500px] w-[500px] rounded-full bg-primary blur-[150px] animate-float" />
<div
className="absolute bottom-1/3 right-1/4 h-[400px] w-[400px] rounded-full bg-accent blur-[150px]"
style={{ animationDelay: "3s" }}
/>
</div>
{/* Header */}
<div className="relative z-10 border-b border-border/50 bg-background/80 backdrop-blur-sm">
<div className="max-w-5xl mx-auto px-6 py-4 flex items-center justify-between">
<a
href="/"
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors"
>
<ArrowLeft className="h-4 w-4" />
Jeff Emmett
</a>
<span className="text-sm font-mono text-muted-foreground border border-border px-3 py-1 rounded-full">
{"{ Presentations }"}
</span>
</div>
</div>
{/* Hero */}
<div className="relative z-10 max-w-5xl mx-auto px-6 pt-20 pb-16">
<h1 className="text-5xl md:text-6xl font-bold mb-6">Presentations</h1>
<p className="text-xl text-muted-foreground max-w-2xl text-balance leading-relaxed">
Research into the intersection of mycelium networks, emancipatory technologies,
and convivial tooling. Designing systems that support collective action and
community self-organization.
</p>
</div>
{/* Presentations grid */}
<div className="relative z-10 max-w-5xl mx-auto px-6 pb-32">
<div className="space-y-10">
{presentations.map((p) => (
<Card
key={p.id}
id={p.id}
className="group/card overflow-hidden bg-card/80 backdrop-blur-sm border-border hover:border-primary/50 transition-all duration-300 scroll-mt-24"
>
<div className="p-6 pb-4">
<h2 className="text-2xl font-semibold group-hover/card:text-primary transition-colors">
<a
href={`#${p.id}`}
onClick={(e) => {
e.preventDefault()
window.history.replaceState(null, "", `#${p.id}`)
document.getElementById(p.id)?.scrollIntoView({ behavior: "smooth", block: "start" })
copyLink(p.id)
}}
className="group/link inline-flex items-start gap-2"
>
<span>{p.title}</span>
<Link2 className="h-5 w-5 mt-1 opacity-0 group-hover/link:opacity-100 text-muted-foreground transition-opacity shrink-0" />
</a>
</h2>
<p className="text-muted-foreground mt-2 leading-relaxed">{p.description}</p>
{p.tags && (
<div className="flex flex-wrap gap-2 mt-3">
{p.tags.map((tag, i) => (
<span
key={i}
className="text-xs font-mono px-3 py-1 bg-secondary text-secondary-foreground rounded-full"
>
{tag}
</span>
))}
</div>
)}
</div>
<div className="px-6 pb-4">
<div className="rounded-lg overflow-hidden border border-border/50">
<div style={{ position: "relative", paddingTop: "max(60%, 324px)", width: "100%", height: 0 }}>
<iframe
style={{ position: "absolute", border: "none", width: "100%", height: "100%", left: 0, top: 0 }}
src={p.embedUrl}
seamless
scrolling="no"
frameBorder="0"
allowTransparency
allowFullScreen
title={p.title}
/>
</div>
</div>
</div>
<div className="px-6 pb-6 flex flex-wrap items-center justify-between gap-3 border-t border-border/30 pt-4 mx-6">
<span className="text-sm text-muted-foreground italic font-mono">{p.venue}</span>
{p.videoUrl ? (
<a
href={p.videoUrl}
target="_blank"
rel="noopener noreferrer"
className="group/ext inline-flex items-center gap-1.5 text-sm font-medium px-4 py-2 bg-secondary text-secondary-foreground rounded-lg transition-all hover:scale-105 hover:bg-primary hover:text-primary-foreground"
>
{p.videoLabel} <ExternalLink className="h-3.5 w-3.5" />
</a>
) : (
<span className="text-sm text-muted-foreground">Video coming soon</span>
)}
</div>
</Card>
))}
</div>
</div>
{/* Footer */}
<div className="relative z-10 border-t border-border py-8 bg-card/30">
<div className="max-w-5xl mx-auto px-6 text-center">
<p className="text-muted-foreground font-mono text-sm">
© 2025 Jeff Emmett. Built with Next.js & TailwindCSS
</p>
</div>
</div>
</main>
</>
)
}

View File

@ -62,6 +62,12 @@ export function HeroSection() {
<span className="relative z-10">View Research</span> <span className="relative z-10">View Research</span>
<div className="absolute inset-0 bg-accent opacity-0 group-hover:opacity-100 transition-opacity" /> <div className="absolute inset-0 bg-accent opacity-0 group-hover:opacity-100 transition-opacity" />
</a> </a>
<a
href="/presentations"
className="px-8 py-4 bg-secondary text-secondary-foreground rounded-lg font-medium transition-all hover:scale-105 hover:bg-secondary/80"
>
Presentations
</a>
<a <a
href="#contact" href="#contact"
className="px-8 py-4 bg-secondary text-secondary-foreground rounded-lg font-medium transition-all hover:scale-105 hover:bg-secondary/80" className="px-8 py-4 bg-secondary text-secondary-foreground rounded-lg font-medium transition-all hover:scale-105 hover:bg-secondary/80"

View File

@ -6,42 +6,42 @@ const projects = [
description: description:
"Cyber-physical commons architecture translating Ostrom's principles into DAO templates. Building open-source, token engineered component libraries for communal management of public goods.", "Cyber-physical commons architecture translating Ostrom's principles into DAO templates. Building open-source, token engineered component libraries for communal management of public goods.",
tags: ["Token Engineering", "DAOs", "Ostrom Compliance", "Public Goods"], tags: ["Token Engineering", "DAOs", "Ostrom Compliance", "Public Goods"],
image: "/commons-stack-dao-governance-blockchain.jpg", image: "/commons-stack.png",
}, },
{ {
title: "Bonding Curve Research Group", title: "Bonding Curve Research Group",
description: description:
"Research and development of Primary Issuance Markets enabling dynamic token supply. Challenging fixed supply paradigms with adaptive mechanisms that dampen volatility.", "Research and development of Primary Issuance Markets enabling dynamic token supply. Challenging fixed supply paradigms with adaptive mechanisms that dampen volatility.",
tags: ["Bonding Curves", "cadCAD", "Token Economics", "DeFi"], tags: ["Bonding Curves", "cadCAD", "Token Economics", "DeFi"],
image: "/bonding-curve-token-economics-chart.jpg", image: "/bonding-curves.png",
}, },
{ {
title: "MycoFi & Mycoeconomics", title: "MycoFi & Mycoeconomics",
description: description:
"Economic systems inspired by fungal networks. Regenerative protocols built on cooperation, mutual aid, and permaculture currency principles. Author of book.mycofi.earth.", "Economic systems inspired by fungal networks. Regenerative protocols built on cooperation, mutual aid, and permaculture currency principles. Author of book.mycofi.earth.",
tags: ["Regenerative Economics", "Biomimicry", "Permaculture", "Web3"], tags: ["Regenerative Economics", "Biomimicry", "Permaculture", "Web3"],
image: "/mycelium-network-nature-fungal.jpg", image: "/mycofi-mycelium.png",
}, },
{ {
title: "Conviction Voting", title: "Conviction Voting",
description: description:
"Novel continuous decision-making mechanism for DAO governance. Eliminates time-boxed voting attack vectors while increasing community participation and long-term alignment.", "Novel continuous decision-making mechanism for DAO governance. Eliminates time-boxed voting attack vectors while increasing community participation and long-term alignment.",
tags: ["Governance", "Voting Systems", "Social Sensor Fusion", "cadCAD"], tags: ["Governance", "Voting Systems", "Social Sensor Fusion", "cadCAD"],
image: "/conviction-voting-governance-dashboard.jpg", image: "/conviction-voting.png",
}, },
{ {
title: "Augmented Bonding Curves", title: "Augmented Bonding Curves",
description: description:
"Primary Issuance Markets that create economic boundaries for commons ecosystems. Enables continuous fundraising, algorithmic liquidity, and price volatility dampening.", "Primary Issuance Markets that create economic boundaries for commons ecosystems. Enables continuous fundraising, algorithmic liquidity, and price volatility dampening.",
tags: ["Token Design", "AMMs", "Cryptoeconomics", "Funding Mechanisms"], tags: ["Token Design", "AMMs", "Cryptoeconomics", "Funding Mechanisms"],
image: "/augmented-bonding-curve-economic-system.jpg", image: "/augmented-bonding-curve.png",
}, },
{ {
title: "Token Engineering Commons", title: "Token Engineering Commons",
description: description:
"First field test of Commons Stack components. Outperformed other public goods tokens in risk-adjusted returns, demonstrating benefits of primary issuance markets.", "First field test of Commons Stack components. Outperformed other public goods tokens in risk-adjusted returns, demonstrating benefits of primary issuance markets.",
tags: ["DAO", "TEC", "Token Engineering", "Community Governance"], tags: ["DAO", "TEC", "Token Engineering", "Community Governance"],
image: "/token-engineering-community-collaborative.jpg", image: "/token-engineering-commons.png",
}, },
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

BIN
public/bonding-curves.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

BIN
public/commons-stack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 KiB

BIN
public/mycofi-mycelium.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB