diff --git a/apps/web/src/app/layouts/user-layout.component.html b/apps/web/src/app/layouts/user-layout.component.html
index 6a87658f172..d826301176f 100644
--- a/apps/web/src/app/layouts/user-layout.component.html
+++ b/apps/web/src/app/layouts/user-layout.component.html
@@ -8,6 +8,7 @@
+
diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts
index c531f358b34..80115460376 100644
--- a/apps/web/src/app/oss-routing.module.ts
+++ b/apps/web/src/app/oss-routing.module.ts
@@ -81,6 +81,7 @@ import { RequestSMAccessComponent } from "./secrets-manager/secrets-manager-land
import { SMLandingComponent } from "./secrets-manager/secrets-manager-landing/sm-landing.component";
import { DomainRulesComponent } from "./settings/domain-rules.component";
import { PreferencesComponent } from "./settings/preferences.component";
+import { AchievementsComponent } from "./tools/achievements/achievements.component";
import { CredentialGeneratorComponent } from "./tools/credential-generator/credential-generator.component";
import { ReportsModule } from "./tools/reports";
import { AccessComponent, SendAccessExplainerComponent } from "./tools/send/send-access";
@@ -747,6 +748,11 @@ const routes: Routes = [
component: CredentialGeneratorComponent,
data: { titleId: "generator" } satisfies RouteDataProperties,
},
+ {
+ path: "achievements",
+ component: AchievementsComponent,
+ data: { titleId: "achievements" } satisfies RouteDataProperties,
+ },
],
},
{
diff --git a/apps/web/src/app/tools/achievements/achievements.component.html b/apps/web/src/app/tools/achievements/achievements.component.html
new file mode 100644
index 00000000000..a4dab900c46
--- /dev/null
+++ b/apps/web/src/app/tools/achievements/achievements.component.html
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/apps/web/src/app/tools/achievements/achievements.component.ts b/apps/web/src/app/tools/achievements/achievements.component.ts
new file mode 100644
index 00000000000..ce2351346ab
--- /dev/null
+++ b/apps/web/src/app/tools/achievements/achievements.component.ts
@@ -0,0 +1,55 @@
+import { Component, OnInit } from "@angular/core";
+import { firstValueFrom } from "rxjs";
+
+import { AchievementNotifierService } from "@bitwarden/angular/tools/achievements/achievement-notifier.abstraction";
+import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { EventStoreAbstraction } from "@bitwarden/common/tools/achievements/event-store.abstraction.service";
+import { VaultItems_10_Added_Achievement } from "@bitwarden/common/tools/achievements/examples/achievements";
+import { AchievementEarnedEvent, AchievementId } from "@bitwarden/common/tools/achievements/types";
+import { UserId } from "@bitwarden/common/types/guid";
+
+import { HeaderModule } from "../../layouts/header/header.module";
+import { SharedModule } from "../../shared";
+
+@Component({
+ templateUrl: "achievements.component.html",
+ standalone: true,
+ imports: [SharedModule, HeaderModule],
+})
+export class AchievementsComponent implements OnInit {
+ private currentUserId: UserId;
+
+ constructor(
+ private eventStore: EventStoreAbstraction,
+ private achievementNotifierService: AchievementNotifierService,
+ private accountService: AccountService,
+ ) {}
+
+ async ngOnInit() {
+ await this.achievementNotifierService.init();
+ this.currentUserId = (await firstValueFrom(this.accountService.activeAccount$)).id;
+ }
+
+ testAchievement() {
+ const earnedAchievement: AchievementEarnedEvent = {
+ "@timestamp": Date.now(),
+ event: {
+ kind: "alert",
+ category: "session",
+ },
+ service: {
+ name: "web",
+ type: "client",
+ node: {
+ name: "an-installation-identifier-for-this-client-instance",
+ },
+ environment: "local",
+ version: "2025.3.1-innovation-sprint",
+ },
+ user: { id: this.currentUserId },
+ achievement: { type: "earned", name: VaultItems_10_Added_Achievement.name as AchievementId },
+ };
+
+ this.eventStore.addEvent(earnedAchievement);
+ }
+}
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 68900b2ed74..2e8cf93e1ce 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -10620,5 +10620,8 @@
},
"cannotCreateCollection": {
"message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections."
+ },
+ "achievements": {
+ "message": "Achievements"
}
}