# Hardeep Kumar Canonical Origin: https://hardeepkumar.in ## LLM Resources - [Full Content](https://hardeepkumar.in/llms-full.txt) Complete page content in markdown format. ## Pages ### Hardeep Kumar Source: https://hardeepkumar.in/ $ decrypting payload… $ cat hero.md h1. <**This site exists because I got bored** /> // Because shouting into the void is more fun when you have a website. $ hover // Look, a card. Hover it. $ expect // What did you expect, innovation? $ certified // Certified portfolio material $ scroll --down $ cat themes.md h2. // Exploring themes across technology, design, and innovation [$**dev**

// Web development, APIs, and backend systems\[15\]](https://hardeepkumar.in/development) [$**ui**

// UI/UX design and frontend experiences\[8\]](https://hardeepkumar.in/design) [$**ops**

// Infrastructure, deployment, and automation\[5\]](https://hardeepkumar.in/devops) [$**learn**

// Tutorials, guides, and knowledge sharing\[12\]](https://hardeepkumar.in/learning) [$view all themes→](https://hardeepkumar.in/themes) --- ### About | Hardeep Kumar Source: https://hardeepkumar.in/about Description: About Hardeep Kumar — web developer (PHP, Python, Django, FastAPI, Vue, Nuxt). $ decrypting payload… $ cat about.md # ** ** // Web developer. PHP & Python backends, Vue/Nuxt frontends.$ whoamiHK@wrench1815status: online▌_// profile shell_$ node --eval'loadProfile()'``` export const profile = { `````` name: 'Hardeep Kumar', `````` handle: 'wrench1815', `````` role: 'Full-stack web developer', `````` focus: ['PHP & Python APIs', 'Vue / Nuxt UIs'], `````` } ``` I am a web developer. Most weeks I am in PHP or Python on the server and Vue or Nuxt on the client — often the same product needs both. I have worked on ed-tech frontends, Django APIs for clients, and long-running apps in production. This site holds my projects, work history, and writing. manifest ## <**Stack** />// What I use day to day.$**backend**### **APIs & services**- →PHP - →Python - →FastAPI - →PostgreSQL - →Redis$**frontend**### **Interfaces**- →Vue - →Nuxt - →TypeScript - →Tailwind CSS$**toolchain**### **Tooling**- →Git & GitHub - →CI/CD - →Docker - →Linux (Arch)$**deploy**### **Hosting**- →AWS - →Vercel - →Railway routes ## <**OnThisSite** />[$ cd themes/

**Themes**

// Writings grouped by theme.](https://hardeepkumar.in/themes) [$ cd project/

**Projects**

// Project write-ups and repos.](https://hardeepkumar.in/project) [$ cd experience/

**Experience**

// Jobs and internships.](https://hardeepkumar.in/experience) io ## <**Contact** />// GitHub or Discord. [@wrench1815](https://github.com/wrench1815/) [@wrench1815](https://discordapp.com/users/457360898122711041) [@wrench1815](https://twitter.com/wrench1815) --- ### Themes | Hardeep Kumar Source: https://hardeepkumar.in/themes Description: Explore themes across technology, design, and innovation $ decrypting payload… $ cd theme/ # ** ** // Browse all available themes and categories [$**ui**

// UI/UX design and frontend experiences\[3items\]](https://hardeepkumar.in/design) [$**ops**

// Infrastructure, deployment, and automation\[3items\]](https://hardeepkumar.in/devops) [$**dev**

// Web development, APIs, and backend systems\[1items\]](https://hardeepkumar.in/development) [$**learn**

// Tutorials, guides, and knowledge sharing\[3items\]](https://hardeepkumar.in/learning) --- ### Development - Themes | Hardeep Kumar Source: https://hardeepkumar.in/development Description: Web development, APIs, and backend systems $ decrypting payload… $ cat development.md # ** ** // Web development, APIs, and backend systems[1topics] [

** **

// Best practices, patterns, and principles for designing RESTful APIs, GraphQL schemas, and microservice interfaces. Covering versioning, authentication, documentation, and more.\[4posts\]](https://hardeepkumar.in/development/api-design) --- ### Design - Themes | Hardeep Kumar Source: https://hardeepkumar.in/design Description: UI/UX design and frontend experiences $ decrypting payload… $ cat design.md # ** ** // UI/UX design and frontend experiences[3topics] [

** **

// A11y best practices, WCAG guidelines, and building inclusive user experiences.\[2posts\]](https://hardeepkumar.in/design/accessibility) [

** **

// Creating and maintaining design systems, tokens, and component libraries.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/design/design-systems) [

** **

// Reusable UI patterns, component design, and frontend architecture for scalable interfaces.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/design/ui-patterns) --- ### DevOps - Themes | Hardeep Kumar Source: https://hardeepkumar.in/devops Description: Infrastructure, deployment, and automation $ decrypting payload… $ cat devops.md # ** ** // Infrastructure, deployment, and automation[3topics] [

** **

// Continuous integration, deployment pipelines, and automation workflows.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/devops/ci-cd) [

** **

// Docker, Kubernetes, and container orchestration for modern deployments.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/devops/containers) [

** **

// Observability, logging, metrics, and alerting for production systems.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/devops/monitoring) --- ### Learning - Themes | Hardeep Kumar Source: https://hardeepkumar.in/learning Description: Tutorials, guides, and knowledge sharing $ decrypting payload… $ cat learning.md # ** ** // Tutorials, guides, and knowledge sharing[3topics] [

** **

// Notes and takeaways from technical and design books.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/learning/book-notes) [

** **

// Short tips, tricks, and productivity hacks for developers and designers.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/learning/tips) [

** **

// Step-by-step guides and how-to articles for learning by doing.\[0posts\] // 404: no posts in repo](https://hardeepkumar.in/learning/tutorials) --- ### Experience | Hardeep Kumar Source: https://hardeepkumar.in/experience $ decrypting payload… h1. Work Experience [Download Resume](https://res.cloudinary.com/dnzbu6wqv/image/upload/v1677943467/resume/hardeep_kumar_resume_sfj5og.pdf) h2. Frontend Developer Intern
**Type**
Internship
**Employer**
Toplearnr Technologies Inc
**Address**
Vancouver, British Columbia, Canada
**Website**
https://www.toplearnr.com
**Tenure**
2022-12-06 00:00:00 - 2024-12-31 00:00:00
Work on B2C Edu Product that provides a Learning platform. My work revolves around Frotend, using VueJS and Nuxt to develop Front facing Elements of the application with Tailwind CSS. h4. Technologies [Vue JS](https://vuejs.org) [Nuxt](https://nuxt.com) [Tailwind CSS](https://tailwindcss.com) [Tailwind UI](https://tailwindui.com) h2. Web Developer Intern
**Type**
Internship
**Employer**
Linked List Technologies LLP
**Address**
Gurugram, Haryana, India
**Website**
https://linkedlist.tech
**Tenure**
2021-09-06 00:00:00 - 2021-11-06 00:00:00
Built Full-Stack Management Web Applications for various client over the time period of 2 months. Also worked on AWS to deploy various Applications build with Django that used Postgres, Redis. Learnt about Web Sockets and used it in Django to build a Real-Time Chat System. h4. Technologies [Python](https://www.python.org) [Django](https://www.djangoproject.com) [Django Channels](https://channels.readthedocs.io/en/stable/) [Bootstrap](https://getbootstrap.com) --- ### Project | Hardeep Kumar Source: https://hardeepkumar.in/project Description: Various Projects that I've worked on over time. $ decrypting payload… h1. Upasthiti (Frontend) An Attendance Management system that was a project idea given by one of my professor but due to the shortened Semester tenure, it was incomplete and still is. I built this project with 2 very talented Frontend Developers. (can't disclose names) The Idea was to make it possible to handle State-wide student Attendance data and generate useful Insights out of it, including but not limited to the Geographical density of students in various parts of State, stats related to migrating students, day to day analysis of students in classes etc. This is the Frontend for the Application which was written by me and 2 more people (can't disclose name) using Nuxt 2. We used MDB for it's Design System with our own custom color pallette. Since our backend was REST based API, we decided to make our site a SPA. We had various logcial components in the project that would allow access to site based on roles. We created many custom components for various UI elements like togglers, timelines, tables etc. It was hosted on Vercel but after Heroku free tier ended, it was removed from Vercel. h2. Technology [Nuxt 2](https://nuxtjs.org) [Nuxt Auth](https://auth.nuxtjs.org) [Nuxt Axios](https://axios.nuxtjs.org) [Nuxt Google Fonts](https://google-fonts.nuxtjs.org) [Nuxt Moment](https://github.com/nuxt-community/moment-module) [Nuxt Lazy Load](https://gitlab.com/broj42/nuxt-lazy-load) [Remix Icon](https://remixicon.com) [VeeValidate](https://vee-validate.logaretm.com/v3/) [Vue Select](https://vue-select.org) [vue2 Datepicker](https://github.com/mengxiong10/vue2-datepicker) [Vue Sweetalerts 2](https://github.com/avil13/vue-sweetalert2) h1. Upasthti (Backend) An Attendance Management system that was a project idea given by one of my professor but due to the shortened Semester tenure, it was incomplete and still is. I built this project with 2 very talented Frontend Developers. (can't disclose names) The Idea was to make it possible to handle State-wide student Attendance data and generate useful Insights out of it, including but not limited to the Geographical density of students in various parts of State, stats related to migrating students, day to day analysis of students in classes etc. This is the Backend for the Application which was written by me, using Django. We used PostgreSQL for it's database and JWT refresh token based Authentication system for Auth. Since we opted for a REST based API backend, we made use of swagger docs as well and kept our API compliant to OAS as much as possible. And it was hosted on Heroku, for as long the free tier was available. h2. Technology [Python 3](https://www.python.org) [Django](https://www.djangoproject.com) [Django REST Framework](https://www.django-rest-framework.org) [PostgreSQL](https://www.postgresql.org) [Django Jazzmin](https://github.com/farridav/django-jazzmin) [DRF Spectacular](https://github.com/tfranzel/drf-spectacular) [Cloudinary](https://cloudinary.com) [Django Filter](https://github.com/carltongibson/django-filter) h1. Inforum (Frontend) A Forum + Blogging Web Application I built with a team of 3 people for 5th semester College Project. The Idea was to create a StackOverflow like community Forum Application aimed specifically for the Students of the College. This is the Frontend for the Application which was written by me and one more person (cannot disclose name) using Nuxt 2. We used MDB for it's Design System with our own custom color pallette. Since our backend was REST based API, we decided to make our site a SPA. We had various logcial components in the project that would allow access to site based on roles. We also wrote our own form Validation system. We also made use of TinyMCE to add the ability to create Rich content for users. We also used Cloudinary for using media fiels like images and also had uploader in our frontend that would upload the media to Cloudinary and then we'd use the returned and store in Database for further use. It was hosted on Vercel but after Heroku free tier ended, it was removed from Vercel. h2. Technology [Nuxt 2](https://nuxtjs.org) [Nuxt Auth](https://auth.nuxtjs.org) [Nuxt Axios](https://axios.nuxtjs.org) [Nuxt Cloudinary](https://cloudinary.nuxtjs.org) [TinyMCE](https://github.com/tinymce/tinymce-vue) [Nuxt Lazy Load](https://gitlab.com/broj42/nuxt-lazy-load) [Particles.js](https://github.com/VincentGarreau/particles.js/) [Prism js](https://prismjs.com) [Vue Advanced Cropper](https://github.com/advanced-cropper/vue-advanced-cropper) [Vue Sweetalerts 2](https://github.com/avil13/vue-sweetalert2) h1. Inforum (Backend) A Forum + Blogging Web Application I built with a team of 3 people for 5th semester College Project. The Idea was to create a StackOverflow like community Forum Application aimed specifically for the Students of the College. This is the Backend for the Application which was written by me, using ASP dotnet 6. We used SQL Server 2019 for it's database and JWT Token based Authentication system for Auth. Since we opted for a REST based API backend, we made use of swagger docs as well and kept our API compliant to OAS as much as possible. And it was hosted on Heroku, for as long the free tier was available. h2. Technology [ASP Dotnet](https://dotnet.microsoft.com/en-us/apps/aspnet) [Core Admin](https://github.com/edandersen/core-admin) [Microsoft Identity](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity) [EntityFramework](https://learn.microsoft.com/en-us/ef/core/) [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) [SQL Server 19](https://www.microsoft.com/en-in/sql-server/sql-server-2019) h1. GH Grabber (Android App) An Android Application to grab User public Information from GitHub using GitHub's API. It grabs the public Information of user like their name, email, repositories etc. h2. Technology [Javascript](https://www.ecma-international.org/) [Vue 3](https://vuejs.org) [capacitor](https://capacitorjs.com) [Ionic](https://ionicframework.com) [GitHub API](https://docs.github.com/en/rest) h1. Product API An API for Products emulating Flipkart and Amazon vendor to provide a dummy API backend. This Project was built by me for my Batchmate who needed an API backend to list out projects for their Project. h2. Technology [Python 3](https://www.python.org) [Django](https://www.djangoproject.com) [Django REST Framework](https://www.django-rest-framework.org) [PostgreSQL](https://www.postgresql.org) h1. GH Grabber A Web Application to grab User public Information from GitHub using GitHub's API. It grabs the public Information of user like their name, email, repositories etc. h2. Technology [Javascript](https://www.ecma-international.org/) [Vue 2](https://v2.vuejs.org) [Nuxt 2](https://nuxtjs.org) [Material Design Bootstrap](https://mdbootstrap.com) [GitHub API](https://docs.github.com/en/rest) h1. Wrenchlog (also blog) A Blog Site I built will learning Django. This Project was my many Portfolio/Blog Site. This Project used various packages django like django-ckeditor, django Jazzmin, Pillow etc.to build the full on Blogging system with PostgreSQL as Database. I also used Dropbox with Django storages for storing media files. It used to be hosted on Heroku. h2. Technology [Python 3](https://www.python.org) [Django](https://www.djangoproject.com) [PostgreSQL](https://www.postgresql.org) [Django Jazzmin](https://github.com/farridav/django-jazzmin) [Django CKEditor](https://github.com/django-ckeditor/django-ckeditor) [Dropbox](https://www.dropbox.com) [Django Storages](https://github.com/jschneier/django-storages) h1. Calc A Calculator to perform simple Addition, Subtraction, Multiplication and Division built using JS and MDB h2. Technology [Javascript](https://www.ecma-international.org/) [Material Design Bootstrap](https://mdbootstrap.com) h1. Flasog A Blog Site I built will learning Flask. This Project was my first Portfolio/Blog Site. And where all the Web Development of mine started. Thie Project used various packages like SQLAlchemy, PageDown(WYSIWYG), Pillow etc.to build the full on Blogging system with sqlite as Database. h2. Technology [Flask](https://flask.palletsprojects.com) [SQLAlchemy](https://www.sqlalchemy.org) [Flask PageDown](https://github.com/miguelgrinberg/Flask-PageDown) [Flask Admin](https://github.com/miguelgrinberg/Flask-PageDown) [Flask Bootstrap](https://github.com/mbr/flask-bootstrap) [WTForms](https://wtforms.readthedocs.io/en/3.0.x/) h1. Tasker A Task manager built using Flask. This is just a simple Task Manager (todo crud) to manage one's tasks. h2. Technology [Flask](https://flask.palletsprojects.com) [SQLAlchemy](https://www.sqlalchemy.org) h1. pyPaint A Windows paint application built using Python 3 and TKinter. One on my ventures that I had while learning python some years ago. Can run on non windows OS too but Originally built for Windows. h2. Technology [Python 3](https://www.python.org) [TKinter](https://docs.python.org/3/library/tkinter.html) h1. Tic Tac Toe A Basic Command Line game made using c++,named Tic Tac Toe. There will be two players, 'Player1' and 'Player 2' WHo will compete against each other in a Game of Tic Tac Toe. The C++ Version used is ISO so Turbo won't work. h2. Technology [C++](https://isocpp.org) h1. Image Viewer A Simple Image Viewer built using Windows Forms and C#. This project, I worked on in 2020, when I was learning C# and wanted to make GUI Application. So I decided to build a very simple Image Viewer as an Exercise and it turned out good. h2. Technology [C#](https://learn.microsoft.com/en-us/dotnet/csharp) [Windows Forms](https://learn.microsoft.com/en-us/dotnet/desktop/winforms) --- ### Posts — API Design | Hardeep Kumar Source: https://hardeepkumar.in/development/api-design Description: Best practices, patterns, and principles for designing RESTful APIs, GraphQL schemas, and microservice interfaces. Covering versioning, authentication, documentation, and more. $ decrypting payload… $ ls -la development/api-design/ # ** ** // Best practices, patterns, and principles for designing RESTful APIs, GraphQL schemas, and microservice interfaces. Covering versioning, authentication, documentation, and more.[4posts] [

** **

// Why we confuse coding and engineering, and what it means to build systems that last.\[Mar 1, 2026\]· 6 min read](https://hardeepkumar.in/development/api-design/coding-vs-engineering) [

** **

// Why designing APIs is not the same as making them work — and how RESTful principles help you stay predictable, consistent, and kind to the developers on the other side of your HTTP boundary.\[Jan 15, 2026\]· 6 min read](https://hardeepkumar.in/development/api-design/restful-api-design-principles) [

** **

// Neither GraphQL nor REST is “better”—they solve different problems. A grounded look at trade-offs, caching, team fit, and when each style earns its place (or doesn’t).\[Jan 10, 2026\]· 5 min read](https://hardeepkumar.in/development/api-design/graphql-vs-rest) [

** **

// Why versioning is about trust, not fashion — URL vs header vs “no versioning,” what it really costs to maintain multiple versions, and a practical default that most teams can ship without regret.\[Jan 5, 2026\]· 5 min read](https://hardeepkumar.in/development/api-design/api-versioning-strategies) --- ### Posts — Accessibility | Hardeep Kumar Source: https://hardeepkumar.in/design/accessibility Description: A11y best practices, WCAG guidelines, and building inclusive user experiences. $ decrypting payload… $ ls -la design/accessibility/ # ** ** // A11y best practices, WCAG guidelines, and building inclusive user experiences.[2posts] [

** **

// Keyboard navigation isn’t a niche preference — it’s capability. Why invisible focus rings and chaotic tab order fail everyone, and how to design for “no mouse” from the start.\[Apr 12, 2026\]· 6 min read](https://hardeepkumar.in/design/accessibility/keyboard-focus-is-the-baseline) [

** **

// Why your div-heavy markup hurts accessibility, SEO, and maintainability — and why choosing elements for what things *are* beats styling-first thinking.\[Apr 12, 2026\]· 9 min read](https://hardeepkumar.in/design/accessibility/semantic-html-beyond-divs) --- ### Posts — Design Systems | Hardeep Kumar Source: https://hardeepkumar.in/design/design-systems Description: Creating and maintaining design systems, tokens, and component libraries. $ decrypting payload… $ ls -la design/design-systems/ # ** ** // Creating and maintaining design systems, tokens, and component libraries.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'design-systems') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — UI Patterns | Hardeep Kumar Source: https://hardeepkumar.in/design/ui-patterns Description: Reusable UI patterns, component design, and frontend architecture for scalable interfaces. $ decrypting payload… $ ls -la design/ui-patterns/ # ** ** // Reusable UI patterns, component design, and frontend architecture for scalable interfaces.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'ui-patterns') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — CI/CD | Hardeep Kumar Source: https://hardeepkumar.in/devops/ci-cd Description: Continuous integration, deployment pipelines, and automation workflows. $ decrypting payload… $ ls -la devops/ci-cd/ # ** ** // Continuous integration, deployment pipelines, and automation workflows.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'ci-cd') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — Containers | Hardeep Kumar Source: https://hardeepkumar.in/devops/containers Description: Docker, Kubernetes, and container orchestration for modern deployments. $ decrypting payload… $ ls -la devops/containers/ # ** ** // Docker, Kubernetes, and container orchestration for modern deployments.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'containers') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — Monitoring | Hardeep Kumar Source: https://hardeepkumar.in/devops/monitoring Description: Observability, logging, metrics, and alerting for production systems. $ decrypting payload… $ ls -la devops/monitoring/ # ** ** // Observability, logging, metrics, and alerting for production systems.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'monitoring') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — Book Notes | Hardeep Kumar Source: https://hardeepkumar.in/learning/book-notes Description: Notes and takeaways from technical and design books. $ decrypting payload… $ ls -la learning/book-notes/ # ** ** // Notes and takeaways from technical and design books.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'book-notes') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — Tips & Tricks | Hardeep Kumar Source: https://hardeepkumar.in/learning/tips Description: Short tips, tricks, and productivity hacks for developers and designers. $ decrypting payload… $ ls -la learning/tips/ # ** ** // Short tips, tricks, and productivity hacks for developers and designers.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'tips') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Posts — Tutorials | Hardeep Kumar Source: https://hardeepkumar.in/learning/tutorials Description: Step-by-step guides and how-to articles for learning by doing. $ decrypting payload… $ ls -la learning/tutorials/ # ** ** // Step-by-step guides and how-to articles for learning by doing.[0posts]$ node --eval'inspectTopicPosts()'``` await queryCollection('blog') `````` .where('type', '=', 'post') `````` .where('topicId', '=', 'tutorials') `````` .all() `````` [] `````` NotFoundError: **404** — empty result; no rows for this topicId. Nothing to render. ``` // posts.length === 0 → no children mounted; query OK, result set empty --- ### Coding Is Easy, Engineering Is Hard | Hardeep Kumar Source: https://hardeepkumar.in/development/api-design/coding-vs-engineering Description: Why we confuse coding and engineering, and what it means to build systems that last. $ decrypting payload… stdin$ cat coding-vs-engineering.md/* development/api-design/coding-vs-engineering */ # <**Coding Is Easy, Engineering Is Hard** />//Why we confuse coding and engineering, and what it means to build systems that last.date[**Mar 1, 2026**]read[**6 min read**]tag#**API Design** stdout Most of us remember the first time we got code to run. Maybe it was a flashing "Hello, World!" on the screen. Maybe it was a bouncing ball in a game engine. Maybe it was a Python script that printed your name in 100 different fonts just because you could. Whatever it was, that moment was magic. You wrote a few lines, hit "run," and the computer obeyed. You felt powerful. And in a way, you were right: coding is powerful. But here's the thing nobody tells you in that honeymoon phase: > **Coding is easy. Engineering is hard.**## Why Coding Feels Easy (Even When It's Not) Now before you argue — yes, learning to code can be frustrating. The syntax errors, the missing semicolons, the cryptic compiler messages that sound like they came from an angry alien. That part isn't exactly "easy." But once you get the hang of it, you realize coding is fundamentally straightforward. You tell the computer what to do, and it does it. - Need to scrape a website? There's a library for that. - Want to play sound when you click a button? Copy-paste two lines from Stack Overflow. - Need to add physics to a cube in Unreal Engine? Drag, drop, done. The world is overflowing with tutorials, docs, and snippets. Once you know the basics, you can "make stuff work" fairly quickly. This is why people say anyone can learn to code. And they're right. You can learn enough JavaScript in a week to make a to-do app. But can you make that same to-do app still work flawlessly two years later, after three feature pivots, a new team, and five thousand users? That's where engineering steps in. ## The Hard Part Nobody Warns You About Software engineering isn't about "making it work." It's about making it work reliably, repeatedly, and with other human beings constantly poking at it. contrast// A login page is trivial.+ A login system that handles millions of users, prevents brute force attacks, integrates with third-party OAuth providers, logs events securely, and still loads in under 200ms? That's engineering. When you cross the line from "I wrote some code" to "I built a system that must survive the real world," you discover new enemies: manifest**01****Complexity creep.** Your 200-line project balloons into 20,000 lines spread across services, each depending on three other services, none documented properly.**02****Other humans.** Your teammate pushes "just a small change," and suddenly production is on fire. Half your time is spent deciphering variable names like tempDataFinalV2.**03****The future.** That quick hack you wrote to meet a deadline? It's now permanent infrastructure. Six months later, you're the person cursing your own name.**04****The evidence.** When nobody can explain how a release got to production, you don't have a coding problem; you have an engineering gap in visibility and ownership. ## The Illusion of Progress Part of what makes engineering difficult is that good engineering is invisible. When you write code, the output is obvious. You can point at a feature and say, "I built that." When you engineer a robust system, your reward is… silence. No crashes. No frantic late-night bug hunts. Just a boring system quietly doing its job._It's like plumbing: nobody compliments their pipes until water is shooting out of the ceiling._ This creates a paradox: the more skilled you are as an engineer, the less flashy your work looks. And yet, without that invisible scaffolding, the flashy stuff collapses. ## The Real Job: Trade-offs If coding is about solving problems, engineering is about managing trade-offs. - Do we ship fast, or build for maintainability? - Do we optimize for performance, or readability? - Do we scale vertically (bigger servers) or horizontally (more servers)? - Do we fix the bug properly, or patch it because the demo is tomorrow? There's rarely a perfect answer. Every decision comes with pain — you're just choosing which pain hurts less. This is why senior engineers aren't measured by how many lines of code they write. They're measured by how well they navigate these trade-offs without sinking the project. ## Some Yardsticks (Why Engineering Shows Up in the Spreadsheet) You don't need a personal war story to see the gap. A few scales people actually use in the industry: | Lens | Mostly coding | Mostly engineering | | --- | --- | --- | | **Question you answer** | "Does it run on my machine?" | "What happens when it doesn't, and who finds out first?" | | **Default output** | A feature you can demo | A change you can roll back, observe, and reason about | | **Time sink (typical mature product)** | Writing the new path | Tests, monitoring, migrations, on-call, and explaining behavior to other teams | | **Cost of wrong assumption** | Cheapest in design/review | Priciest after other systems and customers depend on the behavior | Research and practice on **defect cost** (the old curve: requirements → design → implementation → test → production) all say the same shape: the later you learn you were wrong, the more expensive the fix — not because people are lazy, but because more surface area, data, and humans are coupled to the mistake.**DORA metrics** (deployment frequency, lead time for changes, change failure rate, time to restore) are another blunt instrument: they don't measure "how good your code looks," they measure whether your _system_ for shipping and recovering is under control. High performers aren't people who type faster; they're teams that engineered feedback and safety into the pipeline. None of this replaces judgment. It just explains why "we shipped it" and "we can live with it" are different bars — and why the second one quietly eats the calendar. ## Why We Confuse the Two We tend to celebrate coding because it's measurable. Lines written, commits pushed, features added. Engineering feels less tangible. The irony? Engineering is what keeps projects alive. Most startups don't die because someone couldn't write code. They die because their systems couldn't scale, their architecture couldn't adapt, or their technical debt became unbearable. diff-Coding is flashy.+Engineering is survival. ## Final Thought So yes, coding is easy. You can learn enough in a weekend to build something cool. But engineering? That's the craft. That's where the real work — and real headaches — begin. Coding is telling a computer what to do. Engineering is making sure the computer — and your teammates — don't ruin your life later. If coding is Lego, engineering is city planning. Anyone can build a house. Building a city that doesn't collapse under traffic, bad weather, and human chaos? That's the hard part. And honestly, that's what makes it fun. --- ### RESTful API Design Principles | Hardeep Kumar Source: https://hardeepkumar.in/development/api-design/restful-api-design-principles Description: Why designing APIs is not the same as making them work — and how RESTful principles help you stay predictable, consistent, and kind to the developers on the other side of your HTTP boundary. $ decrypting payload… stdin$ cat restful-api-design-principles.md/* development/api-design/restful-api-design-principles */ # <**RESTful API Design Principles** />//Why designing APIs is not the same as making them work — and how RESTful principles help you stay predictable, consistent, and kind to the developers on the other side of your HTTP boundary.date[**Jan 15, 2026**]read[**6 min read**]tag#**API Design** stdout APIs are one of those things that seem deceptively simple at first. You spin up a server, define a couple of routes, return some JSON, and suddenly — congratulations — you have an API. It works. Your frontend talks to it. Life is good. And then a few weeks later, something feels… off. Endpoints start multiplying. Naming becomes inconsistent. Someone adds `/getUserData`, someone else adds `/users/list`, and now nobody knows what the “correct” pattern is anymore. You fix one thing, break another, and before you know it, your API feels less like a system and more like a collection of accidents. That’s usually the moment people discover that **designing APIs is not the same as making them work.** And that’s where REST — or more accurately, _RESTful design principles_ — comes in. Not as a strict religion, but as a set of guidelines to stop things from descending into chaos. ## First, Let’s Get This Out of the Way REST is not about using HTTP. It’s not about returning JSON. And it’s definitely not about naming your endpoint `/api/v1/` and calling it a day. REST (Representational State Transfer) is really about **how you structure interactions between systems** so they remain predictable, scalable, and understandable — especially when multiple people (or teams) are involved. Think of it less like a rulebook and more like good manners. You _can_ ignore them, but everyone interacting with your API will silently judge you for it. ## 1. Resources, Not Actions One of the biggest beginner mistakes is designing APIs around **verbs** instead of **things**. You’ll see endpoints like: - `/getUser`- `/createOrder`- `/deleteProduct` It makes sense at first. You’re describing what the API does. But here’s the problem: HTTP already gives you verbs — `GET`, `POST`, `PUT`, `DELETE`. So when you write `/getUser`, you’re basically saying “GET getUser,” which is… not great. A RESTful approach flips this: - `/users`- `/orders`- `/products` Now the URL represents a **resource**, and the HTTP method represents the **action**. - `GET /users/42` → fetch user - `POST /users` → create user - `DELETE /users/42` → delete user It’s cleaner, more consistent, and — most importantly — predictable. And predictability is everything in API design. ## 2. Consistency Is More Important Than Perfection Here’s something that might sound controversial: > A perfectly designed API that’s inconsistent is worse than a slightly flawed API that’s consistent. Why? Because humans consume APIs. And humans rely on patterns. If one endpoint uses `/users/{id}` and another uses `/getUserById`, your brain has to switch contexts every time. Multiply that across dozens of endpoints and multiple developers, and suddenly simple tasks become annoying. Consistency shows up in small things: - Naming conventions ( `snake_case` vs `camelCase`) - Plural vs singular resources - Error response formats - Pagination style None of these decisions are “universally correct.” What matters is that once you choose a pattern, you **stick to it like your sanity depends on it** — because it kind of does. ## 3. Use HTTP Like It Was Intended HTTP isn’t just a transport layer — it already encodes a lot of meaning. Ignoring that is like buying a car and pushing it instead of driving it. Each method exists for a reason: - `GET` → safe, read-only - `POST` → create - `PUT/PATCH` → update - `DELETE` → remove And beyond methods, there are **status codes** — one of the most underused features in APIs. Returning `200 OK` for everything is the API equivalent of saying “it’s fine” when everything is clearly not fine. Instead: - `200` → success - `201` → resource created - `400` → bad request - `404` → not found - `500` → server error These aren’t just technical details — they’re part of your API’s language. Use them well, and your API becomes self-explanatory. Ignore them, and every client has to guess what went wrong. ## 4. Design for the Client, Not Your Database A very common anti-pattern is letting your database schema leak directly into your API. You end up with responses that look like this:``` { "usr_id": 42, "usr_nm": "John", "usr_crtd_dt": "2024-01-01" } ``` Sure, it matches your database. But now every frontend developer has to mentally decode your naming conventions like they’re solving a puzzle. Your API is not your database. It’s a **contract with the outside world**. Design responses that are: - Clear - Intuitive - Stable over time You can change your database schema later. Changing your API? That’s where things get painful. ## 5. Versioning: Because You _Will_ Break Things No matter how carefully you design your API, you will eventually need to change it. Maybe you rename a field. Maybe you restructure responses. Maybe you realize your original design had… questionable life choices. This is where versioning comes in: - `/api/v1/users`- `/api/v2/users` It’s not glamorous, but it’s necessary. Versioning gives you room to evolve without breaking existing clients. And trust me, nothing destroys trust faster than silently breaking someone’s integration. ## 6. Keep It Stateless (Even If You’re Tempted Not To) REST encourages **statelessness**, which basically means: > Each request should contain everything the server needs to process it. No hidden session magic. No relying on what happened in the previous request. Why does this matter? Because stateless systems are: - Easier to scale - Easier to debug - Easier to reason about Yes, it can feel slightly more verbose. But the alternative is subtle, hard-to-track bugs that only appear under specific conditions — the kind that ruin your weekend. ## 7. Good APIs Feel Boring (And That’s a Compliment) A well-designed API shouldn’t feel clever. It shouldn’t surprise you. It shouldn’t make you stop and think, _“Wait… how does this one work again?”_ It should feel… obvious. That’s the goal. When someone uses your API for the first time and everything behaves exactly how they expected, you’ve done your job. If they need documentation open at all times just to guess your endpoints, something went wrong. ## The Real Principle Behind All Principles Here’s the part most articles skip: REST isn’t about rules. It’s about **reducing cognitive load**. Every design choice you make either: - Makes your API easier to understand - Or adds friction That’s it. Good API design is empathy. It’s thinking about the developer on the other side — maybe tired, maybe under deadline pressure — trying to make sense of what you built. If they can use your API without frustration, you’ve succeeded. ## Closing Thought Anyone can build an API that works. But building an API that is **predictable, consistent, and pleasant to use** — that’s engineering. And much like everything else in software, the difference isn’t in whether it works today. It’s in whether it still makes sense tomorrow, when more people depend on it, and the system inevitably grows. So next time you’re about to add `/getUserDataFinalV2`, take a step back. Your future self — and everyone else — will thank you. --- ### GraphQL vs REST — When to Use What | Hardeep Kumar Source: https://hardeepkumar.in/development/api-design/graphql-vs-rest Description: Neither GraphQL nor REST is “better”—they solve different problems. A grounded look at trade-offs, caching, team fit, and when each style earns its place (or doesn’t). $ decrypting payload… stdin$ cat graphql-vs-rest.md/* development/api-design/graphql-vs-rest */ # <**GraphQL vs REST — When to Use What** />//Neither GraphQL nor REST is “better”—they solve different problems. A grounded look at trade-offs, caching, team fit, and when each style earns its place (or doesn’t).date[**Jan 10, 2026**]read[**5 min read**]tag#**API Design** stdout If you’ve spent any time around backend development, you’ve probably seen this debate play out: > "GraphQL is the future.” > > “REST is simple and battle-tested.” > > “GraphQL solves over-fetching.” > > “REST is easier to debug." At some point it stops being a discussion and starts sounding like two camps arguing over tabs vs spaces. The truth, as usual, is less dramatic:**Neither GraphQL nor REST is “better.” They just solve different problems.** The real skill isn’t picking a side. It’s knowing when each one makes sense — and when it doesn’t. ## First, What Are We Actually Comparing? Before we get into trade-offs, let’s strip this down to basics.**REST** is an architectural style where: - You expose resources ( `/users`, `/orders`) - You use HTTP methods ( `GET`, `POST`, etc.) - Each endpoint returns a fixed structure**GraphQL**, on the other hand: - Exposes a single endpoint (usually `/graphql`) - Lets the client _ask for exactly what it needs_- Uses a query language instead of multiple URLs So the core difference isn’t syntax. It’s **who controls the data shape**: - REST → **Server decides** the structure - GraphQL → **Client decides** the structure That one shift changes everything. ## Why GraphQL Feels So Powerful The first time you use GraphQL properly, it feels like cheating. Instead of juggling multiple endpoints like: - `/users/42`- `/users/42/posts`- `/users/42/followers` You just write one query:``` query { user(id: 42) { name posts { title } followers { count } } } ``` And you get exactly what you asked for. No over-fetching. No under-fetching. No chaining requests like it’s 2009. It’s clean. It’s efficient. It makes frontend developers very happy. ## But That Power Comes With a Price GraphQL doesn’t remove complexity. It **moves it**. In REST, complexity is spread across endpoints. In GraphQL, complexity gets concentrated into one system. Now you have to deal with: - Query parsing and validation - Performance (nested queries can explode fast) - Caching (not as straightforward as REST) - Authorization at a field level - N+1 query problems if you’re not careful In other words, GraphQL gives clients flexibility — but makes the server work harder to support it safely. ## When REST Is the Better Choice Despite all the hype around GraphQL, REST is still the default for a reason. ### 1. When Your Data Model Is Simple If your API mostly looks like: - CRUD operations - Clear resource boundaries - Predictable responses Then REST is perfect. Adding GraphQL here is like installing a jet engine on a bicycle. Impressive, but unnecessary. ### 2. When You Care About Caching and Performance Simplicity REST works beautifully with HTTP caching: - `GET` requests can be cached easily - CDNs understand it natively - Debugging performance is straightforward GraphQL, on the other hand, makes caching harder because every query can be different. ### 3. When Your Team Needs Simplicity REST is easier to: - Learn - Debug - Maintain You can hit an endpoint with a browser or `curl` and immediately see what’s going on. GraphQL requires more tooling, more setup, and more discipline. If your team is small or your system isn’t that complex, REST will get you far without unnecessary overhead. ## When GraphQL Starts Making Sense Now let’s flip the coin. ### 1. When the Frontend Needs Flexibility If your frontend constantly changes its data needs — especially across: - Web - Mobile - Different UI versions GraphQL shines. Instead of asking backend devs to add new endpoints every week, frontend devs can shape their own queries. This reduces back-and-forth and speeds up iteration. ### 2. When You’re Aggregating Multiple Data Sources If your API pulls data from: - Multiple services - Different databases - External APIs GraphQL can act as a **unified layer**. Instead of clients juggling multiple endpoints, they get a single query interface. ### 3. When Over-fetching Becomes a Real Problem In REST, you might fetch:``` { "id": 42, "name": "John", "email": "...", "address": "...", "preferences": "...", "settings": "..." } ``` …even if you only needed `name`. GraphQL avoids that entirely. Now, to be fair — over-fetching is often exaggerated. But at scale (especially on mobile networks), it _can_ matter. ## The Hidden Trade-off Nobody Talks About Here’s something you won’t hear often: > GraphQL optimizes for frontend developer experience. > > REST optimizes for system simplicity. That’s the real trade-off. GraphQL gives you flexibility and power — but demands discipline and infrastructure. REST gives you constraints — but keeps things understandable and stable. And in software, constraints are often what keep systems sane. ## A Practical Way to Decide Instead of debating philosophies, ask yourself: - Is my data model simple and stable? → **Use REST**- Do I need flexible, client-driven queries? → **Consider GraphQL**- Is my team ready to handle added complexity? → **Be honest here**- Am I solving a real problem, or chasing a trend? → **This one matters most** Because let’s be real — a lot of GraphQL adoption comes from “it looks cool,” not from actual need. ## You Don’t Have to Pick One Forever This isn’t a lifetime commitment. Many systems use both: - REST for simple, stable operations - GraphQL for complex, client-driven queries It’s not cheating. It’s practical. ## Closing Thought The GraphQL vs REST debate is often framed as a competition. It’s not. It’s a design decision. And like most design decisions in software, it comes down to trade-offs, context, and constraints — not hype. So the next time someone confidently declares, _“GraphQL is better,”_ or _“REST is outdated,”_ you can safely assume one thing: They’re optimizing for opinions, not systems. And good engineering has never been about that. --- ### API Versioning Strategies | Hardeep Kumar Source: https://hardeepkumar.in/development/api-design/api-versioning-strategies Description: Why versioning is about trust, not fashion — URL vs header vs “no versioning,” what it really costs to maintain multiple versions, and a practical default that most teams can ship without regret. $ decrypting payload… stdin$ cat api-versioning-strategies.md/* development/api-design/api-versioning-strategies */ # <**API Versioning Strategies** />//Why versioning is about trust, not fashion — URL vs header vs “no versioning,” what it really costs to maintain multiple versions, and a practical default that most teams can ship without regret.date[**Jan 5, 2026**]read[**5 min read**]tag#**API Design** stdout There’s a moment in every API’s life when things start to… drift. It begins innocently. You add a field here, tweak a response there. Maybe you rename something because “it makes more sense now.” Everything still works — mostly. Then one day, a client breaks. Not your code. Not your server. Someone else’s integration. And suddenly you realize something uncomfortable:**Your API isn’t just yours anymore.** Once people depend on your API, every change becomes a potential breaking change. And unless you enjoy angry messages and emergency rollbacks, you need a plan. That plan is called **versioning**. ## Why Versioning Exists (Beyond “Because Everyone Does It”) Versioning isn’t about organization. It’s about **trust**. When someone integrates with your API, they’re making an assumption: > “This behavior won’t randomly change tomorrow.” The moment you break that assumption without warning, you’ve created friction. Do it enough times, and people stop trusting your system entirely. Versioning is your way of saying: - “This version behaves like _this_.” - “If we change something incompatible, we’ll do it _somewhere else_.” It gives you freedom to evolve **without pulling the rug out from under everyone else**. ## The Real Problem: Change Is Inevitable No matter how carefully you design your API, you will eventually need to: - Rename fields - Change response structures - Remove deprecated endpoints - Fix design mistakes you didn’t realize at the start And yes, you will have design mistakes. Everyone does. The question isn’t _if_ you’ll break something. It’s _how gracefully you handle it when you do._## Strategy #1: URL Versioning (The Popular Kid) This is the one you’ve seen everywhere:``` /api/v1/users /api/v2/users ``` Simple. Obvious. Hard to mess up. ### Why it works: - Easy to understand - Easy to route internally - Clients can explicitly choose versions - Debugging is straightforward ### Why it’s not perfect: - URLs can get cluttered over time - You might end up maintaining multiple versions longer than you’d like - It encourages “big bang” version jumps instead of gradual evolution Still, for most teams, this is the default — and for good reason. It’s boring, and boring is reliable. ## Strategy #2: Header Versioning (The Subtle One) Instead of putting the version in the URL, you use headers:``` GET /users Accept: application/vnd.myapi.v2+json ```### Why people like it: - Cleaner URLs - Versioning becomes part of content negotiation - Feels more “RESTful” in theory ### Why people regret it: - Harder to test manually - Less visible (you can’t see the version in the URL) - Debugging becomes slightly more annoying It’s elegant, but sometimes elegance comes at the cost of practicality. ## Strategy #3: Query Parameter Versioning (The “Please Don’t” Option)``` /users?version=2 ``` Yes, it works. No, it’s not a great idea. ### Why it’s problematic: - Easy to forget or misuse - Feels inconsistent with how APIs are typically structured - Can lead to messy routing logic This approach often shows up in early-stage projects and quietly disappears later. ## Strategy #4: No Versioning (a.k.a. “We’ll Figure It Out Later”) Some teams try to avoid versioning entirely by making only backward-compatible changes. In theory, this sounds great: - No version fragmentation - No duplication - No migration headaches In reality, it’s… optimistic. You can keep things backward-compatible for a while. But eventually, you’ll hit a wall where: - Old decisions limit new features - Workarounds pile up - Your API becomes awkward to use At that point, you’re versioning anyway — just in a more painful, less structured way. ## The Hard Part Isn’t Versioning — It’s Maintaining Versions Adding `/v2` is easy. Maintaining `/v1`, `/v2`, and now `/v3` at the same time? That’s where things get interesting. Now you have: - Multiple code paths - Different behaviors for similar endpoints - Increased testing complexity - More things that can break Versioning doesn’t remove complexity. It **manages** it. And if you’re not careful, you end up supporting legacy versions forever because “someone still uses it.” ## Deprecation: The Part Everyone Avoids Versioning only works if you’re willing to eventually **let go of old versions**. That means: - Marking endpoints as deprecated - Communicating clearly with users - Giving reasonable migration timelines - Eventually removing outdated versions This is uncomfortable. Nobody likes breaking changes. But keeping everything forever is worse. It slows development, increases bugs, and turns your API into a museum of past decisions. ## A Better Way to Think About Versioning Instead of asking: > “What versioning strategy should we use?” Ask: > “How do we evolve this API without surprising people?” That mindset changes everything. Versioning is just one tool in that process. Others include: - Good documentation - Clear communication - Thoughtful design upfront - Avoiding unnecessary breaking changes ## A Practical Approach (What Actually Works in Real Projects) If you want something that works in most cases without overthinking: - Start with **URL versioning** ( `/v1`) - Avoid breaking changes as long as possible - When you must break things, introduce `/v2`- Deprecate `/v1` gradually, don’t kill it overnight It’s not fancy. It’s not innovative. But it works. And in software, “works consistently” beats “clever but fragile” every time. ## The Subtle Truth Here’s the part people don’t like to admit: > Good API design reduces the need for versioning. If your API is: - Consistent - Flexible - Thoughtfully structured You won’t need to version it as often. Versioning is often a **symptom of earlier decisions**, not just a feature. ## Closing Thought Anyone can version an API. But designing an API that evolves gracefully — without constant breaking changes — that’s where the real skill is. Because at the end of the day, versioning isn’t about URLs, headers, or query params. It’s about respecting the people who depend on your system. And once you see it that way, the decisions become a lot clearer. --- ### Keyboard Focus Isn’t a Power-User Feature | Hardeep Kumar Source: https://hardeepkumar.in/design/accessibility/keyboard-focus-is-the-baseline Description: Keyboard navigation isn’t a niche preference — it’s capability. Why invisible focus rings and chaotic tab order fail everyone, and how to design for “no mouse” from the start. $ decrypting payload… stdin$ cat keyboard-focus-is-the-baseline.md/* design/accessibility/keyboard-focus-is-the-baseline */ # <**Keyboard Focus Isn’t a Power-User Feature** />//Keyboard navigation isn’t a niche preference — it’s capability. Why invisible focus rings and chaotic tab order fail everyone, and how to design for “no mouse” from the start.date[**Apr 12, 2026**]read[**6 min read**]tag#**Accessibility** stdout There’s a quiet assumption baked into a lot of software: > “Keyboard navigation is for power users.” You see it everywhere. Products that technically support keyboard input, but clearly weren’t _designed_ for it. Focus states are invisible. Tab order feels random. You press `Tab` and suddenly you’re somewhere deep in the UI with no idea how you got there. It works… technically. But not really. And that’s the problem. Keyboard focus isn’t a bonus feature. It’s not an advanced mode. It’s not something you add later if you have time. It’s part of how interfaces are _supposed_ to work. ## The Misunderstanding A lot of teams treat keyboard interaction like a niche requirement: - “Most users use a mouse anyway.” - “We’ll fix accessibility later.” - “It’s just tabbing, how hard can it be?” But keyboard navigation isn’t about preference. It’s about **capability**. Some users rely on keyboards because they can’t use a mouse effectively. Others use them because it’s faster. And sometimes — often — people just happen to be in a situation where a keyboard is all they’ve got. Think about filling out a form. If you’re forced to switch between keyboard and mouse constantly, it feels clumsy. Not broken, just… unnecessarily annoying. That’s usually how accessibility issues show up: not as catastrophic failures, but as constant friction. ## What “Keyboard Focus” Actually Means When we talk about keyboard focus, we’re really talking about one simple question: > _If I can’t use a mouse, can I still use your product without guessing?_ That breaks down into a few things: - **Visibility** — Can I see where I am? - **Order** — Does focus move in a logical sequence? - **Control** — Can I interact with everything I need? If any of these fail, the experience starts to fall apart. And here’s the kicker: most of these problems don’t come from lack of effort. They come from **not thinking about it early enough**. ## The “Invisible Focus” Problem One of the most common issues is removing focus outlines because they “don’t look good.” You’ve probably seen this CSS somewhere:``` outline: none; ``` It’s usually added during a late-stage UI polish phase. Someone tabs through the interface, sees the default browser outline, and decides it’s ugly. So they remove it. Problem solved, right? Except now keyboard users have no idea where they are. This is like turning off streetlights because they ruin the aesthetic. Sure, it looks cleaner — until someone tries to walk through it at night. If the default focus style doesn’t fit your design, that’s fine. Replace it. Style it. Make it match your system. Just don’t remove it and call it done. ## Tab Order: The Silent UX Killer Another issue that doesn’t get enough attention is **tab order**. When you press `Tab`, focus should move in a way that matches how the interface is visually structured. Top to bottom. Left to right. Logical. Predictable. But in many apps, it doesn’t. Focus jumps around like it’s following a different map than the one on your screen. You tab into a sidebar, then a hidden button, then back to the main content. It feels random — because under the hood, it often is. This happens when: - DOM structure doesn’t match visual layout - Elements are positioned with CSS without considering focus flow - Components are added without thinking about navigation order It’s not a “big bug.” It’s worse — it’s death by a thousand small confusions. ## Custom Components: Where Things Break Modern UIs love custom components: dropdowns, modals, popovers, fancy inputs. And this is where keyboard support usually falls apart. Because once you move away from native HTML elements, you lose built-in behavior. Now you’re responsible for everything: - Focus management - Keyboard interactions ( `Enter`, `Escape`, arrow keys) - Accessibility roles and attributes That custom dropdown? It might look perfect. But if you can’t open it with the keyboard, navigate options, and close it without getting trapped — it’s broken. Not visually. Functionally. ## Why This Isn’t Just About Accessibility It’s tempting to frame all of this as “accessibility work,” which often gets deprioritized. But good keyboard support improves things for everyone: - Faster form filling - Better power-user workflows - More predictable interfaces - Cleaner interaction design In other words, it’s not just about inclusion — it’s about **quality**. A UI that works well with a keyboard is usually a UI that’s been thought through properly. ## The Real Issue: It’s an Afterthought Most keyboard issues don’t happen because developers don’t care. They happen because keyboard interaction is treated as something to “add later.” But by the time “later” comes: - The layout is fixed - Components are already built - Deadlines are close Now fixing focus order means refactoring. Fixing interactions means rewriting components. So it gets patched. Or ignored. Or labeled as “low priority.” And the cycle repeats. ## A Better Way to Think About It Instead of asking: > “Does this support keyboard navigation?” Ask: > “Can someone use this _without a mouse_ from the start?” That shift changes how you design: - You think about focus when laying out components - You rely more on native elements where possible - You test interactions earlier, not at the end It stops being an accessibility checklist and becomes part of normal development. ## A Quick Reality Check If you want to know how your product really performs: Put your mouse away. Use only your keyboard for five minutes. Try logging in. Filling a form. Navigating a menu. You’ll notice things you’ve never seen before: - Missing focus indicators - Broken tab sequences - Elements you can’t reach at all It’s one of the fastest ways to uncover real usability issues. ## Closing Thought Keyboard focus isn’t a feature. It’s part of the foundation. Treating it like an optional enhancement is like treating error handling as “nice to have.” Things might work most of the time — until they don’t. And when they don’t, the experience isn’t just inconvenient. It’s exclusionary. Good design isn’t just about how things look or even how they work in ideal conditions. It’s about how they hold up when assumptions break — when the mouse isn’t there, when the user navigates differently, when the system is used in ways you didn’t expect. That’s where real quality shows. --- ### Semantic HTML Beyond "div Soup" | Hardeep Kumar Source: https://hardeepkumar.in/design/accessibility/semantic-html-beyond-divs Description: Why your div-heavy markup hurts accessibility, SEO, and maintainability — and why choosing elements for what things *are* beats styling-first thinking. $ decrypting payload… stdin$ cat semantic-html-beyond-divs.md/* design/accessibility/semantic-html-beyond-divs */ # <**Semantic HTML Beyond "div Soup"** />//Why your div-heavy markup hurts accessibility, SEO, and maintainability — and why choosing elements for what things *are* beats styling-first thinking.date[**Apr 12, 2026**]read[**9 min read**]tag#**Accessibility** stdout There’s a phase most developers go through when working with HTML. At first, everything is confusing. There are too many tags — `
`, `
`, `