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 }) => (
{post.format === 'status' ? 'Note' : post.format} {new Date(post.date).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}
{post.title &&

{post.title}

}
); return (
{view === 'admin' ? ( !isPilot ? (
{authError ? : }

Pilot Identity Required

Verification required to access the Rogue Rocket broadcasting deck.

setAuthEmail(e.target.value)} required /> setAuthPass(e.target.value)} required />
{authError &&

{authError}

}
) : (

Pilot Deck

Managing signals for {user.email} • Isle of Wight

Broadcast Signal

setNewPost({...newPost, title: e.target.value})} />