feat: Minimal mycelial redesign

- Dark earthy palette
- Simple single-page layout
- Just name, typing effect, and real links
- No fabricated content
- Removed custom cursor

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-27 01:51:46 -05:00
parent c78739974e
commit e545359df0
7 changed files with 96 additions and 466 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.next/
node_modules/

View File

@ -4,37 +4,30 @@
@custom-variant dark (&:is(.dark *));
:root {
/* Blueprint color palette - warm cream paper with blue ink */
--background: oklch(0.97 0.01 85);
--foreground: oklch(0.25 0.02 250);
--card: oklch(0.95 0.015 85);
--card-foreground: oklch(0.25 0.02 250);
--popover: oklch(0.96 0.01 85);
--popover-foreground: oklch(0.25 0.02 250);
--primary: oklch(0.45 0.15 250);
--primary-foreground: oklch(0.98 0.01 85);
--secondary: oklch(0.92 0.02 85);
--secondary-foreground: oklch(0.35 0.08 250);
--muted: oklch(0.90 0.015 85);
--muted-foreground: oklch(0.45 0.04 250);
--accent: oklch(0.55 0.12 30);
--accent-foreground: oklch(0.98 0.01 85);
--destructive: oklch(0.55 0.2 25);
--destructive-foreground: oklch(0.98 0.01 85);
--border: oklch(0.75 0.06 250);
--input: oklch(0.92 0.02 85);
--ring: oklch(0.45 0.15 250);
--radius: 0.125rem;
/* Blueprint specific */
--grid-color: oklch(0.75 0.08 250 / 0.3);
--sketch-color: oklch(0.35 0.12 250);
--annotation-color: oklch(0.50 0.15 30);
/* Mycelial palette - dark earth, organic warmth */
--background: oklch(0.12 0.02 60);
--foreground: oklch(0.88 0.03 80);
--card: oklch(0.15 0.02 60);
--card-foreground: oklch(0.88 0.03 80);
--popover: oklch(0.14 0.02 60);
--popover-foreground: oklch(0.88 0.03 80);
--primary: oklch(0.72 0.12 85);
--primary-foreground: oklch(0.12 0.02 60);
--secondary: oklch(0.18 0.02 60);
--secondary-foreground: oklch(0.75 0.04 80);
--muted: oklch(0.22 0.02 60);
--muted-foreground: oklch(0.55 0.03 80);
--accent: oklch(0.65 0.10 140);
--accent-foreground: oklch(0.12 0.02 60);
--border: oklch(0.28 0.03 60);
--input: oklch(0.18 0.02 60);
--ring: oklch(0.72 0.12 85);
--radius: 0px;
}
@theme inline {
--font-sans: "Inter", "Helvetica Neue", system-ui, sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;
--font-sans: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", monospace;
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
@ -49,30 +42,22 @@
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--radius-sm: calc(var(--radius) - 1px);
--radius-md: var(--radius);
--radius-lg: calc(var(--radius) + 2px);
--radius-sm: 0;
--radius-md: 0;
--radius-lg: 0;
}
@layer base {
* {
@apply border-border outline-ring/50;
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-family: var(--font-sans);
/* Blueprint grid paper background */
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 24px 24px;
background-position: -1px -1px;
}
html {
@ -80,221 +65,33 @@
}
::selection {
background: oklch(0.45 0.15 250 / 0.25);
color: oklch(0.20 0.02 250);
background: oklch(0.72 0.12 85 / 0.3);
}
}
/* Sketch/hand-drawn border effect */
.sketch-border {
position: relative;
border: 2px solid var(--sketch-color);
border-radius: 2px;
/* Simple link style */
a {
color: var(--primary);
text-decoration: none;
transition: opacity 0.15s;
}
.sketch-border::before {
content: "";
position: absolute;
inset: -3px;
border: 1px solid var(--sketch-color);
border-radius: 3px;
opacity: 0.3;
pointer-events: none;
a:hover {
opacity: 0.7;
}
/* Blueprint card styling */
.blueprint-card {
background: oklch(0.96 0.01 85 / 0.9);
border: 1.5px solid var(--sketch-color);
border-radius: 2px;
box-shadow:
3px 3px 0 oklch(0.45 0.15 250 / 0.1),
inset 0 0 0 1px oklch(0.45 0.15 250 / 0.05);
/* Fade in */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Node/diagram point styling */
.node-point {
width: 12px;
height: 12px;
border: 2px solid var(--sketch-color);
border-radius: 50%;
background: var(--background);
.fade-in {
animation: fadeIn 0.8s ease-out forwards;
}
.node-point.filled {
background: var(--sketch-color);
}
/* Connection lines */
.connection-line {
stroke: var(--sketch-color);
stroke-width: 1.5;
stroke-dasharray: 4 2;
fill: none;
}
.connection-line.solid {
stroke-dasharray: none;
}
/* Annotation styling */
.annotation {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--annotation-color);
font-style: italic;
}
.annotation::before {
content: "// ";
opacity: 0.6;
}
/* Section label - like blueprint labels */
.section-label {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
background: var(--sketch-color);
color: var(--background);
font-family: var(--font-mono);
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* Handwritten-style text */
.handwritten {
font-family: "Caveat", "Comic Sans MS", cursive;
font-size: 1.1em;
}
/* Fade in animation */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in-up {
animation: fadeInUp 0.6s ease-out forwards;
}
/* Stagger animation delays */
.stagger-1 { animation-delay: 0.1s; }
.stagger-2 { animation-delay: 0.2s; }
.stagger-3 { animation-delay: 0.3s; }
.stagger-4 { animation-delay: 0.4s; }
.stagger-5 { animation-delay: 0.5s; }
/* Cursor blink for typing effect */
/* Cursor blink */
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
.cursor-blink::after {
content: "|";
animation: blink 1s step-end infinite;
margin-left: 2px;
}
/* Graph/chart styling */
.graph-axis {
stroke: var(--sketch-color);
stroke-width: 1.5;
}
.graph-label {
font-family: var(--font-mono);
font-size: 0.65rem;
fill: var(--muted-foreground);
}
/* Tag/label styling */
.tag {
display: inline-flex;
align-items: center;
padding: 0.125rem 0.5rem;
border: 1px solid var(--border);
border-radius: 1px;
font-family: var(--font-mono);
font-size: 0.7rem;
color: var(--muted-foreground);
background: var(--secondary);
}
.tag.primary {
border-color: var(--primary);
color: var(--primary);
background: oklch(0.45 0.15 250 / 0.08);
}
/* Dimension lines (like architectural drawings) */
.dimension-line {
position: relative;
display: flex;
align-items: center;
gap: 0.5rem;
}
.dimension-line::before,
.dimension-line::after {
content: "";
flex: 1;
height: 1px;
background: var(--border);
}
/* Crosshatch pattern for backgrounds */
.crosshatch {
background-image:
repeating-linear-gradient(
45deg,
transparent,
transparent 4px,
oklch(0.45 0.15 250 / 0.03) 4px,
oklch(0.45 0.15 250 / 0.03) 5px
);
}
/* Hover lift effect */
.hover-lift {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.hover-lift:hover {
transform: translateY(-2px);
box-shadow: 4px 4px 0 oklch(0.45 0.15 250 / 0.15);
}
/* Link styling */
a.blueprint-link {
color: var(--primary);
text-decoration: none;
border-bottom: 1px dashed var(--primary);
transition: border-color 0.2s;
}
a.blueprint-link:hover {
border-bottom-style: solid;
}
/* Status indicators */
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
border: 1.5px solid currentColor;
}
.status-dot.active {
background: currentColor;
}

View File

@ -1,20 +1,12 @@
import { CursorEffect } from '@/components/cursor-effect'
import { HeroSection } from '@/components/hero-section'
import { WorkSection } from '@/components/work-section'
import { AboutSection } from '@/components/about-section'
import { SkillsSection } from '@/components/skills-section'
import { ContactSection } from '@/components/contact-section'
export default function Home() {
return (
<>
<CursorEffect />
<main className="relative">
<main>
<HeroSection />
<WorkSection />
<AboutSection />
<SkillsSection />
<ContactSection />
</main>
</>
)

View File

@ -1,101 +1,6 @@
'use client'
import { useEffect, useState } from 'react'
// Minimal - just use default cursor
export function CursorEffect() {
const [position, setPosition] = useState({ x: -100, y: -100 })
const [isHovering, setIsHovering] = useState(false)
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
setPosition({ x: e.clientX, y: e.clientY })
setIsVisible(true)
const target = e.target as HTMLElement
const isInteractive = target.closest('a, button, [role="button"], input, textarea')
setIsHovering(!!isInteractive)
}
const handleMouseLeave = () => {
setIsVisible(false)
}
window.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseleave', handleMouseLeave)
return () => {
window.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseleave', handleMouseLeave)
}
}, [])
if (!isVisible) return null
return (
<>
{/* Simple crosshair cursor */}
<div
className="pointer-events-none fixed z-[9999] mix-blend-difference"
style={{
left: position.x,
top: position.y,
transform: 'translate(-50%, -50%)',
}}
>
{/* Crosshair */}
<svg
width={isHovering ? 32 : 24}
height={isHovering ? 32 : 24}
viewBox="0 0 24 24"
className="transition-all duration-150"
style={{ opacity: 0.7 }}
>
{/* Horizontal line */}
<line
x1="4" y1="12" x2="10" y2="12"
stroke="currentColor"
strokeWidth="1.5"
className="text-blue-900"
/>
<line
x1="14" y1="12" x2="20" y2="12"
stroke="currentColor"
strokeWidth="1.5"
className="text-blue-900"
/>
{/* Vertical line */}
<line
x1="12" y1="4" x2="12" y2="10"
stroke="currentColor"
strokeWidth="1.5"
className="text-blue-900"
/>
<line
x1="12" y1="14" x2="12" y2="20"
stroke="currentColor"
strokeWidth="1.5"
className="text-blue-900"
/>
{/* Center dot */}
<circle
cx="12" cy="12" r="2"
fill="currentColor"
className="text-blue-900"
/>
</svg>
</div>
{/* Subtle trailing dot */}
<div
className="pointer-events-none fixed z-[9998] w-1 h-1 rounded-full bg-blue-400/30"
style={{
left: position.x,
top: position.y,
transform: 'translate(-50%, -50%)',
transition: 'left 0.15s ease-out, top 0.15s ease-out',
}}
/>
</>
)
return null
}

View File

@ -2,14 +2,12 @@
import { useEffect, useState } from "react"
const RESEARCH_DOMAINS = [
const DOMAINS = [
"token engineering",
"regenerative economics",
"commons governance",
"mycoeconomics",
"institutional design",
"mycelial networks",
"collective intelligence",
"crypto commons",
]
export function HeroSection() {
@ -17,9 +15,8 @@ export function HeroSection() {
const [currentDomain, setCurrentDomain] = useState(0)
const [showCursor, setShowCursor] = useState(true)
const fullText = RESEARCH_DOMAINS[currentDomain]
const fullText = DOMAINS[currentDomain]
// Typing effect
useEffect(() => {
let charIndex = 0
setTypedText("")
@ -31,7 +28,7 @@ export function HeroSection() {
} else {
clearInterval(typeInterval)
setTimeout(() => {
setCurrentDomain((prev) => (prev + 1) % RESEARCH_DOMAINS.length)
setCurrentDomain((prev) => (prev + 1) % DOMAINS.length)
}, 2500)
}
}, 70)
@ -39,7 +36,6 @@ export function HeroSection() {
return () => clearInterval(typeInterval)
}, [currentDomain, fullText])
// Cursor blink
useEffect(() => {
const cursorInterval = setInterval(() => {
setShowCursor((prev) => !prev)
@ -48,117 +44,35 @@ export function HeroSection() {
}, [])
return (
<section className="relative min-h-screen flex items-center justify-center px-4 md:px-6 py-20">
{/* Blueprint frame corners */}
<div className="absolute top-8 left-8 w-16 h-16 border-l-2 border-t-2 border-primary/40" />
<div className="absolute top-8 right-8 w-16 h-16 border-r-2 border-t-2 border-primary/40" />
<div className="absolute bottom-8 left-8 w-16 h-16 border-l-2 border-b-2 border-primary/40" />
<div className="absolute bottom-8 right-8 w-16 h-16 border-r-2 border-b-2 border-primary/40" />
<section className="min-h-screen flex items-center justify-center px-6">
<div className="max-w-2xl">
<h1 className="text-4xl md:text-5xl font-light mb-8">
Jeff Emmett
</h1>
{/* Main content */}
<div className="relative z-10 w-full max-w-4xl">
{/* Section label */}
<div className="mb-8">
<span className="section-label">Overview</span>
</div>
<p className="text-xl md:text-2xl text-muted-foreground mb-4">
Exploring{" "}
<span className="text-primary">
{typedText}
<span className={showCursor ? "opacity-100" : "opacity-0"}>|</span>
</span>
</p>
{/* Main title area */}
<div className="blueprint-card p-8 md:p-12 mb-8">
{/* Name */}
<h1 className="text-4xl md:text-6xl lg:text-7xl font-light tracking-tight text-foreground mb-6">
Jeff Emmett
</h1>
<p className="text-muted-foreground mb-12 leading-relaxed">
Building tools for coordination and collective flourishing.
</p>
{/* Exploring line with typing effect */}
<div className="flex items-baseline gap-3 text-lg md:text-xl mb-8">
<span className="text-muted-foreground">Exploring</span>
<span className="text-primary font-medium min-w-[200px]">
{typedText}
<span
className={`inline-block w-0.5 h-5 bg-primary ml-0.5 align-middle ${
showCursor ? "opacity-100" : "opacity-0"
}`}
/>
</span>
</div>
{/* Description */}
<p className="text-muted-foreground leading-relaxed max-w-2xl mb-8">
Token engineering researcher designing systems at the intersection
of regenerative economics, crypto commons, and collective intelligence.
Co-founder of Commons Stack and MycoFi.
</p>
{/* Key affiliations as diagram nodes */}
<div className="flex flex-wrap gap-6 items-center">
<div className="flex items-center gap-3">
<div className="node-point filled" />
<span className="text-sm font-medium">Commons Stack</span>
</div>
<svg className="w-8 h-4 text-border hidden md:block">
<line x1="0" y1="8" x2="32" y2="8" stroke="currentColor" strokeWidth="1.5" strokeDasharray="4 2" />
</svg>
<div className="flex items-center gap-3">
<div className="node-point filled" />
<span className="text-sm font-medium">MycoFi</span>
</div>
<svg className="w-8 h-4 text-border hidden md:block">
<line x1="0" y1="8" x2="32" y2="8" stroke="currentColor" strokeWidth="1.5" strokeDasharray="4 2" />
</svg>
<div className="flex items-center gap-3">
<div className="node-point filled" />
<span className="text-sm font-medium">Bonding Curve Research</span>
</div>
</div>
</div>
{/* Navigation links */}
<div className="flex flex-wrap gap-4">
<a
href="#research"
className="blueprint-card px-6 py-3 hover-lift flex items-center gap-3 group"
>
<div className="node-point group-hover:filled transition-colors" />
<span className="text-sm font-medium">Research</span>
<span className="text-muted-foreground text-sm"></span>
<div className="flex flex-wrap gap-6 text-sm">
<a href="https://commonsstack.org" target="_blank" rel="noopener noreferrer">
Commons Stack
</a>
<a
href="#about"
className="blueprint-card px-6 py-3 hover-lift flex items-center gap-3 group"
>
<div className="node-point group-hover:filled transition-colors" />
<span className="text-sm font-medium">About</span>
<span className="text-muted-foreground text-sm"></span>
<a href="https://mycofi.earth" target="_blank" rel="noopener noreferrer">
MycoFi
</a>
<a
href="#connect"
className="blueprint-card px-6 py-3 hover-lift flex items-center gap-3 group"
>
<div className="node-point group-hover:filled transition-colors" />
<span className="text-sm font-medium">Connect</span>
<span className="text-muted-foreground text-sm"></span>
<a href="https://medium.com/@jeffemmett" target="_blank" rel="noopener noreferrer">
Writing
</a>
</div>
{/* Annotation */}
<div className="mt-12">
<p className="annotation">
Designing systems for collective flourishing since 2015
</p>
</div>
</div>
{/* Scroll indicator */}
<div className="absolute bottom-12 left-1/2 -translate-x-1/2 text-muted-foreground text-xs flex flex-col items-center gap-2">
<span className="font-mono">scroll</span>
<svg width="16" height="24" viewBox="0 0 16 24" className="animate-bounce">
<path
d="M8 4 L8 18 M4 14 L8 18 L12 14"
stroke="currentColor"
strokeWidth="1.5"
fill="none"
/>
</svg>
</div>
</section>
)

6
next-env.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@ -1,6 +1,10 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"target": "ES6",
"skipLibCheck": true,
@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@ -19,9 +23,19 @@
}
],
"paths": {
"@/*": ["./*"]
"@/*": [
"./*"
]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}