Small projects are the fastest mechanism to demonstrate technical competence. A resume lists claims; a repository provides evidence.

This post documents how to scope, build, and document a "Skill Proof"—a micro-project designed to verify a single capability.

You will implement a specific feature, deploy it to a public URL, and write documentation that explains the technical decision-making process.

This is a lab guide. You should execute these steps locally to produce a portfolio asset.

The promise

By the end of this guide, you will:

  • Scoping a project to a single, verifiable technical skill.
  • Implement a functional "Client-Side Search" demo using vanilla JavaScript.
  • Deploy the project to a public URL.
  • Structure a README that functions as technical documentation.

What this is

High level: A Skill Proof is a contained project that demonstrates proficiency in one specific area (e.g., API integration, state management, or performance optimization) without the overhead of a full application.

Low level: You will create a single HTML file that fetches data and filters it, push it to GitHub, and deploy it via a static host.

Key terms:

  • Scope Creep: The tendency to add unnecessary features (like authentication or complex styling) that distract from the core skill being demonstrated.
  • Proof Link: A direct URL to a running instance of the code. Code that does not run is difficult to verify.
  • Context Statement: A specific section in documentation explaining why the solution was built this way.

What you need

  • A GitHub account.
  • A code editor (VS Code).
  • A terminal.
  • A free Vercel or Netlify account (or GitHub Pages).

Start to Finish

Step 1: Define the scope

Goal: Select a single technical problem to solve. For this lab, the skill is "Efficient Client-Side Filtering."

Actions:

  1. Create a local folder named skill-demo-search.
  2. Create a README.md file immediately.
  3. Add the following "Goal Statement" to the top:
    # Client-Side Search Demo
    **Goal:** Demonstrate performant array filtering on a dataset of 500 records using vanilla JavaScript.
    **Constraint:** No external libraries (no React, no Lodash).

Why: Defining the constraint upfront prevents over-engineering. Employers want to see that you can solve problems with native tools before reaching for heavy frameworks. Writing the goal first keeps the development focused.

Verify:

  • Read the README.
  • Confirm it lists exactly one goal.
  • Confirm it lists exactly one constraint.

If it fails:

  • Symptom: You feel the urge to add a "Login" page.
  • Fix: Delete the idea. Authentication is a separate skill. Do not mix them.

Step 2: Build the demo

Goal: Implement the filtering logic in the simplest possible way.

Actions:

  1. Create an index.html file in your folder.
  2. Paste the following code. This sets up a mock dataset and a search input.
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Skill Proof: Search</title>
    <style>
    body { font-family: system-ui, sans-serif; padding: 20px; max-width: 600px; margin: 0 auto; }
    input { padding: 10px; width: 100%; box-sizing: border-box; margin-bottom: 20px; font-size: 16px; }
    .item { padding: 10px; border-bottom: 1px solid #eee; }
    .hidden { display: none; }
    </style>
    </head>
    <body>
    <h1>Employee Directory</h1>
    <input type="text" id="search" placeholder="Type to filter names...">
    <div id="results"></div>
    <script>
    // 1. Generate Mock Data
    const data = Array.from({ length: 500 }, (_, i) => ({
    id: i,
    name: `Employee ${i + 1}`,
    role: i % 3 === 0 ? 'Engineer' : 'Designer'
    }));
    const list = document.getElementById('results');
    const input = document.getElementById('search');
    // 2. Initial Render
    function render(items) {
    list.innerHTML = items.map(i =>
    `<div class="item"><strong>${i.name}</strong> - ${i.role}</div>`
    ).join('');
    }
    render(data);
    // 3. Filter Logic
    input.addEventListener('input', (e) => {
    const term = e.target.value.toLowerCase();
    const filtered = data.filter(item =>
    item.name.toLowerCase().includes(term)
    );
    render(filtered);
    });
    </script>
    </body>
    </html>
  3. Open index.html in your browser.

Why: This code demonstrates three distinct competencies:

  1. Data generation: Creating mock data for testing.
  2. DOM manipulation: Updating the UI based on state.
  3. Event handling: Reacting to user input in real-time.

Verify:

  1. Type "50" into the box.
  2. Expected: The list updates to show only employees with "50" in their name (e.g., "Employee 50", "Employee 150").
  3. Delete the text.
  4. Expected: The full list returns.

If it fails:

  • Symptom: List vanishes.
  • Fix: Check the console for syntax errors. Ensure render is called inside the event listener.

Step 3: Deploy the project

Goal: Make the code accessible to anyone with a web browser.

Actions:

  1. Push to GitHub:
    git init
    git add .
    git commit -m "feat: implement search logic"
    git branch -M main
    # Create a new repo on GitHub and follow the "push an existing repository" instructions
  2. Deploy (Vercel Example):
    • Go to Vercel.com.
    • Click "Add New" > "Project".
    • Import your new GitHub repository.
    • Click "Deploy".
    • Wait for the "Production Deployment" URL.

Why: Code that sits on your hard drive is invisible to recruiters. A live URL proves the code works in a production environment and shows you understand the deployment lifecycle.

Verify:

  1. Open the Vercel/Netlify URL on your phone (a different device).
  2. Expected: The site loads and the search functions correctly.

If it fails:

  • Symptom: 404 Error.
  • Fix: Ensure your file is named index.html. Most static hosts look for this specific filename by default.

Step 4: Document the proof

Goal: Explain your work so a recruiter understands the value without reading the code.

Actions:

  1. Open README.md.
  2. Replace the contents with this structure:
    # Skill Proof: Client-Side Search
    **Live Demo:** [Insert Vercel URL Here]
    **Source Code:** [Insert GitHub Repo URL Here]
    ## The Goal
    To demonstrate efficient array filtering and DOM updates using vanilla JavaScript, ensuring high performance with a dataset of 500 items.
    ## Technical Choices
    - **Vanilla JS:** Used to avoid the bundle size overhead of React/Vue for a simple list interaction.
    - **Array.filter():** Selected for readability and native browser optimization.
    - **Template Literals:** Used for clean HTML generation within the render function.
    ## How to Run Locally
    1. Clone the repo.
    2. Open `index.html` in any browser.
  3. Push the changes to GitHub.

Why: The README is the interface between your code and the human hiring manager. It provides context. Explicitly stating why you chose Vanilla JS over React shows engineering maturity.

Verify:

  1. Go to your GitHub repository page.
  2. Click the "Live Demo" link in your README.
  3. Confirm it opens the deployed site.

If it fails:

  • Symptom: Links are unclickable.
  • Fix: Ensure you use standard Markdown syntax [Link Text](URL).

Verify it worked

Perform this final audit before sharing the project:

  1. Scope Check: Does the project do exactly one thing (Search)? Yes.
  2. Functionality Check: Does the live link work on a mobile device? Yes.
  3. Documentation Check: Does the README explain the "Why" and not just the "How"? Yes.

Common mistakes

  • Symptom: The project has no README or a default "Create React App" README. Cause: Neglecting documentation. Fix: Always replace default READMEs. A generic README suggests a lack of attention to detail.

  • Symptom: The code works locally but shows a blank page online. Cause: Case sensitivity issues or incorrect file paths. Fix: Ensure files are lowercase (e.g., index.html, not Index.html). Linux servers (used by Vercel/Netlify) are case-sensitive.

  • Symptom: You spent 4 hours styling the page with CSS. Cause: Scope creep. Fix: Use standard browser styles or a classless CSS framework (like Water.css) if you must style it. The goal is to prove the logic, not your design skills.

Cheat sheet

  1. Pick: One specific interaction (Search, Sort, Fetch, Form Validation).
  2. Build: Use the simplest tool for the job (often vanilla JS).
  3. Deploy: Get a public URL immediately.
  4. Link: Put the URL at the very top of the README.

Next steps

  • Refactor: Create a version 2 branch that adds a "Debounce" function to the search input to prove performance optimization skills.
  • Test: Add a simple unit test file to verify the filtering logic.
  • Expand: Do this again for a different skill, like "API Data Fetching" or "Form State Management."

Related links