Click anywhere below and type / to see what you can create – headers, tables, to-do’s, etc.
[x] Timport React, { useState } from 'react';import { BookOpen, RotateCcw, Users, MapPin } from 'lucide-react';
const NarrativeApp = () => { const [currentScene, setCurrentScene] = useState('start'); const [playerStats, setPlayerStats] = useState({ courage: 50, wisdom: 50, friendship: 50 }); const [inventory, setInventory] = useState([]); const [storyHistory, setStoryHistory] = useState(['start']);
const scenes = { start: { title: "The Mysterious Forest", text: "You stand at the edge of an ancient forest, moonlight filtering through the dense canopy above. A worn path splits into two directions. To your left, you hear the gentle sound of flowing water. To your right, a faint glow emanates from between the trees.", choices: [ { text: "Follow the sound of water", next: "river", stats: { wisdom: 5 } }, { text: "Investigate the mysterious glow", next: "glow", stats: { courage: 5 } }, { text: "Call out to see if anyone is nearby", next: "call", stats: { friendship: 5 } } ] }, river: { title: "The Whispering River", text: "You discover a crystal-clear river with an old stone bridge crossing it. An elderly woman sits by the water's edge, seemingly waiting for someone. She looks up as you approach with knowing eyes.", choices: [ { text: "Approach the woman and offer help", next: "elder", stats: { friendship: 10 }, item: "Ancient Map" }, { text: "Cross the bridge quietly", next: "bridge", stats: { courage: 5 } }, { text: "Study the river for clues", next: "study", stats: { wisdom: 10 } } ] }, glow: { title: "The Enchanted Clearing", text: "You push through the undergrowth and find yourself in a magical clearing. Floating orbs of light dance around a circle of ancient stones. In the center grows a tree with silver leaves that chime softly in the breeze.", choices: [ { text: "Touch one of the glowing orbs", next: "orb", stats: { courage: 10 }, item: "Light Crystal" }, { text: "Examine the ancient stones", next: "stones", stats: { wisdom: 15 } }, { text: "Wait and observe respectfully", next: "observe", stats: { friendship: 5 } } ] }, call: { title: "The Friendly Echo", text: "Your voice echoes through the forest, and to your surprise, you hear a cheerful response! A group of woodland creatures emerges from the shadows - talking foxes, wise owls, and gentle deer who seem delighted to meet you.", choices: [ { text: "Ask the animals about the forest's secrets", next: "secrets", stats: { wisdom: 10 } }, { text: "Offer to help them with any problems", next: "help", stats: { friendship: 15 } }, { text: "Suggest exploring together", next: "explore", stats: { courage: 5 } } ] }, elder: { title: "The Wise Guardian", text: "The elderly woman smiles warmly and introduces herself as Elena, Guardian of the Forest. She tells you that the forest is in danger from a growing darkness, and she's been waiting for someone brave enough to help. She hands you an ancient map.", choices: [ { text: "Accept the quest to save the forest", next: "quest", stats: { courage: 15, friendship: 10 } }, { text: "Ask about the nature of the darkness", next: "darkness", stats: { wisdom: 15 } }, { text: "Offer to gather allies first", next: "allies", stats: { friendship: 20 } } ] }, orb: { title: "The Power Within", text: "As you touch the orb, warm energy flows through you. Visions flash before your eyes - you see the forest's past, its connection to ancient magic, and a shadow threatening to consume it all. The orb transforms into a crystal that pulses with inner light.", choices: [ { text: "Use the crystal's power to investigate", next: "investigate", stats: { courage: 10, wisdom: 10 } }, { text: "Seek out others who might understand", next: "seek", stats: { friendship: 15 } }, { text: "Return to warn people about the danger", next: "warn", stats: { wisdom: 10, friendship: 10 } } ] }, quest: { title: "The Hero's Journey Begins", text: "Elena's map reveals three locations where ancient guardians once stood watch. The darkness has corrupted these sacred places, and only by restoring them can the forest be saved. Your courage inspires Elena, and she grants you her blessing.", choices: [ { text: "Head to the Northern Peak first", next: "victory" }, { text: "Visit the Eastern Grove", next: "victory" }, { text: "Explore the Western Caves", next: "victory" } ] }, victory: { title: "The Light Returns", text: Through your brave choices and kind heart, you've begun the quest to save the ancient forest. Your courage (${playerStats.courage}), wisdom (${playerStats.wisdom}), and friendship (${playerStats.friendship}) will guide you on the adventures ahead. The forest spirits smile upon you, knowing that hope has returned to their realm., choices: [ { text: "Begin a new story", next: "start", reset: true } ] } };
const defaultScene = { title: "To Be Continued...", text: "This part of the story is still being written. Your choices have led you to new possibilities!", choices: [ { text: "Return to the beginning", next: "start", reset: true } ] };
const handleChoice = (choice) => { if (choice.reset) { setPlayerStats({ courage: 50, wisdom: 50, friendship: 50 }); setInventory([]); setStoryHistory(['start']); setCurrentScene('start'); return; }
if (choice.stats) { setPlayerStats(prev => ({ courage: Math.min(100, prev.courage + (choice.stats.courage || 0)), wisdom: Math.min(100, prev.wisdom + (choice.stats.wisdom || 0)), friendship: Math.min(100, prev.friendship + (choice.stats.friendship || 0)) })); }
if (choice.item && !inventory.includes(choice.item)) { setInventory(prev => [...prev, choice.item]); }
setStoryHistory(prev => [...prev, choice.next]); setCurrentScene(choice.next); };
const resetStory = () => { setCurrentScene('start'); setPlayerStats({ courage: 50, wisdom: 50, friendship: 50 }); setInventory([]); setStoryHistory(['start']); };
const StatBar = ({ label, value, color }) => ( <div className="mb-2"> <div className="flex justify-between text-sm mb-1"> <span className="text-gray-300">{label}</span> <span className="text-gray-300">{value}/100</span> </div> <div className="w-full bg-gray-700 rounded-full h-2"> <div className={h-2 rounded-full transition-all duration-300 ${color}} style={{ width: ${value}% }} ></div> </div> </div> );
const scene = scenes[currentScene] || defaultScene;
return ( <div className="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 text-white"> <div className="container mx-auto px-4 py-8 max-w-4xl"> <div className="text-center mb-8"> <div className="flex items-center justify-center gap-3 mb-4"> <BookOpen className="h-8 w-8 text-purple-400" /> <h1 className="text-4xl font-bold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent"> Interactive Narrative </h1> </div> <p className="text-blue-200">Choose your path and shape your story</p> </div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div className="lg:col-span-2"> <div className="bg-black/30 backdrop-blur-lg rounded-xl p-6 border border-purple-500/20"> <div className="flex items-center gap-2 mb-4"> <MapPin className="h-5 w-5 text-purple-400" /> <h2 className="text-2xl font-bold text-purple-300">{scene.title}</h2> </div> <div className="mb-6"> <p className="text-gray-100 leading-relaxed text-lg"> {scene.text} </p> </div>
<div className="space-y-3"> <h3 className="text-lg font-semibold text-blue-300 mb-3">What do you choose?</h3> {scene.choices.map((choice, index) => ( <button key={index} onClick={() => handleChoice(choice)} className="w-full text-left p-4 bg-gradient-to-r from-purple-600/20 to-blue-600/20 border border-purple-400/30 rounded-lg hover:from-purple-600/30 hover:to-blue-600/30 hover:border-purple-400/50 transition-all duration-200 hover:scale-[1.02] group" > <span className="text-white group-hover:text-purple-200 transition-colors"> {choice.text} </span> {choice.stats && ( <div className="text-xs text-blue-300 mt-1"> {Object.entries(choice.stats).map(([stat, value]) => ( <span key={stat} className="mr-3"> +{value} {stat} </span> ))} {choice.item && <span className="text-yellow-300">• Gain {choice.item}</span>} </div> )} </button> ))} </div> </div> </div>
<div className="space-y-6"> <div className="bg-black/30 backdrop-blur-lg rounded-xl p-6 border border-purple-500/20"> <div className="flex items-center gap-2 mb-4"> <Users className="h-5 w-5 text-purple-400" /> <h3 className="text-xl font-bold text-purple-300">Character Stats</h3> </div> <StatBar label="Courage" value={playerStats.courage} color="bg-red-500" /> <StatBar label="Wisdom" value={playerStats.wisdom} color="bg-blue-500" /> <StatBar label="Friendship" value={playerStats.friendship} color="bg-green-500" /> </div>
<div className="bg-black/30 backdrop-blur-lg rounded-xl p-6 border border-purple-500/20"> <h3 className="text-xl font-bold text-purple-300 mb-4">Inventory</h3> {inventory.length > 0 ? ( <div className="space-y-2"> {inventory.map((item, index) => ( <div key={index} className="bg-yellow-500/20 border border-yellow-400/30 rounded-lg p-3"> <span className="text-yellow-200">{item}</span> </div> ))} </div> ) : ( <p className="text-gray-400 italic">No items yet</p> )} </div>
<button onClick={resetStory} className="w-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white font-bold py-3 px-6 rounded-lg transition-all duration-200 flex items-center justify-center gap-2 hover:scale-105" > <RotateCcw className="h-4 w-4" /> Restart Story </button> </div> </div> </div> </div> );};
export default NarrativeApp;ype /page to add a new page and nest anything, anywhere
[x] Find, organize, and add new pages using the sidebar to the left 👈