DEV3 Hagglo – Local Classifieds Laravel Script with Chat, Offers, Moderation & Paid Promotion (Flutter App)

A self-hosted local classifieds marketplace on Laravel 12 and Filament 4 with a Flutter app: free ads with quotas, radius search, chat with offers, a moderation queue and paid promotion packages. Includes a web installer and demo data.

by DEV3 TechnologiesVerified Author(0) 0 sales 1 viewsUpdated 04 Nov 2026

Video tour. Pick a section below to browse 113 screenshots in 17 sections.

Hagglo is a local classifieds script that you host yourself, built by DEV3 Technologies on Laravel 12 and Filament 4, with one Flutter app for members. People post free ads in a category tree, search by distance, chat with the seller, trade offers and counter-offers, and sellers pay to promote their ads. The owner of the site earns from promotion packages and ad packs, and a moderation queue, report handling and chat-safety rules keep the board tidy. The demo region is a fictional metro called Kestrel Bay.

No live demo: the 66 grouped web screenshots, the 47 grouped app screenshots and the video tours show the marketing site, the public site, the member account and every admin screen. Install it with the bundled demo data to try each role on your own server.

Posting and quotas

  • A step-by-step posting wizard: pick a category, fill the dynamic fields of that category (make, year and mileage for cars; rooms and size for flats), add photos, set the price and a location pin, review the ad and publish.
  • Fields are defined per category in the admin panel and inherited down the tree. They are validated on the server, and the ones marked filterable become search filters.
  • Every root category has a free posting quota over a rolling 30 days. When it is used up, a member buys an ad pack (credits that expire, optionally limited to one category) or waits until the next slot frees up. The quota is checked under a database lock, and a rejected ad gives its slot back.
  • Ad lifetime is a setting. Members can pause, resume, renew and mark ads as sold, choosing the buyer or "sold elsewhere".

Moderation

  • Three modes: auto, manual for every ad and post-moderate (live first, reviewed after).
  • In auto mode each new or materially edited ad gets a score. Rules (keyword, URL, phone number, regular expression) add to it, a phone number or link in the description adds to it, a price far from the category median adds to it, and a new member adds to it. A low score goes live, a high one waits in the listing queue, and a rule can also reject outright.
  • The queue shows the ad, its photos and why it scored what it did. Rejecting needs a reason that goes to the seller, who can edit and resubmit.
  • A rules tester lets staff paste a text and see which rules fire. Duplicate ads from the same member are refused, and banned members cannot post.

Search near you

  • Browse as a grid, a list or a map with price pins, with category filters, price range, condition, seller type, sorting and a radius around a point.
  • Results use cursor paging, so new ads do not shift pages while someone scrolls.
  • Location privacy: public pages and the API show a blurred pin (300 m by default), distances rounded to whole kilometres, and an encrypted paging cursor. Only the owner sees the exact pin, and unrevealed phone numbers are never in public output.
  • Members can save a search and get an hourly alert when new matching ads appear.

Chat, offers and reservations

  • One conversation per buyer and ad, in the web inbox and in the app. Chats carry text, images, locations, offers and system notes.
  • Offers and counter-offers follow turn rules. Accepting an offer reserves the ad for that buyer for a set number of hours, and a reservation or offer that runs out lapses by itself.
  • Chat safety: block users, a limit on new chats per hour, a soft lock when the same text is blasted into many chats, and automatic flags for off-platform payment tricks. Flagged messages go to a moderator list, and a safety note appears in the chat.
  • Phone numbers are revealed only to a signed-in buyer, a limited number of times a day, and every reveal is logged.
  • After a sale both sides can rate each other.

Promotion and packs

  • Sellers buy bump, featured, top and urgent packages, and the owner defines their length and price. A bump moves the ad up the list on a schedule, featured adds a badge and outline, and top gives a paid slot at the head of the results.
  • Pay by card through the payment interface or from the member wallet, with ad packs and wallet top-ups on the same rails. Money is only credited when the payment succeeds, a repeated success event is ignored, and a late or duplicate payment is refunded.
  • Buying a promotion on an ad that is still in review waits until it is approved and is refunded if the ad is rejected. Staff can refund an order, in part or in full, from the admin panel.

Reports and trust

  • Members report ads, people and messages. Enough reports from distinct verified members pauses an ad until a moderator decides, and a dismissed report lowers the reporter's trust score.
  • Staff can warn, ban and verify members, with every action written to a log. A ban removes the member's ads, clears reservations and signs them out.
  • Business members get a shop page with hours and a verified badge.

Admin panel

  • Roles for admin, moderator, finance and content staff on one Filament panel: dashboard with KPIs, charts and a 3D Neighbourhood Pulse map of the districts, listing queue, reports, rules, flagged messages, listings, categories, category fields, locations, promotion packages and orders, ad packs, users, business profiles, ratings, blocks, banners, pages, safety tips, reports and an action log.
  • The core also provides settings, roles, audit log, devices, wallets and a REST API with an OpenAPI document and reference page.

The Flutter app

  • One app for buying and selling: onboarding, location pick, sign-in with a one-time code, home, browse with list, grid and map, filters, listing detail, phone reveal, reporting, the posting wizard, quota and packs, promotion and checkout, my ads with statistics, inbox, chat with offers, favourites, saved searches, profile, shop page, wallet, settings and Arabic. It starts in demo mode with its own data and switches to your server with two build flags.

What is included

  • The Laravel application with Composer packages and compiled assets already inside (no Node.js or Composer needed on the server), the Flutter project in apps/user, the shared DEV3 packages, a web installer with demo or empty data, and documentation.
  • English, with an Arabic translation and right-to-left layout for the main screens, and light and dark themes.

Good to know

  • Payments, SMS and push were not tested with live accounts. The Stripe, PayPal and Razorpay drivers, push notifications (FCM and APNs) and SMS exist as interfaces. The simulated gateway is the default, push and SMS use simulated or log drivers, and the money rules were tested against the simulated gateway only. Run your own test payments before taking real ones.
  • The app was not tested on physical devices. It builds as a debug Android package and runs on the iOS simulator. It was tested against a built-in mock and against API responses captured from the backend, not against a live backend running behind it. Expect to do your own end-to-end pass once you point it at your server.
  • Arabic is partial. It covers the main screens, not every string, and the Filament admin and account panels are not translated.
  • Lighthouse was not run. The front-end size budget was measured (public JS and CSS 30.8 KB gzipped, the 3D chunk loads lazily), but no Lighthouse scores were taken.
  • Account actions have lighter tests. Pause, renew, mark sold, promote, pack and top-up in the web account panel have page-render tests; the API paths behind them are fully tested.
  • Small gaps: price pins on the web map are not spread apart when they overlap, and the static hero poster stays light in dark mode.
  • Scope: Hagglo does not take payments or arrange delivery between users. Money flows only for promotions, packs and wallet top-ups.
  • Name: Hagglo is a working name checked by a web search only, not a trademark clearance. Check it before you launch under it.
  • Real-time: the app refreshes an open chat every few seconds and the inbox less often; it has no live socket client.
  • No hosted demo. All brands, people and ads in the screenshots are fictional.

Quality checks

Hagglo 1.0.0 passed the seven release gates of the DEV3 Laravel suite on the packaged build: static analysis (Larastan level 6, 0 errors), 201 Pest tests with 4,125 assertions, a front-end size budget, migrations and seeding on MySQL 8 and SQLite, a headless-browser pass over 134 pages, an installer test from the zip, and a secret scan. The Flutter app passed analysis and 68 tests, plus debug Android and iOS simulator builds.

How it's built

Architecture, stack, key decisions and the quality gates DEV3 Hagglo passed before release.

The engineering behind Hagglo: Laravel 12 and Filament 4 on a shared core, a rolling posting quota under a lock, a scored moderation pipeline, radius search that hides exact pins, offers with reservations and promotions with their own refund rules.

The problem it solves

A classifieds site looks simple until people start using it. Posting is free, so quotas have to hold when one member publishes from two devices at once. Free posting invites spam and duplicates, so something has to screen ads without a person reading each one. Buyers search by distance, but the seller's home must not be recoverable by querying with different centres. Chat turns into haggling, and two buyers can both have an offer the seller wants to accept. The owner earns from promotions, and these run on time: a bump has to repeat on a schedule, a promotion bought on an ad still in review must wait, and a refund depends on why an ad disappeared. Hagglo had to get these rules right on the server first, then expose them through one API for the web site and the app.

Architecture and approach

Hagglo is a Laravel 12 application with Filament 4 panels: /admin for staff (admin, moderator, finance and content roles) and /account for members. The public site is Blade with a small JavaScript layer and a lazy-loaded three.js scene on the marketing page. The Flutter app talks to the same /api/v1 endpoints. Business rules live in services under app/Services, so the web, the API and the admin all go through the same code.

Rules in services

  • Quota. QuotaService counts free postings per root category over a rolling 30 days, then spends pack credits (category packs first, earliest expiry first). It runs under a lock on the user row. A rejected ad returns its slot; deleting or selling does not.
  • Moderation. ModerationService refuses banned members and duplicates (a fingerprint of member, normalised title and category), adds up rule scores, adds a price-outlier score and a new-member score, and turns the total into live or pending according to the mode. Only material edits are screened again.
  • Search. ListingSearch uses a keyset cursor, so inserts do not shift pages, a bounding box followed by a true circle for the radius, facet counts that ignore their own filter, and a few randomised paid slots per page that are left out of the organic rows.
  • Location privacy. ListingGeo offsets every pin by a stable amount of at most 300 m. The public centre snaps to a grid, the radius rounds up, distances are whole kilometres and cursors are encrypted, so repeated queries cannot triangulate a home.
  • Offers. OfferService locks the listing, enforces turns, supersedes older offers and refuses a second accepted reservation. Scheduled commands expire offers and reservations.
  • Promotion. PromotionService schedules, starts, extends and ends promotions, applies bumps from a scheduled command and refunds by rule: full when an ad in review is rejected, pro rata when staff remove an ad without fault, none when the seller sells or deletes it.

Money and safety

  • Card money moves only on a payment-succeeded event. A repeated event is ignored, and late, duplicate or stale-amount payments are refunded. Wallet entries use idempotent keys.
  • ChatService and ReportService add blocks, rate limits, a soft lock for repeated text, scam-pattern flags, and a report auto-pause that counts distinct verified reporters.

Scheduler

One cron line runs hagglo:expire-listings, hagglo:lapse, hagglo:bump, hagglo:alerts and hagglo:housekeeping. Queues default to sync, so no worker is required to start.

The app

The Flutter app has a built-in mock of the API, so it runs on its own in demo mode. Two build flags point it at a real server. It polls chat every few seconds instead of holding a socket.

Quality gates and results

Hagglo 1.0.0 passed all seven release gates of the DEV3 Laravel suite on the packaged build:

  • Static analysis: composer validate, Pint clean, Larastan level 6 with 0 errors, and a syntax check of 376 PHP files.
  • Tests: 201 Pest tests with 4,125 assertions, with dedicated suites for quota, moderation, search, privacy, offers, chat safety, promotion money, reports, the listing state machine and review fixes.
  • Front-end budget: 11.0 KB of JS and 19.8 KB of CSS gzipped on the public pages (30.8 KB against a 180 KB budget), with the three.js chunk of 187 KB gzipped loaded lazily.
  • Database: demo and empty seeders on MySQL 8 and SQLite.
  • Browser pass: 134 pages in a headless browser, plus parallel-request checks of the quota and offer locks against MySQL.
  • Installer and secrets: the web installer ran from the zip with MySQL and demo data, and the secret scan was clean.

The Flutter app passed analysis, 68 tests, and debug Android and iOS simulator builds.

Limits: payment, push and SMS drivers were not run against live accounts, the app was not run on physical devices and was tested against a mock and captured API responses, Arabic is partial, the Filament panels are English only, and Lighthouse was not run.

Tech stack

Area Technologies
Backend Laravel 12, Filament 4 panels, Livewire chat, REST API under /api/v1, Scheduler commands, Database queue
Marketplace engine Quota service, Moderation scoring, Keyset-paged search, Location blur, Offer and reservation service, Promotion service
Frontend Blade, Tailwind CSS 4, Vite 7, three.js hero, Neighbourhood Pulse map
Mobile Flutter, Riverpod and go_router, Built-in API mock, Captured API fixtures
Data MySQL 8, SQLite, Integer money, Demo and empty seeders
Integrations Stripe, PayPal, Razorpay drivers, Push and SMS drivers, Simulated gateway default

Inside the build

Price tag swarm: Toy goods hang from swinging cardboard price tags over a tilted cobalt map, and the tags sway as the pointer moves. Price tag swarm — Toy goods hang from swinging cardboard price tags over a tilted cobalt map, and the tags sway as the pointer moves.

Drift: Pins drop on the map while the goods swing, with a search bar right under the headline. Drift — Pins drop on the map while the goods swing, with a search bar right under the headline.

Guides & articles

Practical guides and engineering write-ups for DEV3 Hagglo.

Classified ads script: 7 things to check before you pick one

Last updated
Classified ads script: 7 things to check before you pick one: DEV3 Hagglo

Classified ads scripts all show the same screenshots: a grid of ads, a category menu, a post button. The differences appear a month after launch, when one member posts the same bike forty times, when a buyer works out where a seller lives by moving the search pin, when two people both think the seller accepted their offer, or when a paid "top" ad stays up after the ad was removed for fraud. This guide lists seven things worth testing before you choose a self-hosted classifieds script, and how Hagglo, built on Laravel 12 and Filament 4 with a Flutter app, handles each one.

The Hagglo category page: a pin-board of ads with price tags, photos and distance

1. Does free posting have limits that hold?

If posting is free, you need a quota, and a quota that can be beaten by tapping publish on two phones is not a quota. Ask what the window is, what happens at the limit, and what a rejected ad costs the seller.

In Hagglo each root category has its own free allowance over a rolling 30 days. When it is used up, the member can use a pack credit (packs can be tied to a category, and the one that expires first is spent first) or wait for the next slot. The check runs under a lock on the member, so two parallel publishes on the last slot give one success. Pausing, renewing and editing cost nothing, and an ad rejected at first review gives its slot back.

2. Who stops spam before a human sees it?

A script that sends every ad to a queue will bury your moderators. A script that publishes everything will bury your buyers. Look for scoring, with reasons a moderator can read.

Hagglo adds up points: matching rules (keywords, links, phone numbers, patterns), a phone number or link in the description, a price far from the category median, and a member who has few approved ads. A low score goes live, a high one waits, and a rule can reject outright. There are three modes: auto, review everything, and post-moderate. The queue shows the score reasons next to the ad, and a rules tester lets staff paste text to see what would fire.

Score reasons in the Hagglo listing queue: which rules matched and how many points each added

3. Does the "near me" search give away where people live?

Radius search needs coordinates, and coordinates in the API are a privacy leak. Check the public JSON, the map pins and the paging data.

Hagglo shows a pin shifted by a stable amount (300 m by default), returns distances in whole kilometres, and snaps the search centre and radius. The paging cursor is encrypted, so it cannot be used to read exact distances. Only the owner sees the exact pin. Phone numbers stay hidden until a signed-in buyer reveals one, with a daily cap and a log.

The Hagglo map view: ads as price pins on a map with a card for the selected ad

4. Can buyers and sellers haggle without confusion?

A chat box is not enough for a marketplace named after bargaining. You need offers that follow turns and a clear answer to "who got it?".

In Hagglo an offer lives inside the conversation. The other side can accept, counter or decline, a new offer replaces the old one, and unanswered offers expire. Accepting reserves the ad for that buyer for a set number of hours, and a second accept on the same ad is refused. The seller can release the reservation, and marking the ad sold lets them choose the buyer, who can then rate them.

The Hagglo web inbox: a conversation per ad with offer bubbles and a safety note

5. Is chat safe by default?

Scams live in chats. Look for blocking, rate limits and some pattern checks, and make sure a moderator can see flagged threads.

Hagglo limits new chats per hour, soft-locks a member who pastes the same text into many chats, flags messages that point to off-platform payment or contact, and inserts a safety note. Flagged messages are delivered and listed for moderators, who can warn or ban. A ban removes the member's ads and clears their reservations.

6. How does paid promotion behave when things go wrong?

Promotion is how most classifieds sites earn, so test the odd cases: an ad still in review, a rejected ad, an ad sold the next day, a bump bought while another runs.

Hagglo sells bump, featured, top and urgent packages. A bump repeats on a schedule, featured is a badge and outline, and top uses paid slots at the head of the results. A promotion bought on an ad in review waits for approval and is refunded if the ad is rejected. Staff removal without fault is refunded pro rata, and a sale or deletion by the seller is not refunded. Card money counts only after a successful payment event, and a repeated event is ignored.

The Hagglo promote screen: top, bump and highlight packages with the days they run

7. Is there a mobile app, and how was it tested?

Ask whether the app is a real project you can build, what it needs from the server, and what it was tested against.

Hagglo includes a Flutter app (apps/user) for buying, selling and chatting. It starts in demo mode with its own mock data, and two build flags point it at your server. It passed analysis and 68 tests, and builds as a debug Android package and for the iOS simulator. It was tested against the mock and API responses captured from the backend, not on physical devices and not against a live backend, so plan your own device pass.

See it in action

The video tour goes from the 3D marketing site through search, an ad, chat and offers, to selling, promoting, moderation and the admin map of districts.

Video tour of Hagglo

What else to compare

  • Reports: reports pause an ad when enough distinct verified members flag it, a dismissed report lowers the reporter's trust, and staff actions go to a log.
  • Admin: roles for admin, moderator, finance and content; categories and dynamic fields; locations; packages, orders and refunds; and reports on new ads, approval time, sold rate and revenue.
  • Languages: English, plus an Arabic translation that covers the main screens but not every string. The admin panels are English only.
  • What is not included: payments between users and delivery. Money moves only for promotions, ad packs and wallet top-ups.
  • What was not verified: the Stripe, PayPal and Razorpay drivers, push and SMS were not run with live accounts, and Lighthouse was not run.
  • Quality: Hagglo 1.0.0 shipped with 201 Pest tests (4,125 assertions), Larastan level 6 with no errors, a headless-browser pass over 134 pages and an installer test from the zip.

Instead of a live demo, the listing has 66 grouped web screenshots, 47 app screenshots and two video tours, and the "How it's built" section explains the architecture.

Frequently asked questions

The complete source code (version 1.0.0) as a download from your account, with the setup and usage guides shown on this page. You can modify the code to suit your product.

Buying guides: Laravel scripts with Filament panels and a web installer · Next.js or Laravel for a SaaS script?

More from this author

View all

Related in Web Scripts & Software

View all