diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts
index 066ed5db10..29983e3d27 100644
--- a/apps/web/src/app/oss-routing.module.ts
+++ b/apps/web/src/app/oss-routing.module.ts
@@ -8,6 +8,7 @@ import {
tdeDecryptionRequiredGuard,
UnauthGuard,
} from "@bitwarden/angular/auth/guards";
+import { RegistrationStartComponent } from "@bitwarden/auth/angular";
import { flagEnabled, Flags } from "../utils/flags";
@@ -17,6 +18,7 @@ import { VerifyRecoverDeleteProviderComponent } from "./admin-console/providers/
import { CreateOrganizationComponent } from "./admin-console/settings/create-organization.component";
import { SponsoredFamiliesComponent } from "./admin-console/settings/sponsored-families.component";
import { AcceptOrganizationComponent } from "./auth/accept-organization.component";
+import { AnonLayoutWrapperComponent } from "./auth/anon-layout-wrapper.component";
import { deepLinkGuard } from "./auth/guards/deep-link.guard";
import { HintComponent } from "./auth/hint.component";
import { LockComponent } from "./auth/lock.component";
@@ -290,6 +292,18 @@ const routes: Routes = [
{ path: "setup/families-for-enterprise", component: FamiliesForEnterpriseSetupComponent },
],
},
+ {
+ path: "",
+ component: AnonLayoutWrapperComponent,
+ children: [
+ {
+ path: "start-registration",
+ component: RegistrationStartComponent,
+ canActivate: [],
+ data: { pageTitle: "createAccount" },
+ },
+ ],
+ },
{
path: "organizations",
loadChildren: () =>
diff --git a/libs/auth/src/angular/index.ts b/libs/auth/src/angular/index.ts
index 067ed63b8e..0440e6a3d9 100644
--- a/libs/auth/src/angular/index.ts
+++ b/libs/auth/src/angular/index.ts
@@ -13,3 +13,6 @@ export * from "./password-callout/password-callout.component";
export * from "./user-verification/user-verification-dialog.component";
export * from "./user-verification/user-verification-dialog.types";
export * from "./user-verification/user-verification-form-input.component";
+
+// registration
+export * from "./registration/registration-start/registration-start.component";
diff --git a/libs/auth/src/angular/registration/registration-start/registration-start.component.html b/libs/auth/src/angular/registration/registration-start/registration-start.component.html
new file mode 100644
index 0000000000..a0dec38e20
--- /dev/null
+++ b/libs/auth/src/angular/registration/registration-start/registration-start.component.html
@@ -0,0 +1,38 @@
+
diff --git a/libs/auth/src/angular/registration/registration-start/registration-start.component.ts b/libs/auth/src/angular/registration/registration-start/registration-start.component.ts
new file mode 100644
index 0000000000..771002e2dc
--- /dev/null
+++ b/libs/auth/src/angular/registration/registration-start/registration-start.component.ts
@@ -0,0 +1,87 @@
+import { CommonModule } from "@angular/common";
+import { Component, OnDestroy, OnInit } from "@angular/core";
+import {
+ AbstractControl,
+ FormBuilder,
+ FormControl,
+ ReactiveFormsModule,
+ ValidatorFn,
+ Validators,
+} from "@angular/forms";
+import { ActivatedRoute } from "@angular/router";
+import { Subject, takeUntil } from "rxjs";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+import { ButtonModule, CheckboxModule, FormFieldModule } from "@bitwarden/components";
+
+@Component({
+ standalone: true,
+ selector: "auth-registration-start",
+ templateUrl: "./registration-start.component.html",
+ imports: [
+ CommonModule,
+ ReactiveFormsModule,
+ JslibModule,
+ FormFieldModule,
+ CheckboxModule,
+ ButtonModule,
+ ],
+})
+export class RegistrationStartComponent implements OnInit, OnDestroy {
+ queryParamFromOrgInvite: boolean = false;
+
+ showTerms = true;
+
+ formGroup = this.formBuilder.group({
+ email: ["", [Validators.required, Validators.email]],
+ name: [""],
+ acceptPolicies: [false, [this.acceptPoliciesValidator()]],
+ });
+
+ get email(): FormControl {
+ return this.formGroup.get("email") as FormControl;
+ }
+
+ get name(): FormControl {
+ return this.formGroup.get("name") as FormControl;
+ }
+
+ private destroy$ = new Subject();
+
+ constructor(
+ private formBuilder: FormBuilder,
+ private route: ActivatedRoute,
+ private platformUtilsService: PlatformUtilsService,
+ ) {
+ this.showTerms = !platformUtilsService.isSelfHost();
+ }
+
+ async ngOnInit() {
+ this.listenForQueryParamChanges();
+ }
+
+ submit = async () => {};
+
+ private listenForQueryParamChanges() {
+ this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((qParams) => {
+ if (qParams.email != null && qParams.email.indexOf("@") > -1) {
+ this.email?.setValue(qParams.email);
+ this.queryParamFromOrgInvite = qParams.fromOrgInvite === "true";
+ }
+ });
+ }
+
+ private acceptPoliciesValidator(): ValidatorFn {
+ return (control: AbstractControl) => {
+ const ctrlValue = control.value;
+
+ return !ctrlValue && this.showTerms ? { required: true } : null;
+ };
+ }
+
+ ngOnDestroy(): void {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
+}