Welcome
Welcome to the Chahua development guide.
Chahua is a chat application with a backend and multiple client applications. The backend stores data, applies application rules, and delivers messages, while each client provides an interface for people to use Chahua. Clients currently include a Progressive Web App (PWA) and a Flutter app, and other native clients may be added in the future.
This book focuses on developing the PWA frontend and the backend. It explains how these two parts work, how they communicate, and how you can begin contributing to them. The PWA also serves as a concrete example of a Chahua client: once you understand how it sends requests, receives real-time events, and represents shared data, you can use the same model to understand how the Flutter app and future clients interact with the backend. Each client may use different languages and user-interface patterns, but they all build on the same backend capabilities and communication contracts.
You do not need to understand the entire application before making a useful contribution. Large applications are built from many smaller pieces. The goal of this guide is to help you identify those pieces, learn the vocabulary used to describe them, and follow a change through the code without getting lost.
The book follows a practical learning path. You will first learn how a chat application works at a high level. You will then run Chahua on your computer, explore the repository, and follow a message from the frontend to the backend and database. After that, you can study the frontend, the backend, or both.
Along the way, the guide will explain:
- What unfamiliar programming terms mean.
- Why the project uses particular tools and technologies.
- Where to look when you want to change something.
- How to test and debug your work.
- How to prepare a focused contribution for review.
You are not expected to memorize everything. Treat this book as both a guided path and a map you can return to while working.
When you are ready, continue to Who This Book Is For.
Who This Book Is For
This book is for anyone who wants to understand or contribute to Chahua. You may already have extensive programming experience and want a quick, practical map of this project. You may also have no programming experience and want to use Chahua as an opportunity to learn how a real application is built. In either case, the book shows how the clients, backend, database, development tools, and contribution process fit together.
You may be:
- Learning how web applications are built.
- Making your first contribution to an existing project.
- Familiar with frontend development but new to Rust and backend development.
- Familiar with backend development but new to React and Progressive Web Apps.
- An experienced developer who needs a map of this particular codebase.
- Testing, documenting, designing, or supporting the application and wanting to understand how it works.
How This Book Helps You Start
The early chapters provide a brief introduction to the technologies used by Chahua and the role each one plays. They explain the concepts and vocabulary you will encounter, show you how to run the application, and help you find your way through the codebase.
You will also find suggestions for what to learn next and which knowledge is most useful for a particular kind of change. The aim is to help you make a small contribution early, then build a deeper understanding as you continue. This book will not replace a complete programming course, but it should help you understand what to learn, why it matters, and where it appears in Chahua.
Choose the Path That Fits You
Read the foundational and local-setup chapters first if you are new to programming. After the repository tour, you can focus on the PWA frontend, the Rust backend, or continue through both paths. You can always return to the glossary and command cheat sheet when you encounter an unfamiliar term or command.
There is no requirement to understand every technology before contributing. A small documentation improvement, test, styling correction, or carefully scoped code change can all be valuable starting points.
How to Use This Book
This book is both a guided learning path and a reference. You can read it from beginning to end, or start with the sections that match what you want to contribute.
Choose a Starting Point
If you are new to programming or contributing to a software project, begin with Part 0. It is a preface that introduces working with coding agents and Git without expecting you to understand Chahua’s code yet. Continue through Parts I, II, and III to learn how the application works, run it locally, and find your way around the repository.
If you already have programming and Git experience, you may skim or skip Part 0. Begin with Part I for Chahua’s architecture, Part II to run the project, or Part III for a repository tour.
If you already know which side of the application interests you, use:
- Part IV for the PWA frontend.
- Part V for the Rust backend.
- Part VI for planning, testing, and submitting a complete contribution.
Even experienced contributors may find it useful to read the high-level application chapters before changing code. They explain the responsibility boundaries shared by the frontend, backend, database, and other clients.
Use the References as You Go
You are not expected to memorize every term or technology. The appendices include:
- A technology primer with short explanations of topics such as HTTP, APIs, databases, and WebSockets.
- A glossary for quickly looking up terminology used throughout the book.
- A command cheat sheet for commands introduced in the guided chapters.
- References for configuration, project conventions, and further learning.
Chapters link to these references when a term needs more context. Follow the link when it helps, then return to the chapter you were reading.
Learn Enough for the Change in Front of You
You do not need to master the entire stack before contributing. Start by understanding what the relevant part of Chahua is responsible for, how it connects to other parts, and how its changes are verified. Learn additional syntax and implementation details as your contribution requires them.
The exercises are opportunities to practice, not tests you must pass. It is fine to follow them with an agent, repeat them, or skip one that covers something you already understand.
This Book Is a Work in Progress
This guide is still being written alongside Chahua. Some chapters may be incomplete, and parts of the application may change faster than the documentation. An unfinished chapter is not an indication that a reader is expected to already know its subject.
When documentation and current project behavior disagree, inspect the repository and running application, then report or correct the outdated guidance. Improving this book is itself a useful way to begin contributing to Chahua.
Working With Coding Agents
Coding agents can make it easier to begin contributing to Chahua. You can describe a goal in ordinary language, ask an agent to explore unfamiliar parts of the project, and get help making a focused change.
You do not need to memorize every language or framework before you start. Instead, learn what each part of the application does, where a proposed change belongs, and how to decide whether the result is correct. You can learn more syntax and technical detail as you need it.
What an Agent Can Help With
A coding agent can help you:
- Find files related to a feature or problem.
- Explain unfamiliar code and terminology.
- Find an existing project pattern to follow.
- Suggest a plan for a change.
- Make focused edits after you approve the approach.
- Run formatters, builds, and tests.
- Summarize what changed and what still needs checking.
This is useful in Chahua because a feature may involve several parts of the application. An agent can help you follow those connections while you build your own understanding of the project.
What an Agent Cannot Decide for You
An agent begins with incomplete context. It may misunderstand a vague request, miss an undocumented requirement, or make a change that passes a test but does not produce the intended experience.
The contributor remains responsible for:
- Describing the outcome they want.
- Deciding whether the proposed plan makes sense.
- Reviewing what actually changed.
- Checking the result in an appropriate way.
- Deciding whether the change belongs in the project.
An agent’s completion summary is a claim about its work. The changed files, check results, and observed behavior are the evidence you use to evaluate that claim.
You do not need to understand every character of unfamiliar code immediately. You should understand the purpose and consequences of the change well enough to explain it. Ask the agent to clarify anything important that you do not understand.
A Simple Workflow
The same basic process works for many contributions:
Explain the goal
↓
Let the agent inspect the project
↓
Review the proposed plan
↓
Let the agent make the focused change
↓
Review and test the result
↓
Keep, revise, or reject the change
Large goals are easier to manage when divided into smaller changes. A focused change is easier to explain, review, test, and undo if the approach turns out to be wrong.
Chahua also contains instructions for agents in AGENTS.md files. These describe project boundaries and checks that should be followed. An agent should inspect the relevant instructions before changing code.
Give the Agent Useful Context
You do not need to design the technical solution yourself. Start by explaining:
- The goal: What should be different when the work is finished?
- What you observed: What happens now, or what information is missing?
- The boundary: What should remain unchanged?
- Success: How could someone tell that the result works?
For example:
Add a short note to the welcome page explaining that this book focuses on the PWA and backend. Keep the existing introduction and tone. The book should still build successfully.
This gives the agent an outcome and boundaries without telling it exactly how to edit the file. The agent can inspect the documentation structure and suggest an appropriate change.
When the task involves a bug, include the steps that caused it, what you expected, and what happened instead. Screenshots and exact error messages can also provide useful evidence.
Review What Changed
A diff shows the lines that were added, removed, or replaced. Reviewing the diff helps you see the actual change instead of relying only on the agent’s description.
As you review the diff, ask yourself whether you understand the following:
- Which files changed?
- What does the change accomplish?
- Why was the change made in this location?
- Does every change relate to the agreed goal?
- Was anything removed or changed unexpectedly?
If you are unsure, ask the agent to explain a section in plain language or show the existing project pattern it followed. You can also ask for a smaller change if the diff is difficult to review.
Verify the Result
Reviewing the code and checking the result answer different questions. A diff tells you what changed. Verification helps show whether the change works.
Depending on the task, verification may include:
- Building the project.
- Running its automated checks or tests.
- Opening the affected page or feature.
- Repeating the action that previously failed.
- Checking that nearby behavior still works.
Passing checks are useful evidence, but they do not prove every behavior is correct. For a visible change, look at the result. For a behavioral change, try the relevant interaction. Ask the agent what it verified and what it could not verify.
Exercise: Change the Sent Message Bubble Color
Try the workflow with a small, visible PWA change. Treat this as local practice rather than a contribution the project necessarily needs.
-
Ask an agent to find where the PWA defines the colors of sent and received message bubbles. Ask it to explain what it finds before editing.
-
Ask it to change only the sent bubble from the Ionic primary color to the Ionic success color. Require the text to remain readable and the received bubble to remain unchanged.
-
Review the plan. The agent should identify
wetty-chat-mobile/src/components/chat/messages/ChatBubble.module.scssand consider both the background and its corresponding contrast color. -
Approve the focused edit, then review the diff:
git diff -- wetty-chat-mobile/src/components/chat/messages/ChatBubble.module.scss -
Ask yourself whether you understand which selector changed, why each color variable changed, and whether anything outside the requested bubble was affected.
-
Run the frontend checks:
cd wetty-chat-mobile npm run verify -
Start the PWA and open a conversation containing sent and received messages. Confirm that only sent bubbles changed and that their text remains readable. If possible, check both light and dark appearance settings.
-
Keep the change for further practice, ask for a revision, or discard it. Do not submit an exercise-only pull request unless the maintainers want the change.
The goal is not merely to produce a different color. It is to practice asking an agent to explore first, limiting the change, understanding the resulting CSS, and checking the actual interface.
As you continue through this book, you will learn what Chahua’s tools and application layers do. That knowledge will help you give agents better context and review increasingly technical changes without needing to learn everything at once.
Git and GitHub Basics
Software changes over time. A feature may take several attempts, two people may edit the same area, and a change that looked correct may later need to be undone. Source control gives a project a structured history so that this work can be understood and coordinated.
This chapter introduces Git, the source-control tool used by Chahua, and GitHub, the service where the project is shared. You do not need to memorize every command. The important first step is learning what Git keeps track of and where your changes are.
Why Source Control Exists
A source control management system, often shortened to SCM or called a version-control system, records changes to a collection of files. It helps developers:
- See what changed, when it changed, and why.
- Work on different changes without constantly overwriting one another.
- Review a proposed change before adding it to the shared project.
- Return to an earlier version when investigating a problem.
- Connect related file changes to an explanation of their purpose.
Source control is more than a backup. A backup can recover an old copy of a file, but source control organizes changes into meaningful units and records how lines of development relate to one another.
Git and GitHub Are Different
Git is the version-control program. It runs on your computer and can record history without an internet connection. A directory whose history is managed by Git is called a repository, or repo.
GitHub is an online service that hosts Git repositories and adds collaboration tools. Chahua developers use it to share branches, discuss proposed changes, run automated checks, and review pull requests.
You can use Git without GitHub, and other hosting services can host Git repositories. In this project, they are used together:
- Git manages files, branches, and commits.
- GitHub stores a shared copy and supports collaboration around it.
A Mental Model of Git
When working on a change, think of it moving through four places:
working directory -> staging area -> local repository -> remote repository
git add git commit git push
The working directory is the project directory you edit. Its files may differ from the last version Git recorded.
The staging area is the set of changes selected for the next commit. Staging lets you choose which changes belong together instead of committing every modified file at once.
The local repository is the Git history stored on your computer. Creating a commit adds to this local history; it does not immediately upload anything.
A remote repository is a copy stored elsewhere, such as on GitHub. The conventional name for the remote from which you cloned a project is origin.
This model explains an important fact: saving a file, staging it, committing it, and pushing it are four different actions.
Inspect Before You Act
The safest command to run when you are unsure is:
git status
git status reports your current branch and describes files with unstaged changes, staged changes, and some files that Git is not yet tracking. It does not modify anything.
To inspect the actual unstaged changes, run:
git diff
After staging changes, inspect what the next commit would contain with:
git diff --staged
These commands answer different questions: git status summarizes where changes are, while git diff shows what changed inside the files.
Commits and the Staging Area
A commit is a recorded unit of change. It represents a snapshot of the project that incorporates the staged changes. It also has a short identifying hash, an author and time, a message explaining the change, and a connection to the commit that came before it.
A useful commit usually represents one understandable idea. For example, correcting a button label and adding its translation may belong in one commit. An unrelated database change should probably be a separate commit. Focused commits are easier to review and investigate later.
After editing a file, select it for the next commit with:
git add path/to/file
The file is now staged. Staging does not save it permanently and does not upload it. It only updates the proposed contents of the next commit. If you edit the same file again after staging it, the staged version and the new unstaged edits can be different, which git status will show.
Once the staging area contains exactly what you intend, create the commit:
git commit -m "Explain the purpose of the change"
The message should help another person understand the commit without reading every changed line. Prefer a concrete description such as Add empty state to conversation list over a vague message such as updates.
Tracked, Untracked, and Ignored Files
A tracked file is already part of the repository’s history. An untracked file exists in the working directory but has not been added to Git.
A .gitignore file lists patterns for files Git should normally leave untracked. Projects commonly ignore generated build output, dependency directories, editor files, and local configuration containing secrets.
.gitignore does not remove a file that is already tracked. It is also not a security boundary: a secret that has been committed may remain in Git history even if the file is ignored later. Check staged changes before committing and never intentionally commit credentials or private keys.
Branches
A branch is a movable name pointing to a line of commits. Branches let work develop separately from the project’s main line. A contributor can create a branch for one feature while other work continues elsewhere.
To create a branch and switch to it:
git switch -c descriptive-branch-name
To switch to an existing branch:
git switch branch-name
Creating a branch does not duplicate the entire project. Initially, the new branch points to the same commit as the branch from which it was created. As you commit, the branch name moves forward to include the new commits.
Before editing, use git status to confirm that you are on the intended branch.
Combining Lines of Work
Branches eventually need to be combined. Git primarily supports two ways to do this: merge and rebase.
Merge
A merge combines the histories of two branches. When both branches have new commits, Git may create a merge commit that records where the histories joined. The existing commits keep their identities.
Conceptually, merging says: “Bring these two lines of work together here.”
Rebase
A rebase takes commits from one branch and recreates them on top of another starting point. This can produce a simpler, linear history, but the recreated commits have new identities.
Conceptually, rebasing says: “Replay my work as though it began from this newer point.”
Because rebase rewrites commits, do not casually rebase commits that other people are already using. Follow the project’s contribution process or ask a maintainer when unsure.
Merge Conflicts
Git can often combine changes automatically. A merge conflict occurs when Git cannot confidently decide how changes should fit together, such as when two branches changed the same lines differently.
A conflict is not necessarily an error by either developer. It is a request for a person to choose the intended result. Read git status, inspect each conflicted file, understand both changes, and test the resolved result before continuing. Avoid guessing merely to make the conflict markers disappear.
Remotes: Fetch, Pull, and Push
Your local repository and the remote repository do not synchronize automatically. Git provides commands that move information between them.
Fetch downloads information about remote branches and commits without integrating them into your current branch:
git fetch origin
This is useful when you want to inspect what changed remotely before changing local history.
Pull fetches remote changes and then integrates them into the current branch according to Git’s configuration:
git pull
Because it performs both steps, read its output carefully. If you want to understand the remote state first, fetch and inspect it separately.
Push uploads local commits and updates a branch on a remote:
git push
The first push of a new branch commonly sets its upstream relationship:
git push -u origin descriptive-branch-name
After that, Git knows which remote branch corresponds to the local branch, so a plain git push is usually sufficient.
These directions are worth remembering:
fetchbrings remote history to your local repository without integrating it.pullbrings remote history down and integrates it into your current branch.pushsends local commits to the remote repository.
A Git pull and a GitHub pull request are different things. git pull updates a local branch. A pull request proposes that maintainers review and combine a branch on GitHub.
Pull Requests and Review
A pull request, often shortened to PR, is a GitHub collaboration feature rather than a Git command. It presents the difference between branches and provides a place for:
- An explanation of the problem and proposed solution.
- Discussion and code review.
- Automated builds, tests, and other checks.
- Additional commits that respond to feedback.
- A decision to merge or close the proposal.
Opening a pull request does not immediately change the main branch. It makes the proposed work visible for review. When the pull request is accepted, GitHub combines it according to the project’s chosen merge strategy.
Exercise: Make a Small Documentation Contribution
In this exercise, you will add a Markdown comment that helps future authors keep the welcome chapter focused. Unlike visible book text, a Markdown comment gives maintainers guidance without appearing in the rendered page.
Do this exercise in a Chahua clone where you are allowed to create a branch. If your clone uses a main branch with a different name, substitute that name below.
1. Prepare a Branch
Check your current state, update main without creating a merge commit, and create a branch for the exercise:
git status
git switch main
git pull --ff-only
git switch -c docs/comment-welcome-purpose
If git status reports uncommitted work, stop before switching branches or pulling. Preserve and understand that work first. The --ff-only option makes the pull stop instead of creating an unexpected merge commit when the histories have diverged.
2. Make the Change
Open docs/src/welcome.md. Directly below # Welcome, add:
<!-- Keep this chapter welcoming and leave setup instructions for Part II. -->
Save the file. This change is now in your working directory, but it is not staged or committed.
3. Inspect and Stage It
Ask Git where the change is and inspect its contents:
git status
git diff
The file should appear as modified, and the diff should show only the comment you added. Stage that specific file:
git add docs/src/welcome.md
Run git status again. The change should now appear under Changes to be committed. Confirm the exact staged change:
git diff --staged
If anything unexpected is included, stop and investigate before committing.
4. Commit and Push It
Record the staged change in your local repository:
git commit -m "docs: clarify the purpose of the welcome chapter"
Run git status. The working tree should be clean, but the commit still exists only in your local repository. Push the branch to the remote:
git push -u origin docs/comment-welcome-purpose
5. Open a Pull Request
On GitHub, open a pull request from docs/comment-welcome-purpose into main. Explain that the comment helps future authors keep setup instructions in the setup section, and mention that you verified the rendered welcome page is unchanged.
Before submitting it to the real project, ask whether maintainers want exercise contributions. If not, stop after pushing—or keep the exercise entirely local. For a real contribution, use the same workflow with a documentation clarification the project actually needs.
If review leads to another edit, make it on the same branch, inspect it, commit it, and push again. The pull request updates automatically.
Check Your Mental Model
At the end of the exercise, you should be able to identify when the comment existed only in the working directory, when it was staged, when it became a local commit, and when it reached the remote repository.
When You Are Unsure
Before trying a recovery command, pause and locate your work in the mental model:
- Which branch are you on?
- Are the changes only in the working directory?
- Are they staged for a commit?
- Have they been committed locally?
- Have those commits been pushed to a remote?
- Is someone else already using the same branch?
Start with read-only commands such as git status, git diff, git diff --staged, and git log --oneline. Read the output before acting. If a command might discard changes or rewrite shared history, ask for help and preserve the current state until you understand the consequences.
Git becomes easier when you stop treating its commands as a recipe and start asking where each version of your work currently lives. The working directory, staging area, local repository, and remote repository give you a map for answering that question.
How a Chat Application Works
When you use Chahua, several parts of the application work together. You do not need to understand their code yet. Start with the job each part performs and how information moves between them.
The Main Parts
A client is an application a person uses to interact with Chahua. The PWA is one client; the Flutter app is another. In this book, frontend usually means the user-facing part of the PWA: its screens, buttons, forms, and local application state. These and other recurring terms are defined in the glossary.
The backend is a shared service used by every client. It identifies who is making a request, checks what they are allowed to do, applies Chahua’s rules, reads or changes stored information, and returns a result.
The database stores information that must remain available, such as users, chats, and messages. Clients do not access it directly. They ask the backend, and the backend decides what may be read or changed.
The basic flow often looks like person → client/frontend → backend → database. Results travel back in the other direction.
Requests and Responses
Many actions use an HTTP request and response. HTTP is a standard way for applications to exchange information: one side sends a request and the other sends a response. The client asks the backend to do something, then waits for an answer.
For example, opening a chat may cause the PWA to request its recent messages. The backend checks that the person may view the chat, reads the messages from the database, and sends them back. The PWA stores the result in its local state and displays it.
Real-Time Events
A chat application also needs updates that arrive without repeatedly asking for them. Chahua keeps a WebSocket connection open between a client and the backend. The backend uses this connection to send real-time events, such as an event announcing that a new message was created.
HTTP requests are useful when a client initiates an action. WebSocket events are useful when the backend needs to tell connected clients that something has changed. The WebSocket does not replace the API or database; it helps clients stay up to date.
A Message’s Journey
When you send a message from the PWA:
- You enter text and select Send.
- The frontend sends an HTTP request containing the message and chat information.
- The backend identifies the sender and checks that the action is allowed.
- The backend stores the message in PostgreSQL.
- After the database change succeeds, the backend returns a response and sends WebSocket events to connected recipients.
- Each client updates its local state and screen to show the message.
Real applications add details such as errors, retries, permissions, attachments, notifications, and temporary loading states. Keep the simpler journey above as your starting model.
A Map for the Rest of the Book
When exploring a feature, ask:
- What does the person see or do in the client?
- What request or real-time event crosses the client-backend boundary?
- What rule does the backend apply?
- What information is read or stored?
- How does the result reach every relevant client?
This journey shows how information moves through Chahua. The next chapter looks more closely at what each part owns, where application state lives, and how clients stay synchronized with the backend.
Frontend, Backend, Database, and Real-Time Events
The previous chapter followed a message through Chahua. This chapter uses that same journey to answer a different question: which part of the application is responsible for each step?
Clear responsibilities make an application easier to understand and change. They also help you decide where to begin looking when something does not work as expected.
Three Kinds of State
State is information an application needs to remember. It helps to separate state into three broad kinds:
- Interface state describes what is happening on one screen, such as which chat is open, what text is in the message box, or whether a request is loading.
- Local application state is the client’s current view of shared information, such as the messages it has loaded.
- Durable shared state is information saved by the backend in the database, such as the accepted messages in a chat.
The client’s local state is useful, but it may be incomplete or briefly out of date. A client might have loaded only the newest messages, missed events while offline, or still be waiting for a request to finish. The backend and database determine the durable shared result.
The Client: Interaction and Presentation
A client gives a person a way to use Chahua. The PWA runs in a web browser, while the Flutter application is another client with its own interface and implementation.
For the PWA, the frontend is responsible for work such as:
- showing chats, messages, forms, and buttons;
- collecting input, including a message draft;
- representing temporary states such as loading, sending, or an error;
- sending requests in response to a person’s actions;
- receiving data and events and updating the screen; and
- keeping enough local state to provide a responsive interface.
Suppose you type Hello into a message box. That draft belongs to the client until you send it. The frontend can display it immediately because no other user needs to see an unfinished draft.
The client should not have final authority over shared rules. It may hide a button when it knows a person lacks permission, but the backend must still check the permission. A different or modified client could send the request without using that button.
The HTTP API: A Shared Contract
When the person selects Send, the client needs to ask the backend to create the message. It does this through Chahua’s HTTP API.
An API is a contract between software components. For an HTTP API, that contract describes details such as:
- which route and HTTP method to use;
- what information the request must contain;
- how identity is provided;
- what data a successful response contains; and
- which errors the backend may return.
Every Chahua client can use the same backend contract, even though the clients may be written in different languages and display different interfaces. Learning how the PWA makes a request therefore gives you a model for understanding how the Flutter client or a future client can perform the same action.
The contract works in both directions. If the backend changes the shape or meaning of a request or response, clients may also need to change. Later chapters will show where these contracts appear in the code; for now, remember that the API is the boundary through which a client asks for shared work to be done.
The Backend: Rules and Coordination
The backend receives requests from every client and coordinates the shared work. When it receives the request to send Hello, it may need to:
- Authenticate the request by determining who sent it.
- Authorize the action by checking whether that person may send messages in this chat.
- Validate the input by checking that required information has an acceptable form.
- Apply Chahua’s business rules, meaning the rules that define how the application behaves.
- Read or change information in PostgreSQL.
- Return either a result or an error using the API contract.
- Coordinate follow-up work, such as real-time events or notifications.
Authentication and authorization are related but different. Authentication answers, “Who is making this request?” Authorization answers, “May this person perform this action?”
These checks belong in the backend because it is the shared boundary used by all clients. A frontend check can improve the experience, but it cannot safely replace a backend check.
PostgreSQL: Durable Shared State
Chahua uses a PostgreSQL database to store durable information such as users, chats, and messages. Durable means that the information remains available after a request finishes, a browser closes, or a backend process restarts.
Clients do not connect directly to PostgreSQL. They ask the backend for information, and the backend applies permissions and application rules before reading or changing the database.
For the message journey, the database is where Hello becomes an accepted, durable message. Until that change succeeds, the application must be prepared for the operation to fail. The backend might reject the request, or the database operation might not complete.
It is useful to think of PostgreSQL as the durable source of truth for this shared information. A message displayed in one client’s local state is a view of that information, not an independent authoritative copy.
Real-Time Events: Announcing a Change
After the message is stored, other connected clients need to learn about it. Chahua uses WebSocket connections to deliver real-time events such as an announcement that a message was created.
A WebSocket event is not the durable message itself and does not replace the database. It tells a client that shared state changed and gives it information needed to update its local view.
The order matters. The backend should announce a successful change only after the corresponding database change succeeds. Otherwise, a client could display a message that was never durably stored.
Connected clients can use the event to update promptly without repeatedly asking whether anything changed. Each client then updates its own local state and renders the new message in its own interface.
Reconnecting and Catching Up
Real-time connections are not permanent. A laptop can sleep, a phone can lose its network connection, or a backend process can restart. Events sent while a client is disconnected may never reach that client.
For this reason, WebSockets do not replace HTTP requests. A client commonly uses:
- HTTP to load an initial or authoritative view of data and to recover missed information; and
- WebSocket events to apply new changes promptly while connected.
When a client reconnects, it may need to request messages again or request everything after the last item it knows about. The exact recovery mechanism belongs in later implementation chapters. The important concept is that the client must be able to rebuild its local view from durable backend data rather than assuming it received every event.
Supporting Systems
The client, backend, and PostgreSQL form the core path, but a production chat application needs other services. Chahua also has supporting systems for concerns such as:
- object storage, which stores attachment data that does not belong directly in a database row;
- push notifications, which can alert a device when its client is not actively connected; and
- search, which helps find messages efficiently.
These systems have specialized jobs. They support the core application but do not replace its responsibility boundaries. Clients still go through the backend, backend rules still control shared actions, and PostgreSQL remains the durable source for the application’s primary records.
Put the Responsibilities Together
The complete message journey now looks like this:
- The PWA holds the unfinished draft in interface state.
- The PWA sends an HTTP request defined by the API contract.
- The backend authenticates the sender, authorizes the action, validates the request, and applies Chahua’s rules.
- PostgreSQL stores the durable message.
- After that change succeeds, the backend returns a response and sends real-time events.
- Connected clients update their local state and screens.
- A client that was disconnected later uses HTTP to catch up from durable data.
This model will help you trace other features. Ask what belongs only to one interface, what crosses the API boundary, which rules require shared enforcement, what must be stored durably, and how other clients learn about a change.
Exercise: Who Owns This Work?
For each task below, decide which part should have the primary responsibility: the client, HTTP API contract, backend, PostgreSQL, or real-time delivery. Some tasks involve more than one part, but try to identify the owner.
- Keep the text of an unsent message visible while a person types.
- Define the data a client must provide to create a message.
- Check whether the sender belongs to the chat.
- Preserve an accepted message after everyone closes the application.
- Tell another connected client that the message was created.
- Show a temporary spinner while the request is in progress.
- Recover messages missed while a device was offline.
Suggested answers
- The client owns the unsent draft.
- The HTTP API contract defines the request.
- The backend checks membership and permission.
- PostgreSQL stores the durable message, coordinated by the backend.
- Real-time delivery announces the committed change.
- The client represents the temporary loading state.
- The client uses the HTTP API to ask the backend for durable data from PostgreSQL.
You now have a responsibility map for the application. The repository tour later in this book will connect this map to directories and files, and the frontend and backend learning paths will explain how each responsibility is implemented.
The Tools and Languages We Use
Local Development Overview
Install and Configure the Tools
Start the Backend and Frontend
Confirm It Works
Common Setup Problems
Repository Tour
How to Read Unfamiliar Code
Follow a Message Through the System
Frontend Learning Path
TypeScript and React Essentials
Pages, Components, Routes, and State
API Calls, WebSockets, and the PWA Lifecycle
Styling, Localization, and Accessibility
Frontend Testing and Debugging
Make Your First Frontend Change
Backend Learning Path
Rust Essentials
Requests, Handlers, DTOs, and Services
PostgreSQL, Diesel, and Migrations
Authentication, WebSockets, and Supporting Services
Backend Testing and Debugging
Make Your First Backend Change
Plan and Build a Small Full-Stack Change
Keep Frontend and Backend Contracts in Sync
Format, Lint, Build, and Test
Commits, Pull Requests, and Code Review
Technology Primers
This appendix gives quick introductions to technologies mentioned throughout the book. You do not need to study every topic before continuing. Follow a link here when you want more context, then return to the chapter you were reading.
HTTP
HTTP stands for Hypertext Transfer Protocol. It defines a common way for a client and server to exchange information using requests and responses. Just about every website you visit is delivered using HTTP or HTTPS, which is HTTP protected by encryption. Browsers use it to request web pages, images, and other files, and web applications also use it to exchange data with backend servers. A request describes what the client wants to read or change. The response reports the result and may include data.
For example, the Chahua PWA sends an HTTP request when it asks for recent messages. The backend sends an HTTP response containing those messages or an error explaining why the request could not be completed.
API
An Application Programming Interface (API) is a defined way for software to interact with other software. Chahua’s HTTP API describes which requests clients can make, what information each request contains, and what responses the backend returns.
Database
A database stores structured information so it can be found and changed later. Chahua uses PostgreSQL to store information such as users, chats, and messages. Clients ask the backend for this information rather than connecting to the database directly.
WebSocket
A WebSocket is a long-lived connection that allows both sides to send information without starting a new HTTP request each time. Chahua uses it to notify connected clients about events such as newly created messages.
Client and Server
A client asks for information or actions on behalf of a person. A server receives those requests and provides shared services. In Chahua, the PWA and Flutter app are clients, while the backend runs as a server.
Glossary
This glossary provides short definitions of terms used throughout the book. The technology primers explain selected topics in more detail.
API: A defined way for software systems to interact.
Acceptance criteria: Observable conditions used to decide whether a change achieves its intended result.
Coding agent: Software that can inspect a project, explain it, run tools, and propose or make changes in response to instructions.
Authentication: Determining who is making a request.
Authorization: Determining whether someone may perform an action.
Backend: The shared part of Chahua that applies rules, works with stored data, and serves clients.
Branch: A movable name for one line of commits in a Git repository.
Business rules: Rules that define what actions an application permits and how it should behave.
Client: An application that communicates with a server on behalf of a person.
Commit: A recorded snapshot and explanation of a change in a Git repository.
Database: A system for storing and retrieving structured information.
Durable: Able to remain available after a request ends or a program restarts.
Diff: A comparison showing which lines or files were added, removed, or changed.
Frontend: The user-facing part of an application. In this book, it usually means the Chahua PWA.
Git: A version-control program used to record and combine changes to files.
GitHub: An online service for hosting Git repositories and collaborating on their contents.
HTTP: A request-and-response protocol commonly used for communication between web clients and servers.
Local state: A client’s current working view of information, which may be incomplete or briefly out of date.
Linter: A tool that reports suspicious code patterns or violations of project rules.
Object storage: A service for storing files and other large pieces of data as named objects.
PostgreSQL: The relational database system Chahua uses for its primary durable records.
PWA: Progressive Web App; a web application that can provide app-like features while running through web technologies.
Pull request: A proposal on a collaboration platform such as GitHub to review and combine one branch into another.
Remote: A named connection from one Git repository to another repository.
Repository: A project directory and the history Git maintains for it.
Staging area: The changes selected to become part of the next Git commit.
State: Information an application needs to remember while it operates.
Verification: Collecting evidence that a change satisfies its requirements and preserves relevant existing behavior.
WebSocket: A long-lived, two-way connection between a client and server.