# How to Read DevChalk

> What each part of a page does: the code blocks, matching colours, boxes, figures and tools, and the Markdown copies.

By Krishan Kumar. Published 2026-10-24, Updated 2026-10-25.
Source: https://devchalk.com/articles/how-to-read

Each series builds one app from an empty folder, a part at a time. This page shows what each piece of an article does. The examples are real blocks from the [Goravel series](https://devchalk.com/goravel).

## Reading a series

Parts build on each other, so read them in order. Each series page lists the parts that are written and the ones still to come. New parts also come out on the [RSS feed](https://devchalk.com/rss.xml).

You can still start at any part. Each part after the first opens with a block like this one, from [Validation with Form Requests](https://devchalk.com/goravel/08-validation-form-requests). It gets you the code as the part before left it:

Start from the Factories & Seeding code:

```bash
git clone https://github.com/krishankumar01/goravel-taskflow
cd goravel-taskflow
git checkout part-07
cp .env.example .env
go run . artisan key:generate
docker compose up -d
go run . artisan migrate:fresh --seed
go install github.com/air-verse/air@latest
air
```

Each series has its own repository, with one commit per step and a tag for each part: `part-01`, `part-02`, and so on. For Goravel, it is [goravel-taskflow](https://github.com/krishankumar01/goravel-taskflow). The box at the end of each part links to its tag, to its changes since the part before, and to a zip.

## Code blocks

The name on top of a block is the file it belongs to. **Copy** copies the code. In Go blocks it copies tabs, the way `gofmt` writes Go, so pasted code is already formatted.

A block that changes a file shows the whole file. Lines marked `+` are added, and lines marked `-` are removed. Most of the lines you don't touch are folded away; click a fold to open it. **Copy** gives the file as it should end up, with the folded lines and without the removed ones. These blocks from [Reading Request Data](https://devchalk.com/goravel/03-reading-request-data#route-parameters) add a method to a controller, and its route:

```diff lang="go" title="app/http/controllers/task_controller.go" collapse={1-16} t1:name=/RouteInt.("id")/
 package controllers
 
 import (
 	"github.com/goravel/framework/contracts/http"
 )
 
 type TaskController struct {
 	// Dependent services
 }
 
 func NewTaskController() *TaskController {
 	return &TaskController{
 		// Inject services
 	}
 }
 
 func (r *TaskController) Store(ctx http.Context) http.Response {
 	return ctx.Response().String(200, "task created")
 }
+
+func (r *TaskController) Show(ctx http.Context) http.Response {
+	id := ctx.Request().RouteInt("id")
+
+	return ctx.Response().Json(200, map[string]any{
+		"id": id,
+	})
+}
```

```diff lang="go" title="routes/api.go" collapse={1-9} t1:name="{id}"
 package routes
 
 import (
 	"taskflow/app/facades"
 	"taskflow/app/http/controllers"
 
 	"github.com/goravel/framework/contracts/route"
 )
 
 func Api() {
 	taskController := controllers.NewTaskController()
 
 	facades.Route().Prefix("api/v1").Group(func(router route.Router) {
 		router.Post("tasks", taskController.Store).Name("tasks.create")
+		router.Get("tasks/{id}", taskController.Show)
 	})
 }
```

Code keeps its lines as written, so a long line scrolls sideways. Query logs wrap instead, so you can read them without scrolling. The server sends a response on one line, as the terminal blocks show. Response blocks show it indented, for reading.

In a terminal block, a line that starts with `$` is a command, and the dimmed lines are what it prints. **Copy** copies only the commands:

```bash
$ go run . artisan migrate
  INFO    Running migration
  INFO    Running: 20210101000002_create_jobs_table
  INFO    Running: 20261022221906_create_users_table
 SUCCESS  Migration success
```

## Boxes in the text

Each kind of box has its own label and icon:

- A **Gotcha** box, in red, is something that trips you up, with the output that shows it.
- A **Note** box is a side fact, such as another place the code could go.
- A **More** box opens to a side trip, such as another way to do a step or a measurement. You can skip it on a first read.
- A **Code** box gets you the code. At the start of a part it opens to the commands that set up the part before, and at the end it links to the part's tag, its changes and a zip.

## Matching colours

When a word in the text has the same colour as a piece of code, they are the same thing. Here, the `{id}` in the path is what `"id"` reads in `Show` above. The `5` at the end of this request is the value it gets:

```bash wrap t2:value=/tasks.(5)/
$ curl http://localhost:3000/api/v1/tasks/5
{"id":5}
```

Point at a coloured word to light every piece in its group, so you can follow them without telling the colours apart. Click or tap it to keep it lit and go to the next piece, which scrolls into view if it is off the screen. Click anywhere else to let it go.

## Figures

A figure shows how something works, such as what the code does as it runs, or how the tables connect. Some are drawings. On the table design in [Installation & Project Architecture](https://devchalk.com/goravel/01-installation-project-architecture#the-database-design), pointing at a line lights the two columns it joins.

Others have controls along the bottom. A row of choices picks a case, and **Previous** and **Next** go through it one step at a time. The chip in the corner shows the result, and the text under the drawing says what is going on. This one is from [Validation with Form Requests](https://devchalk.com/goravel/08-validation-form-requests):

*What `ValidateRequest` does with a request, in order. Pick a request, then step through it.*

ValidateRequest runs Authorize first; StoreTaskRequest returns nil, so the request goes on. It has no PrepareForValidation. Then the filters run, then the rules, then Bind, and then Store answers. With spaces in the title, trim turns " Ship v1 " into "Ship v1", every rule passes, Bind fills StoreTaskRequest using its form tags, and Store answers 200 OK. With assigned_to 99, exists asks Postgres for user 99, finds no row and fails. With due_at "soon", date fails and bail stops the field before future_date runs. When a rule fails, Bind copies nothing and Store answers 422 with errors.All().

The arrow keys step too, once you have clicked the figure. A longer figure has a few more controls. This one, from [Register & Login with JWT](https://devchalk.com/goravel/09-register-login-jwt), follows one session through TaskFlow:

- **Next** says what it will do, such as "Next: look up the email".
- The bar above the buttons shows where you are. Click a name on it to jump to the start of that request.
- **Play** steps on its own, at reading pace, until you pause it or press a button.
- Click an arrow or a box you have already passed to go back to it.

*One session against TaskFlow, one message at a time.*

Register: the API hashes the password with bcrypt and inserts one row into users. Log in: the API selects the user by email, checks the password against the hash, and signs a token with JWT_SECRET; nothing is written to Postgres or Redis. /me: the API asks Redis whether the token was logged out, checks the signature, and loads the user by the id in the token. Log out: the API writes the token into Redis as disabled. /me again: Redis has the token, so the API answers 401 before checking the signature.

Without JavaScript, each figure is replaced by a short text that says the same thing.

## Tools

Some parts give you a tool to use on your own project, not just on the article's example. In [Register & Login with JWT](https://devchalk.com/goravel/09-register-login-jwt), you paste the token your login returned, and the page takes it apart and checks its signature with your secret. Tools run in your browser, and what you paste is never stored or sent anywhere. Even so, use a local secret, not a production one.

## Jumping to a section

On a wide screen, the list beside each article marks the section you are reading. On a phone, it sits above the article. Click a heading in it to jump there.

## Markdown copies for AI assistants

Every article has a plain Markdown copy at the same address with `.md` added, like [/goravel/08-validation-form-requests.md](https://devchalk.com/goravel/08-validation-form-requests.md). It has the same words, the code exactly as written, full links, and each figure as its text. Give it to an AI assistant when you want help with a part.

[/llms.txt](https://devchalk.com/llms.txt) lists every copy, and [/llms-full.txt](https://devchalk.com/llms-full.txt) has every article in one file.
