---
title: SC Apple III 404
description: "A terminal 404: boot banner, glitch burst, then a working prompt."
url: https://secretocho.design/lab/apple-iii-404/
type: SoftwareSourceCode
status: working
published: 2026-10-05
---

# SC Apple III 404

> A terminal 404: boot banner, glitch burst, then a working prompt.

component 22 / 28 · WORKING

- **type**: Code Component
- **platform**: Framer
- **license**: SecretoCho Design

![A still of the SC Apple III 404 demo, as its module draws it with reduced motion.](https://secretocho.design/_astro/still.BjAP7F-L_OhM6v.webp)

*fig 00 · live demo, ported from **MS404.tsx***

A terminal-style 404 page: ASCII boot banner, glitch burst, then a working command prompt that redirects to the site’s main links.

AppleIII404 is the old site’s 404 screen as a fake terminal. It boots with a SECRETOCHO ASCII banner and progress line, glitches into random symbols, then settles on a 404 banner with a prompt. Visitors can type help, list, home, services, resources, blog, contact, back, retry or cls; the navigation commands redirect to the links set in the controls, everything else prints “not recognized”. A footer row repeats the five links.

- UI
- Text
- Motion

## Main

### Overview

- **Built With**: React (hooks), framer-motion (AnimatePresence), Framer Code Component API
- **Layout Support**: Full viewport height (100vh), scrolls inside
- **Orientation**: Vertical: banner and prompt on top, link row pinned to the bottom
- **Ideal Use Case**: 404 and error pages with a hacker / retro-computer tone

### Tags

- 404
- terminal
- ascii
- glitch
- command line
- error page
- framer-motion

### Code comment

MS404.tsx has no doc comment.

### Dependencies

- **Technologies**: framer-motion (part of the Framer runtime)
- **Notes**: Plays an MP3 from a third-party host at the glitch stage; see Security.

### Complexity

- **Logic Level**: Low–Medium (three timed stages, a command map, redirect timer)
- **Runtime Cost**: Very Low (two timers, one opacity animation)
- **Component Size**: ~10 KB TSX (9,530 bytes, 245 lines)
- **Notes**: Both timers are cleared on unmount.

## Guide

### Instructions

1. Place **AppleIII404** on the 404 page as a full-height layer.
2. Set **Background** and **Font Color** (default black and phosphor green).
3. Set the **Font** object: family (IBM Plex Mono by default), size, style, weight, letter spacing, line height.
4. Fill the five **Link** controls: Home, Services, Resources, Blog, Contact — the prompt’s commands and the footer row use them.

### Examples / Presets

- Apple III
  
  The source defaults: black, phosphor green #33FF33, IBM Plex Mono 16 px, no links set.
  
- As on the site
  
  - **bgColor**: transparent
  - **fontColor**: primary--1000
  - **font.fontFamily**: Recursive
  - **font.fontWeight**: 300
  - **homeLink**: /
  - **servicesLink**: /services
  - **contactLink**: /contact (the old site’s 404 page)
  

## Mechanics

### How it Works

- **Stages**: on mount a 404 ms timer switches from loading (ASCII SECRETOCHO banner, “SYSTEM BOOTING”, a 99 % bar) to glitch and plays the beep; a 2,000 ms timer switches to done.
- **Glitch**: two strings of 300 and 120 random characters from !@#$%^&\*()\_+=-~?\>\<:{}\[\], in a 0.4 s framer-motion opacity fade with repeat 4, reverse (five alternating legs); the done stage replaces it at 2,000 ms.
- **Prompt**: an auto-focused \<input\>; on Enter the lower-cased command is looked up in a map of ten responses, echoed into the history, and for home / services / resources / blog / contact / back the page redirects after 200 ms via window.location.href.
- **Unknown commands** print “Command '…' not recognized.” cls is in the map but only echoes (nothing clears the history).
- **Footer**: five plain links in the font colour under a 1 px rule.

### Performance & Tuning

- Negligible: two timers and one AnimatePresence transition.
- The glitch strings are regenerated on each render of that stage; it lasts under two seconds.

### Compatibility & Limits

- Evergreen browsers; needs framer-motion (bundled with Framer).
- 100vh height: on mobile browsers the bottom link row can sit under the browser chrome.
- Audio autoplay without a gesture is blocked by most browsers, so the beep is often silent (its play() promise is not handled).
- The caret uses a CSS class (blinking-cursor) that the file does not define; it blinks only if the page supplies that style.

## Quality

### Accessibility

- The prompt is a real, auto-focused text input, so keyboard users can type commands; the footer links are plain \<a\>s.
- The ASCII banners are raw text to a screen reader; consider aria-hidden on them and a plain heading.
- The glitch flicker is brief but rapid; no reduced-motion check.

### Security & Privacy

- **Network**: line 12 creates an Audio element for a beep on soundjay.com when the module loads (line 41 plays it during the glitch), so the browser requests that file from a third-party host on every page that loads the component. No fetch of its own, no tracking.
- **Navigation**: window.location.href is set to the configured Link controls, and also for the typed words “constructor” and “\_\_proto\_\_”, which the command lookup matches on the object’s prototype.
- No storage, no permissions; input text is echoed as React text (no HTML injection).

## Reference

### Props

| name | type | default | description |
| --- | --- | --- | --- |
| bgColor | color | #000000 | Background. |
| fontColor | color | #33FF33 | Font Color. Text, caret, rule and footer links. |
| font | object | fontFamily=IBM Plex Mono, fontSize=16, fontStyle=normal, fontWeight=400, letterSpacing=0px, lineHeight=1.6em | Font. Family, size, Normal \| Italic, weight, letter spacing, line height. |
| homeLink | link | — | Home Link. Target of home and back. |
| servicesLink | link | — | Services Link. |
| resourcesLink | link | — | Resources Link. |
| blogLink | link | — | Blog Link. |
| contactLink | link | — | Contact Link. |

The five Link controls have no defaults: an unset link is undefined, so its command sets location.href to the relative path “undefined”, and its footer link renders without an href.

### Notes & Tips

- Type help at the prompt to list the commands; list prints the five paths.
- Set the input’s variable-font MONO axis: the file sets font-variation-settings "MONO" 1 on the input for a Recursive-style font.
- Define .blinking-cursor in the page’s CSS if the caret should blink.

### Troubleshooting / FAQ

No beep

Autoplay without a user gesture is blocked, or the third-party host did not answer; the file does not handle the rejected play().

cls does not clear the screen

Expected: cls only echoes an empty response; nothing resets the history.

The caret does not blink

The blinking-cursor class is not styled in the file.

A command goes to a page called “undefined”

Its Link control is not set; an unset link is undefined (an empty string would reload the current page).

## Source

### Header comment

MS404.tsx has no doc comment.

[props \[REF\]](#reference)

### Key excerpt

The prompt is a ten-entry command map: a known command is echoed with its response and, for the navigation words, redirects after 200 ms; anything else prints “not recognized”.

*MS404.tsx · lines 53–89 · tsx*

```tsx
    const handleCommand = (e: React.KeyboardEvent<HTMLInputElement>) => {
        if (e.key === "Enter") {
            const cmd = input.trim().toLowerCase()
            const responses: Record<string, string> = {
                help: "Available commands: home, services, resources, blog, contact, back, retry, cls, list",
                back: "Redirecting to homepage...",
                retry: "Retrying the broken request... nothing changed.",
                cls: "",
                list: "./home ./services ./resources ./blog ./contact",
                home: `Redirecting to /home ...`,
                services: `Redirecting to /services ...`,
                resources: `Redirecting to /resources ...`,
                blog: `Redirecting to /blog ...`,
                contact: `Redirecting to /contact ...`,
            }

            if (cmd in responses) {
                setHistory((prev) => [...prev, `> ${cmd}`, responses[cmd]])
                setInput("")
                setTimeout(() => {
                    const linkMap: Record<string, string> = {
                        home: homeLink,
                        services: servicesLink,
                        resources: resourcesLink,
                        blog: blogLink,
                        contact: contactLink,
                        back: homeLink,
                    }
                    if (cmd in linkMap) window.location.href = linkMap[cmd]
                }, 200)
                return
            }

            setHistory((prev) => [...prev, `> ${cmd}`, `Command '${cmd}' not recognized.`])
            setInput("")
        }
    }
```

## Credits

### Credits

© SecretoCho Design

- **license**: SecretoCho Design

SecretoCho Design

### Disclaimer

Provided “as is” for visual/UX purposes. Validate performance, accessibility, and licensing within your project.

## Proves

- [Creative coding](https://secretocho.design/about/#capabilities)

## Hiring a design engineer?

I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.

[sc@secretocho.design](mailto:sc@secretocho.design)

[read the CV](https://secretocho.design/cv/) · [LinkedIn](https://www.linkedin.com/in/secretocho/)
