goauthentik / goauthentik/authentik
Allow additional links on application cards
- Dominant language
- Python
- Stars
- 25.6k
- Forks
- 2k
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 659
Description
### The problem
The user library gives every application exactly one action: open it in a browser.
Plenty of self-hosted services also ship a native client, and the card says nothing about it — users
go hunting elsewhere and install the wrong one. Those clients then ask for a server address, which
authentik already knows from the launch URL but never offers in a form you can copy.
### What I'd like
An optional row under the application card, configured per application:
- **Links** — label, URL, optional icon. Native clients, documentation, status page, support.
Nothing is derived automatically.
- **A copy button** — puts the application's address on the clipboard, shows it in a tooltip, and
confirms when it lands. The address is no longer printed on the card: it took a whole line to say
what a button says better.
- **A heading** for the row, optional, aligned left, centre or right.
Two switches in the application's **UI settings** turn each half on, next to *Open in new tab* and
*Hide from Application Dashboard*. Both default to off, and the link editor stays usable whether the
switch is on or not.
The row renders in the list view as well as the grid. That is not a detail: below 768px the library
forces list mode, so a card-only feature is invisible on every phone.
### Related: #16776
#16776 asks for custom schemes such as `steam://` as the application URL. The two are complementary
rather than competing: that one changes what the primary launch does, this one keeps the web launch
primary and adds the rest beside it.
### How it is built
- **Storage** — one `JSONField` on `Application`, following the `Tenant.footer_links` precedent. The
whole block (switches, heading, alignment, links) lives in that single object, so the display
settings cost no extra column and no second migration. The earlier bare-list shape is still read,
so nothing already stored is lost.
- **Icons** — the existing `Application.meta_icon` / `ak-app-icon` convention.
- **Admin UI** — the existing `ak-array-input`.
- **Security** — URLs are validated server-side and anything that is not `http(s)` is rejected. A URL
typed without a scheme is completed to `https://`, but a scheme we refuse is never rewritten into
one we accept.
- **API** — no new endpoint, and no extra request on the dashboard.
I did consider a dedicated `ApplicationLink` model with a foreign key and explicit ordering. I went
with the JSON field because it is the smaller change and follows an existing pattern — happy to
convert it if you would rather have the model.
### Alternatives considered
- **Brand custom CSS** — can restyle, cannot create links.
- **`meta_description`** — not shown on the card, HTML escaped, and mixes configuration with prose.
- **One application per platform** — works, but splits one service across several cards.
- **An external landing page** — works, adds a hop and duplicates what authentik already holds.
- **Homepage, Homarr and friends** — replacing the portal defeats the point of a single door behind
SSO.
- **Custom JavaScript** — far too much surface for something this small.
### Screenshots
before :
after :
### Two things I noticed on the way
Both independent of this proposal, and happy to split them out:
- `ak-file-search-input` appears to fire two identical requests to `/api/v3/admin/file/` per
instance.
- `ak-app-icon` only constrains `max-height`, so an SVG without intrinsic dimensions can overflow
its row.
### Disclosure
I built this with an AI assistant, working under my direction, and I would rather say so upfront.
The design decisions are mine, and claims about existing authentik behaviour — `Tenant.footer_links`,
the library, the icon conventions, the components reused — were checked against the codebase rather
than assumed. If the project has a policy on AI-assisted contributions, I will follow it.
The implementation is open as #25801.
---
Contributor guide
Research direction
Start by reviewing Application storage, the Tenant.footer_links precedent, ak-array-input, and the existing Application.meta_icon/ak-app-icon usage in the dashboard's grid and list views. The implementation is open as #25801; done means the optional links, copy control, heading alignment, UI switches, persistence compatibility, and server-side URL validation work without a new endpoint or dashboard request.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, frontend, full-stack
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100