Skip to main content
The ”???” application is a hidden easter egg in Web XP, featuring an Undertale-inspired interactive experience where you can collect eggs once per day.

Finding the Easter Egg

The application appears as a desktop icon with a tree/leaf image labeled ”???”. It’s intentionally mysterious and meant to be discovered by users exploring the desktop.
Look for the mysterious tree icon on your desktop and double-click to open it!

Features

Daily Egg Collection

The easter egg allows you to collect one egg per day through an interactive dialogue sequence:
  • Time-gated mechanic: You can only receive an egg once every 24 hours
  • Persistent storage: Eggs are saved to localStorage and persist across sessions
  • Dialogue system: Undertale-style dialogue with YES/NO choices
  • Floating eggs: Collected eggs float around your screen at random positions

Audio Experience

The application features:
  • Background music: Plays looping music during the experience (music/man.ogg)
  • Sound effects: A sound plays when you receive an egg (music/egg.mp3)
  • Volume integration: Respects the global volume settings from VolumeContext
  • Autoplay handling: Gracefully handles browser autoplay restrictions

Visual Elements

// The main visual elements
<CenteredContent>
  <StyledGif src={gifSrc} onClick={handleTreeClick} />
</CenteredContent>

// Floating eggs layer
<EggLayer>
  {eggs.map(egg => (
    <StyledEgg
      key={egg.id}
      src={eggImg}
      alt="An Egg"
      data-x={egg.x}
      data-y={egg.y}
    />
  ))}
</EggLayer>

Implementation Details

State Management

The egg application maintains several pieces of state:
// Dialogue progression
const [dialogueStep, setDialogueStep] = useState(0);

// Egg collection with localStorage persistence
const [eggs, setEggs] = useState(() => {
  const saved = localStorage.getItem(EGG_DATA_KEY);
  if (saved) return JSON.parse(saved);
  return [];
});

LocalStorage Keys

The application uses three localStorage keys:
  • eggData: Stores the array of collected eggs with positions
  • eggCount: Legacy key for backwards compatibility
  • lastEggTime: Timestamp of the last egg collection

Dialogue Flow

The dialogue system follows this sequence:
  1. Step 0: Initial state (no dialogue)
  2. Step 1: “(Well, there is a man here.)”
  3. Step 2: “(He offered you something)”
  4. Step 3: YES/NO choice
  5. Step 4: “(You Received an Egg.)” (if YES)
  6. Step 5: ”(…)” (if NO)
  7. Step 7: “(Well, there is no man here…)” (if cooldown active)
  8. Step 8: “(Maybe he’ll be back tomorrow…)”

Egg Positioning

Eggs are positioned using global screen coordinates and tracked relative to the window:
useLayoutEffect(() => {
  const updateEggPositions = () => {
    const rect = containerRef.current.getBoundingClientRect();
    const winX = rect.left;
    const winY = rect.top;

    eggElements.forEach(el => {
      const globalX = parseFloat(el.getAttribute('data-x'));
      const globalY = parseFloat(el.getAttribute('data-y'));
      
      const drawX = globalX - winX;
      const drawY = globalY - winY;
      
      el.style.transform = `translate3d(${drawX}px, ${drawY}px, 0)`;
    });
  };
}, [eggs]);

Typography

The application uses the DeterminationMono font (from Undertale) for authentic dialogue styling:
const FontStyles = createGlobalStyle`
  @font-face {
    font-family: 'DeterminationMono';
    font-weight: normal;
    font-style: normal;
    font-display: block; 
  }
`;

User Interaction

Tree Click Handler

const handleTreeClick = () => {
  if (dialogueStep === 0) {
    const lastTime = parseInt(localStorage.getItem(LAST_EGG_TIME_KEY) || '0', 10);
    const now = Date.now();

    if (now - lastTime < 24 * 60 * 60 * 1000) {
      setDialogueStep(7); // Show cooldown message
    } else {
      setDialogueStep(1); // Start normal dialogue
    }
  }
};

Egg Creation

When the user accepts the egg:
const handleYes = e => {
  e.stopPropagation();
  
  const rect = containerRef.current.getBoundingClientRect();
  const randomX = rect.left + Math.random() * (rect.width - 90);
  const randomY = rect.top + Math.random() * (rect.height - 90);

  const newEgg = { x: randomX, y: randomY, id: Date.now() };
  setEggs([...eggs, newEgg]);
  
  localStorage.setItem(EGG_DATA_KEY, JSON.stringify([...eggs, newEgg]));
  localStorage.setItem(LAST_EGG_TIME_KEY, Date.now().toString());
};

Configuration

The Egg app is configured in src/WinXP/apps/index.jsx:
{
  id: genId(),
  icon: eggIconLarge,
  title: '???',
  component: Egg,
  isFocus: false,
  appName: 'Egg',
}

Assets Required

  • assets/windowsIcons/egg.png - The egg image
  • assets/windowsIcons/tree.gif - The tree/character animation
  • public/gifs/tree.gif - Public asset for the GIF
  • public/music/man.ogg - Background music
  • public/music/egg.mp3 - Egg collection sound effect

Styling

The component uses styled-components with:
  • Black background (#000000)
  • White borders for dialogue boxes
  • Yellow hover state for options
  • Floating animation for eggs using CSS keyframes
  • Pixelated rendering for retro aesthetic
This is an homage to Undertale’s “Egg Man” easter egg. The daily collection mechanic and dialogue style are inspired by that game’s quirky secrets.
  • src/WinXP/apps/Egg/index.jsx - Main component implementation
  • src/WinXP/apps/index.jsx:217-223 - Icon configuration
  • src/context/VolumeContext.jsx - Volume control integration

Build docs developers (and LLMs) love