feat: finalize provider parity and SEO/frontend route coverage

This commit is contained in:
Dwindi Ramadhana
2026-02-04 09:32:25 +07:00
parent a4d2031117
commit 0c45435db9
14 changed files with 550 additions and 57 deletions

View File

@@ -1,49 +1,42 @@
@extends('site.layout')
@section('title', 'API Docs - Dewemoji')
@section('meta_description', 'Dewemoji API docs for emoji search, categories, license verification, activation, and system endpoints.')
@push('jsonld')
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "TechArticle",
"headline": "Dewemoji API Documentation",
"about": "Emoji search API",
"url": "{{ url('/api-docs') }}"
}
</script>
@endpush
@section('content')
<section class="card" style="padding: 20px;">
<h1 style="margin-top:0;">API Docs</h1>
<p style="color:var(--muted);">Current extension-compatible endpoints exposed by the rebuild app.</p>
<div class="max-w-5xl mx-auto px-4 sm:px-6 py-10">
<h1 class="font-display text-4xl font-bold">API Docs</h1>
<p class="text-gray-400 mt-2">Base URL: <code>{{ url('/v1') }}</code></p>
<h2>Base URL</h2>
<p><code>{{ url('/') }}/v1</code></p>
<h2>Endpoints</h2>
<ul>
<li><code>GET /v1/categories</code> - category + subcategory map</li>
<li><code>GET /v1/emojis</code> - paginated emoji list/search</li>
<li><code>POST /v1/license/verify</code> - license validation contract</li>
<div class="glass-card rounded-2xl p-5 mt-6">
<h2 class="text-lg font-semibold">Core endpoints</h2>
<ul class="mt-3 space-y-1 text-sm text-gray-300">
<li><code>GET /v1/categories</code></li>
<li><code>GET /v1/emojis?q=&lt;term&gt;&category=&lt;label&gt;&subcategory=&lt;slug&gt;</code></li>
<li><code>GET /v1/emoji/{slug}</code> or <code>/v1/emoji?slug=</code></li>
<li><code>POST /v1/license/verify</code></li>
<li><code>POST /v1/license/activate</code></li>
<li><code>POST /v1/license/deactivate</code></li>
</ul>
</div>
<h2>Example: emojis</h2>
<pre class="card" style="padding:12px;overflow:auto;">GET /v1/emojis?q=love&category=Smileys%20%26%20Emotion&page=1&limit=20</pre>
<h2>Example response</h2>
<pre class="card" style="padding:12px;overflow:auto;">{
"items": [
{
"emoji": "😀",
"name": "grinning face",
"slug": "grinning-face",
"category": "Smileys & Emotion",
"subcategory": "face-smiling",
"supports_skin_tone": false,
"summary": "A happy smiling face."
}
],
"total": 1,
"page": 1,
"limit": 20
}</pre>
<h2>Try it quickly</h2>
<p>
<a href="{{ url('/v1/categories') }}" target="_blank" style="color:var(--brand);">Open categories JSON</a>
&middot;
<a href="{{ url('/v1/emojis?q=love&limit=5&page=1') }}" target="_blank" style="color:var(--brand);">Open emojis JSON</a>
</p>
</section>
<div class="glass-card rounded-2xl p-5 mt-4">
<h2 class="text-lg font-semibold">Auth</h2>
<p class="text-sm text-gray-300 mt-2">Use <code>Authorization: Bearer YOUR_LICENSE_KEY</code> (preferred) or <code>X-License-Key</code>.</p>
<pre class="mt-3 text-xs overflow-x-auto bg-black/30 rounded-lg p-3"><code>curl -H "Authorization: Bearer YOUR_LICENSE_KEY" \
"{{ url('/v1/emojis') }}?q=love&limit=50&page=1"</code></pre>
</div>
</div>
@endsection

View File

@@ -1,6 +1,7 @@
@extends('site.layout')
@section('title', ($emoji['name'] ?? 'Emoji').' - Dewemoji')
@section('meta_description', ($emoji['description'] ?? 'Emoji detail').' Discover meaning, keywords, and copy-ready formats on Dewemoji.')
@php
$name = $emoji['name'] ?? '';
@@ -22,6 +23,30 @@
$keywords = array_slice($emoji['keywords_en'] ?? [], 0, 16);
@endphp
@push('jsonld')
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@graph": [
{
"@@type": "CreativeWork",
"name": @json($name),
"description": @json($description),
"url": @json(url('/emoji/'.$slug))
},
{
"@@type": "BreadcrumbList",
"itemListElement": [
{"@@type":"ListItem","position":1,"name":"Home","item":@json(url('/'))},
{"@@type":"ListItem","position":2,"name":"Emoji","item":@json(url('/browse'))},
{"@@type":"ListItem","position":3,"name":@json($name),"item":@json(url('/emoji/'.$slug))}
]
}
]
}
</script>
@endpush
@section('content')
<div class="flex h-screen">
<aside class="hidden lg:flex w-20 lg:w-64 h-full glass-panel flex-col justify-between p-4 z-20">
@@ -153,7 +178,7 @@
</div>
<nav class="lg:hidden fixed bottom-0 inset-x-0 z-50 border-t border-white/10 bg-[#0b0b0f]/95 backdrop-blur px-2 py-2">
<div class="grid grid-cols-5 gap-1 text-[11px]">
<div class="grid grid-cols-6 gap-1 text-[11px]">
<a href="{{ route('home') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-brand-sun bg-white/5">
<i data-lucide="layout-grid" class="w-4 h-4"></i><span>Discover</span>
</a>
@@ -163,6 +188,9 @@
<a href="{{ route('pricing') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="badge-dollar-sign" class="w-4 h-4"></i><span>Pricing</span>
</a>
<a href="{{ route('support') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="life-buoy" class="w-4 h-4"></i><span>Support</span>
</a>
<a href="{{ route('privacy') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="shield-check" class="w-4 h-4"></i><span>Privacy</span>
</a>

View File

@@ -1,6 +1,7 @@
@extends('site.layout')
@section('title', 'Dewemoji - Discover')
@section('meta_description', 'Search emojis by keyword, meaning, and category. Explore Dewemoji with fast API-powered results.')
@push('head')
<style>
@@ -35,6 +36,10 @@
<i data-lucide="badge-dollar-sign" class="w-5 h-5 group-hover:scale-110 transition-transform"></i>
<span class="text-sm font-medium hidden lg:block">Pricing</span>
</a>
<a href="{{ route('support') }}" class="flex items-center gap-4 px-3 py-3 rounded-xl text-gray-400 hover:text-white hover:bg-white/5 transition-all group">
<i data-lucide="life-buoy" class="w-5 h-5 group-hover:scale-110 transition-transform"></i>
<span class="text-sm font-medium hidden lg:block">Support</span>
</a>
</nav>
</div>
<div class="space-y-1">
@@ -145,7 +150,7 @@
</div>
<nav class="lg:hidden fixed bottom-0 inset-x-0 z-50 border-t border-white/10 bg-[#0b0b0f]/95 backdrop-blur px-2 py-2">
<div class="grid grid-cols-5 gap-1 text-[11px]">
<div class="grid grid-cols-6 gap-1 text-[11px]">
<a href="{{ route('home') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-brand-sun bg-white/5">
<i data-lucide="layout-grid" class="w-4 h-4"></i><span>Discover</span>
</a>
@@ -155,6 +160,9 @@
<a href="{{ route('pricing') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="badge-dollar-sign" class="w-4 h-4"></i><span>Pricing</span>
</a>
<a href="{{ route('support') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="life-buoy" class="w-4 h-4"></i><span>Support</span>
</a>
<a href="{{ route('privacy') }}" class="flex flex-col items-center justify-center gap-1 rounded-lg py-2 text-gray-300 hover:bg-white/5">
<i data-lucide="shield-check" class="w-4 h-4"></i><span>Privacy</span>
</a>

View File

@@ -10,9 +10,21 @@
$canonicalPath = '/'.trim($canonicalPath, '/');
}
$canonicalUrl = rtrim(config('app.url', request()->getSchemeAndHttpHost()), '/').$canonicalPath;
$metaDescription = trim($__env->yieldContent('meta_description')) ?: 'Search, copy, and explore emojis with Dewemoji. Free browser extension and API for developers.';
$metaTitle = trim($__env->yieldContent('title')) ?: 'Dewemoji';
@endphp
<title>@yield('title', 'Dewemoji')</title>
<meta name="description" content="{{ $metaDescription }}">
<link rel="canonical" href="{{ $canonicalUrl }}">
<meta property="og:title" content="{{ $metaTitle }}">
<meta property="og:description" content="{{ $metaDescription }}">
<meta property="og:url" content="{{ $canonicalUrl }}">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Dewemoji">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ $metaTitle }}">
<meta name="twitter:description" content="{{ $metaDescription }}">
<meta name="theme-color" content="#2053ff">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -87,6 +99,7 @@
}
</style>
@stack('head')
@stack('jsonld')
</head>
<body class="bg-[#050505] text-white min-h-screen selection:bg-brand-ocean selection:text-white">
<div class="fixed top-0 left-0 w-full h-full overflow-hidden -z-10 pointer-events-none">

View File

@@ -1,11 +1,86 @@
@extends('site.layout')
@section('title', 'Pricing - Dewemoji')
@section('meta_description', 'See Dewemoji plans for Free, Pro subscription, and Lifetime. One key unlocks Extension + API with up to 3 Chrome profile activations.')
@push('jsonld')
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@graph": [
{
"@@type": "Product",
"name": "Dewemoji Pro License",
"description": "One Pro license unlocks the Dewemoji extension and API.",
"brand": {"@@type": "Brand", "name": "Dewemoji"},
"offers": [
{"@@type":"Offer","price":"3.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"https://dwindown.gumroad.com/l/dewemoji-pro-subscription"},
{"@@type":"Offer","price":"27.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"https://dwindown.gumroad.com/l/dewemoji-pro-subscription"}
]
},
{
"@@type": "Product",
"name": "Dewemoji Lifetime License",
"description": "Lifetime access to extension + API.",
"brand": {"@@type": "Brand", "name": "Dewemoji"},
"offers": {"@@type":"Offer","price":"69.00","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"https://dwindown.gumroad.com/l/dewemoji-pro-lifetime"}
}
]
}
</script>
@endpush
@section('content')
<section class="card" style="padding: 20px;">
<h1 style="margin-top:0;">Pricing</h1>
<p style="color:var(--muted);">Phase 3 placeholder page. We will wire real pricing content and purchase flow in a later phase.</p>
</section>
@endsection
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-10">
<div class="text-center mb-8">
<h1 class="font-display text-4xl font-bold">Simple, fair pricing</h1>
<p class="text-gray-400 mt-2">One Pro unlocks both Extension + API.</p>
</div>
<div class="grid gap-4 md:grid-cols-3">
<section class="glass-card rounded-2xl p-6">
<h2 class="text-xl font-semibold">Free</h2>
<p class="text-gray-400 text-sm mt-1">For casual usage</p>
<p class="text-3xl font-bold mt-4">$0</p>
<ul class="mt-4 space-y-2 text-sm text-gray-300">
<li>Extension access</li>
<li>API testing access</li>
<li>Daily cap 30 queries</li>
</ul>
</section>
<section class="glass-card rounded-2xl p-6 border border-brand-ocean/40">
<h2 class="text-xl font-semibold">Pro</h2>
<p class="text-gray-400 text-sm mt-1">Most popular</p>
<p class="text-3xl font-bold mt-4">$3/mo <span class="text-sm text-gray-400">or $27/yr</span></p>
<ul class="mt-4 space-y-2 text-sm text-gray-300">
<li>Unlimited extension usage</li>
<li>API pro access</li>
<li>Up to 3 Chrome profiles</li>
</ul>
<a href="https://dwindown.gumroad.com/l/dewemoji-pro-subscription" target="_blank" rel="noopener noreferrer" class="mt-5 inline-flex w-full justify-center rounded-lg bg-brand-ocean hover:bg-brand-oceanSoft px-4 py-2 font-semibold">Subscribe on Gumroad</a>
</section>
<section class="glass-card rounded-2xl p-6">
<h2 class="text-xl font-semibold">Lifetime</h2>
<p class="text-gray-400 text-sm mt-1">Pay once, use forever</p>
<p class="text-3xl font-bold mt-4">$69</p>
<ul class="mt-4 space-y-2 text-sm text-gray-300">
<li>Extension + API access</li>
<li>Future updates included</li>
<li>IDR/Mayar available on request</li>
</ul>
<a href="https://dwindown.gumroad.com/l/dewemoji-pro-lifetime" target="_blank" rel="noopener noreferrer" class="mt-5 inline-flex w-full justify-center rounded-lg bg-brand-sun text-black hover:bg-brand-sunSoft px-4 py-2 font-semibold">Buy Lifetime</a>
</section>
</div>
<div class="glass-card rounded-2xl p-6 mt-6 text-sm text-gray-300">
<h3 class="font-semibold text-white">Licensing basics</h3>
<ul class="mt-3 list-disc pl-5 space-y-1">
<li>One key unlocks both extension and API.</li>
<li>Use <code>Authorization: Bearer YOUR_LICENSE_KEY</code> for API requests.</li>
<li>One license supports up to 3 active Chrome profiles.</li>
</ul>
</div>
</div>
@endsection

View File

@@ -1,6 +1,7 @@
@extends('site.layout')
@section('title', 'Privacy - Dewemoji')
@section('meta_description', 'Read Dewemoji privacy information and data handling practices.')
@section('content')
<section class="card" style="padding: 20px;">
@@ -8,4 +9,3 @@
<p style="color:var(--muted);">Phase 3 placeholder page. We will migrate the full privacy text from legacy content in a later pass.</p>
</section>
@endsection

View File

@@ -0,0 +1,52 @@
@extends('site.layout')
@section('title', 'Support - Dewemoji')
@section('meta_description', 'Get help with Dewemoji installation, Pro activation, API usage, billing, and troubleshooting.')
@push('jsonld')
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "FAQPage",
"mainEntity": [
{"@@type":"Question","name":"How do I activate Pro?","acceptedAnswer":{"@@type":"Answer","text":"Open Dewemoji settings, paste your license key in Pro tab, and activate."}},
{"@@type":"Question","name":"How many devices can I use?","acceptedAnswer":{"@@type":"Answer","text":"One license can activate up to 3 Chrome profiles."}},
{"@@type":"Question","name":"How do I use my key in API?","acceptedAnswer":{"@@type":"Answer","text":"Send Authorization: Bearer YOUR_LICENSE_KEY header in requests."}}
]
}
</script>
@endpush
@section('content')
<div class="max-w-5xl mx-auto px-4 sm:px-6 py-10">
<h1 class="font-display text-4xl font-bold text-center">Support</h1>
<p class="text-gray-400 text-center mt-2">Need help with Dewemoji? We got you.</p>
<div class="grid gap-4 mt-8 md:grid-cols-2">
<section class="glass-card rounded-2xl p-5">
<h2 class="font-semibold">Install & activate</h2>
<ol class="mt-3 list-decimal pl-5 text-sm text-gray-300 space-y-1">
<li>Install from Chrome Web Store.</li>
<li>Open Dewemoji settings.</li>
<li>Paste key in Pro tab and activate.</li>
</ol>
</section>
<section class="glass-card rounded-2xl p-5">
<h2 class="font-semibold">API quick start</h2>
<pre class="mt-3 text-xs overflow-x-auto bg-black/30 rounded-lg p-3"><code>curl -H "Authorization: Bearer YOUR_LICENSE_KEY" \
"{{ url('/v1/emojis') }}?q=love&limit=20"</code></pre>
</section>
<section class="glass-card rounded-2xl p-5 md:col-span-2">
<h2 class="font-semibold">Common issues</h2>
<ul class="mt-3 list-disc pl-5 text-sm text-gray-300 space-y-1">
<li><strong>License limit reached:</strong> deactivate old profile first.</li>
<li><strong>API 401 invalid key:</strong> ensure key is valid and active.</li>
<li><strong>Insert not working:</strong> click into input and retry.</li>
</ul>
<p class="mt-4 text-sm text-gray-400">Still stuck? Email <a class="text-brand-ocean hover:underline" href="mailto:hello@dewemoji.com">hello@dewemoji.com</a>.</p>
</section>
</div>
</div>
@endsection

View File

@@ -1,6 +1,7 @@
@extends('site.layout')
@section('title', 'Terms - Dewemoji')
@section('meta_description', 'Read Dewemoji terms and conditions for website, extension, and API usage.')
@section('content')
<section class="card" style="padding: 20px;">
@@ -8,4 +9,3 @@
<p style="color:var(--muted);">Phase 3 placeholder page. We will migrate complete terms content from legacy sources in a later pass.</p>
</section>
@endsection