import React, { useState, useEffect, useMemo } from 'react';
import { initializeApp } from 'firebase/app';
import {
getAuth,
signInAnonymously,
signInWithCustomToken,
onAuthStateChanged,
signInWithEmailAndPassword,
signOut
} from 'firebase/auth';
import {
getFirestore,
collection,
onSnapshot,
addDoc,
deleteDoc,
updateDoc,
doc,
serverTimestamp
} from 'firebase/firestore';
import {
PlayCircle, Moon, Sun, ArrowRight, Download,
Linkedin, Youtube, Instagram, MessageSquare, Mail, Music, BadgeCheck,
Volume2, Clock, Zap, ChevronDown, Users, Sparkles, Feather, Camera, ArrowLeft, X, Share2,
MapPin, PenTool, Image as ImageIcon, Radio, Plus, Trash2, Send, Layout, Settings, Terminal, Lock, Unlock, ShieldAlert, LogOut
} from 'lucide-react';
// --- CONFIGURATION ---
const ADMIN_EMAIL = "howdy@alexwattsblog.com";
const PROFILE_PHOTO_URL = "https://lh3.googleusercontent.com/d/1_tPRnlXO4VGG9cVZD9lDnZSq-e6jpnsR";
// --- FIREBASE SETUP ---
// Integrated with your Rogue Rocket credentials from screenshot
const firebaseConfig = typeof __firebase_config !== 'undefined'
? JSON.parse(__firebase_config)
: {
apiKey: "AIzaSyDWhsce7nBSAOkC00GN3IGY4_NOHa0w05E",
authDomain: "rogue-rocket.firebaseapp.com",
projectId: "rogue-rocket",
storageBucket: "rogue-rocket.firebasestorage.app",
messagingSenderId: "622357995671",
appId: "1:622357995671:web:7365bf49e32a75ea7309d2",
measurementId: "G-JGQTTPЕ0KH"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const appId = typeof __app_id !== 'undefined' ? __app_id : 'rogue-rocket-prod';
const MOCK_DATA = [
{ date: '2026-04-26T23:00:00', location: 'Freshwater Shoreline', title: '', content: '
Found a gluten-free loaf in a tiny bakery that actually had structural integrity. Didn’t even turn into sawdust when looked at. A genuine Sunday miracle. 🍞✨
', tldr: 'Found edible GF bread. The bar is low, but the joy is high.', format: 'status' },
{ date: '2026-04-24T14:15:00', location: 'In the Studio', title: 'ADHD, AI, and Cognitive Prosthetics', content: 'Stories shouldn\'t be transfixed on AABB or ABBA structure. Zoning in on the nuances of details is what paints the scene. When looking at how neurodivergent minds interact with AI in a remote setting, the little things matter the most. Hyper-focus isn’t a bug; it’s the feature that makes AI actually useful.
Using AI as a cognitive prosthetic allows for the outsourcing of executive function fatigue. Instead of wrestling with the "how," focus shifts entirely to the "what." This isn\'t about shortcuts—it\'s about clearing the mental noise to reach the destination faster.
', tldr: 'Neurodivergent folks use AI as a cognitive prosthetic. Nuance is the focus.', format: 'standard' },
{ date: '2026-04-22T08:30:00', location: 'West Coast', title: 'The Solitude of the Shore', content: 'Captured this morning on the west coast. Specific kinds of silence exist only on an island before the first ferry arrives. Best thinking happens here.
', tldr: 'Early morning photography serves as a form of meditation.', format: 'image', featured_image: 'https://images.unsplash.com/photo-1505144808419-1957a94ca61e?auto=format&fit=crop&w=800&q=80' }
];
const MOCK_TOUR = [
{ date: '2026-10-12', city: 'London, UK', event: 'Neurodiversity in Tech', status: 'Sold Out', link: '' },
{ date: '2026-11-05', city: 'Berlin, DE', event: 'AI & Executive Function', status: 'Tickets', link: 'https://example.com' },
{ date: '2027-01-18', city: 'Austin, TX', event: 'Leadership Summit', status: 'Tickets', link: 'https://example.com' }
];
const getSnippet = (html) => {
if (!html) return '';
const text = html.replace(/<[^>]*>?/gm, '');
const words = text.split(/\s+/);
if (words.length <= 22) return html;
return words.slice(0, 22).join(' ') + '...';
};
const EYEBROW_PHRASES = [
"Alex Watts is just casually fine",
"Alex Watts is risking it all for a pastry",
"Alex Watts is avoiding long paragraphs",
"Alex Watts is cutting through the noise",
"Alex Watts has 73 browser tabs open",
"Alex Watts is operating on a different system"
];
const FILTERS = [
{ id: 'all', label: 'All' },
{ id: 'essays', label: 'Essays' },
{ id: 'notes', label: 'Notes' },
];
export default function App() {
const [user, setUser] = useState(null);
const [view, setView] = useState('public');
const [posts, setPosts] = useState([]);
const [tourDates, setTourDates] = useState([]);
const [activeFilter, setActiveFilter] = useState('all');
const [isDarkMode, setIsDarkMode] = useState(true);
const [openTldrs, setOpenTldrs] = useState({});
const [selectedPost, setSelectedPost] = useState(null);
const [eyebrowText, setEyebrowText] = useState("");
const [isPlaying, setIsPlaying] = useState(false);
const [isBookingExpanded, setIsBookingExpanded] = useState(false);
const [authEmail, setAuthEmail] = useState("");
const [authPass, setAuthPass] = useState("");
const [authError, setAuthError] = useState("");
const [isLoggingIn, setIsLoggingIn] = useState(false);
const [newPost, setNewPost] = useState({ title: '', content: '', tldr: '', format: 'standard', location: 'Freshwater Shoreline' });
const [newTour, setNewTour] = useState({ date: '', city: '', event: '', status: 'Tickets', link: '' });
useEffect(() => {
const initAuth = async () => {
if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) {
await signInWithCustomToken(auth, __initial_auth_token);
} else {
await signInAnonymously(auth);
}
};
initAuth();
const unsubscribe = onAuthStateChanged(auth, (u) => {
setUser(u);
});
return () => unsubscribe();
}, []);
useEffect(() => {
if (!user) return;
const postsRef = collection(db, 'artifacts', appId, 'public', 'data', 'posts');
const unsubPosts = onSnapshot(postsRef, (snapshot) => {
const docs = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
setPosts(docs.sort((a, b) => new Date(b.date) - new Date(a.date)));
}, (err) => console.error("Posts error:", err));
const tourRef = collection(db, 'artifacts', appId, 'public', 'data', 'tour_dates');
const unsubTour = onSnapshot(tourRef, (snapshot) => {
const docs = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
setTourDates(docs.sort((a, b) => new Date(a.date) - new Date(b.date)));
}, (err) => console.error("Tour error:", err));
return () => {
unsubPosts();
unsubTour();
};
}, [user]);
useEffect(() => {
if (selectedPost || view === 'admin') window.scrollTo({ top: 0, behavior: 'smooth' });
if (!eyebrowText) setEyebrowText(EYEBROW_PHRASES[Math.floor(Math.random() * EYEBROW_PHRASES.length)]);
}, [selectedPost, view]);
const toggleAudio = () => setIsPlaying(!isPlaying);
const handleTerminalLogin = async (e) => {
e.preventDefault();
setAuthError("");
setIsLoggingIn(true);
try {
await signInWithEmailAndPassword(auth, authEmail, authPass);
setAuthPass("");
setAuthEmail("");
} catch (err) {
setAuthError("Unauthorized uplink. Credentials rejected.");
console.error(err);
} finally {
setIsLoggingIn(false);
}
};
const handleLogout = async () => {
await signOut(auth);
await signInAnonymously(auth);
setView('public');
};
const filteredPosts = useMemo(() => {
return posts.filter(post => {
if (activeFilter === 'all') return true;
if (activeFilter === 'notes') return post.format === 'status';
if (activeFilter === 'essays') return post.format === 'standard';
return true;
});
}, [posts, activeFilter]);
const handleContactClick = (e) => {
e.preventDefault();
window.location.href = `mailto:howdy@alexwattsblog.com?subject=Speaking Inquiry`;
};
const broadcastPost = async () => {
if (!newPost.content || !isPilot) return;
try {
await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'posts'), {
...newPost,
date: new Date().toISOString(),
timestamp: serverTimestamp()
});
setNewPost({ title: '', content: '', tldr: '', format: 'standard', location: 'Freshwater Shoreline' });
} catch (e) { console.error(e); }
};
const broadcastTour = async () => {
if (!newTour.date || !newTour.event || !isPilot) return;
try {
await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'tour_dates'), newTour);
setNewTour({ date: '', city: '', event: '', status: 'Tickets', link: '' });
} catch (e) { console.error(e); }
};
const deleteItem = async (col, id) => {
if (!isPilot) return;
try {
await deleteDoc(doc(db, 'artifacts', appId, 'public', 'data', col, id));
} catch (e) { console.error(e); }
};
const seedDatabase = async () => {
if (!isPilot) return;
try {
for (const p of MOCK_DATA) {
await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'posts'), p);
}
for (const t of MOCK_TOUR) {
await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'tour_dates'), t);
}
} catch (e) { console.error(e); }
};
const calculateReadTime = (content) => Math.max(1, Math.ceil((content || "").split(' ').length / 200));
const isPilot = user && !user.isAnonymous && user.email === ADMIN_EMAIL;
const PostDetail = ({ post, onBack }) => (
Back to stream
{post.format === 'status' ? 'Note' : post.format}
{new Date(post.date).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}
{post.title &&
{post.title} }
);
return (
{ setView('public'); setSelectedPost(null); }} className="flex items-center group cursor-pointer focus:outline-none">
AlexWattsBlog
{isPilot && view === 'admin' && (
Log Out
)}
{isPilot && view === 'public' && (
setView('admin')} className="text-[10px] font-bold text-[#ff5241] uppercase tracking-[0.2em] px-4 py-2 bg-[#ff5241]/10 rounded-full">Pilot Deck
)}
setIsDarkMode(!isDarkMode)} className="p-2 text-slate-400 hover:text-[#ff5241] rounded-full transition-all active:scale-90">
{isDarkMode ? : }
{view === 'admin' ? (
!isPilot ? (
{authError ? : }
Pilot Identity Required
Verification required to access the Rogue Rocket broadcasting deck.
) : (
Pilot Deck
Managing signals for {user.email} • Isle of Wight
Seed Data
setView('public')} className="flex items-center gap-2 text-[10px] font-bold text-slate-900 dark:text-white uppercase tracking-widest bg-white dark:bg-white/5 hover:bg-slate-100 dark:hover:bg-white/10 px-4 py-2 rounded-xl border border-slate-200 dark:border-white/10">
View Site
Transmission Archive
{posts.map(p => (
{p.format === 'status' ? 'Note' : 'Essay'}
deleteItem('posts', p.id)} className="text-slate-300 dark:text-white/10 hover:text-red-500 p-1 transition-colors">
{p.title || "Untitled Note"}
{new Date(p.date).toLocaleDateString()}
))}
)
) : selectedPost ? (
setSelectedPost(null)} />
) : (
{/* SACRED COMPONENT: HERO */}
Navigating the noise.
Championing the human.
Delivering informed, funny, and lived neurodiversity insights from the Isle of Wight—a physical, by-design disconnect from the corporate noise. I'm here to prove why Red, Amber, and Green spreadsheets will never quantify neurodivergent talent. When the signal is idle? Walking the dog, eating the exact same four meals on repeat, and playing Rocket League with day-one mates.
{/* ROGUE ROCKET BUSINESS SECTION */}
Same world.
different perspective.
Alex Watts is the pilot; Rogue Rocket is the propulsion.
{[{ icon:
, label: "Keynotes" }, { icon:
, label: "Workshops" }, { icon:
, label: "Consulting" }].map((item, i) => (
{item.icon} {item.label}
))}
Let's Chat
Get Kit
setIsBookingExpanded(!isBookingExpanded)} className="group flex items-center gap-5 focus:outline-none">
{isBookingExpanded ? "Collapse Talks & Dates" : "View Talks & Dates"}
{[
{ title: "Trapped in a Cell", icon:
, color: "bg-[#ff5241]/10 text-[#ff5241]", shadow: "group-hover:drop-shadow-[0_0_12px_rgba(255,82,65,0.8)]", text: "Exploring the intangible potential of neurodiverse minds and how measuring worth on a spreadsheet is never a good idea." },
{ title: "AI: The Cognitive Prosthetic", icon:
, color: "bg-pink-500/10 text-pink-500", shadow: "group-hover:drop-shadow-[0_0_12px_rgba(236,72,153,0.8)]", text: "Navigating the workloads and changeable nature of executive function and how AI workflows combat distraction." }
].map((talk, i) => (
))}
{tourDates.length > 0 ? tourDates.map((gig) => (
{new Date(gig.date).toLocaleDateString('en-GB', { month: 'short' })}
{new Date(gig.date).getDate()}
)) : (
Scanning for tour dates...
)}
{/* THE STREAM SECTION */}
The Stream
Digital artifacts, shoreline notes & freewheeling thought.
{FILTERS.map(f => (
setActiveFilter(f.id)} className={`shrink-0 px-7 py-3 rounded-full text-[10px] font-bold uppercase tracking-[0.2em] transition-all duration-300 ${activeFilter === f.id ? 'bg-[#ff5241] text-white shadow-2xl shadow-[#ff5241]/30 scale-105' : 'bg-white dark:bg-white/5 text-slate-400 border border-slate-200 dark:border-white/5 hover:border-[#ff5241]'}`}>
{f.label}
))}
{posts.length > 0 ? filteredPosts.map((post) => (
AlexWattsBlog
{new Date(post.date).toLocaleDateString('en-GB', { day: 'numeric', month: 'short' })}
•
{post.format === 'status' ?
:
}
{post.format === 'status' ? 'Note' : 'Essay'}
setSelectedPost(post)}>
{post.title &&
{post.title} }
{post.featured_image && (
)}
{post.tldr && (
setOpenTldrs(p => ({...p, [post.id]: !p[post.id]}))} className={`flex items-center gap-2 text-[10px] font-bold uppercase tracking-[0.2em] px-5 py-2.5 rounded-xl transition-all ${openTldrs[post.id] ? 'bg-[#ff5241] text-white shadow-lg' : 'bg-[#ff5241]/5 text-[#ff5241] border border-[#ff5241]/10 hover:bg-[#ff5241]/15'}`}>
TL;DR
)}
)) : (
Stream is quiet. Waiting for the ferry...
)}
)}
AlexWattsBlog
© 2026 • Broadcast from the Channel
Send a pigeon
{view !== 'admin' && (
setView('admin')} className="flex items-center gap-2 text-[10px] font-bold text-slate-400 hover:text-[#ff5241] uppercase tracking-[0.3em] transition-colors">
Terminal Access
)}
);
}