diff --git a/src/app/layout/background/particles-bg.component.html b/src/app/layout/background/particles-bg.component.html
new file mode 100644
index 0000000..167f2c6
--- /dev/null
+++ b/src/app/layout/background/particles-bg.component.html
@@ -0,0 +1 @@
+
diff --git a/src/app/layout/background/particles-bg.component.scss b/src/app/layout/background/particles-bg.component.scss
new file mode 100644
index 0000000..d345109
--- /dev/null
+++ b/src/app/layout/background/particles-bg.component.scss
@@ -0,0 +1,2 @@
+:host { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
+.particles { width: 100%; height: 100%; display: block; }
diff --git a/src/app/layout/background/particles-bg.component.ts b/src/app/layout/background/particles-bg.component.ts
new file mode 100644
index 0000000..06e439f
--- /dev/null
+++ b/src/app/layout/background/particles-bg.component.ts
@@ -0,0 +1,68 @@
+import {AfterViewInit, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core';
+import {loadFull} from 'tsparticles';
+
+@Component({
+ selector: 'app-particles-bg',
+ standalone: true,
+ imports: [],
+ templateUrl: './particles-bg.component.html',
+ styleUrl: './particles-bg.component.scss',
+})
+export class ParticlesBgComponent implements AfterViewInit, OnDestroy {
+ @ViewChild('canvas', { static: true }) canvasRef!: ElementRef;
+
+ private container?: Container;
+
+ async ngAfterViewInit() {
+ const engine = new Engine();
+ await loadFull(engine);
+
+ const options: ISourceOptions = {
+ fullScreen: { enable: false }, // we manage size via the canvas
+ background: { color: { value: 'transparent' } },
+ fpsLimit: 60,
+ detectRetina: true,
+ interactivity: {
+ events: {
+ onClick: { enable: true, mode: 'push' },
+ onHover: { enable: false, mode: 'repulse' },
+ resize: true
+ },
+ modes: {
+ push: { quantity: 4 } // <- number of new vertices per click
+ }
+ },
+ particles: {
+ number: { value: 55, density: { enable: true, area: 900 } },
+ color: { value: '#23b7ff' },
+ opacity: { value: 0.35 },
+ size: { value: { min: 1, max: 3 } },
+ move: {
+ enable: true,
+ speed: 0.7,
+ outModes: { default: 'out' }
+ },
+ links: {
+ enable: true,
+ distance: 140,
+ color: '#23b7ff',
+ opacity: 0.25,
+ width: 1
+ }
+ }
+ };
+
+ this.container = await engine.load({
+ element: this.canvasRef.nativeElement,
+ options
+ });
+
+ // Let clicks go through to the canvas (we want pointer events on canvas only)
+ this.canvasRef.nativeElement.style.pointerEvents = 'auto';
+ (this.canvasRef.nativeElement.parentElement as HTMLElement).style.pointerEvents = 'none';
+ }
+
+ ngOnDestroy() {
+ this.container?.destroy();
+ }
+}