Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/all.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,4 +12,5 @@ spec:
- ./resources/*.yaml
- ./domains/*.yaml
- ./apis/*.yaml
- ./templates/*/template.yaml
- ./templates/*/template.yaml
- ./portal-docs/catalog-info.yaml
16 changes: 16 additions & 0 deletions examples/portal-docs/catalog-info.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: portal-docs
title: Developer Portal Docs
description: Onboarding, support, and how-to guides for the Developer Portal.
tags:
- onboarding
- getting-started
- support
annotations:
backstage.io/techdocs-ref: dir:.
spec:
type: documentation
lifecycle: production
owner: group:platform-engineering
44 changes: 44 additions & 0 deletions examples/portal-docs/docs/index.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
# Getting Started with the Developer Portal

Welcome! This guide walks you through your first five minutes in the portal.

## 1. Find what already exists

Use the search bar on the homepage or browse the [Catalog](/catalog) to find
services, APIs, systems, and teams. Every entity has an owner, a lifecycle,
and links out to source code and documentation.

## 2. Create your first service

Head to **Start here → Create your first service** on the homepage, or go
straight to [Self-Service](/self-service). Pick a template, fill in the form,
and the scaffolder will:

1. Create a repository in GitHub or GitLab.
2. Seed it with a starter skeleton (code, docs, CI-ready layout).
3. Register the new component in the catalog so it shows up immediately.

## 3. Register an existing repo

Already have a repository? Use
[Catalog Import](/catalog-import) to add a `catalog-info.yaml` to it and
register it here. Once registered it appears in search, the catalog graph,
and your team's ownership views.

## 4. Read the docs

Technical documentation lives in [Docs](/docs). Anything tagged
`onboarding` or `getting-started` is surfaced directly on the homepage.

## 5. Explore APIs

The [API Explorer](/api-docs) lists every API registered in the catalog,
with OpenAPI/AsyncAPI definitions rendered inline.

## What's next?

- Check the **System Health** panel on the homepage for a snapshot of the
catalog's lifecycle states.
- Visit the [Scorecard](/scorecard) to see how entities measure up against
quality checks.
- See [Support & FAQ](support.md) if you get stuck.
43 changes: 43 additions & 0 deletions examples/portal-docs/docs/support.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
# Support & FAQ

How to get unstuck when something in the portal isn't working.

## Where to get help

1. **This documentation** — start with [Getting Started](index.md).
2. **The catalog** — every entity lists an owner. For questions about a
specific service or API, contact the owning team shown on the entity page.
3. **Platform Engineering** — owns the portal itself (search, scaffolder,
TechDocs, catalog ingestion). See the `platform-engineering` group in the
catalog for current members.

## Frequently asked questions

### My component doesn't show up in the catalog

- Confirm the repo has a `catalog-info.yaml` at its root.
- Confirm the file is registered: use
[Catalog Import](/catalog-import) to locate and register it.
- Check for YAML syntax errors; a single bad entity file can be rejected by
the catalog ingestion loop.

### My TechDocs site isn't building

- Confirm the entity has the `backstage.io/techdocs-ref` annotation.
- Confirm `mkdocs.yml` exists at the referenced path and includes the
`techdocs-core` plugin.
- Docs build on first read; the first page load can take a minute.

### A scaffolder run failed

- Open the failed task from [Self-Service](/self-service) and expand the
step logs — the failing step is highlighted.
- Most failures are permissions: the scaffolder needs a token with write
access to the target GitHub org or GitLab group.

### How do I add a new software template?

Templates live under `examples/templates/` in the portal repository. Add a
folder with a `template.yaml` and a `template/` skeleton, tag it
`recommended` plus a `family:` tag, and it appears on the homepage and the
Self-Service page automatically.
9 changes: 9 additions & 0 deletions examples/portal-docs/mkdocs.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
site_name: Developer Portal Docs
site_description: Onboarding, support, and how-to guides for the Developer Portal.

nav:
- Getting Started: index.md
- Support & FAQ: support.md

plugins:
- techdocs-core
106 changes: 106 additions & 0 deletions examples/templates/ai-hub-service/template.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: ai-hub-service
title: AI Hub Service
tags:
- recommended
- family:ai-native
- provider:github
- ai
- llm
description: |
Scaffold an AI Hub service: a thin, provider-agnostic gateway in front of
your organisation's LLM providers. Centralises authentication, rate
limiting, cost tracking, and audit logging for inference traffic.
Ships with an AGENTS.md, a TechDocs site, and catalog registration.
spec:
owner: platform-engineering
type: service

parameters:
- title: Service details
required:
- owner
- name
properties:
owner:
title: Owner
type: string
description: Owner of the component
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: [Group, User]
name:
title: Name
type: string
description: Unique name of the service
ui:placeholder: ai-hub
description:
title: Description
type: string
description: What this AI Hub fronts (providers, teams, use cases)

- title: Choose a location
required:
- repoUrl
properties:
repoUrl:
title: Repository Location
type: string
ui:field: RepoUrlPicker
ui:options:
requestUserCredentials:
secretsKey: USER_OAUTH_TOKEN
allowedHosts:
- github.com
allowedOwners:
- echohello-dev
allowedOrganizations:
- echohello-dev

steps:
- id: fetch-base
name: Fetch Base
action: fetch:template
input:
url: ./template
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
destination: ${{ parameters.repoUrl | parseRepoUrl }}
description: ${{ parameters.description }}

- id: publish
name: Publish
action: publish:github
input:
allowedHosts:
- github.com
description: ${{ parameters.description }}
repoUrl: ${{ parameters.repoUrl }}
token: ${{ secrets.USER_OAUTH_TOKEN }}
gitAuthorName: ${{ user.entity.metadata.name }}
gitAuthorEmail: ${{ user.entity.spec.profile.email }}
visibility: public

- id: register
name: Register
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml

output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }}
- title: Open in catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }}
text:
- title: Next steps
content: |
Your AI Hub skeleton is ready. Wire a provider in `src/providers/`,
then update `AGENTS.md` with the conventions your team settles on.
27 changes: 27 additions & 0 deletions examples/templates/ai-hub-service/template/AGENTS.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
# Agent instructions for ${{ values.name }}

## What this repo is

An AI Hub gateway: a single, provider-agnostic front door for LLM inference
traffic. Provider SDKs are never called directly by consumers — everything
goes through this service.

## Commands

- Build: `npm run build`
- Run locally: `npm start` (after build), listens on `PORT` (default 8080)
- Type-check without emitting: `npx tsc --noEmit`

## Conventions

- One file per provider in `src/providers/`, each exporting a
`complete(request): Promise<Answer>`-shaped function.
- No provider SDK imports outside `src/providers/`.
- No secrets in the repo. Provider credentials come from environment
variables only.
- Keep request/response shapes stable; consumers depend on them.

## When editing

- Update `docs/` when behaviour, endpoints, or configuration change.
- Keep this file short — move detail into `docs/` and link to it.
15 changes: 15 additions & 0 deletions examples/templates/ai-hub-service/template/Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json tsconfig.json ./
RUN npm install
COPY src ./src
RUN npm run build

FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package.json ./
RUN npm install --omit=dev
COPY --from=build /app/dist ./dist
EXPOSE 8080
CMD ["node", "dist/index.js"]
35 changes: 35 additions & 0 deletions examples/templates/ai-hub-service/template/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
# ${{ values.name }}

{% if values.description %}${{ values.description }}{% else %}AI Hub gateway service.{% endif %}

A thin, provider-agnostic gateway in front of one or more LLM providers.
Route inference traffic through this service so authentication, rate
limiting, cost tracking, and audit logging live in exactly one place.

## Quick start

```bash
npm install
npm run build
npm start
```

The server listens on `PORT` (default `8080`):

- `GET /healthz` — liveness probe
- `POST /v1/answer` — single entry point for inference requests (stubbed
until a provider is wired in `src/providers/`)

## Layout

| Path | Purpose |
|---|---|
| `src/index.ts` | HTTP server and route wiring |
| `src/providers/` | One file per LLM provider (add yours here) |
| `docs/` | TechDocs site source |
| `AGENTS.md` | Repo instructions for AI coding tools |

## Documentation

Rendered docs are published via TechDocs — see the **Docs** tab on this
component's page in the Developer Portal.
21 changes: 21 additions & 0 deletions examples/templates/ai-hub-service/template/catalog-info.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: ${{ values.name | dump }}
description: >-
{% if values.description %}
${{ values.description | dump }}
{% else %}
AI Hub gateway service
{% endif %}
tags:
- ai-native
- ai-hub
- llm
annotations:
github.com/project-slug: ${{ values.destination.owner + "/" + values.destination.repo }}
backstage.io/techdocs-ref: dir:.
spec:
type: service
lifecycle: experimental
owner: ${{ values.owner | dump }}
32 changes: 32 additions & 0 deletions examples/templates/ai-hub-service/template/docs/index.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
# ${{ values.name }}

{% if values.description %}${{ values.description }}{% else %}AI Hub gateway service.{% endif %}

## What it does

This service is the single entry point for LLM inference traffic. Consumers
call `POST /v1/answer`; the hub handles authentication, rate limiting, cost
tracking, and routing to the configured provider.

## Endpoints

| Method | Path | Purpose |
|---|---|---|
| `GET` | `/healthz` | Liveness probe |
| `POST` | `/v1/answer` | Submit a prompt, receive an answer |

## Configuration

| Variable | Default | Purpose |
|---|---|---|
| `PORT` | `8080` | Listen port |

Provider credentials are read from environment variables. Never commit
secrets to this repository.

## Adding a provider

1. Create `src/providers/<name>.ts` implementing the `Provider` interface
from `src/providers/index.ts`.
2. Instantiate it in `src/index.ts` and route `/v1/answer` to it.
3. Document the provider and its configuration here.
10 changes: 10 additions & 0 deletions examples/templates/ai-hub-service/template/mkdocs.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
site_name: ${{ values.name | dump }}
{% if values.description %}
site_description: ${{ values.description | dump }}
{% endif %}

nav:
- Overview: index.md

plugins:
- techdocs-core
17 changes: 17 additions & 0 deletions examples/templates/ai-hub-service/template/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
{
"name": "${{ values.name }}",
"version": "0.1.0",
"private": true,
"description": "{% if values.description %}${{ values.description }}{% else %}AI Hub gateway service{% endif %}",
"main": "dist/index.js",
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js",
"dev": "tsc -p tsconfig.json --watch",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.5.0"
}
}
Loading
Loading