---
title: "Deprecations"
description: "The live list of what is going away, what replaces it, when it was deprecated and when it will be removed."
url: "https://opsinjs.pensievelabs.org/project/deprecations"
source: "https://opsinjs.pensievelabs.org/project/deprecations.md"
section: "Project"
kind: "project"
reviewed: "2026-09-02"
reviewer: "engineering"
aliases: ["removed", "deprecated api", "what is going away"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="project" />

## The list [#the-list]

Nothing has been deprecated, because nothing has been released. This page is not
a placeholder for that reason. It is the address the deprecation process points
at from day one, so that the first deprecation has somewhere to appear and does
not arrive as a surprise in a changelog entry.

<NoDataYet what="The deprecation list" script="scripts/build-registry.mts">
  No script produces it yet. `scripts/build-registry.mts` reads
  `registry/catalogue.ts` and emits `/r`, and it has no deprecation projection, so
  nothing here fills itself in.
</NoDataYet>

When it has rows, each carries: the deprecated thing, its replacement, the
version that deprecated it, the version that will remove it, and one sentence
saying why. Today a row is written by hand, in the same change that sets the
catalogue row to `deprecated`: a pull request that does one without the other is
incomplete, and reviewing for it is the only thing standing in for a generator.
Projecting the rows out of the catalogue is the better answer and is not built.

## What being on this list means [#what-being-on-this-list-means]

**It still works.** A deprecated component, prop or token keeps working for at
least one minor release before 1.0 and for a full major after it. Something that
stops working is a removal, and a removal that called itself a deprecation is a
broken promise, not a policy detail.

**It has a replacement, or an explanation.** Most rows name what to use instead.
Where there is no replacement, it is because the thing should never have
existed. The row says so and links to the reasoning, which is usually a
[decision record](./decisions/index.mdx).

**It is not recommended for anything new.** If you are starting work today,
treat a deprecated row as absent.

## How to find out early [#how-to-find-out-early]

Read [Versioning policy](./versioning-policy.mdx) for the full process, and the
[changelog](./changelog/index.mdx) for what actually happened in each release. If a
deprecation needs more than a paragraph to migrate through, it gets a written
guide rather than a longer changelog entry, and
[Versioning policy](./versioning-policy.mdx) says which kinds of change earn
one.

The other half of this is knowing which version your copy came from, because that
is what tells you whether a deprecation applies to code already sitting in your
repository. Nothing in the file answers that, so the answer has to come from
your own version control: commit the files `shadcn add` writes, in their own
commit, so a later `--diff` has something to compare against.

<LastUpdated />

<Reviewed />
