diff --git a/app/Http/Controllers/MetaGerSearch.php b/app/Http/Controllers/MetaGerSearch.php
index 56566146f0fe230de59a8bfffd0d38079661392f..3596d29bf5139c25a6d2f80d816d0046716b43d8 100644
--- a/app/Http/Controllers/MetaGerSearch.php
+++ b/app/Http/Controllers/MetaGerSearch.php
@@ -4,7 +4,10 @@ namespace App\Http\Controllers;
 
 use App;
 use App\MetaGer;
+use Cache;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Redis;
+use View;
 
 const TIP_SERVER = 'http://metager3.de:63825/tips.xml';
 
@@ -19,13 +22,6 @@ class MetaGerSearch extends Controller
             return redirect()->to('https://maps.metager.de/map/' . $searchinput . '/1240908.5493525574,6638783.2192695495,6');
         }
 
-        /*if ($focus !== "angepasst" && $this->startsWith($focus, "focus_")) {
-        $metager->parseFormData($request);
-        return $metager->createView();
-        }*/
-
-        #die($request->header('User-Agent'));
-        $time = microtime();
         # Mit gelieferte Formulardaten parsen und abspeichern:
         $metager->parseFormData($request);
 
@@ -39,19 +35,132 @@ class MetaGerSearch extends Controller
         # auf Ergebnisse warten und die Ergebnisse laden
         $metager->createSearchEngines($request);
 
+        $metager->startSearch();
+
+        $metager->waitForMainResults();
+
+        $metager->retrieveResults();
+
         # Versuchen die Ergebnisse der Quicktips zu laden
         $quicktipResults = $quicktips->loadResults();
-
         # Alle Ergebnisse vor der Zusammenführung ranken:
         $metager->rankAll();
 
         # Ergebnisse der Suchmaschinen kombinieren:
         $metager->prepareResults();
 
+        # Save the results in Redis
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+        $pipeline = $redis->pipeline();
+        foreach ($metager->getResults() as $result) {
+            $pipeline->rpush($metager->getRedisCurrentResultList(), base64_encode(serialize($result)));
+        }
+        $pipeline->expire($metager->getRedisCurrentResultList(), env('REDIS_RESULT_CACHE_DURATION'));
+        $pipeline->execute();
+
         # Die Ausgabe erstellen:
         return $metager->createView($quicktipResults);
     }
 
+    public function loadMore(Request $request)
+    {
+        /**
+         * There are three forms of requests to the resultpage
+         * 1. Initial Request: Loads the fastest searchengines and sends them to the user
+         * 2. Load more results (with JS): Loads new search engines that answered after the initial request was send
+         * 3. Load more results (without JS): Loads new search engines that answered within 1s timeout
+         */
+        if ($request->filled('loadMore') && $request->filled('script') && $request->input('script') === "yes") {
+            return $this->loadMoreJS($request);
+        }
+
+    }
+
+    private function loadMoreJS(Request $request)
+    {
+        # Create a MetaGer Instance with the supplied hash
+        $hash = $request->input('loadMore', '');
+
+        $metager = new MetaGer($hash);
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+
+        $result = [];
+        # Check if there should be more results
+        $stats = $redis->hgetall($metager->getRedisEngineResult() . "status");
+        $stats["startTime"] = floatval($stats["startTime"]);
+        $stats["engineCount"] = intval($stats["engineCount"]);
+        $stats["engineAnswered"] = intval($stats["engineAnswered"]);
+        $stats["engineDelivered"] = intval($stats["engineDelivered"]);
+
+        $result["finished"] = true;
+        $result["engineCount"] = $stats["engineCount"];
+        $result["engineAnswered"] = $stats["engineAnswered"];
+        $result["engineDelivered"] = $stats["engineDelivered"];
+        $result["timeWaiting"] = microtime(true) - $stats["startTime"];
+
+        # Check if we can abort
+        if ($stats["engineAnswered"] > $stats["engineDelivered"]/*&& $result["timeWaiting"] <= 10 */) {
+            $metager->parseFormData($request);
+            # Nach Spezialsuchen überprüfen:
+            $metager->checkSpecialSearches($request);
+
+            # Read which search engines are new
+            $newEngines = [];
+
+            while (($engine = $redis->lpop($metager->getRedisResultWaitingKey())) != null) {
+                $result["engineDelivered"]++;
+                $newEngines[$engine] = $metager->getSumaFile()->sumas->{$engine};
+            }
+            $cache = Cache::get($hash);
+            if ($cache != null) {
+                $metager->setNext(unserialize($cache)["engines"]);
+            }
+
+            # Check if this request is not for page one
+            $metager->setEngines($request, $newEngines);
+
+            # Add the results already delivered to the user
+            $results = $redis->lrange($metager->getRedisCurrentResultList(), 0, -1);
+            foreach ($results as $index => $oldResult) {
+                $results[$index] = unserialize(base64_decode($oldResult));
+                $results[$index]->new = false;
+            }
+            $metager->setResults($results);
+            $metager->retrieveResults();
+            $metager->rankAll();
+            $metager->prepareResults();
+            $result["nextSearchLink"] = $metager->nextSearchLink();
+            $results = $metager->getResults();
+            foreach ($results as $index => $resultTmp) {
+                if ($resultTmp->new) {
+                    if ($metager->getFokus() !== "bilder") {
+                        $view = View::make('layouts.result', ['result' => $resultTmp, 'metager' => $metager]);
+                        $html = $view->render();
+                        $result['newResults'][$index] = $html;
+                        $result["imagesearch"] = false;
+                    } else {
+                        $view = View::make('layouts.image_result', ['result' => $resultTmp, 'metager' => $metager]);
+                        $html = $view->render();
+                        $result['newResults'][$index] = $html;
+                        $result["imagesearch"] = true;
+                    }
+                }
+            }
+            # Save the results in Redis
+            $pipeline = $redis->pipeline();
+            $pipeline->hincrby($metager->getRedisEngineResult() . "status", "engineDelivered", sizeof($newEngines));
+            $pipeline->hset($metager->getRedisEngineResult() . "status", "nextSearchLink", $result["nextSearchLink"]);
+            foreach ($metager->getResults() as $resultTmp) {
+                $resultTmp->new = false;
+                $pipeline->rpush($metager->getRedisCurrentResultList(), base64_encode(serialize($resultTmp)));
+            }
+            $pipeline->expire($metager->getRedisCurrentResultList(), env('REDIS_RESULT_CACHE_DURATION'));
+            $pipeline->execute();
+
+        }
+        return response()->json($result);
+    }
+
     public function botProtection($redirect)
     {
         $hash = md5(date('YmdHi'));
diff --git a/app/Jobs/Searcher.php b/app/Jobs/Searcher.php
index ec82937b42b85994833d0d930a46ef08deeb002c..2271c7bde5610ead4f2515013c941b8ab3e7a751 100644
--- a/app/Jobs/Searcher.php
+++ b/app/Jobs/Searcher.php
@@ -85,8 +85,7 @@ class Searcher implements ShouldQueue
                     $url = base64_decode($mission[1]); // The url to fetch
                     $timeout = $mission[2]; // Timeout from the MetaGer process in ms
                     $medianFetchTime = $this->getFetchTime(); // The median Fetch time of the search engine in ms
-                    Redis::hset('search.' . $hashValue, $this->name, "connected");
-
+                    Redis::hset('search.' . $hashValue . ".results." . $this->name, "status", "connected");
                     $result = $this->retrieveUrl($url);
 
                     $this->storeResult($result, $poptime, $hashValue);
@@ -99,7 +98,7 @@ class Searcher implements ShouldQueue
 
                 // In sync mode every Searcher may only retrieve one result because it would block
                 // the execution of the remaining code otherwise:
-                if (getenv("QUEUE_DRIVER") === "sync"
+                if (getenv("QUEUE_CONNECTION") === "sync"
                     || $this->counter > $this->MAX_REQUESTS
                     || (microtime(true) - $this->startTime) > $this->MAX_TIME) {
                     break;
@@ -161,16 +160,24 @@ class Searcher implements ShouldQueue
         // Set this URL to the Curl handle
         curl_setopt($this->ch, CURLOPT_URL, $url);
         $result = curl_exec($this->ch);
-
         $this->connectionInfo = curl_getinfo($this->ch);
         return $result;
     }
 
     private function storeResult($result, $poptime, $hashValue)
     {
-        Redis::hset('search.' . $hashValue, $this->name, $result);
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+        $pipeline = $redis->pipeline();
+        $pipeline->hset('search.' . $hashValue . ".results." . $this->name, "response", $result);
+        $pipeline->hset('search.' . $hashValue . ".results." . $this->name, "delivered", "0");
+        $pipeline->hincrby('search.' . $hashValue . ".results.status", "engineAnswered", 1);
         // After 60 seconds the results should be read by the MetaGer Process and stored in the Cache instead
-        Redis::expire('search.' . $hashValue, 60);
+        $pipeline->expire('search.' . $hashValue . ".results." . $this->name, env('REDIS_RESULT_CACHE_DURATION'));
+        $pipeline->rpush('search.' . $hashValue . ".ready", $this->name);
+        $pipeline->expire('search.' . $hashValue . ".ready", env('REDIS_RESULT_CACHE_DURATION'));
+        $pipeline->sadd('search.' . $hashValue . ".engines", $this->name);
+        $pipeline->expire('search.' . $hashValue . ".engines", env('REDIS_RESULT_CACHE_DURATION'));
+        $pipeline->execute();
         $this->lastTime = microtime(true);
     }
 
diff --git a/app/MetaGer.php b/app/MetaGer.php
index 0a80fce1853d32dde0460dbc2ca1885c4b58c620..19d7606956058b7bcc423a6c9fbbefa9f456a141 100644
--- a/app/MetaGer.php
+++ b/app/MetaGer.php
@@ -46,6 +46,7 @@ class MetaGer
     protected $agent;
     protected $apiKey = "";
     protected $apiAuthorized = false;
+    protected $next = [];
     # Konfigurationseinstellungen:
     protected $sumaFile;
     protected $mobile;
@@ -59,8 +60,10 @@ class MetaGer
     protected $languageDetect;
     protected $verificationId;
     protected $verificationCount;
+    protected $searchUid;
+    protected $redisResultWaitingKey, $redisResultEngineList, $redisEngineResult, $redisCurrentResultList;
 
-    public function __construct()
+    public function __construct($hash = "")
     {
         # Timer starten
         $this->starttime = microtime(true);
@@ -90,6 +93,21 @@ class MetaGer
         } catch (ConnectionException $e) {
             $this->canCache = false;
         }
+        if ($hash === "") {
+            $this->searchUid = md5(uniqid());
+        } else {
+            $this->searchUid = $hash;
+        }
+        $redisPrefix = "search";
+        # This is a list on which the MetaGer process can do a blocking pop to wait for new results
+        $this->redisResultWaitingKey = $redisPrefix . "." . $this->searchUid . ".ready";
+        # This is a list of searchengines which have delivered results for this search
+        $this->redisResultEngineList = $redisPrefix . "." . $this->searchUid . ".engines";
+        # This is the key where the results of the engine are stored as well as some statistical data
+        $this->redisEngineResult = $redisPrefix . "." . $this->searchUid . ".results.";
+        # A list of all search results already delivered to the user (sorted of course)
+        $this->redisCurrentResultList = $redisPrefix . "." . $this->searchUid . ".currentResults";
+
     }
 
     # Erstellt aus den gesammelten Ergebnissen den View
@@ -217,21 +235,8 @@ class MetaGer
     public function prepareResults()
     {
         $engines = $this->engines;
-
         // combine
-        $combinedResults = $this->combineResults($engines);
-
-        # Wir bestimmen die Sprache eines jeden Suchergebnisses
-        $this->results = $this->addLangCodes($this->results);
-
-        // sort
-        //$sortedResults = $this->sortResults($engines);
-        // filter
-        // augment (boost&adgoal)
-        // authorize
-        if ($this->apiKey) {
-            $this->apiAuthorized = $this->authorize($this->apiKey);
-        }
+        $this->combineResults($engines);
         // misc (WiP)
         if ($this->fokus == "nachrichten") {
             $this->results = array_filter($this->results, function ($v, $k) {
@@ -274,40 +279,6 @@ class MetaGer
         $counter = 0;
         $firstRank = 0;
 
-        if (isset($this->startForwards)) {
-            $this->startCount = $this->startForwards;
-        } elseif (isset($this->startBackwards)) {
-            $this->startCount = $this->startBackwards - count($this->results) - 1;
-        } else {
-            $this->startCount = 0;
-        }
-
-        foreach ($this->results as $result) {
-            if ($counter === 0) {
-                $firstRank = $result->rank;
-            }
-
-            $counter++;
-            $result->number = $counter + $this->startCount;
-            $confidence = 0;
-            if ($firstRank > 0) {
-                $confidence = $result->rank / $firstRank;
-            } else {
-                $confidence = 0;
-            }
-
-            if ($confidence > 0.65) {
-                $result->color = "#FF4000";
-            } elseif ($confidence > 0.4) {
-                $result->color = "#FF0080";
-            } elseif ($confidence > 0.2) {
-                $result->color = "#C000C0";
-            } else {
-                $result->color = "#000000";
-            }
-
-        }
-
         if (count($this->results) <= 0) {
             if (strlen($this->site) > 0) {
                 $no_sitesearch_query = str_replace(urlencode("site:" . $this->site), "", $this->fullUrl);
@@ -321,62 +292,15 @@ class MetaGer
             $page = $this->page + 1;
             $this->next = [
                 'page' => $page,
-                'startForwards' => $this->results[count($this->results) - 1]->number,
                 'engines' => $this->next,
             ];
-            Cache::put(md5(serialize($this->next)), serialize($this->next), 60);
+            Cache::put($this->getSearchUid(), serialize($this->next), 60);
         } else {
             $this->next = [];
         }
 
     }
 
-    private function addLangCodes($results)
-    {
-        # Wenn es keine Ergebnisse gibt, brauchen wir uns gar nicht erst zu bemühen
-        if (sizeof($results) === 0) {
-            return $results;
-        }
-
-        # Bei der Spracheinstellung "all" wird nicht gefiltert
-        if ($this->getLang() === "all") {
-            return $results;
-        } else {
-            # Ansonsten müssen wir jedem Result einen Sprachcode hinzufügen
-            $id = 0;
-            $langStrings = [];
-            foreach ($results as $result) {
-                # Wir geben jedem Ergebnis eine ID um später die Sprachcodes zuordnen zu können
-                $result->id = $id;
-
-                $langStrings["result_" . $id] = utf8_encode($result->getLangString());
-
-                $id++;
-            }
-            # Wir schreiben die Strings in eine temporäre JSON-Datei,
-            # Da das Array unter umständen zu groß ist für eine direkte Übergabe an das Skript
-            $filename = "/tmp/" . getmypid();
-            file_put_contents($filename, json_encode($langStrings));
-            $langDetectorPath = app_path() . "/Models/lang.pl";
-            $lang = exec("echo '$filename' | $langDetectorPath");
-            $lang = json_decode($lang, true);
-
-            # Wir haben nun die Sprachcodes der einzelnen Ergebnisse.
-            # Diese müssen wir nur noch korrekt zuordnen, dann sind wir fertig.
-            foreach ($lang as $key => $langCode) {
-                # Prefix vom Key entfernen:
-                $id = intval(str_replace("result_", "", $key));
-                foreach ($this->results as $result) {
-                    if ($result->id === $id) {
-                        $result->langCode = $langCode;
-                        break;
-                    }
-                }
-            }
-            return $results;
-        }
-    }
-
     public function combineResults($engines)
     {
         foreach ($engines as $engine) {
@@ -407,6 +331,9 @@ class MetaGer
         $tldList = "";
         try {
             foreach ($results as $result) {
+                if (!$result->new) {
+                    continue;
+                }
                 $link = $result->anzeigeLink;
                 if (strpos($link, "http") !== 0) {
                     $link = "http://" . $link;
@@ -431,7 +358,7 @@ class MetaGer
                 $hash = $el[1];
 
                 foreach ($results as $result) {
-                    if ($hoster === $result->tld && !$result->partnershop) {
+                    if ($result->new && $hoster === $result->tld && !$result->partnershop) {
                         # Hier ist ein Advertiser:
                         # Das Logo hinzufügen:
                         if ($result->image !== "") {
@@ -512,7 +439,7 @@ class MetaGer
     public function createQuicktips()
     {
         # Die quicktips werden als job erstellt und zur Abarbeitung freigegeben
-        $quicktips = new \App\Models\Quicktips\Quicktips($this->q, $this->lang, $this->getTime(), $this->getHashCode());
+        $quicktips = new \App\Models\Quicktips\Quicktips($this->q, $this->lang, $this->getTime());
         return $quicktips;
     }
 
@@ -534,7 +461,6 @@ class MetaGer
         if (empty($this->sumaFile->foki->{$this->fokus})) {
             $this->fokus = "web";
         }
-
         foreach ($this->sumaFile->foki->{$this->fokus}->sumas as $suma) {
             # Check if this engine is disabled and can't be used
             $disabled = empty($this->sumaFile->sumas->{$suma}->disabled) ? false : $this->sumaFile->sumas->{$suma}->disabled;
@@ -589,8 +515,6 @@ class MetaGer
             $this->enabledSearchengines["yahoo-ads"] = $this->sumaFile->sumas->{"yahoo-ads"};
         }
 
-        #die(var_dump($this->enabledSearchengines));
-
         if (sizeof($this->enabledSearchengines) === 0) {
             $filter = "";
             foreach ($this->queryFilter as $queryFilter => $filterPhrase) {
@@ -601,53 +525,36 @@ class MetaGer
                 'filter' => $filter]);
             $this->errors[] = $error;
         }
-
         $engines = [];
         $typeslist = [];
         $counter = 0;
+        $this->setEngines($request);
+    }
 
+    public function setEngines(Request $request, $enabledSearchengines = [])
+    {
         if ($this->requestIsCached($request)) {
+            # If this is a page other than 1 the request is "cached"
             $engines = $this->getCachedEngines($request);
             # We need to edit some Options of the Cached Search Engines
             foreach ($engines as $engine) {
-                $engine->setResultHash($this->getHashCode());
+                $engine->setResultHash($this->getSearchUid());
             }
+            $this->engines = $engines;
         } else {
-            $engines = $this->actuallyCreateSearchEngines($this->enabledSearchengines);
+            if (sizeof($enabledSearchengines) > 0) {
+                $this->enabledSearchengines = $enabledSearchengines;
+            }
+            $this->actuallyCreateSearchEngines($this->enabledSearchengines);
         }
+    }
 
+    public function startSearch()
+    {
         # Wir starten alle Suchen
-        foreach ($engines as $engine) {
+        foreach ($this->engines as $engine) {
             $engine->startSearch($this);
         }
-
-        /* Wir warten auf die Antwort der Suchmaschinen
-         * Die Verbindung steht zu diesem Zeitpunkt und auch unsere Requests wurden schon gesendet.
-         * Wir zählen die Suchmaschinen, die durch den Cache beantwortet wurden:
-         * $enginesToLoad zählt einerseits die Suchmaschinen auf die wir warten und andererseits
-         * welche Suchmaschinen nicht rechtzeitig geantwortet haben.
-         */
-
-        $enginesToLoad = [];
-        $canBreak = false;
-        foreach ($engines as $engine) {
-            if ($engine->cached) {
-                if ($overtureEnabled && ($engine->name === "overture" || $engine->name === "overtureAds")) {
-                    $canBreak = true;
-                }
-            } else {
-                $enginesToLoad[$engine->name] = false;
-            }
-        }
-
-        $this->waitForResults($enginesToLoad, $overtureEnabled, $canBreak);
-
-        $this->retrieveResults($engines);
-        foreach ($engines as $engine) {
-            if (!empty($engine->totalResults) && $engine->totalResults > $this->totalResults) {
-                $this->totalResults = $engine->totalResults;
-            }
-        }
     }
 
     # Spezielle Suchen und Sumas
@@ -696,7 +603,7 @@ class MetaGer
 
             $engines[] = $tmp;
         }
-        return $engines;
+        $this->engines = $engines;
     }
 
     public function getAvailableParameterFilter()
@@ -779,128 +686,75 @@ class MetaGer
         $next = unserialize(Cache::get($request->input('next')));
         $this->page = $next['page'];
         $engines = $next['engines'];
-        if (isset($next['startForwards'])) {
-            $this->startForwards = $next['startForwards'];
-        }
-        if (isset($next['startBackwards'])) {
-            $this->startBackwards = $next['startBackwards'];
-        }
         return $engines;
     }
 
-    # Passt den Suchfokus an, falls für einen Fokus genau alle vorhandenen Sumas eingeschaltet sind
-    public function adjustFocus($sumas, $enabledSearchengines)
+    public function waitForMainResults()
     {
-        # Findet für alle Foki die enthaltenen Sumas
-        $foki = []; # [fokus][suma] => [suma]
-        foreach ($sumas as $suma) {
-            if ((!$this->sumaIsDisabled($suma)) && (!isset($suma['userSelectable']) || $suma['userSelectable']->__toString() === "1")) {
-                if (isset($suma['type'])) {
-                    # Wenn foki für diese Suchmaschine angegeben sind
-                    $focuses = explode(",", $suma['type']->__toString());
-                    foreach ($focuses as $foc) {
-                        if (isset($suma['minismCollection'])) {
-                            $foki[$foc][] = "minism";
-                        } else {
-                            $foki[$foc][] = $suma['name']->__toString();
-                        }
-                    }
-                } else {
-                    # Wenn keine foki für diese Suchmaschine angegeben sind
-                    if (isset($suma['minismCollection'])) {
-                        $foki["andere"][] = "minism";
-                    } else {
-                        $foki["andere"][] = $suma['name']->__toString();
-                    }
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+        $engines = $this->engines;
+        $enginesToWaitFor = [];
+        $mainEngines = $this->sumaFile->foki->{$this->fokus}->main;
+        foreach ($mainEngines as $mainEngine) {
+            foreach ($engines as $engine) {
+                if (!$engine->cached && $engine->name === $mainEngine) {
+                    $enginesToWaitFor[] = $engine;
                 }
             }
         }
 
-        # Findet die Namen der aktuell eingeschalteten Sumas
-        $realEngNames = [];
-        foreach ($enabledSearchengines as $realEng) {
-            $nam = $realEng["name"]->__toString();
-            if ($nam !== "qualigo" && $nam !== "overtureAds") {
-                $realEngNames[] = $nam;
-            }
-        }
+        $timeStart = microtime(true);
+        $answered = [];
+        $results = null;
 
-        # Anschließend werden diese beiden Listen verglichen (jeweils eine der Fokuslisten für jeden Fokus), um herauszufinden ob sie vielleicht identisch sind. Ist dies der Fall, so hat der Nutzer anscheinend Suchmaschinen eines kompletten Fokus eingestellt. Der Fokus wird dementsprechend angepasst.
-        foreach ($foki as $fok => $engines) {
-            $isFokus = true;
-            $fokiEngNames = [];
-            foreach ($engines as $eng) {
-                $fokiEngNames[] = $eng;
-            }
-            # Jede eingeschaltete Engine ist für diesen Fokus geeignet
-            foreach ($fokiEngNames as $fen) {
-                # Bei Bildersuchen ist uns egal, ob alle Suchmaschinen aus dem Suchfokus eingeschaltet sind, da wir sie eh als Bildersuche anzeigen müssen
-                if (!in_array($fen, $realEngNames) && $fok !== "bilder") {
-                    $isFokus = false;
-                }
-            }
-            # Jede im Fokus erwartete Engine ist auch eingeschaltet
-            foreach ($realEngNames as $ren) {
-                if (!in_array($ren, $fokiEngNames)) {
-                    $isFokus = false;
-                }
-            }
-            # Wenn die Listen identisch sind, setze den Fokus um
-            if ($isFokus) {
-                $this->fokus = $fok;
-            }
+        # If there is no main searchengine to wait for or if the only main engine is yahoo-ads we will define a timeout of 1s
+        $forceTimeout = null;
+        if (sizeof($enginesToWaitFor) === 0 || (sizeof($enginesToWaitFor) === 1 && $enginesToWaitFor[0]->name === "yahoo-ads")) {
+            $forceTimeout = 1;
         }
-    }
-
-    public function waitForResults($enginesToLoad, $overtureEnabled, $canBreak)
-    {
 
-        $timeStart = microtime(true);
-        $results = null;
-        while (true) {
-            $results = Redis::hgetall('search.' . $this->getHashCode());
-
-            $ready = true;
-            // When every
-            $connected = true;
-            foreach ($results as $key => $value) {
-                if ($value === "waiting" || $value === "connected") {
-                    $ready = false;
-                }
-                if ($value === "waiting") {
-                    $connected = false;
+        while (sizeof($enginesToWaitFor) > 0 || ($forceTimeout !== null && (microtime(true) - $timeStart) < $forceTimeout)) {
+            $newEngine = $redis->blpop($this->redisResultWaitingKey, 1);
+            if ($newEngine === null || sizeof($newEngine) !== 2) {
+                continue;
+            } else {
+                $newEngine = $newEngine[1];
+                foreach ($enginesToWaitFor as $index => $engine) {
+                    if ($engine->name === $newEngine) {
+                        unset($enginesToWaitFor[$index]);
+                        break;
+                    }
                 }
+                $answered[] = $newEngine;
             }
-
-            // If $ready is false at this point, we're waiting for more searchengines
-            // But we have to check for the timeout, too
-            if (!$connected) {
-                $timeStart = microtime(true);
+            if ((microtime(true) - $timeStart) >= 2) {
+                break;
             }
+        }
 
-            $time = (microtime(true) - $timeStart) * 1000;
-            // We will apply the timeout only if it's not Yahoo we're waiting for since they are one the most
-            // important search engines.
-            $canTimeout = !((isset($results["overture"]) && $results["overture"] === "waiting") || (isset($results["overtureAds"]) && $results["overtureAds"] === "waiting"));
-            if ($time > $this->time && $canTimeout) {
-                $ready = true;
-            }
+        # Now we can add an entry to Redis which defines the starting time and how many engines should answer this request
 
-            if ($ready) {
-                break;
+        $pipeline = $redis->pipeline();
+        $pipeline->hset($this->getRedisEngineResult() . "status", "startTime", $timeStart);
+        $pipeline->hset($this->getRedisEngineResult() . "status", "engineCount", sizeof($engines));
+        $pipeline->hset($this->getRedisEngineResult() . "status", "engineDelivered", sizeof($answered));
+        # Add the cached engines as answered
+        foreach ($engines as $engine) {
+            if ($engine->cached) {
+                $pipeline->hincrby($this->getRedisEngineResult() . "status", "engineDelivered", 1);
+                $pipeline->hincrby($this->getRedisEngineResult() . "status", "engineAnswered", 1);
             }
-            usleep(50000);
         }
-
-        # Wir haben nun so lange wie möglich gewartet. Wir registrieren nun noch die Suchmaschinen, die geanwortet haben.
-        foreach ($results as $key => $value) {
-            $enginesToLoad[$key] = true;
+        foreach ($answered as $engine) {
+            $pipeline->hset($this->getRedisEngineResult() . $engine, "delivered", "1");
         }
-        $this->enginesToLoad = $enginesToLoad;
+        $pipeline->execute();
+
     }
 
-    public function retrieveResults($engines)
+    public function retrieveResults()
     {
+        $engines = $this->engines;
         # Von geladenen Engines die Ergebnisse holen
         foreach ($engines as $engine) {
             if (!$engine->loaded) {
@@ -910,9 +764,10 @@ class MetaGer
                     Log::error($e);
                 }
             }
+            if (!empty($engine->totalResults) && $engine->totalResults > $this->totalResults) {
+                $this->totalResults = $engine->totalResults;
+            }
         }
-
-        $this->engines = $engines;
     }
 
 /*
@@ -1037,6 +892,9 @@ class MetaGer
                 $this->apiKey = "";
             }
         }
+        if ($this->apiKey) {
+            $this->apiAuthorized = $this->authorize($this->apiKey);
+        }
 
         // Remove Inputs that are not used
         $this->request = $request->replace($request->except(['verification_id', 'uid', 'verification_count']));
@@ -1262,7 +1120,7 @@ class MetaGer
             if ($this->request->input('out', '') !== "results" && $this->request->input('out', '') !== '') {
                 $requestData["out"] = $this->request->input('out');
             }
-            $requestData['next'] = md5(serialize($this->next));
+            $requestData['next'] = $this->getSearchUid();
             $link = action('MetaGerSearch@search', $requestData);
         } else {
             $link = "#";
@@ -1358,6 +1216,11 @@ class MetaGer
         }
     }
 
+    public function setNext($next)
+    {
+        $this->next = $next;
+    }
+
     public function addLink($link)
     {
         if (strpos($link, "http://") === 0) {
@@ -1472,10 +1335,9 @@ class MetaGer
         return $link;
     }
 
-    public function getHashCode()
+    public function getSearchUid()
     {
-        $string = url()->full();
-        return md5($string);
+        return $this->searchUid;
     }
 
 # Einfache Getter
@@ -1485,6 +1347,11 @@ class MetaGer
         return $this->verificationId;
     }
 
+    public function getNext()
+    {
+        return $this->next;
+    }
+
     public function getVerificationCount()
     {
         return $this->verificationCount;
@@ -1500,6 +1367,11 @@ class MetaGer
         return $this->newtab;
     }
 
+    public function setResults($results)
+    {
+        $this->results = $results;
+    }
+
     public function getResults()
     {
         return $this->results;
@@ -1628,4 +1500,23 @@ class MetaGer
     {
         return $this->startCount;
     }
+
+    public function getRedisResultWaitingKey()
+    {
+        return $this->redisResultWaitingKey;
+    }
+
+    public function getRedisResultEngineList()
+    {
+        return $this->redisResultEngineList;
+    }
+
+    public function getRedisEngineResult()
+    {
+        return $this->redisEngineResult;
+    }
+    public function getRedisCurrentResultList()
+    {
+        return $this->redisCurrentResultList;
+    }
 }
diff --git a/app/Models/Quicktips/Quicktips.php b/app/Models/Quicktips/Quicktips.php
index 6e5c053bc7d76e962af777366be8b71f4373cc79..1b7b7e046ea4523727db90379496333bb70eb812 100644
--- a/app/Models/Quicktips/Quicktips.php
+++ b/app/Models/Quicktips/Quicktips.php
@@ -3,7 +3,6 @@
 namespace App\Models\Quicktips;
 
 use App\Jobs\Searcher;
-use Cache;
 use Illuminate\Foundation\Bus\DispatchesJobs;
 use Illuminate\Support\Facades\Redis;
 use Log;
@@ -12,8 +11,8 @@ class Quicktips
 {
     use DispatchesJobs;
 
-    const QUICKTIP_URL   = "http://localhost:63825/1.1/quicktips.xml";
-    const QUICKTIP_NAME  = "quicktips";
+    const QUICKTIP_URL = "http://localhost:63825/1.1/quicktips.xml";
+    const QUICKTIP_NAME = "quicktips";
     const CACHE_DURATION = 60;
 
     private $hash;
@@ -26,18 +25,17 @@ class Quicktips
     public function startSearch($search, $locale, $max_time)
     {
         $url = self::QUICKTIP_URL . "?search=" . $this->normalize_search($search) . "&locale=" . $locale;
-
-        $hash = md5($url);
-
         # TODO anders weitergeben
-        $this->hash = $hash;
+        $this->hash = md5($url);
 
         # TODO cache wieder einbauen (eventuell)
         if ( /*!Cache::has($hash)*/true) {
-            Redis::hset("search." . $hash, self::QUICKTIP_NAME, "waiting");
+            $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+
+            $redis->hset("search." . $this->hash . ".results." . self::QUICKTIP_NAME, "status", "waiting");
 
             // Queue this search
-            $mission = $hash . ";" . base64_encode($url) . ";" . $max_time;
+            $mission = $this->hash . ";" . base64_encode($url) . ";" . $max_time;
             Redis::rpush(self::QUICKTIP_NAME . ".queue", $mission);
 
             // Check the current status of Searchers for QUICKTIP_NAME
@@ -85,14 +83,11 @@ class Quicktips
     public function retrieveResults($hash)
     {
         $body = "";
-        #if (Cache::has($hash)) {
-        $body = Cache::get($hash);
-        #} elseif (Redis::hexists('search.' . $hash, self::QUICKTIP_NAME)) {
-        $body = Redis::hget('search.' . $hash, self::QUICKTIP_NAME);
-        Redis::hdel('search.' . $hash, self::QUICKTIP_NAME);
-        Cache::put($hash, $body, self::CACHE_DURATION);
-        #}
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
+        $body = $redis->hget('search.' . $hash . ".results." . self::QUICKTIP_NAME, "response");
 
+        $redis->del('search.' . $hash . ".results." . self::QUICKTIP_NAME);
+        $redis->del('search.' . $hash . ".ready");
         if ($body !== "") {
             return $body;
         } else {
@@ -157,14 +152,14 @@ class Quicktips
                 $descr = $quicktip_xml->content->__toString();
 
                 // Details
-                $details       = [];
+                $details = [];
                 $details_xpath = $quicktip_xml->xpath('mg:details');
                 if (sizeof($details_xpath) > 0) {
                     foreach ($details_xpath[0] as $detail_xml) {
                         $details_title = $detail_xml->title->__toString();
-                        $details_link  = $detail_xml->url->__toString();
+                        $details_link = $detail_xml->url->__toString();
                         $details_descr = $detail_xml->text->__toString();
-                        $details[]     = new \App\Models\Quicktips\Quicktip_detail(
+                        $details[] = new \App\Models\Quicktips\Quicktip_detail(
                             $details_title,
                             $details_link,
                             $details_descr
diff --git a/app/Models/Result.php b/app/Models/Result.php
index 529788464d4021f4f3739c7181e594243059e58d..127626bb9241bf7d6d4cb4dc86b381d9a2b12472 100644
--- a/app/Models/Result.php
+++ b/app/Models/Result.php
@@ -27,6 +27,7 @@ class Result
     public $strippedDomain; # Die Domain in Form "bar.de"
     public $strippedLink; # Der Link in Form "foo.bar.de/test"
     public $rank; # Das Ranking für das Ergebnis
+    public $new = true;
 
     # Erstellt ein neues Ergebnis
     public function __construct($provider, $titel, $link, $anzeigeLink, $descr, $gefVon, $gefVonLink, $sourceRank, $additionalInformation = [])
@@ -67,6 +68,7 @@ class Result
         $this->price = isset($additionalInformation["price"]) ? $additionalInformation["price"] : 0;
         $this->price_text = $this->price_to_text($this->price);
         $this->additionalInformation = $additionalInformation;
+        $this->hash = spl_object_hash($this);
     }
 
     private function price_to_text($price)
diff --git a/app/Models/Searchengine.php b/app/Models/Searchengine.php
index 03b5840485d244b565a6fb2a807e5a73c82289ac..f6bacb0969824ad4d4a414946dd7225cd3973a97 100644
--- a/app/Models/Searchengine.php
+++ b/app/Models/Searchengine.php
@@ -87,7 +87,7 @@ abstract class Searchengine
 
         $this->getString = $this->generateGetString($q);
         $this->hash = md5($this->engine->host . $this->getString . $this->engine->port . $this->name);
-        $this->resultHash = $metager->getHashCode();
+        $this->resultHash = $metager->getSearchUid();
         $this->canCache = $metager->canCache();
     }
 
@@ -102,13 +102,15 @@ abstract class Searchengine
     # Prüft, ob die Suche bereits gecached ist, ansonsted wird sie als Job dispatched
     public function startSearch(\App\MetaGer $metager)
     {
-
         if ($this->canCache && Cache::has($this->hash)) {
             $this->cached = true;
             $this->retrieveResults($metager);
         } else {
+            $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
             // We will push the confirmation of the submission to the Result Hash
-            Redis::hset('search.' . $this->resultHash, $this->name, "waiting");
+            $redis->hset($metager->getRedisEngineResult() . $this->name, "status", "waiting");
+            $redis->expire($metager->getRedisEngineResult() . $this->name, env('REDIS_RESULT_CACHE_DURATION'));
+
             // We need to submit a action that one of our workers can understand
             // The missions are submitted to a redis queue in the following string format
             // <ResultHash>;<URL to fetch>
@@ -190,10 +192,6 @@ abstract class Searchengine
     {
         foreach ($this->results as $result) {
             $result->rank($eingabe);
-            if (str_contains($this->engine->{"display-name"}, "Yahoo")) {
-                #die(var_dump($result));
-            }
-
         }
     }
 
@@ -210,12 +208,12 @@ abstract class Searchengine
         }
 
         $body = "";
+        $redis = Redis::connection(env('REDIS_RESULT_CONNECTION'));
 
         if ($this->canCache && $this->cacheDuration > 0 && Cache::has($this->hash)) {
             $body = Cache::get($this->hash);
-        } elseif (Redis::hexists('search.' . $this->resultHash, $this->name)) {
-            $body = Redis::hget('search.' . $this->resultHash, $this->name);
-            Redis::hdel('search.' . $this->resultHash, $this->name);
+        } elseif ($redis->hexists($metager->getRedisEngineResult() . $this->name, "response")) {
+            $body = $redis->hget($metager->getRedisEngineResult() . $this->name, "response");
             if ($this->canCache && $this->cacheDuration > 0) {
                 Cache::put($this->hash, $body, $this->cacheDuration);
             }
@@ -251,13 +249,7 @@ abstract class Searchengine
 
         # Append the Query String
         $getString .= "&" . $this->engine->{"query-parameter"} . "=" . $this->urlEncode($query);
-/*
-die(var_dump($getString));
 
-# Affildata
-if (strpos($getString, "<<AFFILDATA>>")) {
-$getString = str_replace("<<AFFILDATA>>", $this->getOvertureAffilData($url), $getString);
-}*/
         return $getString;
     }
 
diff --git a/app/Models/lang.pl b/app/Models/lang.pl
deleted file mode 100755
index 2be7f502cb792c45d2ff8c9a34602b7cfbc9a9e3..0000000000000000000000000000000000000000
--- a/app/Models/lang.pl
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/perl
-
-use Lingua::Identify qw(:language_identification);
-use JSON;
-use warnings;
-use strict;
-binmode STDOUT, ":utf8";
-binmode STDIN, ":utf8";
-use utf8;
-
-chomp(my $filename = <STDIN>);
-
-# Lets open the given file:
-open(my $fh, "<", $filename)
-	or die "Can't open < $filename: $!";
-my $json = <$fh>;
-close $fh;
-
-# Decode the JSON String
-my $data = JSON->new->utf8->decode($json);
-
-# Wir durchlaufen den Hash:
-foreach my $key (keys %{$data}){
-	$data->{$key} = langof($data->{$key});
-}
-
-$data = encode_json($data);
-
-# Nur noch die temporäre Datei löschen:
-unlink($filename);
-
-print $data;
diff --git a/readme.md b/readme.md
index b2ac2b86c6cb647420b9f9a0fec8cf60832cc7a5..26920c06bbc130723e345b62d23b8f86db019eda 100644
--- a/readme.md
+++ b/readme.md
@@ -18,9 +18,6 @@
   * php-gd
 * sqlite3
 * redis-server
-* Die Perl-Pakete
-  * Lingua::Identify (http://search.cpan.org/~ambs/Lingua-Identify-0.56/lib/Lingua/Identify.pm)
-  * JSON (http://search.cpan.org/~makamaka/JSON-2.90/lib/JSON.pm)
 
 ---
 [<img src="public/img/Browserstack-logo_2x.png" width="250px" alt="Browserstack Logo" />](https://www.browserstack.com) <br /> 
diff --git a/resources/js/scriptResultPage.js b/resources/js/scriptResultPage.js
index d2c1491b31aca9769d1e3b58bce4ae35ac0d4e19..dd140c82180bdc03f0a6f9d5009f3b5e614432f7 100644
--- a/resources/js/scriptResultPage.js
+++ b/resources/js/scriptResultPage.js
@@ -1,7 +1,7 @@
 $(document).ready(function () {
   botProtection();
-
   enableFormResetter();
+  loadMoreResults();
 });
 
 function botProtection() {
@@ -50,4 +50,72 @@ function enableFormResetter() {
       timeout = null;
     }, 500);
   });
+}
+
+function loadMoreResults() {
+  var searchKey = $("meta[name=searchkey]").attr("content");
+  var updateUrl = document.location.href;
+  updateUrl += "&loadMore=" + searchKey + "&script=yes";
+
+  updateUrl = updateUrl.replace("/meta.ger3", "/loadMore");
+
+  var expectedEngines = -1;
+  var deliveredEngines = -1;
+
+  var currentlyLoading = false;
+
+  // Regularily check for not yet delivered Results
+  var resultLoader = window.setInterval(function () {
+    if (!currentlyLoading) {
+      currentlyLoading = true;
+      $.getJSON(updateUrl, function (data) {
+        // Check if we can clear the interval (once every searchengine has answered)
+        if (data.engineDelivered == data.engineCount || data.timeWaiting > 15) {
+          clearInterval(resultLoader);
+        }
+        // If there are new results we can add them
+        if (typeof data.newResults != "undefined") {
+          for (var key in data.newResults) {
+            var value = data.newResults[key];
+
+            // If there are more results than the given index we will prepend otherwise we will append the result
+            if (!data.imagesearch) {
+              var results = $(".result:not(.ad)");
+              if (key == 0) {
+                if ($(".result.ad").length > 0) {
+                  $(value).insertAfter($($(".result.ad")[$(".result.ad").length - 1]));
+                } else {
+                  $("#results").prepend(value);
+                }
+              } else if (typeof results[key] != "undefined") {
+                $(value).insertBefore($(results[key]));
+              } else if (typeof results[key - 1] != "undefined") {
+                $(value).insertAfter($(results[key - 1]));
+              }
+            } else {
+              var results = $(".image-container > .image");
+              if (key == 0) {
+                $(".image-container").prepend(value);
+              } else if (typeof results[key] != "undefined") {
+                $(value).insertBefore($(results[key]));
+              } else if (typeof results[key - 1] != "undefined") {
+                $(value).insertAfter($(results[key - 1]));
+              }
+            }
+          }
+          if ($(".no-results-error").length > 0 && ($(".image-container > .image").length > 0) || $(".result:not(.ad)").length > 0) {
+            $(".no-results-error").remove();
+            if ($(".alert.alert-danger > ul").children().length == 0) {
+              $(".alert.alert-danger").remove();
+            }
+          }
+          console.log(data);
+        }
+        currentlyLoading = false;
+      });
+    }
+  }, 1000);
+  //clearInterval(resultLoader);
+  console.log(updateUrl);
+
 }
\ No newline at end of file
diff --git a/resources/views/layouts/image_result.blade.php b/resources/views/layouts/image_result.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..01c48941306fc8cd8947e66de1bd64a52cdbf5d5
--- /dev/null
+++ b/resources/views/layouts/image_result.blade.php
@@ -0,0 +1,8 @@
+<div class="image">
+	<a href="{{ $result->link }}" target="_blank">
+		<div title="{{ $result->titel }}">
+			<img src="{{ $metager->getImageProxyLink($result->image)}}" alt="{{ $result->titel }}"/>
+			<div>{{ $result->gefVon }}</div>
+		</div>
+	</a>
+</div>
diff --git a/resources/views/layouts/result.blade.php b/resources/views/layouts/result.blade.php
index a8f0eb2da387b305580d694f661d4bfa2ff4616e..347fb056b5a98dbf12a68c25ab96601faaadfd28 100644
--- a/resources/views/layouts/result.blade.php
+++ b/resources/views/layouts/result.blade.php
@@ -1,4 +1,4 @@
-<div class="result" data-count="{{ $result->number }}">
+<div class="result" data-count="{{ $result->hash }}">
 	<div class="result-header">
 		<div class="result-headline">
 			<h2 class="result-title" title="{{ $result->titel }}">
@@ -47,7 +47,7 @@
 			</div>
 		@endif
 	</div>
-	<input type="checkbox" id="result-toggle-{{$result->number}}" class="result-toggle" style="display: none">
+	<input type="checkbox" id="result-toggle-{{$result->hash}}" class="result-toggle" style="display: none">
 	<div class="result-footer">
 		<a class="result-open" href="{{ $result->link }}" target="_self" rel="noopener">
 			{!! trans('result.options.7') !!}
@@ -58,10 +58,10 @@
 		<a class="result-open-proxy" onmouseover="$(this).popover('show');" onmouseout="$(this).popover('hide');" data-toggle="popover" data-placement="auto right" data-container="body" data-content="@lang('result.proxytext')" href="{{ $result->proxyLink }}" target="{{ $metager->getNewtab() }}" rel="noopener">
 			{!! trans('result.options.5') !!}
 		</a>
-		<label class="open-result-options navigation-element" for="result-toggle-{{$result->number}}">
+		<label class="open-result-options navigation-element" for="result-toggle-{{$result->hash}}">
 			{{ trans('result.options.more')}}
 		</label>
-		<label class="close-result-options navigation-element" for="result-toggle-{{$result->number}}">
+		<label class="close-result-options navigation-element" for="result-toggle-{{$result->hash}}">
 			{{ trans('result.options.less')}}
 		</label>
 	</div>
@@ -69,7 +69,7 @@
 		<div class="options">
 				<ul class="option-list list-unstyled small">
 					<li class="js-only">
-						<a href="javascript:resultSaver({{ $result->number }});" class="saver">
+						<a href="javascript:resultSaver("{{ $result->hash }}");" class="saver">
 							<nobr><i class="fa fa-floppy-o"></i> {!! trans('result.options.savetab') !!}</nobr>
 						</a>
 					</li>
diff --git a/resources/views/layouts/resultPage.blade.php b/resources/views/layouts/resultPage.blade.php
index 00a2cd2070d41d4b6882e7e3b3b2a75e7089e409..3450762bae67b736997cfbf7b656ff55076fa721 100644
--- a/resources/views/layouts/resultPage.blade.php
+++ b/resources/views/layouts/resultPage.blade.php
@@ -11,6 +11,7 @@
 		<meta name="l" content="{{ LaravelLocalization::getCurrentLocale() }}" />
 		<meta name="mm" content="{{ $metager->getVerificationId() }}" />
 		<meta name="mn" content="{{ $metager->getVerificationCount() }}" />
+		<meta name="searchkey" content="{{ $metager->getSearchUid() }}" />
 		<link rel="search" type="application/opensearchdescription+xml" title="{!! trans('resultPage.opensearch') !!}" href="{{  LaravelLocalization::getLocalizedURL(LaravelLocalization::getCurrentLocale(), action('StartpageController@loadPlugin', ['params' => base64_encode(serialize(Request::all()))])) }}">
 		<link type="text/css" rel="stylesheet" href="{{ mix('css/fontawesome.css') }}" />
 		<link type="text/css" rel="stylesheet" href="{{ mix('css/fontawesome-solid.css') }}" />
diff --git a/resources/views/parts/errors.blade.php b/resources/views/parts/errors.blade.php
index f40b8b0ef270f70b8e273adad4d8abbe7449deac..cdd23071526943ee0aea6815e7bb1d30127129e6 100644
--- a/resources/views/parts/errors.blade.php
+++ b/resources/views/parts/errors.blade.php
@@ -3,7 +3,7 @@
 	<div class="alert alert-danger">
 		<ul>
 			@foreach($errors as $error)
-				<li>{!! $error !!}</li>
+				<li @if($error === trans('metaGer.results.failed')) class="no-results-error" @endif>{!! $error !!}</li>
 			@endforeach
 		</ul>
 	</div>
diff --git a/resources/views/parts/pager.blade.php b/resources/views/parts/pager.blade.php
index 5dd39e50ccdae4cbe1c5779cd1983ffb0a20f42f..5bb3011ca9911019820cf0c06f4c652da82320c9 100644
--- a/resources/views/parts/pager.blade.php
+++ b/resources/views/parts/pager.blade.php
@@ -3,7 +3,7 @@
     <div @if($metager->getPage() === 1) class="disabled" @endif>
         <a @if($metager->getPage() !== 1) href="javascript:history.back()" @endif>{{ trans('results.zurueck') }}</a>
     </div>
-    <div @if($metager->nextSearchLink() === "#") class="disabled" @endif>
+    <div id="next-search-link" @if($metager->nextSearchLink() === "#") class="disabled" @endif>
         <a @if($metager->nextSearchLink() !== "#") href="{{ $metager->nextSearchLink() }}" @endif>{{ trans('results.weiter') }}</a>
     </div>
-</nav>
\ No newline at end of file
+</nav>
diff --git a/resources/views/resultpages/results.blade.php b/resources/views/resultpages/results.blade.php
index e9e717e563763926b7577a6e060a484c737c05c7..8b242029225455afe9dbd2f59015fd5c841efb84 100644
--- a/resources/views/resultpages/results.blade.php
+++ b/resources/views/resultpages/results.blade.php
@@ -7,17 +7,17 @@
 		@endfor
 	@endif
 	{{-- Create results and ongoing ads --}}
-	@foreach($metager->getResults() as $result)
+	@foreach($metager->getResults() as $index => $result)
 		@if($mobile)
-			@if($result->number % 4 === 0)
+			@if($index % 4 === 0)
 				@include('layouts.ad', ['ad' => $metager->popAd()])
 			@endif
 		@else
-			@if($result->number % 7 === 0)
+			@if($index % 7 === 0)
 				@include('layouts.ad', ['ad' => $metager->popAd()])
 			@endif
 		@endif
 		@include('layouts.result', ['result' => $result])
 	@endforeach
 	@include('parts.pager')
-</div>
\ No newline at end of file
+</div>
diff --git a/resources/views/resultpages/results_images.blade.php b/resources/views/resultpages/results_images.blade.php
index 2eedcf6514223f165c186a0007be622ae736f28d..78c4338e50f380dc92ed1404171970bae5e2dbc9 100644
--- a/resources/views/resultpages/results_images.blade.php
+++ b/resources/views/resultpages/results_images.blade.php
@@ -1,15 +1,6 @@
-@include('parts.errors')
-@include('parts.warnings')
 <div id="container" class="image-container">
 	@foreach($metager->getResults() as $result)
-		<div class="image">
-			<a href="{{ $result->link }}" target="_blank">
-				<div title="{{ $result->titel }}">
-					<img src="{{ $metager->getImageProxyLink($result->image)}}" alt="{{ $result->titel }}"/>
-					<div>{{ $result->gefVon }}</div>
-				</div>
-			</a>
-		</div>
+		@include('layouts.image_result', ['result' => $result])
 	@endforeach
 </div>
 @include('parts.pager')
diff --git a/routes/web.php b/routes/web.php
index 913101e1db25268d425378ba067d2976a13ea8e3..d687370404ad06b941f91e6a8666f28bf5900191 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -179,6 +179,7 @@ Route::group(
         Route::get('settings', 'StartpageController@loadSettings');
 
         Route::match(['get', 'post'], 'meta/meta.ger3', 'MetaGerSearch@search')->middleware('humanverification');
+        Route::get('meta/loadMore', 'MetaGerSearch@loadMore');
         Route::post('img/cat.jpg', 'HumanVerification@remove');
         Route::get('r/metager/{mm}/{pw}/{url}', ['as' => 'humanverification', 'uses' => 'HumanVerification@removeGet']);
         Route::post('img/dog.jpg', 'HumanVerification@whitelist');