Master Software Design & Architecture
Your guide to building maintainable software in a post-LLM world.

In the post-LLM world,
taste is most important.
AI can generate code faster than ever before. It can write functions, refactor modules, and scaffold entire applications in seconds. But this is code you still need to understand, maintain, extend, and fix at 3 AM in the morning if it breaks.
You need to know what good code looks like and be able to recognize it when you see it.
LLMs can produce volume. They can't produce judgment. They don't know when an abstraction is overkill, when a pattern is misapplied, or when simplicity beats cleverness. That's your job now.
The developers who will thrive are those who can look at AI-generated code and instantly tell: "This is elegant" or "This is a mess waiting to happen."
- ✓Remove unnecessary abstractions
- ✓Pick the right library
- ✓Make the right trade-off
- ✓Spot flawed domain logic
What is this book?
Software development is about more than shipping features, it's about building code that stands the test of time and remains adaptable to changing requirements.
This book teaches principles of maintainable software design, demonstrating how key patterns apply across REST APIs, front-end state, or tiny scripts.
By the end, you'll refine your taste in code, knowing how to create maintainable software in any environment.
Domain Logic
This is the logic you (or your AI) write. How you organize it is super important.
Clean Architecture
Learn how to structure your codebase beyond the buzzwords through practical examples.
Practical Refactoring
Code is never finished, it's always a work in progress.
Refined Taste
Know when some repetition beats overkill abstractions.
Who is this book for?
Technologies we use
Full-Stack Tao uses popular technologies to explain key concepts. However, the principles discussed are applicable across all programming languages and technology stacks. The goal is to teach you timeless software design principles that you can apply throughout your career.
Table of contents
Part 1
- —A Story
- —Good Code Doesn't Take More Time
- —Maintainability
- —Everything Matters
- —Why We Don't Learn Software Design
- —Why We Need Principles
- —Principles Instead of Dogma
- —Do Not Follow Paradigms Blindly
- —Quality Can Be Objective
- —Structure Helps Teams Grow
- —Why Full-Stack?
Part 2
- —Learn the Building Blocks
- —Tactical & Strategic Code
- —Variables
- —Bad Naming
- —Conditionals
- —Use Empty Collections
- —Functions Should Be at One Level of Abstraction
- —Functions in Detail
- —Loops
- —Performance vs Maintainability
- —Program Errors Out of ExistenceREAD FOR FREE
Part 3
- —How Can a Function Know Something?
- —Knowledge and Responsibilities
- —The Single Responsibility Principle
- —The Interface Segregation PrincipleREAD FOR FREE
- —The Liskov Substitution Principle
- —Dependency Injection
- —Dependency Inversion
- —Context as Conditional Dependency Injection
- —The Open/Closed Principle
- —Designing APIs
- —Build Your Intuition
Part 4
- —The Types are Always There
- —Functional Core, Imperative Shell
- —The Layers in Every Application
- —Clean Architecture in ReactREAD FOR FREE
- —Another Approach to Clean Architecture
- —Building a Well-Structured REST APIREAD FOR FREE
- —Locality of BehaviorREAD FOR FREE
- —Repeating Yourself Twice
- —Modularity
- —Managing Modules
- —Don't Overinvest in Architecture
- —Naming Components
- —State Management
- —Design Practically
- —Managing Query Logic
- —Hiding Information With Abstractions
- —Extracting Custom Hooks
- —Extracting Domain Objects
- —API Schemas as the Source of Truth
- —Business Logic in a REST API
- —Criticism of Custom Hooks
- —Styling ApplicationsREAD FOR FREE
- —Dealing with Forms
Part 5
- —Using Tools
- —Designing a Lambda Function
- —Designing a Script
- —Code Quality is a Result of Culture
- —Remove Complexity with Product Decisions
- —Junior Engineers Need Structure
- —Design the Interface First
- —Centralize Authentication Logic
- —A Testing PhilosophyREAD FOR FREE
- —How to Write Good Comments
- —ORMs and Query Builders
- —Dealing with Complexity in the Data Layer
- —Don't Put Domain Logic in DatabasesREAD FOR FREE
Part 6
- —Start with the DomainREAD FOR FREE
- —Setting Up the ProjectREAD FOR FREE
- —Picking a Tech StackREAD FOR FREE
- —How to Build a Feature
- —Avoid Design Systems
- —Architectural Decision Records
- —Debating Software Design
- —Buy vs Build
- —The Cost of Scalability
- —Improving Existing Codebases
- —Notes on Refactoring
- —Indie Hacking
- —The Perfect System Doesn't ExistREAD FOR FREE
What will you learn?
Locality of Behavior
Things that change together should be close together — this gives us better maintainability.
Cohesive Modules
We don't make changes to all our requests at once, nor do we change all our schemas together.
Easy Modifications
When we have to make changes, it's most likely in the context of a single request. So we keep the query, the schema, and the API call function together.
// 1. Schema - validates the input for this featureexport const createCommentInputSchema = z.object({discussionId: z.string().min(1, "Required"),body: z.string().min(1, "Required"),});export type CreateCommentInput = z.infer<typeof createCommentInputSchema>;// 2. API call - handles the request for this featureexport const createComment = ({data}: {data: CreateCommentInput}): Promise<Comment> => {return api.post("/comments", data);};// 3. Hook - manages state for this featuretype UseCreateCommentOptions = {discussionId: string;mutationConfig?: MutationConfig<typeof createComment>;};export const useCreateComment = ({mutationConfig,discussionId,}: UseCreateCommentOptions) => {const queryClient = useQueryClient();const { onSuccess, ...restConfig } = mutationConfig || {};return useMutation({onSuccess: (...args) => {queryClient.invalidateQueries({queryKey: getCommentsQueryOptions(discussionId).queryKey,});onSuccess?.(...args);},...restConfig,mutationFn: createComment,});};
Get the book
You buy me dinner and I tell you everything I've learned about software design throughout my career. It's a good deal.
About me
Hey, I'm Alex, and I've been building software for the last 10 years.
I got tired of rewriting codebases and dealing with messy legacy code. So I set out to learn everything I could about writing software that lasts.
Over the past decade, I've shipped complex front-end applications, built API gateways, and worked with event-driven systems using Kafka - for companies like The Financial Times, News Corp, SumUp, and early stage Silicon Valley startups.
I'm also the author of Tao of React and Tao of Node. This book is a collection of everything that has actually worked in my career. No academic theory, just practical wisdom from the trenches.
Frequently asked questions
Is this book suitable for beginners?
While Full-Stack Tao covers advanced topics, it's designed to be accessible to developers at all levels. It starts from fundamental concepts and builds up to more advanced topics. Beginners will find it challenging, but rewarding.
Do I need to know all the technologies mentioned to benefit from this book?
No, you don't need to be an expert in all the technologies covered. The book focuses on universal principles that can be applied across different tech stacks. Familiarity with React & Node.js is recommended but if you're proficient in other technologies you will still be able to follow along.
How is this book different from other programming books?
Full-Stack Tao doesn't teach you the syntax of a library or how to build applications with a specific stack. It teaches you principles of good software design so you can build maintainable products.
Is there any practical project work in the book?
The book shows a lot of practical examples, but it's not a project-based book. It focuses on principles and every chapter examines a particular problem.
How often is the book updated?
While the core principles remain constant, I try to keep the book up-to-date with latest trends. If the technologies used in the examples change drastically, the book will reflect these changes.
What if I don't like it?
Drop me a line and I'll give you a full refund. No questions asked. This has always been my policy and I've kept it for my previous books as well.
Do I have to read your other books?
Just read this one. It's the best one I've written so far and it covers both front-end and back-end development.
Letters about building software
I share my write-ups and thoughts on software design and architecture, together with the most interesting articles and books I find.
My Newsletter