Last updated on
Build an Accessible Tic Tac Toe Game with AI and Codex CLI
Build an accessible tic-tac-toe game with Codex CLI, React, and Vite while working with NVDA. This walkthrough covers project instructions, a focused prompt, test setup, command approvals, and manual screen-reader testing.
Watch the video
Loading this video connects you to YouTube (Google), which receives your IP address and may store or read information on your device for playback and advertising. YouTube may show ads. Choose Load YouTube video to allow this for this video. See Google's privacy policy.
Watch Build an Accessible Tic Tac Toe Game with AI and Codex CLI on YouTube
What I built
I wanted to see how far Codex CLI could get with one focused prompt and a small React starter project. I scaffolded the project with Vite, gave Codex instructions for working in the repository, and asked it to build a two-player tic-tac-toe game with screen-reader support.
I did the whole workflow with the NVDA screen reader on Windows 11. The project ran inside Ubuntu on WSL, I worked in VS Code, and I tested the finished game in Brave.
The result was a solid accessible first draft. The game used native buttons, announced each move and turn, gave every square a row-and-column label, and announced the winner. Because my prompt required test-driven development, the build came with five component tests and a clean lint and production build.
I called the game "fully accessible" in the original prompt and video title. That is a useful goal, but one NVDA test and five automated tests do not prove complete accessibility. In this article, I call it accessible and explain exactly what I tested.
Tools I used
This was my setup for the recording:
- Windows 11
- Ubuntu on WSL
- NVDA
- VS Code
- Brave
- Node.js and npm
- Codex CLI
- React and Vite
If you are new to Codex CLI, I have separate videos on installing Codex CLI and selecting a model and reasoning effort.
The finished project is available in the tic-tac-toe-ai GitHub repository.
Create the React project
I started in my React projects directory and created a folder for the game:
mkdir tic-tac-toe
cd tic-tac-toe
I already had a local Markdown file with my Vite setup notes, so I copied that file into the new directory. Then I opened the directory in VS Code:
code .
Before scaffolding the project, I checked my Node.js version and installed the current LTS release through nvm:
node -v
nvm install --lts
I created the Vite project in the current directory with:
npm create vite@latest . -- --template react
The period tells Create Vite to use the current directory, and --template react selects the React starter template. The interactive questions can change between releases. In my recording, I kept the existing setup-notes file, selected ESLint, and let the tool install the npm packages and start the development server.
Once the server was running, I opened the local address in Brave and confirmed that the default React counter worked. That gave me a known starting point before asking Codex to replace the starter interface.
Give Codex project instructions first
I kept the Vite server running and opened another terminal with Ctrl+Shift+Backtick (the grave accent key). Then I started Codex:
codex
For this recording, I selected GPT-5.6 Sol with medium reasoning effort. Use whatever current model your Codex offers.
My first request was not to build the game. I asked Codex to inspect the starter project and create an AGENTS.md file:
Good afternoon. Please start by analyzing the current project and creating an AGENTS.md file.
Codex documented the React and Vite versions, repository structure, npm commands, coding conventions, accessibility expectations, and verification steps. That put my project rules in place before any game code was written.
I also created a directory for plans and a text file for the main prompt:
mkdir plan
echo > prompt.txt
Write a focused accessibility prompt
The prompt was intentionally small. It described the outcome I wanted and the rules that should shape the implementation.
Here is a cleaned version of what I typed in the video. I corrected the typing mistakes and changed "fully accessible" to "accessible" because the finished game still needs broader testing.
Facts are important throughout. Assumptions need to be flagged.
The goal is to create a professional tic-tac-toe game that is simple and accessible for
screen readers.
Use ARIA where it is appropriate. A live region should announce game information that would
otherwise only appear visually.
Any game-flow instruction also needs to be announced.
Rules for writing code:
1. Test-driven development is required.
2. Be Socratic about the goal and direction.
3. Keep it clean. Write modern code, prefer simple solutions, and do not look for unnecessary
code to write.
The prompt did not describe every React component or CSS rule. It established the goal, accessibility requirements, and engineering constraints while leaving the implementation to Codex.
Save a clean starting point
Before sending the build request, I initialized Git and saved the starter project:
git init
git add .
git commit -m "Initial commit"
git branch -M main
git status
This gave me a clean baseline. If the generated work went in the wrong direction, I could inspect exactly what changed instead of trying to remember the original state.
Ask Codex to build the game
With AGENTS.md, prompt.txt, and the initial commit in place, I sent one short request:
Now please read prompt.txt and execute the application.
Codex interpreted "execute the application" as both implementing the prompt and launching the result. While it worked, it asked for permission to install the test dependencies:
npm install --save-dev vitest jsdom @testing-library/react @testing-library/user-event @testing-library/jest-dom
I read the command before approving it and chose the one-time approval. I did not select the option that would automatically approve every future command beginning with npm install.
There is an important distinction between two of those packages. Vitest is the test runner. jsdom provides a simulated browser-like DOM environment so the React component tests can run under Node.js. It is not another test runner.
The Codex interface reported 9 minutes and 2 seconds of work. Its handoff reported:
- Five tests passed
- ESLint passed
- The production build passed
- The HTTP smoke check passed
- The dependency audit found no vulnerabilities
The source repository contains five tests covering the empty board, alternating moves, a win, a draw, and starting a new game.
The accessibility details I asked for
My prompt asked for game information to be announced, not just shown. Here is what the build included, and what I checked with NVDA:
- Each square is a native button.
- Every square has an accessible name containing its row, column, and current state.
- The board is a named group associated with the game instructions.
- A polite, atomic live region announces the selected square, next turn, win, draw, and new game state.
- Occupied squares and the finished board become unavailable.
- Keyboard focus has a visible outline.
- The CSS includes high-contrast text and game-mark colors and reduced-motion support.
- The Play again button starts a fresh board and announces the new game.
For example, an empty square is announced as "Row 2, column 1: empty." After selecting it, the status message includes the move and tells the player whose turn comes next.
Play the game with NVDA
Codex launched the finished application on a second local port. I copied the address from its handoff and opened it in Brave.
At the top of the page, NVDA announced the Tic Tac Toe heading, the instruction that X goes first, and the current game status. The board was exposed as a group named "Tic tac toe board."
I used B and Shift+B to move between the square buttons. NVDA announced each square by row, column, and state, so I did not have to infer the board from its visual position.
I played these moves:
- X in row 2, column 1.
- O in row 2, column 2.
- X in row 3, column 1.
- O in row 3, column 3.
- X in row 1, column 1.
That gave X the first column. The live region announced the final move, said that X won, and instructed me to select Play again to start a new game.
After the board, NVDA found the Play again button and the keyboard instruction explaining that players can use Tab to move between available squares and Enter or Space to play.
What this result proves
This project shows that a coding agent can produce a useful accessible first draft when I give it a clear outcome, project rules, a test-driven-development requirement, and specific screen-reader requirements. The prompt did not need to prescribe every line of code, but it did need to say what success meant.
It does not mean I can ignore software fundamentals or accept the first result without checking it. I still needed to inspect the command approval, read the handoff, understand the test setup, and play the game with NVDA.
The next round of testing would cover more browsers and screen readers, more keyboard paths, zoom and reflow, color contrast, mobile layouts, and a WCAG review. For now, five tests and one good NVDA game are a solid start.
If you want to play it yourself, Run the Tic Tac Toe Game on Windows with NVDA shows how to download it and start it with Docker.