diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..c7bfef07d9c523de8c8c4b80d41aaf1b92c2fdf9
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "cc-player"]
+	path = cc-player
+	url = git@gitlab.fachschaften.org:spoccify/spoccify-cc-player.git
+[submodule "frontend"]
+	path = frontend
+	url = git@gitlab.fachschaften.org:spoccify/spoccify-frontend.git
diff --git a/cc-player b/cc-player
new file mode 160000
index 0000000000000000000000000000000000000000..53617a52534ccd8795277408c0892bda190481f6
--- /dev/null
+++ b/cc-player
@@ -0,0 +1 @@
+Subproject commit 53617a52534ccd8795277408c0892bda190481f6
diff --git a/cc/audio-receiver b/cc/audio-receiver
deleted file mode 100644
index 7587af2269cb2854b9f6567aa01bd47ae039044f..0000000000000000000000000000000000000000
--- a/cc/audio-receiver
+++ /dev/null
@@ -1,156 +0,0 @@
-local speaker = peripheral.find("speaker")
-local monitor = peripheral.find("monitor")
-
-local args = {...}
-tobool={ ["true"]=true, ["false"]=false }
-
-local paused = false
-
-if #args < 2 or #args > 3 then
-	error("audio-receiver <websocket_url> <authentication_token> [headless]")
-end -- if
-
-local headless = true
-
-if #args == 3 then
-    headless = tobool[args[3]]
-end -- if
-
-function eprint(message)
-    if headless then
-        print(message)
-    else
-        term.redirect(term.native())
-        print(message)
-        term.redirect(monitor)
-    end -- if
-end -- eprint
-
-function resetMonitor()
-	term.redirect(monitor)
-	
-	term.setBackgroundColour(colours.black)
-	
-	term.clear()
-	
-	monitor.setTextScale(0.5)
-end --setupMonitor
-
-function inputButton(x1, y1, x2, y2, colour_border, colour_normal, colour_pressed, button_id, togglebutton)
-	paintutils.drawBox(x1, y1, x2, y2, colour_border)
-	paintutils.drawFilledBox(x1 + 1, y1 + 1, x2 - 1, y2 - 1, colour_normal)
-	
-	while true
-	do
-		local eventData = {os.pullEvent()}
-		local event = eventData[1]
-		
-		if event == "monitor_touch" then
-			local x = eventData[3]
-			local y = eventData[4]
-		
-			if x >= x1 and x <= x2 and y >= y1 and y <= y2
-			then
-				os.queueEvent("button_touch", button_id)
-
-                if not togglebutton then
-				    paintutils.drawFilledBox(x1 + 1, y1 + 1, x2 - 1, y2 - 1, colour_pressed)
-
-                    sleep(0.5)
-
-                    paintutils.drawFilledBox(x1 + 1, y1 + 1, x2 - 1, y2 - 1, colour_normal)
-                end -- if
-			end -- if
-		end -- if
-	end -- while
-end -- monitorInput
-
-local function handle_websocket_audio()
-    eprint("Trying to connect to websocket server!")
-
-    local websocket, error = http.websocket(args[1])
-
-    if websocket == false then
-        eprint(error)
-        return
-    end -- if
-
-    websocket.send(args[2])
-
-    eprint("Connected to websocket server!")
-
-    while true do
-        data, binary = websocket.receive()
-
-        if (not binary) then
-            eprint(data)
-            break
-        end -- if
-
-        eprint("Playing Sample!")
-
-        buffer = {}
-        
-        for i = 1, string.len(data) do
-            buffer[i] = string.byte(data, i) - 128
-        end -- for
-
-        if paused then
-            os.pullEvent("unpause")
-        end -- if
-
-        while not speaker.playAudio(buffer) do
-            os.pullEvent("speaker_audio_empty")
-        end -- while
-
-        websocket.send("next")
-    end -- while
-
-    eprint("Shutting down!")
-
-    os.pullEvent("speaker_audio_empty")
-end -- handle_websocket_audio
-
-local function handle_screen()
-    while true do
-        local event, button_id = os.pullEvent("button_touch")
-
-        if button_id == "play_pause" then
-            if paused then
-                eprint("Playing!")
-                paused = false
-                os.queueEvent("unpause")
-                paintutils.drawFilledBox(3 + 1, 2 + 1, 34 - 1, 12 - 1, colours.green)
-            else
-                eprint("Stopping!")
-                paused = true
-                -- speaker.stop()
-                paintutils.drawFilledBox(3 + 1, 2 + 1, 34 - 1, 12 - 1, colours.red)
-            end -- if
-        elseif button_id == "skip" then
-            eprint("Skipping!")
-        end -- if
-    end -- while
-end -- handle_screen
-
-local function button_play_pause()
-    inputButton(3, 2, 34, 12, colours.white, colours.green, colours.red, "play_pause", true)
-end -- button_play_pause
-
-local function button_skip()
-    inputButton(3, 14, 34, 23, colours.white, colours.yellow, colours.orange, "skip", false)
-end -- button_skip
-
-if headless then
-    eprint("Running headless!")
-
-    handle_websocket_audio()
-else
-    eprint("Using 2x2 advanced monitor!")
-
-    resetMonitor()
-
-    parallel.waitForAny(handle_websocket_audio, handle_screen, button_play_pause, button_skip)
-end -- if
-
-eprint("Done!")
diff --git a/frontend b/frontend
new file mode 160000
index 0000000000000000000000000000000000000000..e9fda016e59626cd189f7b479838fd722d362550
--- /dev/null
+++ b/frontend
@@ -0,0 +1 @@
+Subproject commit e9fda016e59626cd189f7b479838fd722d362550