# Bernardo Trindade de Abreu: notes for agents

Senior Full Stack Engineer specializing in React, Node.js, Python, AI, and cloud technologies at ustwo. This is a personal site and engineering blog: a homepage, an
archive at /writing, and one page per article. There is nothing to authenticate
against and nothing to install. Every surface below is a plain GET.

This page is the whole setup and getting-started guide for integrating the site.
There is no SDK, no MCP server and no API beyond the GET routes listed here, so
there is nothing else to look for.

## Configuration

No API key, no account, no rate limit beyond ordinary fair use. Two request
headers change what you get back:

- `Accept: text/markdown` on any page returns that page's Markdown mirror
  instead of HTML.
- `Accept: text/html` (what browsers send) always returns the rendered page.

Responses are cached at the edge for an hour (`Cache-Control: public,
s-maxage=3600`). Markdown mirrors carry a `Link: <…>; rel="canonical"` header
pointing at the HTML page they mirror. Prefer that URL when citing.

## Usage

Read the site's map, then a single article as Markdown:

```sh
# Every page and machine-readable surface, one line each
curl https://btrindade.com/llms.txt

# Full text of every article, concatenated
curl https://btrindade.com/llms-full.txt

# One article as Markdown, two equivalent ways
curl https://btrindade.com/writing/same-devops-new-gremlins.md
curl -H 'Accept: text/markdown' https://btrindade.com/writing/same-devops-new-gremlins
```

Each Markdown mirror opens with YAML frontmatter and closes with a `## Sitemap`
section, so one fetch is enough to discover the rest of the site:

```markdown
---
title: "Same DevOps, new gremlins"
description: "DevOps didn't shrink when AI arrived. The shape is the same, but every stage has had to absorb a class of failure that wasn't there before. Here's what's changed in practice."
doc_version: "1"
last_updated: "2026-06-11"
canonical: "https://btrindade.com/writing/same-devops-new-gremlins"
---
```

## Errors

- A page that does not exist answers 404. With `Accept: text/markdown`, the
  body is Markdown linking to /sitemap.md and /llms.txt.
- Anything under `/api/` fails as RFC 9457 problem details
  (`application/problem+json`). Branch on `code`
  (`invalid_email`, `subscription_failed`, `post_not_found`,
  `endpoint_not_found`, `endpoint_gone`); `detail` says what went wrong in
  words.

## Versioning

Paths carry no version and do not change under you. A change that would break
a caller ships at a new path instead, and the old path keeps answering for at
least 90 days. During that time its responses carry:

- `Deprecation` (RFC 9745): when the path was deprecated, as a structured
  field date, e.g. `Deprecation: @1688169599`.
- `Sunset` (RFC 8594): when it is retired, as an HTTP date, e.g.
  `Sunset: Sun, 30 Jun 2024 23:59:59 GMT`. Never earlier than the deprecation.
- `Link: <…>; rel="successor-version"` (RFC 5829): the path that replaces it.

The operation is also marked `deprecated: true` in /openapi.json. After the
Sunset date the path answers `410 Gone` as problem details with code
`endpoint_gone`, still linking its successor.

A new field or a new endpoint is treated as compatible and gets no notice, so
read responses tolerantly: take the fields you need and ignore the rest.

Nothing is deprecated today. /openapi.json and the JSON endpoints already send
`Link: </AGENTS.md>; rel="deprecation"` (RFC 9745) pointing at this policy.

## Other surfaces

- [/llms.txt](https://btrindade.com/llms.txt): llmstxt.org site map
- [/llms-full.txt](https://btrindade.com/llms-full.txt): full text of every article
- [/sitemap.md](https://btrindade.com/sitemap.md): every URL, as Markdown
- [/sitemap.xml](https://btrindade.com/sitemap.xml): the same, as XML
- [/openapi.json](https://btrindade.com/openapi.json): schema for the routes above
- [/.well-known/api-catalog](https://btrindade.com/.well-known/api-catalog): RFC 9727
  catalog pointing at that schema
- [/rss.xml](https://btrindade.com/rss.xml): feed of new articles
