prod@blog:~$

Building a Dynamic Terminal Widget on My Blog

I’ve recently redesigned my blog using the Sten theme, and I wanted to add a little extra “hacker message” at the top of the page. The idea was simple: a terminal-style widget that looks like a preproduction console, complete with a flashing cursor, glowing border, and a randomly selected phrase.

Visual Images

This is the widget in action on my blog:



Then on a refresh you get a new message:


Step 1: The Original Widget

To start, I wanted a basic terminal banner that displayed a single phrase. This would simulate a “machine gun” style message inspired by Die Hard — something fun but also a signal that this is not the live site.

Here’s the HTML and CSS I used initially:

<div id="terminal-preprod" style="
    background-color: #111;
    color: #ffcc00;
    padding: 20px;
    margin: 20px 0;
    font-family: 'Courier New', Courier, monospace;
    font-size: 18px;
    border: 2px solid #ffcc00;
    border-radius: 6px;
    text-align: left;
    box-shadow: 0 0 15px rgba(255, 204, 0, 0.8);
    animation: pulse-yellow 1.5s infinite;
">
    <span style="color:#ffe066;">preprod@staging</span>:<span style="color:#fff2b3;">~$</span>
    THIS IS PREPRODUCTION - NOW I HAVE A MACHINE GUN HO HO HO
    <span class="cursor">█</span>
</div>

<style>
@keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}

@keyframes pulse-yellow {
    0%   { box-shadow: 0 0 6px rgba(255,204,0,0.5); }
    50%  { box-shadow: 0 0 18px rgba(255,204,0,1); }
    100% { box-shadow: 0 0 6px rgba(255,204,0,0.5); }
}

.cursor {
    animation: blink 1s infinite;
}
</style>

This version worked well, but it was static — the same phrase every time. I wanted it more dynamic.

Step 2: Introducing Random Phrases

The next step was to make the widget dynamic. I wanted to have multiple phrases that could be randomly displayed whenever the page refreshed or when a user navigated around the site.

I chose two themes for the phrases:

  1. Die Hard–style action quotes

  2. Skeletor–style villainous quotes

I created a JavaScript array to store all the phrases:

const phrases = [
    // Die Hard
    "THIS IS PREPRODUCTION - NOW I HAVE A MACHINE GUN HO HO HO",
    "WELCOME TO PREPROD, PAL",
    "YIPPIE-KI-YAY, CHANGE MANAGEMENT",
    // ...additional Die Hard phrases
    "CONGRATULATIONS, YOU FOUND STAGING",

    // Skeletor
    "FOOLS - THIS IS PREPRODUCTION",
    "YOUR CHANGES AMUSE ME, BUT THEY WILL FAIL",
    "YOU DARE DEPLOY WITHOUT TESTING",
    // ...additional Skeletor phrases
    "FAILURES GIVE ME STRENGTH"
];

To ensure the widget displayed clean, readable text, I also added a sanitization function to remove any unexpected characters or smart punctuation that Blogger sometimes inserts:

function sanitizeAscii(str) {
    return str
        .replace(/[‘’“”]/g, "'")
        .replace(/[–—]/g, "-")
        .replace(/[^\x20-\x7E]/g, "");
}

Finally, I used JavaScript to pick a random phrase and inject it into the banner:

const phrase = phrases[Math.floor(Math.random() * phrases.length)];
document.getElementById("randomPhrase").textContent = sanitizeAscii(phrase);

This allowed me to have 30 phrases (15 Die Hard + 15 Skeletor) and display a different one every time the page loads.

Step 3: Adding a Theme Color Variable

Once the phrases were dynamic, I wanted to make the look of the widget configurable. Specifically, I wanted to be able to change the color of the text, border, and glow with a single variable — either by name ("red""purple") or a hexadecimal value ("#ffcc00").

I added a simple configuration variable at the top of the script:

const THEME_COLOR = "#ffcc00"; // Change this to any color

Then, I applied this color to the entire widget:

const container = document.getElementById("terminal-preprod");
container.style.color = THEME_COLOR;
container.style.border = `2px solid ${THEME_COLOR}`;
container.style.boxShadow = `0 0 15px ${THEME_COLOR}`;

const user = document.getElementById("prompt-user");
const path = document.getElementById("prompt-path");

user.style.color = THEME_COLOR;
path.style.color = THEME_COLOR;

This approach ensures that every element of the widget inherits the same color, keeping it consistent while allowing me to change the theme quickly.

Step 4: The Complete Widget Code

Here is the final widget with all phrases, random selection, sanitization, and theme color support:

<div id="terminal-preprod" style="
    background-color: #111;
    padding: 20px;
    margin: 20px 0;
    font-family: 'Courier New', Courier, monospace;
    font-size: 18px;
    border-radius: 6px;
    text-align: left;
">
    <span id="prompt-user"></span>:<span id="prompt-path"></span>
    <span id="randomPhrase"></span>
    <span class="cursor">█</span>
</div>

<script>
(function () {
    // Theme color
    const THEME_COLOR = "#ffcc00";

    // All phrases (Die Hard + Skeletor)
    const phrases = [
        "THIS IS PREPRODUCTION - NOW I HAVE A MACHINE GUN HO HO HO",
        "WELCOME TO PREPROD, PAL",
        "YIPPIE-KI-YAY, CHANGE MANAGEMENT",
        "PREPROD - WHERE PLANS GO TO DIE",
        "JUST A FRIENDLY REMINDER - THIS IS NOT LIVE",
        "NOW I KNOW WHAT A DEPLOY FEELS LIKE",
        "PREPRODUCTION DOES NOT CARE ABOUT YOUR DEADLINES",
        "COME OUT TO PREPROD, WE WILL GET TOGETHER, HAVE A FEW BUGS",
        "THIS ENVIRONMENT IS FULL OF SURPRISES",
        "PROCEED CAREFULLY, HERO",
        "PREPROD - GLASS EVERYWHERE",
        "THIS IS WHAT HAPPENS WHEN YOU SKIP TESTING",
        "WELCOME TO THE PARTY, DEVOPS",
        "PREPROD IS WATCHING YOU",
        "CONGRATULATIONS, YOU FOUND STAGING",
        "FOOLS - THIS IS PREPRODUCTION",
        "YOUR CHANGES AMUSE ME, BUT THEY WILL FAIL",
        "YOU DARE DEPLOY WITHOUT TESTING",
        "I WILL RULE THIS PIPELINE",
        "YOUR CONFIDENCE IS YOUR WEAKNESS",
        "PREPROD BENDS TO MY WILL",
        "ANOTHER MISCONFIGURATION FOR MY COLLECTION",
        "YOU THOUGHT IT WAS LIVE - HA",
        "RUN WHILE YOU STILL CAN",
        "YOUR CODE IS NO MATCH FOR ME",
        "THIS ENVIRONMENT OBEYS SKELETOR",
        "I WARNED YOU ABOUT PREPRODUCTION",
        "YOU HAVE ACTIVATED MY TRAP",
        "YOUR PIPELINE SHALL FALL",
        "FAILURES GIVE ME STRENGTH"
    ];

    // Sanitize for ASCII
    function sanitizeAscii(str) {
        return str
            .replace(/[‘’“”]/g, "'")
            .replace(/[–—]/g, "-")
            .replace(/[^\x20-\x7E]/g, "");
    }

    // Terminal container
    const container = document.getElementById("terminal-preprod");
    container.style.color = THEME_COLOR;
    container.style.border = `2px solid ${THEME_COLOR}`;
    container.style.boxShadow = `0 0 15px ${THEME_COLOR}`;

    // Terminal prompt
    const user = document.getElementById("prompt-user");
    const path = document.getElementById("prompt-path");
    user.textContent = "preprod@staging";
    path.textContent = "~$";
    user.style.color = THEME_COLOR;
    path.style.color = THEME_COLOR;

    // Random phrase
    const phrase = phrases[Math.floor(Math.random() * phrases.length)];
    document.getElementById("randomPhrase").textContent = sanitizeAscii(phrase);
})();
</script>

<style>
.cursor {
    animation: blink 1s infinite;
}

@keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}
</style>

Step 5: Using the Widget

  • Change color: edit THEME_COLOR to any CSS color name or hex value.

  • Add new phrases: add them to the phrases array.

  • Randomization: every page refresh or navigation loads a new phrase.

This setup makes it highly customizable while keeping the terminal look consistent, perfect for a header banner.

Conclusion

I now have a dynamic, terminal-style widget at the top of my Sten-themed blog that is Hacker-style, terminal-inspired widget that randomly displays phrases (Die Hard or Skeletor) which is fully ASCII-safe for Blogger.

It’s a small addition, but it adds personality and interactivity while reminding readers that this is not the live site.