Resource Documentation
Within an entity, we saw that we have a docs section that is missing an annotation.

And right in the overview we can also observe that View Source redirects directly to the repository, but View TechDocs is disabled.

It is necessary to inform in the definition of this component where its documentation is located through an annotation.
Let's make it happen and then explain. Let's add the following annotation.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: artist-web
description: The place to be, for great artists
labels:
example.com/custom: custom_label_value
annotations:
example.com/service-discovery: artistweb
circleci.com/project-slug: github/example-org/artist-website
backstage.io/techdocs-ref: dir:. # We add this annotation
## ...
spec:
## ...
TechDocs will look for where the docs folder is located. Let's create it in the root of the project's backstage folder and place some markdown documentation there. Let's name it documentation.md.
β― tree
.
βββ README.md
βββ backstage
β βββ api-external.yaml
β βββ api.yaml
β βββ component-website.yaml
β βββ docs
β β βββ documentation.md
β βββ group.yaml
β βββ system.yaml
βββ openapi
βββ swagger.json

It's building, but an error will occur. Actually, it looks for index.md, so by renaming the file from documentation.md to index.md we will get our result in the docs tab.

Also, we can navigate through the documentation using the sidebar and we see that it generated the documentation for the component.

But how did this actually happen?
Techdocs Configurationβ
The TechDocs configuration is in the app-config.yaml file.
# Reference documentation http://backstage.io/docs/features/techdocs/configuration
# Note: After experimenting with basic setup, use CI/CD to generate docs
# and an external cloud storage when deploying TechDocs for production use-case.
# https://backstage.io/docs/features/techdocs/how-to-guides#how-to-migrate-from-techdocs-basic-to-recommended-deployment-approach
techdocs:
builder: 'local' # Alternatives - 'external'
generator:
runIn: 'docker' # Alternatives - 'local'
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read documentation for using alternatives.
What is MkDocs?β
We need to understand what it is because TechDocs uses MkDocs to generate documentation from markdown files.
MkDocs is a static documentation generation tool, designed to create documentation sites based on Markdown files.
It transforms the content from a Markdown documents folder into HTML pages that can be easily hosted on servers or static site hosting services, such as GitHub Pages.
Knowing this, if MkDocs needs to process an input to generate an output, we need to define how it will do this and where the generated files will go.
We don't necessarily need to generate this locally, we could have a completely external runner to do this processing. Even the generated files could be stored completely external to Backstage, such as an S3 bucket on AWS.
Instead of using Docker, we could simply use a container as a service.
In the default configuration as we saw above, it's using Docker locally to process the files. This spotify/techdocs image was never directly downloaded by me; it was executed during the process.
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kindest/node <none> 6f8c6c736970 2 weeks ago 1.04GB
spotify/techdocs v1.2.4 55addc1021da 5 months ago 663MB
If we were running Backstage as a container, would it need to spin up a container inside another container if done this way? So to maintain this, keep in mind that the image must be capable of doing this.
Python is required for the TechDocs plugin. If we have the packages installed on the same machine or container running Backstage, we wouldn't need to do this.
- python3
- python3-pip
- python3-venv
And run pip3 install mkdocs-techdocs-core.
If we were to add this to the Backstage container itself in the future, we would need this.
RUN apt-get update && apt-get install -y python3 python3-pip python3-venv
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN pip3 install mkdocs-techdocs-core
Using locally and keeping Docker, we need to define where the generated files will go. Let's add and configure the directory and see what happens.
techdocs:
builder: 'local' # Alternatives - 'external'
generator:
runIn: 'docker' # Alternatives - 'local'
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read
local:
publishDirectory: '/home/david/labs/backstage-site'
When we go to the component page again, it will be processed again and the container will place the files in this folder.
~/labs/backstage-site
tree
.
βββ default
βββ component
βββ artist-web
βββ 404.html
βββ assets
β βββ images
β β βββ favicon.png
β βββ javascripts
β β βββ bundle.c8d2eff1.min.js
β β βββ bundle.c8d2eff1.min.js.map
β β βββ lunr
β β β βββ min
β β β β βββ lunr.ar.min.js
β β β β βββ lunr.da.min.js
β β β β βββ lunr.de.min.js
β β β β βββ lunr.du.min.js
β β β β βββ lunr.el.min.js
β β β β βββ lunr.es.min.js
β β β β βββ lunr.fi.min.js
β β β β βββ lunr.fr.min.js
β β β β βββ lunr.he.min.js
β β β β βββ lunr.hi.min.js
β β β β βββ lunr.hu.min.js
β β β β βββ lunr.hy.min.js
β β β β βββ lunr.it.min.js
β β β β βββ lunr.ja.min.js
β β β β βββ lunr.jp.min.js
β β β β βββ lunr.kn.min.js
β β β β βββ lunr.ko.min.js
β β β β βββ lunr.multi.min.js
β β β β βββ lunr.nl.min.js
β β β β βββ lunr.no.min.js
β β β β βββ lunr.pt.min.js
β β β β βββ lunr.ro.min.js
β β β β βββ lunr.ru.min.js
β β β β βββ lunr.sa.min.js
β β β β βββ lunr.stemmer.support.min.js
β β β β βββ lunr.sv.min.js
β β β β βββ lunr.ta.min.js
β β β β βββ lunr.te.min.js
β β β β βββ lunr.th.min.js
β β β β βββ lunr.tr.min.js
β β β β βββ lunr.vi.min.js
β β β β βββ lunr.zh.min.js
β β β βββ tinyseg.js
β β β βββ wordcut.js
β β βββ workers
β β βββ search.b8dbb3d2.min.js
β β βββ search.b8dbb3d2.min.js.map
β βββ stylesheets
β βββ main.7e359304.min.css
β βββ main.7e359304.min.css.map
β βββ palette.06af60db.min.css
β βββ palette.06af60db.min.css.map
βββ documentation
β βββ index.html
βββ index.html
βββ search
β βββ lunr.js
β βββ main.js
β βββ search_index.json
β βββ worker.js
βββ sitemap.xml
βββ sitemap.xml.gz
βββ techdocs_metadata.json
13 directories, 53 files
If we put the annotation on an API for example like this, we are using the same previous documentation.
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: petstore-api
description: Petstore API Swagger
annotations:
backstage.io/techdocs-ref: dir:.
###...
It is highly recommended that the docs folder be alongside the yaml file, so let's completely change our structure from this point forward.
I tried to make references using the annotation backstage.io/techdocs-ref: dir:./docs/newdocs and other attempts to indicate the path, but I couldn't, so let's change it. That's why I made the comment about structure error in catalog.
Another proposal is to keep the folders with the names of the things and all files should be called catalog-info.yaml, which is the standard used by Backstage.
Understanding these limitations, the correct approach to work with, considering that we may have monorepo (worst case), is:
- Not having the backstage folder as we previously defined.
- Having a catalog-info.yaml in the root of the project, because if it actually is a monorepo then it will probably be a system.
- In each folder of the different projects in the monorepo, we will have the catalog-info.yaml and its docs.
For this, we need to modify the definition of the providers that we have looking for files.
providers:
github:
providerId:
organization: davidpuziol
schedule:
frequency: { minutes: 3 }
timeout: { minutes: 3 }
filters:
branch: 'main' # string
repository: '.*' # Regex
#catalogPath: '/backstage/**/*.{yaml,yml}' # Search recursively
catalogPath: '/**/catalog-info.{yaml,yml}'
The approach above ensures that even if you have a backend folder it will work, because it won't require the folder, but we'll fix the name as catalog-info.yaml. Within this same file, if necessary, we can define more than one object inside it.
We're like this for now.
β― tree
.
βββ README.md
βββ backstage
β βββ api
β β βββ catalog-info.yaml
β β βββ docs
β β βββ index.md
β βββ api-external
β β βββ catalog-info.yaml
β β βββ docs
β β βββ index.md
β βββ docs
β β βββ index.md
β βββ group
β β βββ catalog-info.yaml
β βββ system
β β βββ catalog-info.yaml
β βββ website
β βββ catalog-info.yaml
β βββ docs
β βββ index.md
βββ openapi
βββ swagger.json
And everything will work accordingly. Remember that each of the catalog-info.yaml files have completely different definitions.
If you've made it this far, it's necessary to make these changes also in backstage-base which defines some initial groups that we will use in the future. This repository will work as the structure of the fake company we're building. We create domain, groups, subgroups, user to simulate a company.