diff --git a/Dockerfile b/Dockerfile
index 293b85ddcd004a17bc78e61712f0a01ad1259508..bee682a15c8297a99baf8b87a0fb52c7f50a759f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -20,7 +20,7 @@ COPY /src ./src
 ARG conf
 
 # Building the Angular app /dist i18n
-RUN npm run build:dev
+RUN npm run build:prod
 
 # Stage 1, based on Nginx, to have only the compiled app
 FROM nginx
@@ -29,7 +29,6 @@ FROM nginx
 RUN apt-get update
 
 COPY --from=build /app/dist/fr /usr/share/nginx/html
-COPY --from=build /app/dist/fr /usr/share/nginx/html/fr
 
 RUN touch /var/run/nginx.pid
 RUN ls -l /usr/share/nginx/html
diff --git a/angular.json b/angular.json
index 6e95360f6a90b5417e30d67c101ad0e1abe2b9be..962c5cd18d48fe6f6aa52040ec860e7d1878885b 100644
--- a/angular.json
+++ b/angular.json
@@ -14,9 +14,15 @@
       "sourceRoot": "src",
       "prefix": "app",
       "i18n": {
-        "sourceLocale": "fr",
+        "sourceLocale": {
+          "code": "fr",
+          "baseHref": ""
+        },
         "locales": {
-          "en": "src/locale/messages.en.xlf"
+          "en": {
+            "baseHref": "/en/",
+            "translation": "src/locale/messages.en.xlf"
+          }
         }
       },
       "architect": {
@@ -54,6 +60,7 @@
                   "with": "src/environments/environment.prod.ts"
                 }
               ],
+              "aot": true,
               "optimization": true,
               "outputHashing": "all",
               "sourceMap": false,
diff --git a/nginx/dev.conf b/nginx/dev.conf
index 5998c857466cf8d5284d3aceea9e96b15f7e689d..4d727b257fe18fcdd966ab101a930d9da0abc7b9 100644
--- a/nginx/dev.conf
+++ b/nginx/dev.conf
@@ -1,25 +1,38 @@
-
 server {
   listen 8080 default_server;
 
-  root /usr/share/nginx/html;
+  root /usr/share/nginx/html/;
+  set $matomo_script
+  "<script type='text/javascript'>
+    var _paq = window._paq = window._paq || [];
+    _paq.push(['trackPageView']);
+    _paq.push(['enableLinkTracking']);
+    (function() {
+      var u='<URL_GDLYON>';
+      _paq.push(['setTrackerUrl', u+'piwik.php']);
+      _paq.push(['setSiteId', '<SITE_ID>']);
+      var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+      g.type='text/javascript'; g.async=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+    })();
+  </script>";
 
   location / {
     # First attempt to serve request as file, then
     # as directory, then fall back to displaying a 404.
     try_files $uri $uri/ /index.html;
+    sub_filter '</head>' '$matomo_script</head>';
   }
 
-  location /api {
-    rewrite ^/api/(.*) /$1 break;
-    proxy_pass http://json-server:3000/api;
+    location /api {
+        rewrite ^/api/(.*) /$1 break;
+        proxy_pass http://service-ram:3000/api;
   }
 
-  # Public api redirect
-    location /base-adresse/base-adresse-nationale/streets {
+  location /base-adresse/base-adresse-nationale/streets {
     proxy_pass https://passerelle.formulaireextranet.grandlyon.com/base-adresse/base-adresse-nationale/streets;
   }
 
+
   location /geocoding/photon/api {
     proxy_pass https://download.data.grandlyon.com/geocoding/photon/api;
   }
@@ -32,9 +45,11 @@ server {
     proxy_pass https://download.data.grandlyon.com/wfs/grandlyon;
   }
 
+
   # REALLY important for JavaScript modules (type="module") to work as expected!!!
   location ~ \.js {
     add_header  Content-Type   text/javascript;
   }
 
 }
+
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index ca2b510f11ad37605306738bf353917834d1f60e..efacd3c848b600e4743d252025c6d9bee9c3fe48 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -6,6 +6,7 @@ import { HomeComponent } from './home/home.component';
 import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
 import { ProfileComponent } from './profile/profile.component';
 import { ResetEmailComponent } from './reset-email/reset-email.component';
+import { ResetPasswordComponent } from './reset-password/reset-password.component';
 import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
 import { StructureListComponent } from './structure-list/structure-list.component';
 import { UserVerificationComponent } from './user-verification/user-verification.component';
@@ -53,6 +54,10 @@ const routes: Routes = [
     canActivate: [AuthGuard],
     component: ProfileComponent,
   },
+  {
+    path: 'reset-password',
+    component: ResetPasswordComponent,
+  },
   {
     path: '**',
     redirectTo: 'home',
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f46c10874aaab363c3b0a907122e882197bc567a..1a02174b10116efa3ecd4d721e85175b3d4acd57 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -26,6 +26,7 @@ import { AuthGuard } from './guards/auth.guard';
 import { CustomHttpInterceptor } from './config/http-interceptor';
 import { ProfileModule } from './profile/profile.module';
 import { ResetEmailComponent } from './reset-email/reset-email.component';
+import { ResetPasswordComponent } from './reset-password/reset-password.component';
 
 @NgModule({
   declarations: [
@@ -45,6 +46,7 @@ import { ResetEmailComponent } from './reset-email/reset-email.component';
     FormComponent,
     UserVerificationComponent,
     ResetEmailComponent,
+    ResetPasswordComponent,
   ],
   imports: [BrowserModule, HttpClientModule, AppRoutingModule, SharedModule, MapModule, ProfileModule],
   providers: [
diff --git a/src/app/reset-password/reset-password.component.html b/src/app/reset-password/reset-password.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..f9c3810a248f7332f14c2dc7e4049afd51d14537
--- /dev/null
+++ b/src/app/reset-password/reset-password.component.html
@@ -0,0 +1,66 @@
+<div fxLayout="column" class="content-container">
+  <div class="section-container" fxLayout="column" fxLayoutAlign="center center">
+    <h1>Réinitialisation du mot de passe</h1>
+    <form *ngIf="!token" [formGroup]="resetForm" (ngSubmit)="onSubmit()">
+      <div class="form-group">
+        <label for="email">Email</label>
+        <input
+          type="email"
+          autocomplete="on"
+          formControlName="email"
+          class="form-control"
+          [ngClass]="{ 'is-invalid': submitted && f.email.errors }"
+        />
+        <div *ngIf="submitted && f.email.errors" class="invalid-feedback">
+          <div *ngIf="f.email.errors.required">Email is required</div>
+        </div>
+      </div>
+      <div class="form-group">
+        <button [disabled]="loading" class="btn btn-primary">
+          <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
+          Envoyer
+        </button>
+        <a routerLink="../login" class="btn btn-link">Cancel</a>
+      </div>
+    </form>
+    <form *ngIf="token" [formGroup]="resetFormChangePassword" (ngSubmit)="onSubmitPassword()">
+      <div class="form-group">
+        <label for="password">Mot de passe</label>
+        <input
+          type="password"
+          autocomplete="on"
+          formControlName="password"
+          class="form-control"
+          [ngClass]="{ 'is-invalid': submitted && fPassword.password.errors }"
+        />
+        <div *ngIf="submitted && fPassword.password.errors" class="invalid-feedback">
+          <div *ngIf="fPassword.password.errors.required">Le mot de passe est obligatoire</div>
+          <div *ngIf="fPassword.password.errors.pattern">
+            Le mot de passe doit avoir au minimun 8 caractères, une majuscule, une minuscule, un chiffre et un caractère
+            spécial.
+          </div>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="confirmPassword">Confirmation du mot de passe</label>
+        <input
+          type="password"
+          autocomplete="on"
+          formControlName="confirmPassword"
+          class="form-control"
+          [ngClass]="{ 'is-invalid': submitted && fPassword.confirmPassword.errors }"
+        />
+        <div *ngIf="submitted && fPassword.confirmPassword.errors" class="invalid-feedback">
+          <div *ngIf="fPassword.confirmPassword.errors.required">La confirmation du mot de passe est obligatoire</div>
+          <div *ngIf="fPassword.confirmPassword.errors.mustMatch">Les mot de passe ne sont pas les mêmes</div>
+        </div>
+      </div>
+      <div class="form-group">
+        <button [disabled]="loading" class="btn btn-primary">
+          <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
+          Enregistrer
+        </button>
+      </div>
+    </form>
+  </div>
+</div>
diff --git a/src/app/reset-password/reset-password.component.spec.ts b/src/app/reset-password/reset-password.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92e44ad4534e2126ee299a3dcfce553d9a95ea0f
--- /dev/null
+++ b/src/app/reset-password/reset-password.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ResetPasswordComponent } from './reset-password.component';
+
+describe('ResetPasswordComponent', () => {
+  let component: ResetPasswordComponent;
+  let fixture: ComponentFixture<ResetPasswordComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ ResetPasswordComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ResetPasswordComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/reset-password/reset-password.component.ts b/src/app/reset-password/reset-password.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ed5a77541a12372197e202763e6216c12fb822eb
--- /dev/null
+++ b/src/app/reset-password/reset-password.component.ts
@@ -0,0 +1,95 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { AuthService } from '../services/auth.service';
+import { MustMatch } from '../shared/validator/form';
+
+@Component({
+  selector: 'app-reset-password',
+  templateUrl: './reset-password.component.html',
+})
+export class ResetPasswordComponent implements OnInit {
+  public resetForm: FormGroup;
+  public resetFormChangePassword: FormGroup;
+  public token: string;
+  public loading = false;
+  public submitted = false;
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private authService: AuthService,
+    private router: Router,
+    private activatedRoute: ActivatedRoute
+  ) {}
+
+  ngOnInit(): void {
+    this.activatedRoute.queryParams.subscribe((params) => {
+      this.token = params['token'];
+    });
+
+    this.initPasswordForm();
+    this.resetForm = this.formBuilder.group({
+      email: ['', Validators.required],
+    });
+  }
+
+  private initPasswordForm(): void {
+    this.resetFormChangePassword = this.formBuilder.group(
+      {
+        password: [
+          '',
+          [Validators.required, Validators.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/)],
+        ],
+        confirmPassword: [''],
+      },
+      { validator: MustMatch('password', 'confirmPassword') }
+    );
+  }
+
+  // getter for form fields
+  get f(): { [key: string]: AbstractControl } {
+    return this.resetForm.controls;
+  }
+
+  get fPassword(): { [key: string]: AbstractControl } {
+    return this.resetFormChangePassword.controls;
+  }
+
+  public onSubmit(): void {
+    this.submitted = true;
+
+    // stop here if form is invalid
+    if (this.resetForm.invalid) {
+      return;
+    }
+
+    this.loading = true;
+    this.authService.resetPassword(this.f.email.value).subscribe(
+      () => {
+        this.router.navigate(['']);
+      },
+      () => {
+        this.loading = false;
+      }
+    );
+  }
+
+  public onSubmitPassword(): void {
+    this.submitted = true;
+
+    // stop here if form is invalid
+    if (this.resetFormChangePassword.invalid) {
+      return;
+    }
+
+    this.loading = true;
+    this.authService.resetPasswordApply(this.token, this.fPassword.password.value).subscribe(
+      () => {
+        this.router.navigate(['']);
+      },
+      () => {
+        this.loading = false;
+      }
+    );
+  }
+}
diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts
index 4f40f2c3de4bac22ba01f1723f73e3f9d68ce71b..4e98779cf926d18cb540833cd4a6341ed0cbff09 100644
--- a/src/app/services/auth.service.ts
+++ b/src/app/services/auth.service.ts
@@ -66,4 +66,15 @@ export class AuthService {
       params: { token },
     });
   }
+
+  public resetPassword(email: string): Observable<any> {
+    return this.http.post(`api/users/reset-password`, { email });
+  }
+
+  public resetPasswordApply(token: string, password: string): Observable<any> {
+    return this.http.post(`api/users/reset-password/apply`, {
+      token,
+      password,
+    });
+  }
 }
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.html b/src/app/shared/components/signup-modal/signup-modal.component.html
index e12cffd1bb4d9ddf98e5be88099be372786c06c3..cf0a3fa0ada7f83d43ac102f4e11f41d0d98cdc0 100644
--- a/src/app/shared/components/signup-modal/signup-modal.component.html
+++ b/src/app/shared/components/signup-modal/signup-modal.component.html
@@ -40,6 +40,7 @@
           </button>
           <button (click)="sendSwitchToSignIn()">Inscription</button>
         </div>
+        <a (click)="swithToResetPassword()">Mot de passe oublié</a>
       </form>
     </div>
   </div>
diff --git a/src/app/shared/components/signup-modal/signup-modal.component.ts b/src/app/shared/components/signup-modal/signup-modal.component.ts
index 1ef87d4d1f9ba8924e4642ec8a60bd5b3a834f56..3d70b98aeb373a6b83cd9679c00cec138305f346 100644
--- a/src/app/shared/components/signup-modal/signup-modal.component.ts
+++ b/src/app/shared/components/signup-modal/signup-modal.component.ts
@@ -48,6 +48,11 @@ export class SignUpModalComponent implements OnInit {
     this.closed.emit(false);
   }
 
+  public swithToResetPassword(): void {
+    this.closed.emit(true);
+    this.router.navigate(['/reset-password']);
+  }
+
   public onSubmit(): void {
     this.submitted = true;
 
diff --git a/src/index.html b/src/index.html
index 9e350807caa211c6211153b2bd75853378be4ac2..034e83f362a671532cf29573af2a2b3ebd73ad4a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="fr">
   <head>
     <meta charset="utf-8" />
     <title>Réseau des Acteurs de la Médiation</title>