diff --git a/code/exercise04/README.txt b/code/exercise04/README.txt
new file mode 100644
index 0000000..c4b0581
--- /dev/null
+++ b/code/exercise04/README.txt
@@ -0,0 +1 @@
+Hier entsteht die Lösung zu Praktikum 04
\ No newline at end of file
diff --git a/code/exercise04/app/css/style.css b/code/exercise04/app/css/style.css
new file mode 100644
index 0000000..3a7a30d
--- /dev/null
+++ b/code/exercise04/app/css/style.css
@@ -0,0 +1,14 @@
+body {
+ background-color: lightblue;
+ text-align: center;
+}
+div {
+ padding-top: 20px;
+ border-style: groove;
+ border-color: black;
+ background-image: url("../img/schriftrolle.png");
+ background-repeat: no-repeat;
+ background-position: center top;
+ margin-left: 300px;
+ margin-right: 300px;
+}
diff --git a/code/exercise04/app/einkaufsliste.html b/code/exercise04/app/einkaufsliste.html
new file mode 100644
index 0000000..47e489d
--- /dev/null
+++ b/code/exercise04/app/einkaufsliste.html
@@ -0,0 +1,22 @@
+
+
+
+
+ Einkaufsliste
+
+
+
+
+
+ Einkaufsliste
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/code/exercise04/app/img/kisspng-shopping-bag-grocery-store-shopping-cart-vegetable-bag2-myspeedyx-5cb7cce50fbf87.6493526215555494130645.png b/code/exercise04/app/img/kisspng-shopping-bag-grocery-store-shopping-cart-vegetable-bag2-myspeedyx-5cb7cce50fbf87.6493526215555494130645.png
new file mode 100644
index 0000000..66919bb
Binary files /dev/null and b/code/exercise04/app/img/kisspng-shopping-bag-grocery-store-shopping-cart-vegetable-bag2-myspeedyx-5cb7cce50fbf87.6493526215555494130645.png differ
diff --git a/code/exercise04/app/img/ohm.ico b/code/exercise04/app/img/ohm.ico
new file mode 100644
index 0000000..d00ece5
Binary files /dev/null and b/code/exercise04/app/img/ohm.ico differ
diff --git a/code/exercise04/app/img/schriftrolle.png b/code/exercise04/app/img/schriftrolle.png
new file mode 100644
index 0000000..f1bb69d
Binary files /dev/null and b/code/exercise04/app/img/schriftrolle.png differ
diff --git a/code/exercise04/app/scripts/einkaufsliste.js b/code/exercise04/app/scripts/einkaufsliste.js
new file mode 100644
index 0000000..056e617
--- /dev/null
+++ b/code/exercise04/app/scripts/einkaufsliste.js
@@ -0,0 +1,25 @@
+
+var counter = 0;
+
+function onClick() {
+ var element = document.getElementById("element");
+ console.log(element.value);
+ add(element.value);
+}
+
+function add(input) {
+ counter++;
+ var liste = document.getElementById("liste");
+
+ var checkbox = document.createElement("input");
+ checkbox.setAttribute("type", "checkbox");
+ checkbox.setAttribute("id", "cb" + counter);
+
+ var label = document.createElement("label");
+ label.innerHTML = input;
+ label.setAttribute("for", "cb" + counter);
+
+ liste.appendChild(checkbox);
+ liste.appendChild(label);
+ liste.appendChild(document.createElement("br"));
+}
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..71a3d17
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,79 @@
+const gulp = require('gulp');
+const imagemin = require('gulp-imagemin');
+const uglify = require('gulp-uglify');
+const uglifycss = require('gulp-uglifycss');
+const sass = require('gulp-sass');
+const concat = require('gulp-concat');
+
+/*
+ * Toplevelfunction
+ * gulp.task
+ * gulp.src
+ * gulp.dest
+ * gulp.watch
+ */
+
+// Logs Message
+gulp.task('message', async function () {
+ return console.log('Gulp is running...');
+});
+
+// Copy All HTML files
+gulp.task('copyHtml', async function () {
+ gulp.src('app/*.html')
+ .pipe(gulp.dest('dist'));
+});
+
+// Optimize Images
+gulp.task('imageMin', async function () {
+ gulp.src('app/img/*')
+ .pipe(imagemin())
+ .pipe(gulp.dest('dist/images'))
+});
+
+// Minify JS
+gulp.task('minify', async function () {
+ gulp.src('app/scripts/*.js')
+ .pipe(uglify())
+ .pipe(gulp.dest('dist/js'));
+});
+
+// Compile Sass
+gulp.task('sass', async function () {
+ gulp.src('app/sass/*.scss')
+ .pipe(sass().on('error', sass.logError))
+ .pipe(gulp.dest('app/css'));
+});
+
+// Minify CSS
+gulp.task('css', async function () {
+ gulp.src('app/css/*.css')
+ .pipe(uglifycss({
+ "maxLineLen": 80,
+ "uglyComments": true
+ }))
+ .pipe(gulp.dest('./dist/css'));
+});
+
+// Scripts
+gulp.task('scripts', async function () {
+ gulp.src('app/scripts/*.js')
+ .pipe(concat('landung.js'))
+ .pipe(uglify())
+ .pipe(gulp.dest('dist/js'));
+});
+
+gulp.task('run', function(done) { // <--- Insert `done` as a parameter here...
+ gulp.series('message','sass', 'css', 'copyHtml', 'imageMin', 'scripts')
+ done(); // <--- ...and call it here.
+})
+/*
+gulp.task('default', ['message', 'copyHtml', 'imageMin', 'sass', 'scripts']);
+*/
+gulp.task('watch', async function () {
+ gulp.watch('app/scripts/*.js', gulp.series('scripts'));
+ gulp.watch('app/img/*', gulp.series('imageMin'));
+ gulp.watch('app/sass/*.scss', gulp.series('sass'));
+ gulp.watch('app/css/*.css', gulp.series('css'));
+ gulp.watch('app/*.html', gulp.series('copyHtml'));
+});