I'm Ralph. I'm one of the developers at histre. Today, I'll share with you my story as a blind programmer working on the project and how I'm helping build histre into a tool that empowers everyone.
My Journey As A Blind Developer
I've been working at histre since 2021, primarily as a backend developer. My journey into programming has been a bit unique because I was diagnosed with retinitis pigmentosa (RP) when I was 16. For those who aren't familiar, RP is a hereditary eye condition that causes people to gradually lose their vision and, in some cases, eventually leads to complete blindness.
When I first started programming, I still had a decent amount of vision, but as the years went on, it got worse. This meant I had to look for ways to continue reading and writing code. At first, I relied on tools like screen magnifiers and high contrast settings, but eventually, I needed to make the jump to screen readers once a huge part of my vision had disappeared. Thankfully, coding is mostly text-based, which makes it something a blind person can still do quite effectively, given the right tools and setup.
Most of my work revolves around backend development, which is great because it means I don't need to deal with the more visual elements of our app that much. But, like many blind developers, I do face a number of challenges. These challenges have shaped the way I approach my work in a few key ways. I'll talk more about them later, but there are two main things that my blindness affects as a programmer:
- Problem-solving: Blind developers "look" at code and software differently than their sighted peers, which means having to parse code and work out solutions a little differently than most programmers.
- Technology/Tools: When choosing tools, I have to consider compatibility with the assistive technology I rely on, which adds an extra layer of complexity to the decision-making process.
And honestly, that second part is one of the reasons I'm so proud of our app. Accessibility has always been important to me, and I can confidently say that our knowledge-management app is a tool that blind users like myself can truly benefit from. I know this because I helped build it!
A Few Tools I Use
I use many of the same tools that most developers today rely on, but as a blind programmer, I also need to work with special software called a screen reader. In addition to screen readers, I pay special attention to the exact code editors I use, and I rely heavily on operating system-level tools and settings to optimize my workflow. Below, I'll go into detail on some of the key tools that power my day-to-day work.
Screen Readers
A screen reader is software that converts text displayed on the screen into speech or braille, allowing blind and visually impaired users to interact with computers. I don't have much experience with braille, so I use screen readers exclusively in text-to-speech mode.
For programming, I use two screen readers:
Both NVDA and Orca are open-source software, and they're completely free to install and use.
Code Editors
When it comes to code editors, compatibility with screen readers is my number-one concern. I use a few different editors depending on the operating system:
- On Linux, I use VS Code and Geany.
- On Windows, I primarily use VS Code, though (at the risk of revealing how old I am) I also used to work with Notepad++ back in the day.
All these editors have excellent compatibility with the screen readers I'm using on each OS. For example, VS Code can detect if a screen reader is active and adjust its UI accordingly, making it much easier to navigate through code, tabs, and other UI elements.
Operating Systems
I primarily use Linux in my day-to-day work, although I also use Windows for some specific tasks. Each operating system has its own set of quirks and behaviors when it comes to accessibility and compatibility with the assistive tools I'm using. My preference is definitely Linux for most coding tasks, but I still need Windows occasionally, especially when manually testing specific portions of our app.
I primarily use Linux because it feels so smooth and responsive when using just a keyboard. I'm running Debian 12 and Ubuntu (20.04 and 24.04), with the GNOME desktop environment. GNOME comes with the Orca screen reader already installed on many distributions, so it's been really easy to get up and running.
Apart from enabling the screen reader option in the Accessibility settings, Orca works out of the box for me on both Debian and Ubuntu. I'll go into detail on how I configure Orca for programming later in this article.
For some specific tasks, I do need to use Windows instead of Linux. One reason I occasionally switch to Windows is that I find some tools, like Chrome DevTools, tend to work better with NVDA than with Orca. Additionally, some specialized third-party platforms and apps also offer better accessibility support when using NVDA, making certain tasks much easier to manage on Windows.
While Windows comes with a built-in screen reader called Narrator, I prefer using NVDA when working with code. NVDA offers more advanced features and customizations that make it better suited for my development work.
Other Tools
The command-line tools I regularly use all work well with Orca on Linux, often without needing any additional configuration. In my experience, these are all screen reader-friendly: Bash, Git, Docker, Postgres (psql), Python/iPython shell, Node.js shell, and SSH.
I also work with AI agents on the terminal, using both Claude Code and Codex. The latest versions of these tools are pretty accessible with screen readers. Claude Code has a screen reader mode for its TUI, while I mostly use Codex in non-interactive mode (codex exec).
Furthermore, platforms and apps like GitHub, Sentry, ChatGPT, Slack, Zoom, and others generally work well with both Orca on Linux and NVDA on Windows, making collaboration and communication with my team as accessible as possible.
I think that's all the major tools I currently use every day. It's an evolving list, but the key thing is that any change to my setup always has to answer the question: does it play nice with my screen reader?
Setting Up an Accessible Development Environment
For blind developers, having a well-configured development environment is key to being able to work productively and independently. While having the basics like screen readers, code editors, and other tools is important, it's the small tweaks that can make all the difference.
In this section, I'll share some of the ways I set up my tools (from screen reader settings to code editor configurations) that help me work more productively. I'll also talk about how I manage some of the unique challenges that come with debugging, testing, and navigating large codebases as a blind developer, along with examples of how I set up my environment for doing my daily tasks.
If you don't have any experience setting up your (or a team member's) development environment for screen readers, I recommend starting out with the following resources:
Screen Reader Settings and Usage
To make screen readers suitable for coding, I make several configuration changes to ensure that they're able to provide all the information I need.
Read All Punctuation
Both NVDA and Orca have settings that allow users to choose how much punctuation the screen reader should read. The options usually range from "none" to "all."
I always set this to read all punctuation, since every character in each line of code can play a role in the syntax and meaning.
For Orca:
- Open Orca settings (press Insert + Space).
- Press the left arrow key until you reach the "Speech" tab.
- Press the tab key until you reach the "Punctuation Level" options.
- Choose the "All" punctuation radio button.
- Save changes.
For NVDA (NVDA key is Insert by default):
- Open the NVDA menu (NVDA key + N).
- Use the down arrow key to go to "Preferences", then choose "Settings".
- Press the down arrow key until you reach "Speech".
- Press the tab key until you reach the "Punctuation/Symbol Level" combo box.
- Choose "All".
- Save changes.
Speak Indentation Levels and Blank Lines
It's important for screen readers to announce indentation levels, especially for programming languages that rely on indentation (like Python) or when dealing with nested structures in any language (like HTML, JSON, etc.). This feature helps me track where I am in the code and helps me understand its structure.
A related setting that I also enable is the "Speak Blank Lines" option. When enabled, it helps me definitively know that the current line is empty instead of trying to guess why the screen reader stops speaking when I move into a line.
For Orca:
- Open Orca settings (press Insert + Space).
- Press the left arrow until you reach the "Speech" tab.
- Press the tab key until you reach the "Speak blank lines" checkbox and check it.
- Press the tab key until you reach the "Speak indentation and justification" checkbox and check it.
- Save changes.
For NVDA (NVDA key is Insert by default):
- Open the NVDA menu (NVDA key + N).
- Use the down arrow key to go to "Preferences", then choose "Settings".
- Press the down arrow key until you reach "Document Formatting".
- Press the tab key until you reach the "Line Indentation Reporting" combo box.
- Choose "Speech".
- Save changes.
Once enabled, the screen reader should now say something like "four spaces" or "2 tabs" whenever it encounters indentation in a line of code. In NVDA, indentation can also be indicated using tones, but I haven't tried that setting out myself.
Pitch Level for Capital Letters
I configure my screen readers to use a significantly higher pitch when reading capitalized letters. This helps me distinguish between lowercase and uppercase letters, which is important for variable names, class definitions, and constants.
For Orca, I configure the voice used for uppercase text separately from the default voice:
- Open Orca settings (press Insert + Space).
- Press the left arrow until you reach the "Voice" tab.
- Select the voice type used for uppercase text.
- Adjust its pitch so that capitalized text sounds noticeably different from regular text.
- I leave "Capitalization Style" set to "None" because I use the capitalization voice rather than an additional tone or spoken "capital" indicator.
- Save changes.
For NVDA (NVDA key is Insert by default):
- Open the NVDA menu (NVDA key + N).
- Use the down arrow key to go to "Preferences", then choose "Settings".
- Press the down arrow key until you reach "Speech".
- Press the tab key until you reach the "Capitalization Pitch Change" edit box.
- Adjust the value to increase or decrease the pitch difference.
- Save changes.
With my preferred settings, the capitalization pitch is different enough that I can easily tell uppercase and lowercase letters apart. It's also possible to use other ways to indicate capitalization, like beeps/tones or having the screen reader say "capital." But I find the change in pitch to be the most comfortable for me to listen to.
Speech Rate
When I first started using screen readers, I kept the speech rate quite slow to get used to the flow. Over time, as I became more comfortable, I increased the rate gradually, and now I have it set to the maximum level.
The key is to find the balance between speed and accuracy. You don't want the screen reader to be talking so fast that you can't follow it, since it can be easy to mishear text or completely miss characters in the code. But, at the same time, you also don't want it to be speaking so slowly that you find yourself falling asleep!
For Orca:
- Open Orca settings (press Insert + Space).
- Press the left arrow until you reach the "Voice" tab.
- Press the tab key until you reach the "Rate" slider.
- Press the left or right arrow key to decrease or increase the speech rate.
- Save changes.
For NVDA (NVDA key is Insert by default):
- Open the NVDA menu (NVDA key + N).
- Use the down arrow key to go to "Preferences", then choose "Settings".
- Press the down arrow key until you reach "Speech".
- Press the tab key until you reach the "Rate" slider.
- Use the arrow keys to increase or decrease the speech rate.
- Save changes.
Screen Reader Profiles
Both NVDA and Orca allow you to create and switch between different profiles. This is a feature I use regularly. It lets me save specific screen reader settings for different use cases. For example, I have a profile for programming that uses the settings I've described above, while I also have a different one for personal use that's less verbose. Switching between profiles saves time and makes the screen reader feel more flexible and adaptable to different tasks.
Code Editor Settings and Usage
While both VS Code and Geany work nicely with NVDA and Orca almost right out of the box, there are still a few settings and behaviors I need to change to make reading and writing code as smooth as possible.
Accessibility Mode
VS Code automatically detects if a screen reader is being used and switches into an accessibility-friendly mode. If this doesn't happen automatically, you can force it by adding the following setting in your settings.json file:
"editor.accessibilitySupport": "on",
Other text editors I've used typically don't need to be run with an accessibility mode enabled, since they're already compatible with screen readers by default.
Blank/Empty Workspace on Startup
One setting I find really useful is configuring the editor to always start with an empty session or a blank workspace when opening. This prevents the possibility of accidentally typing characters into an existing file before I realize which file is open, which could cause some hard-to-resolve confusion down the line!
This can be set in VS Code's settings.json:
"workbench.startupEditor": "none",
"window.restoreWindows": "none",
Code Formatting
Most codebases today follow strict code formatting and styling conventions. But aside from making code more readable to programmers who read with their eyes, a well-formatted codebase is also easier to navigate and peruse for developers who rely on a screen reader.
So whether it's an extension, a language setting, or a pre-commit hook, I find that automating code styling and formatting helps me read and write code faster. At the very, very least, I always make sure to set language-specific indentation levels, consistent double/single quote formats, and max line lengths.
Terminal and Command Line
The terminal is where I spend a great deal of time working, running commands, and managing various tasks. Over the years, I've experimented with my terminal setup and consistently leaned on a number of tweaks and workarounds that make life easier for me.
Setup for Reading Command Output
Typing out commands with a screen reader is mostly straightforward, but the challenge comes when trying to read the output of a command or process. It can be difficult (or, in some cases, impossible) to read earlier parts of the output using a screen reader, especially when the output is extensive.
In Linux (using gnome-terminal), for example, you can't easily do something like Ctrl + A (select all) and Ctrl + C (copy) to grab all the output from the terminal. To work around this limitation, I use a couple of different strategies.
For short commands, I often pipe the output into a program called xclip so that I can easily copy and paste the output into an empty text editor. For example:
ls -la | xclip -selection clipboard
I also create a .bash_aliases entry for the xclip command.
For longer commands or processes, I often redirect the output into a file using > or pipe it using tee, so I can open it in an editor and parse it more fully there. One thing to make sure of is that the output file doesn't get accidentally added to version control. So I save the output outside the repo or include the file/directory in .gitignore.
On Windows, I use Git Bash, which fortunately allows me to select the output text and copy it into the clipboard, making it a bit easier to handle command output.
Tab Completion
As a screen reader user, tab completion is essential for command-line work. Instead of having to remember or manually type out long file names or commands, I can simply type the first few characters and let the terminal fill in the rest. I rely on it all the time.
In Linux, using Bash, tab completion works seamlessly with Orca. It's particularly useful when there are multiple possible completions, as the screen reader will read out the list of options when I press Tab twice. I can then use the arrow keys or type a few more characters to narrow down the options.
One challenge with tab completion as a screen reader user is managing a long list of suggestions. When there are too many options, hearing all the possible completions can be overwhelming. In these cases, I usually try to narrow down my selection by typing more of the name before hitting Tab, which reduces the number of suggestions and makes it easier to find what I'm looking for.
There are some instances where tab completion isn't enabled by default after installing common CLI tools like git or docker. I always make sure that tab completion for the CLI tools I use is properly enabled (e.g., in .bashrc).
That pretty much covers the little tweaks I make in my development environment. Like the choice of tools I'm using, my setup is also a work-in-progress, and I'm always looking for ways to make tiny improvements here and there.
What It's Like Coding While Blind
As a blind developer, I've learned that coding is much more than just a technical exercise. It's about problem-solving, persistence, and finding creative ways to adapt. The tools I use are essential to what I do, but what really matters is how I approach the challenges that come with working in a sighted world. Coding while blind has forced me to develop a deep understanding of my tools, my code, and how to communicate clearly with others.
Reading and Writing Code: More Than Just Syntax
Reading and writing code is something I've had to adapt to over the years as my vision worsened. In the early days, I relied on screen magnifiers, but now I'm completely dependent on my screen reader. One of the biggest challenges is maintaining focus. By nature, code is structured and visual, and when you can't see that structure, it requires a lot more mental energy to keep track of what's happening.
I've found that consistency is key. Having a clear coding style and well-structured code isn't just a nice-to-have, it's a must-have. When every line and character has to be read aloud, even minor formatting inconsistencies can slow me down. That's why I rely on code formatting and linting tools. But beyond tools, it's about developing an instinct for clean, readable code. The more readable the code is, the easier it is to navigate using just my screen reader.
Navigating Codebases: Mental Maps and Patience
Navigating through a large codebase without being able to see the screen is like trying to walk through a city you've never been to before: it takes time to build a mental map. Programmers spend a great deal of their time traversing codebases. This is even more so for blind developers, since we parse code a single chunk (i.e., line, identifier, symbol, or character) at a time instead of being able to view whole blocks or sections of code in one glance.
Early on, I realized that my approach to navigating code has to be more deliberate. I can't just skim through a file to find what I need; I have to rely on tools like VS Code's go-to definition, file search, or grep, but more importantly, I have to develop a mental model of the code structure.
There are times when it feels overwhelming, especially when jumping into a large unfamiliar codebase, but I've learned to break things down into smaller, more manageable pieces. It's a slower process, but it also forces me to understand the code at a deeper level. I've had to embrace patience. There's no quick way to "see" the whole picture, so I focus on the details and gradually put everything together in my head.
Debugging: Listening to Errors
Debugging as a blind developer requires a different approach. I can't rely on visual cues from the UI or quickly scan logs and lines of terminal output. Instead, I rely heavily on workarounds to review the results of commands and processes, like piping the output into files or the clipboard. Reading through long logs using a screen reader can be tedious, but I've learned to set up the right tools and filters to help me zero in on the relevant information. It also helps to write and run as many automated tests as possible, to make sure the code I touch works as expected.
It's not just about the tools, though. Debugging is as much about listening as it is about logic. When I encounter an error, I have to focus on the sounds and patterns of the feedback I'm getting from my screen reader. It forces me to pay attention to the smallest details while also tuning out unnecessary noise, just like how a sighted developer skims through endless rows of log output.
Of course, I've also had my fair share of bugs and 500 errors in production. But in almost all of those instances, it wasn't necessarily being blind that caused the problem. It was due to carelessness or having an incorrect understanding of the moving parts behind the issue, which are things that affect all software developers and programmers regardless of ability or disability.
Working with Other Developers: Communicating Clearly
I'm quite lucky to be working with developers who deeply understand and adeptly handle the challenges of having a blind colleague on the team.
One key challenge is discussing visual aspects of the app. My team and I have had to learn how to communicate in a way that aligns visual and non-visual perspectives. When we talk about design changes or UI elements, we rely on precise language and description to make sure everyone's on the same page.
In addition, pair programming is where my team and I really had to adapt. Instead of simply looking at the same screen, we rely on clear verbal communication. My teammates describe what they're seeing, and I talk through my code. This kind of collaboration has taught me the importance of patience, clarity, and trust. We're not just sharing a screen, we're sharing a mental space, and that requires a level of focus and understanding that goes beyond the code itself.
In coding while blind, the challenges aren't just about using the right tools. I've come to realize that while I may work differently than my sighted peers, the end goal is the same: creating clean, maintainable code and building software that works.
Helping Build histre
In my more than five years at histre, I've had the chance to work on several key features and changes, mostly on the backend side of things. While my primary focus has been on backend development, I've also had opportunities to contribute to other areas of our app.
One of the first features I developed was our user-facing API. This allowed our users to integrate histre into their own apps and programs. In addition, one other early feature I implemented was functionality that enabled users to publish their histre collections as RSS feeds.
Another major project I worked on was migrating our background task management system. Originally, we were using Google Cloud Tasks, but we needed to move to our own internal system. The tricky part was that during the migration, the tasks had to remain compatible with both Google Cloud and the new system. It was a challenging project, requiring careful planning and testing, but in the end, we successfully made the transition.
I also had the chance to move our search functionality from Postgres to Elasticsearch, which was a significant upgrade. Initially, the search only covered notes, but I helped expand it to include other items like collections, highlights, research history, and conversations. This allowed users to get more out of the search feature, making it easier to find exactly what they were looking for across different areas of the app.
In addition to core backend work, I've implemented a number of third-party integrations with our app, such as IFTTT, Slack, Notion, and even Salesforce. These integrations helped users connect our app with the tools they're already using.
Most recently, I've been involved in helping add AI capabilities to histre. This included developing features like AskAI, which lets users ask questions about a web page they're currently visiting using the browser extension. I also developed the backend for importing ChatGPT conversations into histre so that users can better manage their ChatGPT chats and make them searchable.
Though my focus is on the backend, I've also done some front-end work here and there. For example, when I first started with histre, I worked on features for our browser extension, which was a fun change of pace. I've also had to wire up some front-end UI/UX elements to the backend, particularly when we were building new features for the web app.
Overall, our app is a powerful knowledge-management tool for everyone, and I'm happy that I've been able to contribute in a meaningful way.
Making histre Accessible
As both a developer and a user of histre, I know firsthand how important it is that accessibility is at the core of everything we build. When we're developing features, we try to make sure the app works for everyone, no matter their needs. Here are a few ways we've worked to make accessibility part of histre.
Compatibility with Screen Readers
Both the histre web app and the browser extension are designed to work well with screen readers. We follow accessibility best practices by properly labeling and structuring UI elements, menus, and content so that screen readers can interpret the information and relay it to users with visual impairments. That's something obviously important to me as a blind developer. My own experience using screen readers plays a big role in testing these features and catching accessibility issues.
Dark Theme
While I don't personally use the dark theme feature, I know it's a useful addition for people who prefer a darker interface or find it more comfortable in certain lighting conditions. It's simple to enable, and histre remembers your preference, so it stays on across your browsers and sessions.
Support for Keyboard-only Navigation
For those who prefer or need to use only the keyboard, histre is designed to support keyboard navigation throughout the app. UI elements can be reached and operated using the keyboard, making it possible to move around the app or browser extension without relying on a mouse. We've also added a command palette feature in the browser extension, which lets you quickly perform actions using keyboard shortcuts.
Clean and Intuitive UI
For someone like myself who interacts with the histre app one UI element at a time, histre feels smooth to move around in. It's easy to understand how components are laid out, and UI elements are easy to locate in both the web app and browser extension with just a screen reader. Most importantly, though, we always put ease of use as a top requirement in the features we develop for histre.
I use histre for managing my own knowledge base. Over the years, I've accumulated a mountain of links, bookmarks, and notes from my work and my personal life. I think histre is the most user-friendly tool that lets me organize everything so I can tag, annotate, lump together, search for, and keep what really matters. Of course, I'm a little biased because I'm part of the histre team. But I really believe this is a tool that empowers people by helping everyone harness their most valuable resource: their knowledge. And that's our team's shared vision for the app.
Conclusion
That's my story. I hope that if you're a blind developer reading this, you've picked up some useful tips and ideas from my experiences and the tools I've shared. The journey of coding while blind can be challenging, but with the right setup and mindset, it's definitely worth it.
If you're someone who works with or is considering hiring a blind developer, I hope this article has given you a better understanding of the tools, requirements, and challenges we face. Working with a blind programmer is really about collaboration and ensuring everyone has access to the right resources to succeed.
And finally, whether you're blind or sighted, I hope you start to see the value in tools like histre, not just for their accessibility but for how they can help you organize and manage knowledge resources better. I've been proud to help build it, and I encourage you to try it out for yourself!
One more thing: I mentioned in passing how accessible AI coding tools like Claude Code and Codex have now gotten. They're now a crucial part of my dev workflow. But it wasn't always this way. It took a while for the tools to evolve into blind-friendly tech (as well as for my own dev process to adapt). In my next article, I'm going to go into more detail on my agentic coding setup and workflow.