diff --git a/apps/web/app/bounties/page.tsx b/apps/web/app/bounties/page.tsx index c623180..fa686f9 100644 --- a/apps/web/app/bounties/page.tsx +++ b/apps/web/app/bounties/page.tsx @@ -44,6 +44,25 @@ const STATUS_COLORS: Record = { paid: 'bg-gray-100 text-gray-500 border-gray-200', }; +const FAQ = [ + { + q: 'What is a coupon bounty?', + a: 'A bounty is a cash reward posted by a shopper who wants a working coupon code for a specific store. Anyone can submit a valid code to claim the reward.', + }, + { + q: 'How much can I earn?', + a: 'Bounty creators set their own reward amount (minimum $0.10). Rewards are paid instantly to your CoinPay DID as soon as a valid code is accepted.', + }, + { + q: 'How do I post a bounty?', + a: 'Connect your CoinPay account, then click "Post Bounty". Name the store, describe the discount you\'re looking for, and set your reward amount.', + }, + { + q: 'What happens if no code is found?', + a: 'Open bounties remain listed until a valid code is submitted or the creator cancels. Funds are only released when a working code is confirmed.', + }, +]; + export default async function BountiesPage() { const [bounties, did] = await Promise.all([getBounties(), getSessionDid()]); const storeName = (b: Bounty) => b.store_name_resolved ?? b.store_name ?? 'Any store'; @@ -92,9 +111,64 @@ export default async function BountiesPage() { {/* Bounty list */} {bounties.length === 0 ? ( -
-

No open bounties yet.

-

Be the first to post one!

+
+
+

No open bounties yet.

+

+ Be the first to post one — set any reward amount and let the community find your code. +

+ {did ? ( + + Post the first bounty + + ) : ( + + Connect & post a bounty + + )} +
+ + {/* FAQ — keeps the page content-rich for crawlers even when list is empty */} +
+

Frequently asked questions

+
+ {FAQ.map(({ q, a }) => ( +
+
{q}
+
{a}
+
+ ))} +
+
+ + {/* Benefits */} +
+

Why use c0upons bounties?

+
    +
  • + + Instant crypto payouts — no waiting for bank transfers or gift cards +
  • +
  • + + You only pay when a working code is confirmed — no risk of paying for duds +
  • +
  • + + The whole community is incentivised to find the best coupon for your store +
  • +
  • + + Found codes are added to c0upons so future shoppers benefit too +
  • +
+
) : (
diff --git a/apps/web/app/search/page.tsx b/apps/web/app/search/page.tsx index 6180d84..afe5a86 100644 --- a/apps/web/app/search/page.tsx +++ b/apps/web/app/search/page.tsx @@ -1,10 +1,19 @@ export const dynamic = 'force-dynamic'; +import type { Metadata } from 'next'; +import Link from 'next/link'; import CouponCard from '@/components/CouponCard'; import SearchBar from '@/components/SearchBar'; import { getDb } from '@/lib/db'; import { Coupon } from '@/lib/types'; +export const metadata: Metadata = { + title: 'Search Coupons', + description: + 'Search thousands of community-submitted coupon codes and promo deals. Find discounts for any store — electronics, fashion, groceries, travel and more.', + alternates: { canonical: 'https://c0upons.com/search' }, +}; + async function search(q: string): Promise { if (!q) return []; try { @@ -26,6 +35,24 @@ async function search(q: string): Promise { } } +const SEARCH_TIPS = [ + { tip: 'Search by store name', example: '"Amazon", "Nike", "Spotify"' }, + { tip: 'Search by discount type', example: '"free shipping", "20% off", "BOGO"' }, + { tip: 'Search by product category', example: '"shoes", "electronics", "software"' }, + { tip: 'Search by coupon code', example: 'paste a code you already have to check it' }, +]; + +const POPULAR_SEARCHES = [ + 'free shipping', + '20% off', + 'electronics', + 'fashion', + 'groceries', + 'travel', + 'software', + 'subscription', +]; + export default async function SearchPage({ searchParams }: { searchParams: Promise<{ q?: string }> }) { const { q = '' } = await searchParams; const results = q ? await search(q) : []; @@ -37,13 +64,40 @@ export default async function SearchPage({ searchParams }: { searchParams: Promi
- {q && ( + {q ? (

{results.length} result{results.length !== 1 ? 's' : ''} for “{q}”

{results.length === 0 ? ( -

No coupons found. Try a different search term.

+
+
+

No coupons found for “{q}”.

+

+ Try a different search term, or be the first to submit a coupon for this store. +

+ + Submit a coupon code + +
+
+

Try a popular search

+
+ {POPULAR_SEARCHES.map((term) => ( + + {term} + + ))} +
+
+
) : (
{results.map((c) => ( @@ -52,6 +106,93 @@ export default async function SearchPage({ searchParams }: { searchParams: Promi
)}
+ ) : ( + /* Landing state — shown when no query is present; must be content-rich for crawlers */ +
+ {/* Popular searches */} +
+

Popular searches

+
+ {POPULAR_SEARCHES.map((term) => ( + + {term} + + ))} +
+
+ + {/* Search tips */} +
+

Search tips

+
+ {SEARCH_TIPS.map(({ tip, example }) => ( +
+ {tip} + {example} +
+ ))} +
+
+ + {/* About the search */} +
+

How c0upons search works

+

+ c0upons searches across coupon titles, descriptions, store names, and coupon codes + simultaneously. Results are ranked by community votes, so the most reliable, recently + verified codes always appear first. +

+

+ Can't find what you're looking for?{' '} + + Submit a coupon + {' '} + and help the community save, or post a{' '} + + bounty + {' '} + and pay someone to find it for you. +

+
+ + {/* Links to other sections */} +
+

Browse without searching

+
+ + 🏪 + Browse by store + Find all coupons for a specific retailer + + + 💰 + View bounties + Earn rewards by hunting coupon codes + + + + Submit a coupon + Share a working code with the community + +
+
+
)}
); diff --git a/apps/web/app/stores/page.tsx b/apps/web/app/stores/page.tsx index 9bb6a39..f4700ba 100644 --- a/apps/web/app/stores/page.tsx +++ b/apps/web/app/stores/page.tsx @@ -1,5 +1,7 @@ export const dynamic = 'force-dynamic'; +import type { Metadata } from 'next'; +import Link from 'next/link'; import StoreCard from '@/components/StoreCard'; import { getDb } from '@/lib/db'; import { Store } from '@/lib/types'; @@ -8,6 +10,13 @@ interface StoreWithCount extends Store { coupon_count: number; } +export const metadata: Metadata = { + title: 'All Stores', + description: + 'Browse coupon codes for hundreds of online stores — from fashion and electronics to groceries and travel. Find the best promo codes for your favourite retailer.', + alternates: { canonical: 'https://c0upons.com/stores' }, +}; + async function getStores(): Promise { try { const db = getDb(); @@ -23,6 +32,15 @@ async function getStores(): Promise { } } +const STORE_CATEGORIES = [ + { name: 'Fashion & Apparel', examples: 'clothing, shoes, accessories' }, + { name: 'Electronics & Tech', examples: 'gadgets, software, subscriptions' }, + { name: 'Home & Garden', examples: 'furniture, tools, décor' }, + { name: 'Food & Groceries', examples: 'meal kits, delivery, snacks' }, + { name: 'Travel & Hotels', examples: 'flights, stays, car rental' }, + { name: 'Beauty & Health', examples: 'skincare, fitness, wellness' }, +]; + export default async function StoresPage() { const stores = await getStores(); @@ -39,20 +57,26 @@ export default async function StoresPage() {

All Stores

-

{stores.length} stores with active coupons

+

+ {stores.length > 0 + ? `${stores.length} stores with active coupons` + : 'Browse coupon codes by retailer'} +

-
- {letters.map((l) => ( - - {l} - - ))} -
+ {stores.length > 0 && ( +
+ {letters.map((l) => ( + + {l} + + ))} +
+ )} {letters.map((letter) => (
@@ -66,7 +90,78 @@ export default async function StoresPage() { ))} {stores.length === 0 && ( -

No stores yet.

+
+ {/* Call-to-action */} +
+

Stores are being added.

+

+ Know a store that should be here? Submit a coupon and the store will be created automatically. +

+ + Submit a coupon code + +
+ + {/* Category overview so the page is never content-empty for crawlers */} +
+

Store categories

+

+ c0upons covers coupon codes across a wide range of retail categories. Once stores are + added they will appear here, organised alphabetically. +

+
+ {STORE_CATEGORIES.map((cat) => ( +
+

{cat.name}

+

{cat.examples}

+
+ ))} +
+
+ + {/* How stores work */} +
+

How store pages work

+
    +
  1. + 1 +
    +

    Submit a coupon for any store

    +

    + Use the Submit page + to add a working promo code. If the store doesn't exist yet, it is created automatically. +

    +
    +
  2. +
  3. + 2 +
    +

    Community verifies the code

    +

    + Other shoppers upvote or flag codes as expired, keeping the store's coupon list + accurate and up-to-date. +

    +
    +
  4. +
  5. + 3 +
    +

    Store page grows over time

    +

    + Each store gets a dedicated page listing all its available discount codes, sorted by + community votes so the best deals are always at the top. +

    +
    +
  6. +
+
+
)}
);