diff --git a/next.config.mjs b/next.config.mjs
new file mode 100644
index 0000000000000000000000000000000000000000..ee4fab103342350f01407dcfaaa8c231db4a012d
--- /dev/null
+++ b/next.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+  output: 'export',
+  distDir: 'public',  
+
+}
+ 
+export default nextConfig
diff --git a/src/app/layout.jsx b/src/app/layout.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0471ac699d031f1e92e1328e9fe540ae6bdc91df
--- /dev/null
+++ b/src/app/layout.jsx
@@ -0,0 +1,19 @@
+import Head from "next/head";
+
+export const Metadata = {
+    title: 'Sorting Visualizer',
+    description: 'Visualize sorting algorithms',
+}
+
+export default function RootLayout({children}) {
+    return (
+        <html lang="en">
+        <Head>
+            <link rel="icon" href="/src/styles/favicon.ico" />
+        </Head>
+        <body>
+        <div id="root">{children}</div>
+        </body>
+        </html>
+    )
+}
\ No newline at end of file
diff --git a/src/app/page.jsx b/src/app/page.jsx
index 5aae9c65dd569459378c1b24210e9edec916509b..6a8d2519bab6fd0fd1557a3ca375c637ab1fe1a5 100644
--- a/src/app/page.jsx
+++ b/src/app/page.jsx
@@ -1,12 +1,9 @@
 import SortingVisualizer from '../components/SortingVisualizer.jsx'
-import Head from "next/head";
 
 export default function Home() {
     return (
         <main>
-            <Head>
-                <link rel="icon" href="/src/styles/favicon.ico" />
-            </Head>
+
             <SortingVisualizer />
         </main>
     )
diff --git a/src/components/SortingVisualizer.jsx b/src/components/SortingVisualizer.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..6220c820d4175fe72fa171252785ce64c51dd506
--- /dev/null
+++ b/src/components/SortingVisualizer.jsx
@@ -0,0 +1,156 @@
+"use client";
+
+import {useState, useEffect} from 'react';
+import '../styles/SortingVisualizer.css'
+import BubbleSort from "../libs/BubbleSort.jsx";
+import RangeSlider from 'react-bootstrap-range-slider';
+import 'react-bootstrap-range-slider/dist/react-bootstrap-range-slider.css';
+import {Dropdown} from 'react-bootstrap';
+import 'bootstrap/dist/css/bootstrap.min.css';
+
+function SortingVisualizer() {
+
+    const moduloFive = ((window.innerWidth / 45)).toFixed(0) % 5;
+    const monitorSize = (window.innerWidth / 45).toFixed(0) - moduloFive;
+    const [BarNumber, setBarNumber] = useState(() => monitorSize > 100 ? 100 : monitorSize); // max of 100 bars
+    const [bars, setbars] = useState(() => generateArray(BarNumber));
+    const [sorting, setSorting] = useState(false);
+    const [alreadySorted, setAlreadySorted] = useState();
+    const [isSorted, setIsSorted] = useState(false);
+    const [sortSpeed, setSortSpeed] = useState('40');
+
+    const SliderWithInputFormControl = () => {
+        const [sliderValue_intern, setSliderValue_intern] = useState(BarNumber);
+        return (
+            <RangeSlider
+                value={sliderValue_intern}
+                step={5}
+                max={100}
+                min={5}
+                disabled={sorting}
+                onChange={changeEvent => setSliderValue_intern(Number(changeEvent.target.value))}
+                onAfterChange={() => setBarNumber(sliderValue_intern)}
+            />
+        );
+    };
+
+    useEffect(() => {
+        resetBars();
+    }, [BarNumber]);
+
+    function getRandomArbitrary(min, max) {
+        return Math.floor(Math.random() * (max - min + 1)) + min;
+    }
+
+    function generateArray(numberBars) {
+        return Array.from({length: numberBars}, () => getRandomArbitrary(50, 300));
+    }
+
+    async function handleSorting() {
+        if (sorting) return;
+        setSorting(true);
+        await BubbleSort(bars, setbars, setAlreadySorted, sortSpeed);
+        setSorting(false);
+    }
+
+    function resetBars() {
+        setAlreadySorted(1000);
+        setbars(generateArray(BarNumber));
+        let ColoredBars = document.getElementsByClassName('sorted');
+        document.getElementById('startButton').innerText = 'Sort!';
+        while (ColoredBars.length > 0) {
+            ColoredBars[0].className = 'bar';
+        }
+        setIsSorted(false);
+
+
+    }
+
+    function finishAnimation() {
+        let ColoredBars = document.getElementsByClassName('sorted');
+        while (ColoredBars.length > 0) {
+            ColoredBars[0].className = 'finished';
+        }
+    }
+
+    function handleButton() {
+        if (!sorting && !isSorted) {
+            setAlreadySorted(1000);
+            handleSorting();
+        } else if (isSorted) {
+            resetBars();
+
+        }
+    }
+
+    useEffect(() => {
+        if (alreadySorted == 0) {
+            setIsSorted(true);
+            finishAnimation();
+            document.getElementById('startButton').innerText = 'Reset!';
+        }
+    }, [alreadySorted]);
+
+
+    return (
+        <>
+            <div className='Container'>
+                <div id='ToolBar'>
+                    <div className="Label">How many bars?</div>
+                    <SliderWithInputFormControl style={{className: 'range-slider'}}/>
+                    <input type='number' max={100} min={0} disabled={sorting}
+                           onChange={changeEvent => {
+                               let value = Number(changeEvent.target.value);
+                               if (value > 100) value = 100;
+                               if (value < 5) value = 5;
+                               setBarNumber(value);
+                           }} defaultValue={BarNumber}
+                           value={BarNumber} style={{
+                        width: '42px',
+                        margin: '10px',
+                        borderRadius: '5px',
+                        border: 'none',
+                        textAlign: 'center'
+                    }}/>
+                    <div style={{background: 'gray', height: '70%', marginLeft: '10px', width: '2px'}}></div>
+                    <Dropdown id="dropdown">
+                        <Dropdown.Toggle
+                            id="dropdown"
+                            disabled={sorting}
+                        >
+                            Sorting-Speed: {
+                            {
+                                100: 'Slow',
+                                40: 'Medium',
+                                0: 'Fast'
+                            }[sortSpeed] || ''
+                        }
+                        </Dropdown.Toggle>
+                        <Dropdown.Menu id="dropdown-menu">
+                            <Dropdown.Item id="dropdown-item" onClick={() => setSortSpeed(100)}>
+                                Slow
+                            </Dropdown.Item>
+                            <Dropdown.Item id="dropdown-item" onClick={() => setSortSpeed(40)}>
+                                Medium
+                            </Dropdown.Item>
+                            <Dropdown.Item id="dropdown-item" onClick={() => setSortSpeed(0)}>
+                                Fast
+                            </Dropdown.Item>
+                        </Dropdown.Menu>
+                    </Dropdown>
+                    <button id='startButton' className="Button" disabled={sorting}
+                            style={{background: `${sorting ? 'red' : ''}`}} onClick={() => {
+                        handleButton()
+                    }}>{sorting ? 'Sorting...' : 'Sort!'}</button>
+                </div>
+                <div className='DivArray'>
+                    {bars.map((height, index) => (<div key={index} data-key={index}
+                                                       className={`bar + ${alreadySorted <= index ? 'sorted' : ''}`}
+                                                       style={{height: `${height}px`}}></div>))}
+                </div>
+
+            </div>
+        </>
+    )
+};
+export default SortingVisualizer;
\ No newline at end of file
diff --git a/src/libs/BubbleSort.jsx b/src/libs/BubbleSort.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..03b4c9da8fc6afeeaaf352e2be91221e9807c183
--- /dev/null
+++ b/src/libs/BubbleSort.jsx
@@ -0,0 +1,23 @@
+async function BubbleSort(EingangsArray, updateBars, setColor, sortSpeed){
+    const len = EingangsArray.length;
+    for(let i = 0; i< len -1; ++i){
+        for(let k=0; k< len -1-i; k++){
+            let tmp;
+
+            if (k == len -2-i){
+                setColor([(len-1-i)]);
+            }
+            if(EingangsArray[k] > EingangsArray[k+1]){
+                tmp = EingangsArray[k];
+                EingangsArray[k] = EingangsArray[k+1];
+                EingangsArray[k+1] = tmp;
+            }
+            updateBars([...EingangsArray]);
+            await new Promise(resolve => setTimeout(resolve, sortSpeed)); //  Pause für Animation
+        }
+    }
+    setColor([(len-len)]);
+    console.log(EingangsArray);
+    return EingangsArray;
+}
+export default BubbleSort;
\ No newline at end of file
diff --git a/src/styles/SortingVisualizer.css b/src/styles/SortingVisualizer.css
new file mode 100644
index 0000000000000000000000000000000000000000..4d120a84518fce493e22b832d7f68490293d2676
--- /dev/null
+++ b/src/styles/SortingVisualizer.css
@@ -0,0 +1,165 @@
+body {
+    margin: 0;
+}
+
+.Container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+
+.bar {
+    background-color: blue;
+    display: inline-block;
+    height: 100px;
+    flex: 1 1 20px;
+    min-width: 2px;
+}
+
+.sorted {
+    background-color: deeppink;
+    animation: ScaleAnimation 0.5s ease-in-out;
+
+}
+
+.finished {
+    background-color: lawngreen;
+    flex: 1 1 20px;
+    min-width: 2px;
+    margin: 2px;
+    display: inline-block;
+    animation: GreenScaleAnimation 1s ease-in;
+
+}
+
+.range-slider {
+    padding: 0px;
+}
+
+#ToolBar {
+    height: 50px;
+    width: 100%;
+    background: #34495e;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+
+}
+
+#startButton {
+    height: 78%;
+    width: 85px;
+    font-size: 12px;
+    margin: 10px;
+    background: #1abc9c;
+    text-align: center;
+    display: grid;
+    place-items: center;
+    border-radius: 5px;
+    border: none;
+    color: white;
+    font-size: 14px;
+    font-family: Arial, sans-serif;
+    font-weight: bold;
+
+}
+
+button:active {
+    box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.46);
+    transform: translateY(2px);
+}
+
+.Label {
+    margin: 10px;
+    font-size: 15px;
+    font-family: Arial, sans-serif;
+    font-weight: bold;
+    color: white;
+}
+
+.DivArray {
+    transform: scaleY(-1);
+    display: flex;
+    flex-wrap: nowrap;
+    justify-content: center;
+    gap: 2px;
+    width: 90%;
+    margin-top: 5px;
+}
+
+#dropdown-menu {
+    background-color: #34495e;
+    border: none;
+    border-radius: 5px;
+    margin-top: 3px;
+}
+
+
+#dropdown-item {
+    color: white;
+    font-size: 16px;
+    font-weight: normal;
+    border-radius: 5px;
+}
+
+#dropdown-item:hover {
+    background-color: #1abc9c;
+    color: white;
+}
+
+#dropdown {
+    background: none;
+    border: none;
+    border-radius: 0px;
+    color: white;
+    fontSize: 14px;
+    fontWeight: normal;
+    padding: 0;
+    height: 100%;
+    display: flex;
+    alignItems: center;
+    place-items: center;
+    margin-inline: 10px;
+    width: 190px;
+}
+
+#dropdown:hover {
+    color: #1abc9c;
+}
+
+#dropdown:active {
+    box-shadow: none;
+    transform: none;
+}
+
+#dropdown.show {
+    background-color: #1abc9c;
+    color: white;
+}
+
+
+@keyframes ScaleAnimation {
+    0% {
+        transform: scale(1);
+    }
+    50% {
+        transform: scale(1.05);
+    }
+    100% {
+        transform: scale(1);
+    }
+}
+
+@keyframes GreenScaleAnimation {
+    0% {
+        transform: scale(1);
+    }
+    50% {
+        transform: scale(1.1);
+    }
+    100% {
+        transform: scale(1);
+    }
+}
diff --git a/src/styles/favicon.ico b/src/styles/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..b3acbd6c1b785768b3563e233314d14e7e75ac21
Binary files /dev/null and b/src/styles/favicon.ico differ