Good API documentation should help developers understand a project, make their first request, and figure out what to do when something goes wrong.
Thally is a platform for building and managing developer documentation. In this tutorial, I'll show how I used it to document TaskSocial, a task management API, from setting up the documentation site to configuring navigation, connecting an OpenAPI specification, and publishing the result.
While testing the documentation, I also found a difference between a successful authenticated request with curl and a failed request in the API playground. I'll explain what I tested and what I learned from it.
The published TaskSocial documentation site, organised around getting started, practical guides, and the API reference.
1. What you’ll need
Before starting, make sure you have:
A Thally Cloud account.
Git installed.
A GitHub account.
Node.js and npm installed.
An existing project or API to document.
Basic familiarity with Markdown and the terminal.
Check your local setup:
node -v
npm -v
git --version
You don't need to build a complete application. A small project is enough if you can explain how another developer would use it.
2. Create your Thally site
Start with the Thally quickstart and sign in to Thally Cloud.
Create a workspace if you don't already have one, then start creating a documentation site. I named mine TaskSocial Docs and chose tasksocial-docs.thally.app as the site address.
Next, connect GitHub. Thally offers a fresh-repository option and an option to use an existing compatible repository. I chose to create a new docs repository for the assessment because my first repository name conflicted with an existing one. I didn't want to overwrite another project.
For this walkthrough, select Create a new docs repository, choose the connected GitHub account, and enter a repository name. If you're creating a fresh repository, make sure the Thally GitHub App has the required All repositories access.
Select the production branch you intend to publish from. In my project, that branch was main.
I skipped the optional product-source tracking setup because it wasn't needed for this documentation exercise.
After completing setup, wait until the initial deployment is marked as live. Open the published site to confirm that the starter documentation is accessible before moving on.
In this tutorial, I'll start with the repository generated during Thally setup and customise it rather than build the documentation project from scratch. The generated project provides the initial configuration and file structure; I'll use those files to add content, organise navigation, and connect the API reference.
3. Clone the repository and run it locally
Once Thally has generated the repository and connected it to your site, open that repository on GitHub, copy its clone URL, and run:
git clone <YOUR_REPOSITORY_URL>
cd <YOUR_REPOSITORY_NAME>
npm install
npm run dev
Use the clone URL of the repository connected to your own Thally site. You must have permission to access it. Replace the placeholders with your repository URL and directory name.
Keep the terminal running and open the local URL printed in its output. In my setup, the development server ran at http://localhost:3040. You should see the starter documentation site before you begin editing files.
My project’s relevant files were organised like this:
tasksocial-thally-assessment/
├── docs.json
├── openapi.yaml
├── package.json
├── public/
└── src/
├── data/
│ └── site.ts
└── content/
├── introduction.mdx
├── quickstart.mdx
├── guides/
│ └── authentication-and-tasks.mdx
└── api/
├── introduction.mdx
└── authentication.mdx
This is a simplified view of the relevant files, not the entire project.
src/content/contains the Markdown/MDX pages.docs.jsonorganises navigation and site features.src/data/site.tscontains product details, links, and brand defaults you can customise.openapi.yamldescribes the API endpoints, schemas, and authentication.public/holds static assets such as logos and favicons, if you need to add or replace them.package.jsondefines the commands used to run and build the project.
The diagram below shows how the source files connect to validation, the build process, and the published site.
The main source files, validation and build steps, and the published documentation site.
One issue I encountered was that changes to MDX pages didn't consistently appear in my local browser until I restarted the development server. I could reproduce this behaviour but couldn't establish its cause. Restarting the server was my workaround.
4. Write the content
I organised the site around three questions: What is TaskSocial? How can a developer get started? How can they use the API?
Start with an introduction that explains what your project does, who it's for, and where a new user should go next.
Then write a quickstart that leads to a useful result. For TaskSocial, that meant explaining how to register, log in, and retrieve the authenticated user's tasks. The relevant routes are:
POST /api/v1/auth/register
POST /api/v1/auth/login
GET /api/v1/tasks/my-tasks
For example, a quickstart can introduce a task like this:
# Quickstart
## Retrieve your tasks
1. Create an account using the registration endpoint.
2. Log in to receive the authentication cookie.
3. Send the cookie with a request to
`GET /api/v1/tasks/my-tasks`.
A successful request returns the tasks associated
with the authenticated user.
The example above shows the structure of a quickstart, not a complete runnable workflow. For a working example, see the published TaskSocial Quickstart. It documents the actual steps for registering, logging in, and retrieving the authenticated user's tasks.
When writing a quickstart for your own API, make each step reproducible. Include the actual request fields, a copyable request example, the authentication requirements, and a representative response. Verify these details against the API implementation rather than assuming that the OpenAPI specification or an example is correct.
I also created a practical guide at src/content/guides/authentication-and-tasks.mdx. It covers the authentication and task-management workflow, including what to check when a protected request fails.
MDX let me write these pages in Markdown while keeping them in the same repository as the site configuration.
5. Configure navigation and the API reference
Writing pages doesn't automatically give readers a useful way to find them. I configured three tabs in docs.json: Get started, Guides, and API Reference.
Edit the generated pages or create new MDX files under src/content/, then add their paths to the top-level tabs array in docs.json.
The following snippets show individual tab entries from my configuration, not complete configuration files. Update the corresponding entries in your generated configuration rather than replacing the entire file.
Make sure each page path in docs.json matches an existing MDX file under src/content/. For the API reference, openapi.yaml must also exist at the location specified by the source setting.
Configure the Guides tab
In my project, the Guides tab contains a group called TaskSocial workflows, with a page about authentication and task management.
Here is a snippet from my actual configuration:
{
"tab": "Guides",
"groups": [
{
"group": "TaskSocial workflows",
"pages": [
"guides/authentication-and-tasks"
]
}
]
}
This places the authentication and task guide under the Guides tab. The path guides/authentication-and-tasks corresponds to src/content/guides/authentication-and-tasks.mdx; the .mdx extension is omitted from the configuration.
If you want to add another guide, create its MDX file under src/content/guides/ and add its path to the appropriate group's existing pages array in docs.json. Make sure the path matches the file's location and name. Then check the local site to confirm that the page appears under the intended tab.
Connect the API reference
For the API reference, my configuration includes:
{
"tab": "API Reference",
"groups": [
{
"group": "Overview",
"pages": [
"api/introduction",
"api/authentication"
]
}
],
"api": {
"source": "openapi.yaml"
}
}
This connects the API tab to openapi.yaml while keeping the introductory and authentication pages in the same section. The specification describes the API in OpenAPI format, including endpoints, request bodies, authentication requirements, and response schemas.
For TaskSocial, I documented cookie-based authentication for protected endpoints. The important detail was to explain not only that authentication uses a cookie, but also how a client obtains and sends it.
Keep navigation focused and make sure the specification matches the actual API. A plausible endpoint or response schema is still incorrect if the implementation behaves differently.
6. Validate and publish
Before pushing my changes, I ran the Thally CLI check and production build:
npx --yes @thallylabs/cli@latest check
npm run build
The CLI reported zero errors and six orphan-page warnings for unused starter pages that remained in the repository but were not included in my intended navigation.
The Thally CLI check reported zero errors and six orphan-page warnings for starter pages left out of the navigation.
The production build completed successfully, including TypeScript checks and static page generation.
The production build compiled successfully
These checks serve different purposes: the CLI check highlights documentation issues, while the production build verifies that the project can compile. Neither guarantees that every instruction or API example works, so test important steps manually too.
I then committed and pushed the changes:
git status
git add docs.json openapi.yaml src/content/
git commit -m "docs: customize TaskSocial documentation"
git push origin main
If you modify other files, stage those changes too before committing. These commands assume your production branch is main. Adjust the final command if you use another branch.
After pushing, open the live site and check the introduction, quickstart, guide, navigation, and API reference. A successful local build is useful, but the deployed site is what readers will actually use.
7. Test the API authentication flow
I wanted to check whether the documented authentication flow worked against the real TaskSocial API, not just in the documentation interface.
The command examples use a Bash-compatible terminal. Install curl if you want to follow the API authentication test.
First, register a test account using the registration endpoint documented in the TaskSocial API reference. You need an existing account before running the login request below. Then log in using curl and save the returned cookie to a local cookie jar. Replace the placeholders with credentials for your own test account:
API_BASE="https://tasksocial-p2cw.onrender.com"
curl -i \
-X POST "$API_BASE/api/v1/auth/login" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"YOUR_EMAIL","password":"YOUR_PASSWORD"}'
The -c cookies.txt option saves cookies returned by the server. I then sent that cookie with the protected request:
curl -i \
"$API_BASE/api/v1/tasks/my-tasks" \
-b cookies.txt
Both requests returned HTTP 200 in my test. The task request returned an empty task list, which was a valid response for that account.
Calling the same protected endpoint through my site’s API playground returned HTTP 401 with a ‘No token provided’ message. The playground indicated that the cookie was not being sent. I couldn't establish why, but the comparison showed that a successful request with curl didn't guarantee the same result in the playground.
When an example fails, test the same request independently before deciding whether the issue lies with the API, the documentation, or the client. Also, cookies.txt contains session credentials: never commit or share it, and remove it after testing.
rm -f cookies.txt
8. Before you publish
Before sharing your documentation, check three things:
Check navigation and content paths. Make sure every page listed in
docs.jsonexists and appears in the intended section.Verify API examples. Confirm that endpoints, request bodies, and authentication requirements match the actual API.
Test the complete workflow. Run the production build, open the published site, and test important API requests independently of the documentation playground.
These checks help catch problems that a successful build alone won't reveal.
You can use TaskSocial Docs as a reference for the finished site.






Top comments (0)