> ## Documentation Index
> Fetch the complete documentation index at: https://backstage.spotify.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Customizing Skill Exchange

> Customize Skill Exchange UI labels, categories, skills lists, and page text using the message customization API and configuration options.

export const CarouselWithReferenceTable = ({items}) => {
  const [currentIndex, setCurrentIndex] = useState(0);
  const hideCarousel = items.length <= 1;
  const nextItem = () => {
    setCurrentIndex(prevIndex => (prevIndex + 1) % items.length);
  };
  const prevItem = () => {
    setCurrentIndex(prevIndex => (prevIndex - 1 + items.length) % items.length);
  };
  return <>
      <div className="relative w-full mb-6">
        <div className="bg-gray-100 dark:bg-gray-800 rounded-xl overflow-hidden">
          {}
          <div className="text-center text-lg font-semibold py-4 px-6 text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700">
            {items[currentIndex].image.alt}
          </div>

          {}
          <div className="relative w-full overflow-hidden">
            <div className="flex transition-transform duration-500 ease-in-out" style={{
    transform: `translateX(-${currentIndex * 100}%)`
  }}>
              {items.map((item, index) => <div key={index} className="w-full flex-shrink-0 flex items-center justify-center p-8" style={{
    minWidth: '100%'
  }}>
                  <img src={item.image.src} alt={item.image.alt} className="max-w-full max-h-[600px] object-contain rounded-lg shadow-lg" />
                </div>)}
            </div>

            {}
            {!hideCarousel && <>
                <button className="absolute top-1/2 -translate-y-1/2 left-4 w-12 h-12 rounded-full bg-white/95 dark:bg-gray-800/95 hover:bg-white dark:hover:bg-gray-800 shadow-xl flex items-center justify-center text-3xl font-bold text-gray-800 dark:text-white transition-all duration-200 hover:scale-110 z-10" onClick={prevItem} aria-label="Previous item">
                  ‹
                </button>

                <button className="absolute top-1/2 -translate-y-1/2 right-4 w-12 h-12 rounded-full bg-white/95 dark:bg-gray-800/95 hover:bg-white dark:hover:bg-gray-800 shadow-xl flex items-center justify-center text-3xl font-bold text-gray-800 dark:text-white transition-all duration-200 hover:scale-110 z-10" onClick={nextItem} aria-label="Next item">
                  ›
                </button>
              </>}
          </div>

          {}
          {!hideCarousel && <div className="flex justify-center gap-2 py-4">
              {items.map((_, index) => <button key={index} className={`h-2.5 rounded-full transition-all duration-200 ${currentIndex === index ? 'bg-[#1DB954] w-8' : 'bg-gray-400 dark:bg-gray-600 hover:bg-gray-500 dark:hover:bg-gray-500 w-2.5'}`} onClick={() => setCurrentIndex(index)} aria-label={`Go to item ${index + 1}`} />)}
            </div>}
        </div>
      </div>
      {items[currentIndex].references && <table>
          <caption className="text-left font-semibold mb-4">
            Translation references for {items[currentIndex].image.alt}
          </caption>
          <thead>
            <tr>
              <th>#</th>
              <th>Key</th>
              <th>Default Text</th>
            </tr>
          </thead>
          <tbody>
            {items[currentIndex].references.map(reference => <tr key={reference.key}>
                <td>{reference.index}</td>
                <td className="p-3">
                  <code>{reference.key}</code>
                </td>
                <td>{reference.defaultText}</td>
              </tr>)}
          </tbody>
        </table>}
    </>;
};

export const homePageCarouselItems = [{
  image: {
    src: '/plugins/skill-exchange/assets/home-page.png',
    alt: 'Home Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'homePage.title',
    defaultText: 'Find people who can help'
  }, {
    index: 5,
    key: 'homePage.search.placeholder',
    defaultText: 'Search for people by discipline, skill, or team'
  }, {
    index: 6,
    key: 'homePage.cards.embeds.title',
    defaultText: 'Start an embed'
  }, {
    index: 7,
    key: 'homePage.cards.embeds.details',
    defaultText: 'Discover short-term opportunities to learn from another team or share your expertise.'
  }, {
    index: 8,
    key: 'homePage.cards.embeds.myEmbeds',
    defaultText: 'My Embeds'
  }, {
    index: 9,
    key: 'homePage.cards.mentors.title',
    defaultText: 'Find mentorships and pairing'
  }, {
    index: 10,
    key: 'homePage.cards.mentors.details',
    defaultText: 'Problem-solve with a pair or search for the perfect mentor/mentee match. Sometimes the best learning happens one-on-one.'
  }, {
    index: 11,
    key: 'homePage.cards.mentors.myMentorships',
    defaultText: 'My Mentorships'
  }, {
    index: 12,
    key: 'homePage.cards.hacks.title',
    defaultText: 'Join a hack'
  }, {
    index: 13,
    key: 'homePage.cards.hacks.details',
    defaultText: "Find a project to hack on, or a team to get to know. Use your skills to build something fun and expand what's possible."
  }, {
    index: 14,
    key: 'homePage.cards.hacks.myHacks',
    defaultText: 'My Hacks'
  }]
}];

export const embedsPageCarouselItems = [{
  image: {
    src: '/plugins/skill-exchange/assets/embeds-page.png',
    alt: 'Embeds Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'embedsPage.title',
    defaultText: 'Embeds'
  }, {
    index: 5,
    key: 'embedsPage.actions.create.label',
    defaultText: 'Create Post'
  }, {
    index: 6,
    key: 'embedsPage.search.placeholder',
    defaultText: 'Search embeds'
  }, {
    index: 7,
    key: 'embedsPage.search.filters.myEmbeds',
    defaultText: 'My embeds'
  }, {
    index: 8,
    key: 'embedsPage.cards.chips.embed',
    defaultText: 'Embed'
  }, {
    index: 9,
    key: 'embedsPage.cards.embedDetails',
    defaultText: 'Embed details'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/embeds-page-view.png',
    alt: 'View Embed Page'
  },
  references: [{
    index: 1,
    key: 'embedsPage.view.embedDetails',
    defaultText: 'Embed details'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/embeds-page-create.png',
    alt: 'Create Embed Page'
  },
  references: [{
    index: 1,
    key: 'embedsPage.create.title',
    defaultText: 'Create Embed'
  }, {
    index: 2,
    key: 'embedsPage.form.priority.label',
    defaultText: 'High priority embed'
  }, {
    index: 3,
    key: 'embedsPage.form.priority.description',
    defaultText: 'Is this a high priority embed?'
  }, {
    index: 4,
    key: 'embedsPage.card.chips.embed',
    defaultText: 'Embed'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/embeds-page-edit.png',
    alt: 'Edit Embed Page'
  },
  references: [{
    index: 1,
    key: 'embedsPage.edit.title',
    defaultText: 'Edit Embed'
  }, {
    index: 2,
    key: 'embedsPage.form.priority.label',
    defaultText: 'High priority embed'
  }, {
    index: 3,
    key: 'embedsPage.form.priority.description',
    defaultText: 'Is this a high priority embed?'
  }, {
    index: 4,
    key: 'embedsPage.card.chips.embed',
    defaultText: 'Embed'
  }, {
    index: 5,
    key: 'embedsPage.card.embedDetails',
    defaultText: 'Embed details'
  }]
}];

export const mentorsPageCarouselItems = [{
  image: {
    src: '/plugins/skill-exchange/assets/mentors-page-mentorships.png',
    alt: 'Mentorships Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'mentorsPage.navigation.events',
    defaultText: 'Events'
  }, {
    index: 5,
    key: 'mentorsPage.navigation.mentorships',
    defaultText: 'Mentorships'
  }, {
    index: 6,
    key: 'mentorsPage.mentorships.actions.create.label',
    defaultText: 'Create Post'
  }, {
    index: 7,
    key: 'mentorsPage.mentorships.search.placeholder',
    defaultText: 'Search mentorships'
  }, {
    index: 8,
    key: 'mentorsPage.mentorships.search.filters.myMentorships',
    defaultText: 'My mentorships'
  }, {
    index: 9,
    key: 'mentorsPage.mentorships.search.filters.beAMentor',
    defaultText: 'Be a mentor'
  }, {
    index: 10,
    key: 'mentorsPage.mentorships.search.filters.findAMentor',
    defaultText: 'Find a mentor'
  }, {
    index: 11,
    key: 'mentorsPage.mentorships.search.filters.lookingToPair',
    defaultText: 'Looking to pair'
  }, {
    index: 12,
    key: 'mentorsPage.mentorships.results.sections.lookingToPair.title',
    defaultText: 'Looking to pair'
  }, {
    index: 13,
    key: 'mentorsPage.mentorships.results.sections.offeringToMentor.title',
    defaultText: 'Offering to mentor'
  }, {
    index: 14,
    key: 'mentorsPage.mentorships.results.sections.lookingForMentor.title',
    defaultText: 'Looking for a mentor'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/mentors-page-mentorships-create.png',
    alt: 'Create Mentorship Page'
  },
  references: [{
    index: 1,
    key: 'mentorsPage.mentorships.create.title',
    defaultText: 'Create Mentorship'
  }, {
    index: 2,
    key: 'mentorsPage.mentorships.form.requestType.label',
    defaultText: 'What are you looking for?'
  }, {
    index: 3,
    key: 'mentorsPage.mentorships.form.requestType.options.offering',
    defaultText: 'I am offering to mentor'
  }, {
    index: 4,
    key: 'mentorsPage.mentorships.form.requestType.options.looking',
    defaultText: 'I am looking for a mentor'
  }, {
    index: 5,
    key: 'mentorsPage.mentorships.form.requestType.options.pairing',
    defaultText: 'I am looking to pair with'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/mentors-page-mentorships-edit.png',
    alt: 'Edit Mentorship Page'
  },
  references: [{
    index: 1,
    key: 'mentorsPage.mentorships.edit.title',
    defaultText: 'Edit Mentorship'
  }, {
    index: 2,
    key: 'mentorsPage.mentorships.form.requestType.label',
    defaultText: 'What are you looking for?'
  }, {
    index: 3,
    key: 'mentorsPage.mentorships.form.requestType.options.offering',
    defaultText: 'I am offering to mentor'
  }, {
    index: 4,
    key: 'mentorsPage.mentorships.form.requestType.options.looking',
    defaultText: 'I am looking for a mentor'
  }, {
    index: 5,
    key: 'mentorsPage.mentorships.form.requestType.options.pairing',
    defaultText: 'I am looking to pair with'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/mentors-page-events.png',
    alt: 'Mentorships Events Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'mentorsPage.navigation.events',
    defaultText: 'Events'
  }, {
    index: 5,
    key: 'mentorsPage.navigation.mentorships',
    defaultText: 'Mentorships'
  }, {
    index: 6,
    key: 'mentorsPage.events.actions.create.label',
    defaultText: 'Create Post'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/mentors-page-events-view.png',
    alt: 'View Mentorship Event Page'
  },
  references: [{
    index: 1,
    key: 'mentorsPage.events.view.actions.findAMentorship.label',
    defaultText: 'Find mentorship'
  }, {
    index: 2,
    key: 'mentorsPage.events.view.actions.postAMentorship.label',
    defaultText: 'Post mentorship'
  }]
}];

export const hacksPageCarouselItems = [{
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-hacks.png',
    alt: 'Hacks Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'hacksPage.navigation.events',
    defaultText: 'Events'
  }, {
    index: 5,
    key: 'hacksPage.navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 6,
    key: 'hacksPage.hacks.actions.create.label',
    defaultText: 'Create Post'
  }, {
    index: 7,
    key: 'hacksPage.hacks.search.filters.myHacks',
    defaultText: 'My Hacks'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-hacks-view.png',
    alt: 'View Hack Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'hacksPage.hacks.view.vote.voteForThisHack',
    defaultText: 'Vote for this hack'
  }, {
    index: 5,
    key: 'hacksPage.hacks.view.vote.remove',
    defaultText: 'Remove vote'
  }, {
    index: 6,
    key: 'hacksPage.hacks.view.vote.noVotesLeft',
    defaultText: 'No votes left'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-hacks-create.png',
    alt: 'Create Hack Page'
  },
  references: [{
    index: 1,
    key: 'hacksPage.hacks.create.title',
    defaultText: 'Create Hack'
  }, {
    index: 2,
    key: 'hacksPage.hacks.form.status.options.adoptable',
    defaultText: 'Adoptable 💡'
  }, {
    index: 3,
    key: 'hacksPage.hacks.form.status.options.lookingForMember',
    defaultText: 'Looking for members 👀'
  }, {
    index: 4,
    key: 'hacksPage.hacks.form.status.options.inProgress',
    defaultText: 'In progress 🏃'
  }, {
    index: 5,
    key: 'hacksPage.hacks.form.status.options.paused',
    defaultText: 'Paused ⏱'
  }, {
    index: 6,
    key: 'hacksPage.hacks.form.status.options.completed',
    defaultText: 'Hack completed 🏁'
  }, {
    index: 7,
    key: 'hacksPage.hacks.form.status.options.dropped',
    defaultText: 'Dropped 🥔'
  }, {
    index: 8,
    key: 'hacksPage.hacks.form.status.options.failed',
    defaultText: 'Dumpster fire 🗑️🔥'
  }, {
    index: 9,
    key: 'hacksPage.hacks.form.status.options.shipped',
    defaultText: 'Shipped to users 🛳'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-hacks-edit.png',
    alt: 'Edit Hack Page'
  },
  references: [{
    index: 1,
    key: 'hacksPage.hacks.edit.title',
    defaultText: 'Edit Hack'
  }, {
    index: 2,
    key: 'hacksPage.hacks.form.status.options.adoptable',
    defaultText: 'Adoptable 💡'
  }, {
    index: 3,
    key: 'hacksPage.hacks.form.status.options.lookingForMember',
    defaultText: 'Looking for members 👀'
  }, {
    index: 4,
    key: 'hacksPage.hacks.form.status.options.inProgress',
    defaultText: 'In progress 🏃'
  }, {
    index: 5,
    key: 'hacksPage.hacks.form.status.options.paused',
    defaultText: 'Paused ⏱'
  }, {
    index: 6,
    key: 'hacksPage.hacks.form.status.options.completed',
    defaultText: 'Hack completed 🏁'
  }, {
    index: 7,
    key: 'hacksPage.hacks.form.status.options.dropped',
    defaultText: 'Dropped 🥔'
  }, {
    index: 8,
    key: 'hacksPage.hacks.form.status.options.failed',
    defaultText: 'Dumpster fire 🗑️🔥'
  }, {
    index: 9,
    key: 'hacksPage.hacks.form.status.options.shipped',
    defaultText: 'Shipped to users 🛳'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-events.png',
    alt: 'Hacks Events Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'hacksPage.navigation.events',
    defaultText: 'Events'
  }, {
    index: 5,
    key: 'hacksPage.navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 6,
    key: 'hacksPage.events.actions.create.label',
    defaultText: 'Create Post'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-events-view.png',
    alt: 'View Hack Event Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'hacksPage.events.view.actions.findATeam',
    defaultText: 'Find a team'
  }, {
    index: 5,
    key: 'hacksPage.events.view.actions.postAHack',
    defaultText: 'Post a hack'
  }, {
    index: 6,
    key: 'hacksPage.events.view.actions.seeAllHacks',
    defaultText: 'See all hacks'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-events-create.png',
    alt: 'Create Hack Event Page'
  },
  references: [{
    index: 1,
    key: 'hacksPage.events.create.title',
    defaultText: 'Create Event'
  }, {
    index: 2,
    key: 'hacksPage.events.form.voting.toggle.label',
    defaultText: 'Turn on voting for this block'
  }, {
    index: 3,
    key: 'hacksPage.events.form.voting.toggle.description',
    defaultText: 'Once turned on, participants can vote for eligible hacks.'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-events-edit.png',
    alt: 'Edit Hack Event Page'
  },
  references: [{
    index: 1,
    key: 'hacksPage.events.edit.title',
    defaultText: 'Edit Event'
  }]
}, {
  image: {
    src: '/plugins/skill-exchange/assets/hacks-page-metrics.png',
    alt: 'Hack Metrics Page'
  },
  references: [{
    index: 1,
    key: 'navigation.embeds',
    defaultText: 'Embeds'
  }, {
    index: 2,
    key: 'navigation.mentors',
    defaultText: 'Mentors'
  }, {
    index: 3,
    key: 'navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 4,
    key: 'hacksPage.navigation.events',
    defaultText: 'Events'
  }, {
    index: 5,
    key: 'hacksPage.navigation.hacks',
    defaultText: 'Hacks'
  }, {
    index: 6,
    key: 'hacksPage.metrics.emptyState.title',
    defaultText: 'Insufficient information to form meaningful metrics.'
  }, {
    index: 7,
    key: 'hacksPage.metrics.emptyState.description',
    defaultText: 'There are no hacks to display metrics for the selected event. Please create a hack before viewing metrics.'
  }, {
    index: 8,
    key: 'hacksPage.metrics.entity.hacks',
    defaultText: 'Hacks'
  }]
}];

## Introduction

We understand that the default terminology within Skill Exchange is not one size fits all. To help adjust Skill Exchange's terminology to fit what makes sense for your organization, we've created and enabled some features that allow you to customize Skill Exchange.

## Setting Up Custom Translations

Skill Exchange uses [Backstage's internationalization feature](https://backstage.io/docs/plugins/internationalization) to customize the frontend text. You can customize various text elements throughout the application by providing your own translations. All available translation keys are listed below.

<Info>
  Custom translations only affect the frontend text. If you're looking to also
  customize url feature paths, please refer to the [Customizing Skill Exchange
  Feature Paths](#customizing-skill-exchange-feature-paths) section.
</Info>

```ts title="packages/app/src/App.tsx" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { TranslationBlueprint } from '@backstage/frontend-plugin-api';
import { skillExchangeTranslationRef } from '@spotify/backstage-plugin-skill-exchange/alpha';

const skillExchangeCustomTranslations = TranslationBlueprint.make({
  name: 'skill-exchange-custom-translations',
  params: {
    resource: createTranslationMessages({
      ref: skillExchangeTranslationRef,
      messages: {
        // Your custom translations here
        'navigation.hacks': 'Jams',
        'homePage.title': 'Find others who can help',
        // ... more translations
      },
    }),
  },
});

export const app = createApp({
  features: [
    createFrontendModule({
      pluginId: 'app',
      extensions: [
        // ... extensions,
        skillExchangeCustomTranslations,
        // ... other extensions,
      ],
    }),
  ],
});
```

### Home

<CarouselWithReferenceTable items={homePageCarouselItems} />

### Embeds

<CarouselWithReferenceTable items={embedsPageCarouselItems} />

### Mentors

<CarouselWithReferenceTable items={mentorsPageCarouselItems} />

### Hacks

<CarouselWithReferenceTable items={hacksPageCarouselItems} />

## Customizing Skill Exchange Feature Paths

Skill Exchange uses feature paths to determine the url path for each feature. At default, feature paths are set to `embeds`, `mentors`, and `hacks`. You can customize these paths by providing your own feature paths in your backend `app-config.yaml` file.

```yaml title="app-config.yaml" theme={"theme":{"light":"github-light","dark":"dracula"}}
skillExchange:
  embedsPath: 'remixes' # default: 'embeds'
  mentorsPath: 'pairings' # default: 'mentors'
  hacksPath: 'jams' # default: 'hacks'
```

The example configuration above will change the url paths for each feature to the following:

* Embeds -> `http://localhost:3000/skill-exchange/remixes`
* Mentors -> `http://localhost:3000/skill-exchange/pairings`
* Hacks -> `http://localhost:3000/skill-exchange/jams`

## Customizing Skill Exchange Notifications

Skill Exchange notifications can be customized to match your organization's communication style and preferences. You can tailor notification messages, formatting, and content for [Backstage's native notification system](#customizing-backstage-notifications).

### Customizing Backstage Notifications

Backstage notifications appear directly within your Backstage instance and can be customized to match your organization's terminology and communication style.

#### Prerequisites

Before customizing Backstage notifications, you must first enable Backstage notifications. Please refer to the [Backstage Notifications setup](../notifications#backstage-notifications) section for detailed configuration instructions.

#### Example: Customizing Embed Notifications for Backstage Notifications

The following example shows how to customize embeds notification messages. Since we're only providing a custom embeds message builder, the default message builders for mentors and hacks will continue to be used. For detailed information on available methods and customization options, refer to the [EmbedsMessageBuilder](../references/EmbedsMessageBuilder), [MentorsMessageBuilder](../references/MentorsMessageBuilder), and [HacksMessageBuilder](../references/HacksMessageBuilder) documentation.

```ts title="src/customNotificationEmbedsMessageBuilder.ts" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { DefaultNotificationEmbedsMessageBuilder } from '@spotify/backstage-plugin-skill-exchange-backend';
import { InquiryMessageArgs } from '@spotify/backstage-plugin-skill-exchange-node/alpha';

export class CustomNotificationEmbedsMessageBuilder extends DefaultNotificationEmbedsMessageBuilder {
  // Override other methods as needed
  buildInquiryMessage({
    postTitle,
    sender,
    customMessage,
  }: InquiryMessageArgs): string {
    return `${sender} is interested in your Embed ${postTitle}. They sent you a message: ${customMessage}`;
  }
}
```

Once you've created your custom message builder, you can [register it with Skill Exchange using the extension point](#registering-custom-message-builders).

### Registering Custom Message Builders

Once you've created your custom message builders, register them with Skill Exchange by using the `skillExchangeMessageBuilderExtensionPoint` extension point.

```ts title="src/customSkillExchangeMessageBuilderModule.ts" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { createBackendModule } from '@backstage/backend-plugin-api';
import { skillExchangeMessageBuilderExtensionPoint } from '@spotify/backstage-plugin-skill-exchange-node/alpha';
import { CustomNotificationEmbedsMessageBuilder } from './customNotificationEmbedsMessageBuilder';

export default createBackendModule({
  pluginId: 'skill-exchange',
  moduleId: 'custom-message-builder',
  register(env) {
    env.registerInit({
      deps: {
        messageBuilder: skillExchangeMessageBuilderExtensionPoint,
      },
      async init({ messageBuilder }) {
        // Register custom embeds message builder for Backstage Notifications
        messageBuilder.setNotificationsEmbedMessageBuilder(
          new CustomNotificationEmbedsMessageBuilder(),
        );

        // You can also register custom builders for other features
        // messageBuilder.setNotificationsMentorsMessageBuilder(new CustomNotificationMentorsMessageBuilder());
        // messageBuilder.setNotificationsHacksMessageBuilder(new CustomNotificationHacksMessageBuilder());
      },
    });
  },
});
```

```ts title="src/index.ts" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();
// ...
backend.add(import('@backstage/plugin-notifications-backend'));

backend.add(import('@spotify/backstage-plugin-skill-exchange-backend'));
backend.add(
  import('@spotify/backstage-plugin-search-backend-module-skill-exchange'),
);
backend.add(import('./customSkillExchangeMessageBuilderModule'));
// ...

backend.start();
```
