Fix Backstage Plugin Install – Plugin Not Appearing in UI
DodaTech
Updated 2026-06-24
3 min read
In this tutorial, you'll learn about Fix Backstage Plugin Install. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
You follow the docs to install a Backstage plugin — you yarn add it, add the route binding, restart — but nothing changes. The plugin page doesn't appear in the sidebar, and navigating to the URL gives a blank page or 404.
Wrong ❌
# You install the plugin
yarn add --cwd packages/app @backstage/plugin-techdocs
```<a href="/programming-languages/typescript/">TypeScript</a>
// packages/app/src/App.tsx — you add this
import { TechDocsPage } from '@backstage/plugin-techdocs';
const routes = (
<FlatRoutes>
<Route path="/docs" element={<TechDocsPage />} />
</FlatRoutes>
);
Restart: `yarn dev`. Navigate to `/docs`. Blank page. Console error:
Element type is invalid: expected a string or class/function but got: object
## Right ✅
**Correct plugin registration pattern:**
```typescript
// packages/app/src/App.tsx
import { TechDocsPage } from '@backstage/plugin-techdocs';
// Step 1 — create a route ref
import { createRouteRef } from '@backstage/core-plugin-api';
const techdocsRouteRef = createRouteRef({ id: 'techdocs' });
// Step 2 — bind the route
const App = () => (
<AppProvider>
<AppRouter>
<Root>
<Sidebar>
<SidebarItem icon={DocsIcon} to="/docs" text="Docs" />
</Sidebar>
<FlatRoutes>
<Route
path="/docs"
element={<TechDocsPage />}
/>
</FlatRoutes>
</Root>
</AppRouter>
</AppProvider>
);
**Also register the plugin's API:**
Many plugins need an API Factory:
```<a href="/programming-languages/typescript/">TypeScript</a>
// packages/app/src/apis.ts
import { techdocsApiRef, techdocsStorageApiRef } from '@backstage/plugin-techdocs';
export const apis = [
// ... existing APIs
createApiFactory({
api: techdocsApiRef,
deps: {},
Factory: () => new TechDocsClient(),
}),
createApiFactory({
api: techdocsStorageApiRef,
deps: {},
Factory: () => new TechDocsStorageClient(),
}),
];
**Restart — plugin appears:**
📁 Backstage App
📁 Docs ← new sidebar item
📁 Catalog
📁 API
Navigate to `/docs`:
Docs Home
├── Team Handbook
├── Architecture Decision Records
├── API Documentation
## Root Cause
Backstage plugins consist of frontend components, API factories, and route bindings. Missing API factories or incorrect route registration are the most common reasons a plugin doesn't render.
## Prevention
- Read the plugin's `README` for the exact registration pattern — each plugin differs slightly.
- Use `yarn backstage-cli create-plugin` to generate a skeleton with correct wiring.
- Check the browser console and backend logs for errors after adding a plugin.
- Import plugins from their published entry point (e.g. `@backstage/plugin-techdocs`), not internal paths.
## Common Mistakes with plugin install
1. **Forgetting `deriving (Show, Eq)` on custom data types needed for debugging**
2. **Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable**
3. **Using `head` and `tail` instead of pattern matching, causing runtime errors on empty lists**
These mistakes appear frequently in real-world BACKSTAGE code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
## Practice Exercise
**Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.**
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
## FAQ
<details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: Where do I put API factories?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: In <code>packages/app/src/apis.ts</code>. The file exports an array of <code>ApiFactory</code> objects passed to the <code>AppProvider</code>.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: My plugin is visible but the page is empty — why?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: The plugin may need backend support (e.g. TechDocs needs <code>techdocs-backend</code>). Check the backend plugin installation steps.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: How do I use a plugin's optional extensions?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: Extensions like tabs or cards are imported separately. Check the plugin's API report.</p>
</div></details><details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">**Q: Can I add a plugin without modifying `App.tsx`?**</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>A: Some plugins use dynamic route discovery. Others require explicit route binding. Always check the plugin docs.</p>
</div></details>
---
*Plugin installation is covered in the [DodaTech Backstage Plugin Development course](https://dodatech.com/courses/backstage).*
← Previous
Backstage Permission Policy Returns Unexpected Deny
Next →
Backstage Proxied Auth Session Loop
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro