+++
title = "Plugin Creation Tutorial"
weight = 4
+++
Backstage plugins and functionality extensions should be writen in TypeScript/Node.js because backstage is written in those languages

### General Algorithm for Adding a Plugin in Backstage

1. **Create the Plugin**  
   To create a plugin in the project structure, you need to run the following command at the root of Backstage:

   ```bash
   yarn new --select plugin
   ```

   The wizard will ask you for the plugin ID, which will be its name. After that, a template for the plugin will be automatically created in the directory `plugins/{plugin id}`. After this install all needed dependencies. After this install required dependencies. In example case this is `"axios"` for API requests  
   Emaple:
   ```bash
    yarn add axios
   ```
2. **Define the Plugin’s Functionality**  
   In the newly created plugin directory, focus on defining the plugin's core functionality. This is where you will create components that handle the logic and user interface (UI) of the plugin. Place these components in the `plugins/{plugin_id}/src/components/` folder, and if your plugin interacts with external data or APIs, manage those interactions within these components.

3. **Set Up Routes**  
   In the main configuration file of your plugin (typically `plugins/{plugin_id}/src/routs.ts`), set up the routes. Use `createRouteRef()` to define route references, and link them to the appropriate components in your `plugins/{plugin_id}/src/components/` folder. Each route will determine which component renders for specific parts of the plugin.

4. **Register the Plugin**  
   Navigate to the `packages/app` folder and import your plugin into the main application. Register your plugin in the `routs` array within `packages/app/src/App.tsx` to integrate it into the Backstage system. It will create a rout for your's plugin page

5. **Add Plugin to the Sidebar Menu**  
   To make the plugin accessible through the Backstage sidebar, modify the sidebar component in `packages/app/src/components/Root.tsx`. Add a new sidebar item linked to your plugin’s route reference, allowing users to easily access the plugin through the menu.

6. **Test the Plugin**  
   Run the Backstage development server using `yarn dev` and navigate to your plugin’s route via the sidebar or directly through its URL. Ensure that the plugin’s functionality works as expected.

### Example

All steps will be demonstrated using a simple example plugin, which will request JSON files from the API of jsonplaceholder.typicode.com and display them on a page.

1. Creating test-plugin:
   ```bash
   yarn new --select plugin
   ```
   Adding required dependencies. In this case only "axios" is needed for API requests
   ```bass
   yarn add axios
   ```
2. Implement code of the plugin component in  `plugins/{plugin-id}/src/{Component name}/{filename}.tsx`
   ```javascript
   import React, { useState } from 'react';
   import axios from 'axios';
   import { Typography, Grid } from '@material-ui/core';
   import {
     InfoCard,
     Header,
     Page,
     Content,
     ContentHeader,
     SupportButton,
   } from '@backstage/core-components';

   export const TestComponent = () => {
     const [posts, setPosts] = useState<any[]>([]);
     const [loading, setLoading] = useState(false);
     const [error, setError] = useState<string | null>(null);

     const fetchPosts = async () => {
       setLoading(true);
       setError(null);

       try {
         const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
         setPosts(response.data);
       } catch (err) {
         setError('Ошибка при получении постов');
       } finally {
         setLoading(false);
       }
     };

     return (
       <Page themeId="tool">
         <Header title="Welcome to the Test Plugin!" subtitle="This is a subtitle">
           <SupportButton>A description of your plugin goes here.</SupportButton>
         </Header>
         <Content>
           <ContentHeader title="Posts Section">
             <SupportButton>
               Click to load posts from the API.
             </SupportButton>
           </ContentHeader>
           <Grid container spacing={3} direction="column">
             <Grid item>
               <InfoCard title="Information Card">
                 <Typography variant="body1">
                   This card contains information about the posts fetched from the API.
                 </Typography>
                 {loading && <Typography>Загрузка...</Typography>}
                 {error && <Typography color="error">{error}</Typography>}
                 {!loading && !posts.length && (
                   <button onClick={fetchPosts}>Request Posts</button>
                 )}
               </InfoCard>
             </Grid>
             <Grid item>
               {posts.length > 0 && (
                 <InfoCard title="Fetched Posts">
                   <ul>
                     {posts.map(post => (
                       <li key={post.id}>
                       <Typography variant="h6">{post.title}</Typography>
                       <Typography>{post.body}</Typography>
                       </li>
                      ))}
                   </ul>
                 </InfoCard>
               )}
             </Grid>
           </Grid>
         </Content>
       </Page>
     );
   };

   ```

3. Setup routs in plugins/{plugin_id}/src/routs.ts

  ```javascript
  import { createRouteRef } from '@backstage/core-plugin-api';

  export const rootRouteRef = createRouteRef({
    id: 'test-plugin',
  });
  ```

4. Register the plugin in `packages/app/src/App.tsx` in routes
  Import of the plugin:

  ```javascript
  import { TestPluginPage } from '@internal/backstage-plugin-test-plugin';
  ```

  Adding route:

  ```javascript
  const routes = (
      <FlatRoutes>
         ... //{Other Routs}
         <Route path="/test-plugin" element={<TestPluginPage />} />
      </FlatRoutes>
  )
  ```

5. Add Item to sidebar menu of the backstage in `packages/app/src/components/Root/Root.tsx`. This should be added in to Root object as another SidebarItem

  ```javascript
  export const Root = ({ children }: PropsWithChildren<{}>) => (
    <SidebarPage>
      <Sidebar>
        ... //{Other sidebar items}
        <SidebarItem icon={ExtensionIcon} to="/test-plugin" text="Test Plugin" />
      </Sidebar>
      {children}
    </SidebarPage>
  );
  ```

6. Plugin is ready. Run the application

 ```bash
  yarn dev
 ```

![example](example_1.png)
![example](example_2.png)
