zaflache
live · checked 15:50A classifieds portal for a city: listings, companies and services in one place, with a phone app on its way to the stores.
Screenshots
01044 screens · test data
Left and right arrow keys switch the item shown on the stage.
Item 1 of 4: Homepage

Homepage
zaflache homepage: AI-powered search and listing categories, September 2026
Company profile
Company profile in zaflache, test data, September 2026
Moderation
Moderation screen in zaflache, test data, September 2026
Alerts
Alerts and notifications in zaflache, test data, September 2026
Four screens from our own test copy, filled with made-up data; no phone frames around them, no retouching.
Technologies: React · TypeScript · Vite · Supabase (PostgreSQL) · Capacitor · Tailwind
Under the hood
Ten parts that keep the system running. Each one has a name, so you can ask about it by name when you describe your own project.
0106
Ten parts under the hood
011010 parts · each with a name you can quote
Left and right arrow keys switch the item shown on the stage.
Item 1 of 10: Accounts and roles
Accounts and roles
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Company profiles
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Moderation in three layers
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Reports and appeals
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Listing-writing assistant
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Import from spreadsheets
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Public connection for partners
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Signed automatic notifications
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Showing up in Google, even as one single app
- Status
- live
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Phone app
- Status
- in progress
- System
- zaflache
- Address
- zaflache.pl
ask about this part when you describe your project · Describe your project →
Accounts and roles
Roles from ordinary user, through company and moderator, up to administrator. The permission rules sit in the database on every table, so no screen and no small program will show someone else's data, even if the check is forgotten in the code.
Company profiles
A company sets up a profile with its tax number; we check that number against the official VAT register before the badge is granted. The profile has a team with roles and a publishing calendar, so several people can run one company's listings without sharing a password.
Moderation in three layers
Automatic rules stop the obvious violations, an AI model rates text and photos, and a person decides the borderline cases. Every layer writes down its reason, so the next one does not start from scratch.
Reports and appeals
Every moderation decision carries a reason visible to the author and an appeal path with a deadline, as the Digital Services Act (DSA) requires. AI-generated content is labelled at publication.
Listing-writing assistant
It helps write the text, suggests a price based on similar listings and drafts a listing from a photo. The result always goes to editing, never straight to publication.
Import from spreadsheets
A company uploads a spreadsheet file; before anything is saved we list the mistakes row by row, and nothing is saved until the whole file is clean.
Public connection for partners
A partner signs in without ever seeing a password, the access pass is swapped for a fresh one on a cycle, and each partner has a cap on how often it may ask. FufuTool uses the same connection; we wrote down what it promises as if dealing with an outside company, with a version and a date on every change.
Signed automatic notifications
A partner learns that a listing changed from a message carrying the time it was sent and a signature only the two of us can produce. A delivery that fails is tried again after a longer and longer wait, and every attempt stays visible in the log.
Showing up in Google, even as one single app
The server sends every listing page out complete, with its own title, description and marked-up details, plus a map of the site holding the date each page changed and the one address that counts as real. Google then lists them like pages of an ordinary site.
Phone app
Android and iPhone from one set of code, talking to the same connection as the website. Test builds work; getting into the stores is still in progress.
How it works
One diagram and two short pieces of code. They show the pattern, not the code that runs the live version: no addresses, no identifiers, no service names.
0206
Diagram
- New listing
- Rules
- AI rating
- Human
- Published
- Partners
moderation: three layers
Pieces of code
An author edits only their own listings, a moderator sees only the reported ones; the limit lives in the database, independent of the application code.
-- The database guards access: the rule applies to every question asked of it,
-- including one the application code knows nothing about.
alter table ogloszenia enable row level security;
create policy autor_edytuje_swoje on ogloszenia
for update to authenticated
using (autor_id = auth.uid())
with check (autor_id = auth.uid());
create policy moderator_widzi_zgloszone on ogloszenia
for select to authenticated
using (ma_role('moderator') and stan = 'zgloszone');Every message carries the time it was sent and a signature of its contents; the receiver throws away anything stale or signed differently.
// Each message to a partner carries the time it was sent and a signature.
// The receiver rejects one older than five minutes or signed otherwise.
export function podpiszWebhook(tresc: string, sekret: string, teraz = Date.now()) {
const znacznik = Math.floor(teraz / 1000)
const podpis = createHmac('sha256', sekret)
.update(znacznik + '.' + tresc)
.digest('hex')
return { 'X-Podpis': 't=' + znacznik + ',v1=' + podpis }
}Three decisions
Decisions we made in this system and would make the same way in yours.
0306
Three decisions from this system
01033 decisions · the same way in your project
Left and right arrow keys switch the item shown on the stage.
Item 1 of 3: We treat our own system like an outside company
We treat our own system like an outside company
- Risk
- a database shortcut between our own systems
- Decision
- a written, versioned promise and a secret that gets swapped
- Not done
- no master key, no shared database
zaflache · technical details below the scene
The company badge only after the tax check
- Risk
- a "company" badge with nothing behind it
- Decision
- tax number checked at sign-up and on a cycle
- Not done
- no account block when the register fails
zaflache · technical details below the scene
The phone app comes from the same code as the website
- Risk
- three versions of every feature, three lists of bugs
- Decision
- one set of code, the rules on the server
- Not done
- no separate connection for the app
zaflache · technical details below the scene
We treat our own system like an outside company
FufuTool connects to zaflache through the same public connection as any partner, with no shortcut through the database.
Technical details
- Context
- Both systems are ours; wiring them together straight through the database was tempting.
- Decision
- What the connection promises is written down in a document with a version number, questions and answers are exchanged in writing, and the shared secret is swapped for a new one by a set procedure; FufuTool has no access to the zaflache database.
- What we did not do
- We did not give FufuTool a master key or a shared database; there is no "special mode" for applications of our own.
The company badge only after the tax check
A company profile gets its badge once the tax number matches the official VAT register, not once the number is typed in.
Technical details
- Context
- The "company" badge builds a buyer's trust; without a check anyone could award it to themselves.
- Decision
- A check against the register when the profile is created and again on a cycle; the result and its date stored with the profile; on a mismatch the badge goes away and the profile stays.
- What we did not do
- We do not block an account when the external register fails; we keep nothing beyond the result and the date of the check.
The phone app comes from the same code as the website
Android and iPhone are built from one set of code and talk to the same connection, so a new feature reaches every screen in one release.
Technical details
- Context
- Two apps written separately for each kind of phone would have meant three versions of every feature and three lists of bugs.
- Decision
- One set of code, with phone-specific parts only where the phone insists on them (notifications, camera); the rules stay on the server side of the connection.
- What we did not do
- We did not build a separate connection just for the app, and we did not copy the checking rules into the app itself.
Numbers
Every number about the product in one place, under one date stamp.
0406
status as of 2026-09-03| What we count | Count |
|---|---|
| Recorded changes to the database layout | 292 |
| Database tables | 137 |
| Permission rules kept in the database itself | 392 |
| Server-side functions | 54 |
| Functions that check what people post | 12 |
| Phone systems served by one set of code | 2 |
What is still missing
0506
The Android and iPhone apps run as test builds, but they are not in the stores yet. Card payments do not yet take real money. We write it here so that nobody has to discover it after signing a contract.
- Android and iPhone apps in the stores.
- Card payments with real money.
What we would carry over to your project
0606
To a project with accounts, content and payments we carry over three things from zaflache:
- Permission rules kept in the database rather than in the screen code, with a review of those rules after every change to the database layout.
- A public connection with a written promise, a version number and signed notifications, ready for the partner who turns up later.
- Checking what people post, and the legal duties around it (a reason, an appeal, a label on anything written with AI), built in from day one rather than patched in after a letter from a lawyer.