FufuTool
live · checked 15:50One listing, one screen, many portals. Today it publishes to zaflache, Allegro and OLX; Otomoto is still in progress.
Screenshots
01044 screens · test data
Left and right arrow keys switch the item shown on the stage.
Item 1 of 4: Homepage

Homepage
FufuTool homepage: one listing published to many portals, with a publication status preview, September 2026
Background jobs
The list of background jobs in FufuTool, test data, September 2026
Automations
"When... then..." rules in FufuTool, test data, September 2026
Status
FufuTool status page, public data, September 2026
Four screens from our own test copy, filled with made-up data; no phone frames around them, no retouching.
Technologies: Next.js · React · TypeScript · Supabase (PostgreSQL) · Stripe · 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: Wizard with a list of gaps
Wizard with a list of gaps
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Team and the list of background jobs
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Three layers of duplicate protection
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Plug-ins for Allegro and zaflache
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Stripe payments
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
"When... then..." rules
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Price autopilot
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Photo drop with a QR code
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Connection to ChatGPT and Claude
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Backups and status page
- Status
- live
- System
- FufuTool
- Address
- fufutool.pl
ask about this part when you describe your project · Describe your project →
Wizard with a list of gaps
The listing form knows each portal's requirements and, before publication, names what is missing and for which portal. That section is usually empty, because we ask for everything once.
Team and the list of background jobs
An account is split into work areas with roles; every order (publish, update, withdraw) is written into a waiting list in the database, tried again after a longer and longer wait, and visible on screen with the full history of attempts.
Three layers of duplicate protection
A fingerprint of the request itself (the technical name: an idempotency key), a lock on the row while a job is being taken, and a question to the portal before anything is sent. On Allegro a duplicate is a paid listing, so no layer here is optional.
Plug-ins for Allegro and zaflache
Every portal gets a plug-in with the same fixed set of functions: matching the fields, categories, photos, publishing, state. Allegro through its official connection with a password-free sign-in, zaflache through the partner connection, OLX through its own plug-in. Otomoto waits on a partner agreement and on access.
Stripe payments
Plans are billed in Stripe with real money; the signed messages Stripe sends back are handled on the server, and a change of plan is recorded only once the payment is confirmed.
"When... then..." rules
Rules such as "when a listing does not sell within two weeks, lower the price" can be rehearsed: they show what they would do before they do it.
Price autopilot
The price changes on a schedule the user sets, never below a floor and never above a ceiling, with a log of every change and a way back.
Photo drop with a QR code
A QR code on screen opens, on the phone, an upload page for one specific listing, with no sign-in and no install; the link expires.
Connection to ChatGPT and Claude
A set of tools (the technical name: MCP) lets you start a draft listing, pick a category and check whether it is ready from inside an AI assistant; publishing still needs a confirmation on screen.
Backups and status page
A daily copy of the database, one copy loaded back on 29 August 2026 to prove it works, and a public page showing whether the system is up, with a history of past outages. An outage is visible before a customer writes about it.
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
- Listing form
- Jobs waiting
- zaflache ●Allegro ●OLX ●Otomoto ◐
portal plug-ins
● working today · ◐ in preparation
Pieces of code
Ordering the same publication twice returns the job that already exists instead of making a new one; the fingerprint comes from the content, not from the clock.
// The fingerprint comes from the order itself, not from the clock.
// A second order with the same fingerprint returns the job that exists.
export async function zlecPublikacje(
baza: Baza, ogloszenieId: string, portal: Portal,
): Promise<Zadanie> {
const klucz = skrotIdempotencji({ ogloszenieId, portal, operacja: 'publikacja' })
const istniejace = await baza.zadania.znajdzPoKluczu(klucz)
if (istniejace && istniejace.stan !== 'blad') {
return istniejace
}
return baza.zadania.dodaj({ klucz, typ: 'publikacja', ogloszenieId, portal })
}A background worker takes one job and locks its row; the other background workers skip that row instead of waiting for it.
-- One background worker takes one job; the others skip the locked row
-- instead of waiting for it to be released.
update zadania
set stan = 'w_toku', pobrano_o = now(), proby = proby + 1
where id = (
select id from zadania
where stan = 'oczekuje' and uruchom_po <= now()
order by uruchom_po
limit 1
for update skip locked
)
returning id, typ, ladunek;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: A change reaches the portals after a delay you can call back
A change reaches the portals after a delay you can call back
- Risk
- a typo on several portals at once costs money
- Decision
- saved at once, sent after the "Undo" window
- Not done
- no "send now" by default
FufuTool · technical details below the scene
A rule shows first and acts second
- Risk
- a pricing rule reprices the whole account in a minute
- Decision
- rehearsal by default, going live is a separate click
- Not done
- no rules running unseen, with no log
FufuTool · technical details below the scene
One fixed set of functions for every portal
- Risk
- every portal's own quirks end up in the form code
- Decision
- one shape for every plug-in, with tests
- Not done
- no Otomoto plug-in without access
FufuTool · technical details below the scene
A change reaches the portals after a delay you can call back
Once an edit is saved the user gets an "Undo" window; only after it closes does the job go into the waiting list.
Technical details
- Context
- Editing a listing on several portals at once means several paid or capped operations; a typo costs money.
- Decision
- Saved on our side at once, sent to the portals after a window in which it can be called back; the waiting job carries the time it may run from.
- What we did not do
- We did not make "send now" the default; we do not hide the delay either, it is there on screen.
A rule shows first and acts second
Every "when... then..." rule can be rehearsed, and the rehearsal lists the items it would touch.
Technical details
- Context
- A pricing rule let loose on a whole account can change the price of every listing in a minute.
- Decision
- A new rule starts in rehearsal mode; the result of the rehearsal is kept next to the rule; switching it on for real takes a separate click.
- What we did not do
- No rule runs "in the background" without a log, and no change exists that cannot be traced back to a rule.
One fixed set of functions for every portal
A portal is a plug-in with a fixed set of operations, so adding a portal changes neither the form, nor the waiting list, nor the screens.
Technical details
- Context
- Every portal connects differently, sorts things into different categories and sets different limits; without one fixed set of functions each of them would end up inside the form's own code.
- Decision
- One shape every plug-in has to keep (matching fields, checking, publishing, state, withdrawal), tests that prove each plug-in keeps it, and the portal's own test version wherever it offers one.
- What we did not do
- We did not write the Otomoto plug-in without access; we mark it as in progress and say so plainly.
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 | 97 |
| Database tables | 68 |
| Permission rules kept in the database itself | 101 |
| Test cases | 2,010 |
| Test files | 222 |
| Kinds of job the system runs in the background | 15 |
| Tools for connecting to ChatGPT and Claude | 9 |
What is still missing
0506
Otomoto does not publish; it waits on a partner agreement and on access we do not have yet. InPost labels wait on the real access keys. Until that changes both carry the "in progress" stamp, exactly as in the table on the home page.
- Otomoto (dependent on a partner agreement).
- InPost labels (the real access keys are not set yet).
What we would carry over to your project
0606
To a program for running orders, or to a connection between systems, we carry over three things from FufuTool:
- A list of background jobs kept in the database, with a second attempt after a failure and a fingerprint on every request, so that a dropped connection does not cost you a doubled operation.
- One fixed shape for every outside system we plug in (a warehouse and accounting system, a courier, a portal), with tests that prove the shape holds and a rehearsal mode.
- A release with a way back: a copy before it, the new version running next to the live one, and a check that the main screens open after it.