Michele – Michele Born https://micheleborn.com Software developer Fri, 27 Mar 2026 01:07:18 +0000 en-US hourly 1 https://wordpress.org/?v=7.1 https://micheleborn.com/wp-content/uploads/2023/09/cropped-001-bear-32x32.png Michele – Michele Born https://micheleborn.com 32 32 Growth project https://micheleborn.com/2026/03/27/growth-project/ https://micheleborn.com/2026/03/27/growth-project/#respond Fri, 27 Mar 2026 01:04:54 +0000 https://micheleborn.com/?p=222 I build this little vercel project to test a few things.

Project:
https://gmd-assessment.vercel.app/

Github:
https://github.com/micheleborn/gmd-assessment

The Context

This project was built as part of a Growth Marketing Designer assessment — a role that requires end-to-end ownership of landing pages, from design to deployment, with performance measured by conversion rate .

But the brief came with a twist:

  • No clear audience
  • No defined product positioning
  • No brand guidelines
  • No funnel stage

So instead of “executing,” I had to define the strategy from scratch.

The Goal

Design and build three landing page variants:

  • /control
  • /variant-1
  • /variant-2

Each with:

  • A different conversion hypothesis
  • A consistent structure for testing
  • Measurable behavioral tracking

Step 1 — Defining the Strategy (Before Design)

Instead of jumping into UI, I started with who this is for.

Target audience (assumed)

  • Mid-size DTC brands ($3M–$30M)
  • Paid acquisition fatigue (Meta, CPMs rising)
  • Distrust in attribution
  • Pressure from finance teams

Core emotional state

“I don’t trust my growth anymore.”

That became the foundation of everything.

Step 2 — Hypothesis Design

Each variant explores a different persuasion model:

1. Control — USP Clarity

  • Straightforward messaging
  • “What it does” framing
  • Minimal psychological layering

2. Variant 1 — Authority + Social Proof

  • Borrowed credibility
  • Proof-driven messaging
  • Reduces skepticism

3. Variant 2 — Risk Mitigation (Most interesting)

  • Focus on predictability + control
  • Addresses emotional anxiety directly
  • Designed for decision-makers under pressure

This is not UI variation.
This is psychological positioning testing.

Step 3 — UX & UI Decisions

UX Principles

  • Single goal: conversion
  • No distractions, no navigation complexity
  • Repeated CTA for scanning behavior
  • Clear hierarchy (problem → solution → action)

UI Decisions

  • Clean, high-contrast typography
  • Modular components reused across variants
  • Visual consistency to isolate messaging impact

Important:
I intentionally avoided “fancy design”
Because design should not contaminate the experiment

Step 4 — Development (Next.js + Vercel)

Built with:

  • Next.js + TypeScript
  • Component-based architecture
  • Route-based variant system

Routing strategy

  • /control
  • /variant-1
  • /variant-2

Each route:

  • Injects different content
  • Reuses the same components

This ensures:

  • Fast iteration
  • Clean experiment structure
  • Scalability for future tests

Deployment

  • Deployed via Vercel
  • Instant previews + production parity
  • CI/CD built-in

Step 5 — Analytics (PostHog)

Implemented full tracking:

Events

  • variant_viewed
  • signed_up
  • CTA clicks (with placement tracking)

Data captured

  • Variant name
  • CTA location (hero, footer, etc.)
  • Referral codes

Every interaction is measurable.

Also:

  • Ensured event capture before redirect
  • Structured for funnel analysis

Step 6 — Experiment Design

This is the part most people skip.

What I controlled:

  • Same layout across all variants
  • Same CTA wording
  • Same visual design

What I changed:

  • Messaging strategy only

That’s how you isolate causality

What AI Changed

This project took ~3 days.

Without AI, it would realistically take ~2 weeks.

AI helped with:

  • Validating messaging directions
  • Exploring persuasion angles
  • Speeding up iteration

But:
The strategy decisions were still human

Key Takeaways

  • Conversion is psychology first, design second
  • Most landing pages fail because they skip strategy
  • A/B testing is useless without clear hypotheses
  • Speed matters — but only if direction is correct

Final Thought

This wasn’t a design exercise.

  • It was:
  • Strategy
  • Psychology
  • Engineering
  • Measurement

All in one system.

I actually love the way this turned out – super happy with the results.

]]>
https://micheleborn.com/2026/03/27/growth-project/feed/ 0
Moving a Static Site Off Shared Hosting https://micheleborn.com/2026/03/10/moving-a-static-site-off-shared-hosting/ https://micheleborn.com/2026/03/10/moving-a-static-site-off-shared-hosting/#respond Tue, 10 Mar 2026 16:58:52 +0000 https://micheleborn.com/?p=189 I moved one of my projects off HostGator and onto Cloudflare this morning.

Spoiler alert, it’s this one:

https://hansonhotline.com


Mostly after spending way too much time with support trying to resolve an SSL error. After a few conversations that went nowhere, it felt like the right moment to, as usual, take matters into my own busy hands (on about three hours of sleep, naturally).

A few quick stats:

  • Build time: ~10 seconds
  • Total migration time: ~1.5 hours

Infrastructure steps:

  • Attach custom domain
  • Push React project to GitHub
  • Connect repo to Cloudflare Pages
  • Build & deploy (automatic)
  • Move DNS to Cloudflare

Where we’re at: Vite + TypeScript + Cloudflare + GitHub

The site is now a simple React build (Vite + TypeScript) deployed through Cloudflare Pages, with GitHub triggering the builds. DNS, SSL, and the CDN are handled by Cloudflare, so there’s no server to manage and deployments are just a git push.

It was also a good reminder that sometimes we already know how to do a lot more than we think — it just takes being forced to deploy something for all those pieces to finally click together.

]]>
https://micheleborn.com/2026/03/10/moving-a-static-site-off-shared-hosting/feed/ 0
HansonHotline.com (React + TypeScript) https://micheleborn.com/2026/02/23/hansonhotline-com-react-typescript/ https://micheleborn.com/2026/02/23/hansonhotline-com-react-typescript/#respond Mon, 23 Feb 2026 06:29:56 +0000 https://micheleborn.com/?p=174 Today I designed, built, and deployed a full React application from scratch – not all content is up:

The project was inspired by the band Hanson’s recent “pause” — something longtime fans fear may signal the end. Hanson has been a defining part of my life for over 20 years, and I spent much of that time as a Hanson webmaster, building fan archives and community spaces.

This project blends that history with modern engineering.

Stack

  • React
  • TypeScript
  • Vite
  • TailwindCSS

What I Built

  • Typed archival data model
  • Deterministic timeline navigation with global cursor state
  • Calendar popover with date filtering
  • Speaker-based UI system with typed tone styling
  • Responsive, custom glass UI
  • Full production deployment (build → dist → hosting → OG → favicon)

Highlights

  • Refactored navigation logic to eliminate blank-state edge cases
  • Used import.meta.glob for scalable content ingestion
  • Implemented portal rendering to resolve z-index stacking issues
  • Designed and iterated UX hierarchy intentionally

Timeline

Built end-to-end in a focused ~9-hour session (5pm–2am), including design iteration, debugging, and deployment.

Not bad for a Sunday evening.

]]>
https://micheleborn.com/2026/02/23/hansonhotline-com-react-typescript/feed/ 0
Drowning in Spam https://micheleborn.com/2025/11/27/drowning-in-spam/ https://micheleborn.com/2025/11/27/drowning-in-spam/#respond Thu, 27 Nov 2025 03:57:34 +0000 https://micheleborn.com/?p=167 When Your Friend’s WordPress Site Is Drowning in Spam (And You’re the “Tech Person”)

Every now and then someone messages me with a classic WordPress emergency:

“HELP. My site is getting 400 spam comments a day. What do I do?”

And because I’m the designated “tech friend,” I obviously end up fixing it… for free… at 11 PM… while holding a cappuccino in one hand and my sanity in the other.

So let’s turn this into a teaching moment, shall we?

Here’s how to stop WordPress comment spam quickly:


Option 1: Decide Whether Comments Should Exist at All

Hot take: Most business sites don’t need comments.
If your friend isn’t running a blog with an actual audience, comments are basically an invitation for bots to have a rave in your inbox.

So the fastest possible fix is:

Settings → Discussion → Uncheck “Allow people to submit comments.”

Then kill comments on old posts:

Posts → All Posts → Bulk Edit → Comments → “Do Not Allow.”

Boom. Done. Enjoy the silence.

Here’s a visual:

Screenshot

Option 2: If You Must Keep Comments, At Least Approve Them First

If comments are “important” (read: someone said they might get one someday):

Settings → Discussion → “Comment must be manually approved.”

This stops the spam from showing publicly.
It doesn’t stop it from existing, but at least you’re not advertising Viagra in your testimonial section.


Option 3: Install the Only Plugin That Doesn’t Require Therapy

I absolutely hate plugins (except for ACF – I looooove ACF), but if you don’t have a dev, you might need one – and that’s ok. Just make sure you always have the latest version up. Here’s a suggestion.

Antispam Bee

  • Free
  • Lightweight
  • No API keys
  • No Jetpack accounts
  • No “connect to cloud protection” scams
  • Just works

You literally install it and walk away.

Plugins → Add New → Search “Antispam Bee” → Install → Activate

If that worked, congratulations — you’re now a junior sysadmin.


Option 4: If you must install CAPTCHA

CAPTCHAs are annoying… but sometimes we need it. So, let’s go over that.

Part 1: Get Google reCAPTCHA API Keys 

  1. Go to the Google reCAPTCHA Admin Console at google.com/recaptcha/admin.
  2. Sign in with your Google Account.
  3. Register a new site by providing the required information:
    • Label: A name to help you identify the website (e.g., “My Test Website”).
    • reCAPTCHA type: Choose the version you want (v2 “I’m not a robot” checkbox is common and visually clear; v3 runs in the background and provides a score).
    • Domains: Enter your website’s domain name (e.g., www.yourwebsite.com).
    • Accept the reCAPTCHA Terms of Service and click Submit.
  4. Copy the generated Site Key and Secret Key. You will need these for the next steps. 

Part 2: Install and Configure a WordPress Plugin 

  1. Log in to your WordPress dashboard.
  2. In the left-hand menu, navigate to Plugins > Add New.
  3. In the search bar, type in “CAPTCHA” or “reCAPTCHA”. Recommended plugins include “reCaptcha by BestWebSoft” or “Advanced Google reCAPTCHA”.
  4. Click Install Now next to the chosen plugin, then click Activate.
  5. After activation, go to the plugin’s settings page (usually found under Settings or as its own menu item in the sidebar).
  6. Paste your Site Key and Secret Key into the designated fields.
  7. Configure the settings to choose where the CAPTCHA should appear (e.g., login form, registration form, comment form, contact forms).
  8. Click Save Changes.
  9. Test the CAPTCHA by logging out and checking the form(s) where you enabled it to ensure it is working correctly. 

And… we’re done!

See you next time.

]]>
https://micheleborn.com/2025/11/27/drowning-in-spam/feed/ 0
GDPR Notes https://micheleborn.com/2025/02/09/gdpr-notes/ https://micheleborn.com/2025/02/09/gdpr-notes/#respond Sun, 09 Feb 2025 00:24:13 +0000 https://micheleborn.com/?p=118 Back when I started, not only the front-end developer, the back-end developer, the UX designer and the UI designer was the same person, we also didn’t have the concept of GDPR. The concept of GDPR specifically did not exist in 1998. GDPR was introduced in 2016 and fully enforced in 2018. However, data protection laws did exist before then. The EU had the Data Protection Directive (1995), which laid the groundwork for GDPR but was less strict and not directly enforceable across member states.
We must ensure that websites align with global data privacy regulations, which are becoming increasingly critical in today’s digital landscape.

Here’s a breakdown of the basic rules for each data privacy regulation:

GDPR (Europe)

  • Requires explicit and informed consent before collecting personal data.
  • Grants users the right to access, rectify, and erase their data (“right to be forgotten”).
  • Requires businesses to provide clear privacy policies explaining data usage.
  • Mandates data breach notifications within 72 hours.
  • Enforces data minimization, ensuring only necessary data is collected.
  • Restricts data transfers outside the EU unless safeguards are in place.

CCPA (California, USA)

  • Gives consumers the right to know what personal data is collected and how it’s used.
  • Allows users to opt out of the sale of their personal data.
  • Provides the right to delete personal information upon request.
  • Prohibits discrimination against users who exercise their privacy rights.
  • Requires businesses to have a “Do Not Sell My Personal Information” link on their website.

LGPD (Brazil)

  • Similar to GDPR, it requires clear and informed consent for data collection.
  • Grants users the right to access, correct, delete, and transfer their data.
  • Businesses must appoint a Data Protection Officer (DPO) to oversee compliance.
  • Requires data breach notifications within a reasonable timeframe.
  • Applies to any business handling Brazilian citizens’ data, regardless of location.

PIPEDA (Canada)

  • Organizations must obtain valid consent before collecting personal data.
  • Requires businesses to identify the purpose of data collection and limit its use.
  • Grants individuals the right to access and correct their personal information.
  • Mandates security safeguards to protect data from breaches.
  • Requires data breach reporting if there’s a risk of significant harm.

Each of these regulations has unique rules, but they all emphasize transparency, user control, and data protection. – hence the banner at the bottom of this page!

]]>
https://micheleborn.com/2025/02/09/gdpr-notes/feed/ 0
Memory Game https://micheleborn.com/2025/02/05/memory-game/ https://micheleborn.com/2025/02/05/memory-game/#respond Wed, 05 Feb 2025 04:14:14 +0000 https://micheleborn.com/?p=103 As a part of a JS course that I bought a long time ago from an influecer I really like ( Erick Wendel ) I completed a cute memory game!

I created the images using AutoCAD for the vectors and Photoshop for colouring.

The code is mainly JS and obviously the usual HTML/CSS.

Enjoy!

https://www.quietoode.com/memory-game

]]>
https://micheleborn.com/2025/02/05/memory-game/feed/ 0
Colorful WordPress Tags https://micheleborn.com/2024/02/19/colorful-wordpress-tags/ https://micheleborn.com/2024/02/19/colorful-wordpress-tags/#respond Mon, 19 Feb 2024 00:12:59 +0000 https://micheleborn.com/?p=75 The goal today is to get the tags on my wordpress posts to look like this:

My guidelines are:

  • Add a css tag to every tag on my list, the list being my most common tags: PHP, JS, WP, CSS and GIT
  • Add a css tag for any random tag that I may come up with in the future that matches my main tags.

It’s a very simple php bit I added to my front-page.php file, because that’s where I wanted it to show.

  <?php
    // Define tag name to CSS class mappings
    $tag_class_map = array(
        'Git' => 'git-tag',
        'php' => 'php-tag',
        'wp' => 'wp-tag',
        'css' => 'css-tag',
        'js' => 'js-tag'
    );

    // Check if there are any tags for the current post
    $tags = get_the_tags();
    if ($tags) {
        echo '<ul class="tag-list">';
        foreach ($tags as $tag) {
            // Default CSS class
            $tag_classes = 'code';

            // Check if the tag name exists in the mapping
            if (isset($tag_class_map[$tag->name])) {
                // Assign corresponding CSS class
                $tag_classes = $tag_class_map[$tag->name];
            }

            echo '<li class="' . $tag_classes . '"><a href="' . get_tag_link($tag->term_id) . '">' . $tag->name . '</a></li>';
        }
        echo '</ul>';
    }
?>

I think it looks very nice and organized and I’ve kept the default wordpress settings, meaning the user can click on a tag and use it as a filter.

Another way of setting these, would be using Javascript. I think it’s longer and messier and, in general, I prefer the PHP solution, but here’s the Javacript version:

<ul id="tag-list" class="tag-list">
    <!-- Tags will be dynamically added here -->
</ul>

<script>
    // Define tag name to CSS class mappings
    var tagClassMap = {
        'Git': 'git-tag',
        'php': 'php-tag',
        'wp': 'wp-tag',
        'css': 'css-tag',
        'js': 'js-tag'
    };

    // Function to add tags dynamically
    function addTag(tag) {
        var tagList = document.getElementById('tag-list');
        var tagClasses = tagClassMap[tag.name] || 'code'; // Default to 'code' if no matching CSS class found
        var listItem = document.createElement('li');
        listItem.className = tagClasses;
        var link = document.createElement('a');
        link.href = getTagLink(tag.term_id); // Assuming getTagLink function is defined elsewhere
        link.textContent = tag.name;
        listItem.appendChild(link);
        tagList.appendChild(listItem);
    }

    // Assuming you have an array of tag objects 'tags'
    var tags = [
        { name: 'Git', term_id: 1 },
        { name: 'php', term_id: 2 },
        { name: 'css', term_id: 3 },
        { name: 'html', term_id: 4 } // An example tag with no mapping, defaults to 'code'
    ];

    // Add each tag dynamically
    tags.forEach(function(tag) {
        addTag(tag);
    });
</script>

See you next time,

Michele

]]>
https://micheleborn.com/2024/02/19/colorful-wordpress-tags/feed/ 0
WordPress Custom Header/Footer https://micheleborn.com/2023/10/12/wordpress-custom-header-footer/ https://micheleborn.com/2023/10/12/wordpress-custom-header-footer/#respond Thu, 12 Oct 2023 05:39:25 +0000 https://micheleborn.com/?p=57 By default, our wordpress themes will pull the file header.php and place it at the top of all of our pages.

This is a basic WordPress template structure:

<?php get_header(); ?>

<div class="container">
    <?php if(have_posts()) : while(have_posts()) : the_post(); ?>
        
        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
        <?php the_content(); ?>

    <?php endwhile; endif; ?>
</div>

<?php get_footer(); ?>

Now, for my portfolio page – for example – I may want the header to be different. This requires 2 steps:

Create a header-portfolio.php file

Create a header-portfolio.php file where the word “portfolio” can be replaced with whatever we want, but the naming structure of “header-{any-name-we-want}.php” must be kept.

Our portfolio header may look a little like this:

<!DOCTYPE html>
<html <?php language_attributes(); ?>>

<head>
    <meta charset="<?php bloginfo('charset'); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>

    <header>
        <div class="container">
            <h1>Hello, I am the portfolio header</h1>
            <p><?php bloginfo('description'); ?></p>

            <!-- Navigation Menu -->
            <?php 
                if (has_nav_menu('primary')) {
                    wp_nav_menu(array(
                        'theme_location' => 'primary',
                        'container' => 'nav',
                        'container_class' => 'main-navigation',
                        'menu_class' => 'menu',
                        'depth' => 2,
                    ));
                }
            ?>
        </div>
    </header>

Site note: In this example, I’m using a menu, which requires adding in the functions.php file. This step is not necessary if the new header doesn’t have a menu.

function register_custom_menus() {
    register_nav_menus(
        array(
            'primary' => __('Primary Menu', 'textdomain'),
        )
    );
}
add_action('after_setup_theme', 'register_custom_menus');

Create a page-portfolio.php file

Now, we must create a page-portfolio.php file where the word “portfolio” can be replaced with whatever we want, but the naming structure “page-{any-name-we-want}.php”. must be kept.

The comment at the top of the page is extremely important and not optional*

Notice how on the 3rd line we use <?php get_header(‘portfolio’); ?> , to grab our custom header.

<?php /* Template Name: Portfolio Page */ ?>

Here's what the php could look like:

<?php get_header('portfolio'); ?> 

<div class="container"> 

<h1>This is the Portfolio Page</h1> 

<?php if(have_posts()) : while(have_posts()) : the_post(); ?> 

<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2> 

<?php the_content(); ?> 

<?php endwhile; endif; ?> 

</div> 

<?php get_footer(); ?>

The result should be that now our page will load the custom header (if we select “Portfolio Page” as the template!) . The same rule applies to the footer, where we’d have footer-portfolio.php and <?php get_footer(portfolio); ?> on our code!

]]>
https://micheleborn.com/2023/10/12/wordpress-custom-header-footer/feed/ 0
Github Page https://micheleborn.com/2023/10/12/github-page/ https://micheleborn.com/2023/10/12/github-page/#respond Thu, 12 Oct 2023 04:15:15 +0000 https://micheleborn.com/?p=44 It is still possible to host a personal website/portfolio on GitHub Pages that is publicly accessible at username.github.io. This feature has been and continues to be popular among developers and other GitHub users.

I am only ever on github once in a blue moon. However, I don’t like it one bit when my user page is just blank. So, I took the time to actually put something in there and I am leaving a few notes-to-self here – because there might be another 3 years before I’m in there again.

Create a New Repository:

Go to GitHub and create a new repository.

The repository name must be username.github.io where username is your GitHub username.

Add Content:

Clone the repository to your computer.

git clone https://github.com/username/username.github.io.git

Navigate to the repository directory.

cd username.github.io

Add an index.html file (or a Jekyll theme if you’re familiar with it). This index.html file will be the main page of your website.

Add content to the index.html.

Push to GitHub:

Add the file to git.

git add index.html

Commit the changes.

git commit -m "Initial commit"

Push the changes to GitHub.

git push origin master

Access Your Website:

https://username.github.io/

And here’s what my github site looks like:

https://micheleborn.github.io/

]]>
https://micheleborn.com/2023/10/12/github-page/feed/ 0
GitHub profile README https://micheleborn.com/2023/10/01/github-profile-readme/ https://micheleborn.com/2023/10/01/github-profile-readme/#respond Sun, 01 Oct 2023 04:36:06 +0000 https://micheleborn.com/?p=53 1. Set Up:
  • Create a new repository named the same as your GitHub username (e.g., username/username).
  • This repository should have a README.md file. This README will be displayed on your GitHub profile page.

2. Editing Content:

  • Go to the repository you created.
  • Click on the README.md file.
  • Click the pencil icon (Edit this file).
  • Edit the content using Markdown syntax.
  • Describe your changes in the commit summary and description.
  • Click “Commit changes”.

3. Viewing Changes:

Go to your GitHub profile by clicking on your profile picture on the top right corner and selecting “Your profile”. You’ll see the content of the README.md displayed on your profile.

For both GitHub Pages and GitHub profile README, you can also use git commands (clonecommitpush, etc.) to manage and update your content if you’re familiar with the command line or use a GUI git client.

]]>
https://micheleborn.com/2023/10/01/github-profile-readme/feed/ 0