Back to Projects
CodeIn ProgressFebruary 2026

Tic-tac-toe

A game of tic-tac-toe to demonstrate the core components of fullstack development.

Tic-tac-toe preview

My Role

All

Duration

1 week

Team

Solo

Status

In Progress

Key Highlights

  • World's greatest tic-tac-toe game
ReactTypescriptNodeFullstack

Multiplayer Tic-Tac-Toe Real-Time Web Application

What I Built:

A full-stack tic-tac-toe game that works both as a single-player experience against an AI opponent and as a real-time multiplayer game where two players can compete from separate browser windows.

The Problem:

Most beginner web projects stop at a static page or a simple client-side app. I wanted to go further by building something that handles the real complexity of modern web applications: server-side state, multiple users seeing the same data at the same time, and instant updates without refreshing the page.

How It Works:

The app has two screens: a Lobby where you can see all active games and create new ones, and a Game Board where you play. A single React component at the top of the app controls which screen you see, keeping things simple.

When you play locally, the game runs entirely in your browser. When you play multiplayer, every move is sent to a Node.js server that acts as the single source of truth. The server validates the move, updates its records, and then does two things at once: it responds to the player who moved, and it pushes the updated board to every other player watching that game over a WebSocket connection. This means both players see the board update instantly, without polling or refreshing.

The AI opponent runs on the client side using a layered strategy — it checks for winning moves first, then blocks the opponent, then plays tactically. It sends its moves through the same server endpoint as a human player, so the multiplayer experience stays consistent regardless of who is playing.

Tech Stack:

Frontend: React with TypeScript, Vite for bundling Backend: Express with ViteExpress, serving both the API and the frontend from a single process Real-Time: WebSockets via express-ws for live game state synchronisation State Management: React hooks (useState, useEffect) with server-authoritative game state Testing: Vitest for unit and integration tests covering game logic and API endpoints

What I Learned:

Client-server architecture: How to split responsibilities between the browser and the server, and why the server should be the single source of truth for shared state as well as storing anything that should not be share to clients... i.e. API keys and the like.

WebSockets: How persistent connections differ from HTTP request-response, and how to manage subscriptions, broadcasting, and cleanup when clients disconnect.

React effect lifecycle: How useEffect handles setup and teardown, particularly with WebSocket connections that need careful cleanup to avoid errors during component unmounting.

API design: Structuring REST endpoints for game creation, moves, and statistics, with proper validation and error handling.

Pure functional logic: Writing the core game engine (win detection, move validation, draw detection) as pure functions that are easy to test in isolation and reuse across both client and server.

Interested in working together?

I'm always open to discussing new projects and opportunities.