diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php
index 683038c..843db21 100644
--- a/app/Http/Controllers/SiteController.php
+++ b/app/Http/Controllers/SiteController.php
@@ -3,18 +3,20 @@
namespace App\Http\Controllers;
use App\Models\Site;
+use App\Support\GuestPreview;
use Illuminate\Contracts\View\View;
class SiteController extends Controller
{
public function show(Site $site): View
{
- $pages = $site->pages()->orderBy('url')->paginate(50, ['*'], 'pages_page');
+ $pages = GuestPreview::paginate($site->pages()->orderBy('url'), 50, 'pages_page');
- $backlinks = $site->inboundLinks()
- ->with(['site', 'sitePage'])
- ->latest()
- ->paginate(50, ['*'], 'backlinks_page');
+ $backlinks = GuestPreview::paginate(
+ $site->inboundLinks()->with(['site', 'sitePage'])->latest(),
+ 50,
+ 'backlinks_page'
+ );
$referringDomainsCount = $site->inboundLinks()->distinct()->count('site_id');
$outboundLinksCount = $site->outboundLinks()->count();
diff --git a/app/Livewire/Auth/Login.php b/app/Livewire/Auth/Login.php
new file mode 100644
index 0000000..ed557f4
--- /dev/null
+++ b/app/Livewire/Auth/Login.php
@@ -0,0 +1,42 @@
+validate([
+ 'email' => ['required', 'email'],
+ 'password' => ['required'],
+ ]);
+
+ if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
+ throw ValidationException::withMessages([
+ 'email' => 'These credentials do not match our records.',
+ ]);
+ }
+
+ session()->regenerate();
+
+ $this->redirect(route('sites.index'), navigate: false);
+ }
+
+ public function render(): View
+ {
+ return view('livewire.auth.login');
+ }
+}
diff --git a/app/Livewire/Auth/Register.php b/app/Livewire/Auth/Register.php
new file mode 100644
index 0000000..d09c8c4
--- /dev/null
+++ b/app/Livewire/Auth/Register.php
@@ -0,0 +1,48 @@
+validate([
+ 'name' => ['required', 'string', 'max:255'],
+ 'email' => ['required', 'email', 'max:255', 'unique:users,email'],
+ 'password' => ['required', 'confirmed', Password::defaults()],
+ ]);
+
+ $user = User::create([
+ 'name' => $validated['name'],
+ 'email' => $validated['email'],
+ 'password' => $validated['password'],
+ ]);
+
+ Auth::login($user);
+
+ session()->regenerate();
+
+ $this->redirect(route('sites.index'), navigate: false);
+ }
+
+ public function render(): View
+ {
+ return view('livewire.auth.register');
+ }
+}
diff --git a/app/Livewire/Discover/Search.php b/app/Livewire/Discover/Search.php
index 3f50e60..e303a13 100644
--- a/app/Livewire/Discover/Search.php
+++ b/app/Livewire/Discover/Search.php
@@ -3,6 +3,7 @@
namespace App\Livewire\Discover;
use App\Models\Site;
+use App\Support\GuestPreview;
use Illuminate\Contracts\View\View;
use Illuminate\Pagination\LengthAwarePaginator;
use Livewire\Attributes\Layout;
@@ -67,7 +68,7 @@ class Search extends Component
if (! $hasQuery) {
$sites = new LengthAwarePaginator([], 0, 25, 1, ['path' => request()->url()]);
} else {
- $sites = Site::query()
+ $sites = GuestPreview::paginate(Site::query()
->when(
$keyword !== '',
fn ($query) => $query->whereHas(
@@ -98,8 +99,7 @@ class Search extends Component
}
}])
->orderByDesc('matching_pages_count')
- ->orderBy('domain')
- ->paginate(25);
+ ->orderBy('domain'));
}
return view('livewire.discover.search', ['sites' => $sites, 'hasQuery' => $hasQuery]);
diff --git a/app/Livewire/Sites/Index.php b/app/Livewire/Sites/Index.php
index 36251a7..a0a75da 100644
--- a/app/Livewire/Sites/Index.php
+++ b/app/Livewire/Sites/Index.php
@@ -3,6 +3,7 @@
namespace App\Livewire\Sites;
use App\Models\Site;
+use App\Support\GuestPreview;
use Illuminate\Contracts\View\View;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Url;
@@ -24,14 +25,15 @@ class Index extends Component
public function render(): View
{
- $sites = Site::query()
- ->withCount('pages')
- ->when(
- $this->search !== '',
- fn ($query) => $query->where('domain', 'like', '%'.$this->search.'%')
- )
- ->orderBy('domain')
- ->paginate(25);
+ $sites = GuestPreview::paginate(
+ Site::query()
+ ->withCount('pages')
+ ->when(
+ $this->search !== '',
+ fn ($query) => $query->where('domain', 'like', '%'.$this->search.'%')
+ )
+ ->orderBy('domain')
+ );
return view('livewire.sites.index', ['sites' => $sites]);
}
diff --git a/app/Support/GuestPreview.php b/app/Support/GuestPreview.php
new file mode 100644
index 0000000..1ecbe22
--- /dev/null
+++ b/app/Support/GuestPreview.php
@@ -0,0 +1,33 @@
+paginate(self::LIMIT, ['*'], $pageName, 1);
+ }
+
+ return $query->paginate($fullPerPage, ['*'], $pageName);
+ }
+
+ public static function isLimited(): bool
+ {
+ return ! auth()->check();
+ }
+}
diff --git a/phpunit.xml b/phpunit.xml
index e7f0a48..f896766 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -23,8 +23,12 @@
+ Showing a preview ({{ $paginator->count() }} of {{ number_format($paginator->total()) }} results). + Sign in + or + create a free account + to see everything. +
+@endif diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index a2bcd2f..3c0c134 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -12,11 +12,23 @@+ Huginn indexes the web using Common Crawl's public archive and helps you find competitors + by product, location, and even the platform they're built on — e.g. "who sells honey with a + .es domain," or "which of my competitors run WordPress." +
+ + + + @guest ++ Browsing without an account shows a limited preview of results — + create a free account to see everything. +
+ @endguest ++ Don't have an account? Sign up. +
++ Already have an account? Log in. +
+