Poxtal turns the places you visit into seals in a digital passport, and your photos into virtual postcards that you can print or send virtually through Poxtal.
Watcher mode lets you follow a loved one's posts without interacting. It is completely optional.
Without this, no one could impersonate you.
You can explore and create, but no one sees your activity until you are approved.
Point the camera at the QR the other person is showing you.
Select the spot where you will leave it physically — it is marked as delivered there.
Place up to 5 emojis and 5 stickers or GIFs on the back. You decide where they go and how big they are.
All messages are deleted for both of you — neither you nor the other person will be able to see them again. This cannot be undone.
poxtal-postcards (dragging the whole folder in the Cloudflare panel), following the path the import file indicates — then paste here the JSON you were given, and confirm.This does not count as one of your 3 messages of the day. It is sent immediately, marked as urgent, and alerts the other person even if they have notifications muted.
Point the camera at the QR shown at the place.
This seal needs a photo of the place — an administrator reviews it before giving it to you.
You were randomly selected because you are verified and have no relationship with this person. Your vote is anonymous and cannot be changed.
Your report is confidential. The other person does not see who sent it.
The face is a "special category of data" (GDPR Art. 9). Accepting general terms is not enough: you need its own checkbox, unchecked by default, specific to biometrics — as is done in the face verification step.
Only the mathematical vector of your face is stored (irreversible, your photo cannot be reconstructed from it), never the original image after processing. Same for location: the city/coordinate of the moment is stored, not a permanent movement history.
You can ask for your face vector and personal data to be deleted at any time (GDPR Art. 17). You can also request a copy of everything Poxtal has about you in a readable format (GDPR Art. 20). This must be resolved within 30 days at most.
If you close your account or request deletion, the biometric vector is deleted permanently and irreversibly, not just "hidden". BIPA requires deleting biometric data at most 3 years after the last interaction, or sooner if the user requests it — Poxtal must obey the shorter limit of the two.
Biometric data is never sold, leased or used for advertising — this is explicitly forbidden by BIPA and is bad practice under GDPR. It is only used for the exact purpose for which you gave consent: verifying that you are you.
All personal and biometric data must travel encrypted (HTTPS/TLS) and be stored encrypted at rest on the server — never in plain text. Passwords are already stored this way (PBKDF2 with salt, 100,000 iterations), and all communication with the server goes over HTTPS.
Processing the biometrics of minors requires verifiable parental consent (GDPR Art. 8, and laws such as COPPA in the US) — Poxtal needs real age verification before allowing registration.
Poxtal already has a real server: passwords are stored encrypted (PBKDF2), account verification is confirmed by email with a one-time code, and real postcards, seals and cards are stored and validated on the server side, not on the phone. What does not exist yet is real face recognition (it needs a GPU server, documented separately) — in the meantime, that specific step remains a visual simulation, and is marked as such in the app.
Upload a photo of your document (ID card, passport, license). It is reviewed only once and replaces the guarantee of your 3 contacts.
Your profile photo becomes a vector of 128-512 numbers (a face "embedding", with a model such as FaceNet or ArcFace) that describes your features, not the image itself. Every time you re-verify, another vector is generated and compared by cosine similarity: if the result exceeds ~0.6-0.7, it is the same person. The original photo is never stored identically twice — only the vector, and encrypted. This runs on a GPU server, not in the browser.
So that no one uses a printed photo or a screen instead of a real face, a random challenge is requested at that moment: blink, turn your head, or smile, while the camera records for a few seconds. The model verifies that there is real 3D movement (not a flat image). Without this, any stolen photo would be enough to pretend to be someone.
If the phone already has a fingerprint reader, the system's Face ID / native fingerprint is used (Android BiometricPrompt, iOS LocalAuthentication) — the app never sees the fingerprint, it only receives a "yes/no" from the operating system. If the device has no fingerprint sensor, the real replacement is not "photographing the finger" (a fingerprint cannot be reliably verified that way) — the right replacement is using the same face recognition from step 1 as the only biometric factor, strengthened by the liveness challenge from step 2. It is safer than trying to simulate a fingerprint with a camera.
3 signals are crossed; none is enough alone, but together they reveal the pattern:
• Device Fingerprint: hash generated from Canvas/WebGL fingerprint + hardware IDs (native: identifierForVendor on iOS, Android ID) — if the same device creates 2+ accounts, it is flagged.
• Grouping by Location: many new accounts activated from almost identical GPS coordinates in a short time is the classic signal of an "account farm".
• The Face Embedding from Step 1: if two different profiles have face vectors with similarity above ~0.9, it is almost certainly the same face with two identities — automatic block until human review.
Instead of an annoying CAPTCHA, the behavior is measured: typing speed, mouse/finger movement, time between registration steps. A perfectly uniform pattern (typical of a script) adds suspicion points. Since this registration ALREADY requires a real camera + liveness challenge + 3 approving contacts, a bot cannot pass on its own — it would need a real person behind it, which defeats the purpose of a mass bot.
Real face recognition needs a trained AI model running on a server with a GPU — a browser cannot do it reliably or securely on its own (someone could manipulate the client-side code). This screen is the exact specification for when Poxtal has that server — the prototype simulates the flow and the screens, not the AI model itself.
No web browser has a way to prevent a screenshot — it is a design decision by Apple/Google/Microsoft, not something a page's code can avoid. Only a native app can request it: on Android, the flag FLAG_SECURE makes the screen appear black in any capture or recording; on iOS you cannot block the capture itself, but you can detect when it happened (UIScreen.capturedDidChangeNotification) and react (warn the other user, momentarily darken). In this web prototype, the only honest action possible is disabling "save image" on right-click/long-press — a small friction, not a real barrier.
Every uploaded photo becomes a perceptual hash (pHash or similar) — it is not like a normal hash, but one that gives similar values to similar images. When a photo is uploaded, the server compares its hash against all photos already existing at the same place:
• Different Angles of the Same Place (without being the same photo) accepted normally, everyone has their own memory of the place.
• Very Similar (slight edit, crop, filter) rejected as new valid photos — it does not count as "your" original photo.
• Identical the exact date of upload and the quality (resolution, if it has its own EXIF) of each copy are stored. The oldest and best-quality one wins — that one stays as the original, the others are deleted from the account that uploaded them later.
If an account has 3 photos disabled for this reason, it is banned automatically for impersonation — as severe as the rest of the app's anti-fraud rules.
But the real situation of someone whose OWN photo was stolen and who has no way to prove it (they lost it, they don't have the original) is considered. For that there is an appeal to the community: they can ask their own verified contacts to attest that the photo is theirs — such a situation is studied separately, it is not solved by the hash alone. The goal is to prioritize the truth, not just the date.
Identity Table (what already exists: face, social circle, ban) decides who you are and what you can do. Transport Table (this one) decides how the information travels — it never knows or cares who you are, it only moves encrypted packets from one node to another. Strict Rule: a failure in the Transport Table (no signal, a failed node, a corrupted packet) can never freeze, block or affect what the user sees or does in the Identity Table — it runs in a separate process/thread (background service), with its own error caught and isolated there. And conversely: nothing that happens in the Identity Table (opening a photo, navigating, verifying your profile) can halt a send that is already traveling through the mesh network.
Every packet is processed one by one, never all-or-nothing: if one fails, the others still get through. Without a connection, the send is stored locally and stays visible as "pending" (the user is never lied to by saying "sent" if it didn't leave). As soon as the signal returns, it is retried automatically until delivery is confirmed — with per-item retry and without blocking the interface in the meantime.
It automatically selects the best available channel, in this order: 1) Bluetooth LE (CoreBluetooth on iOS, BLE API on Android — both allow the app to advertise itself as a "peripheral", something a browser can never do). 2) Ultrasound as a fallback when there is no Bluetooth nearby: the data is encoded as sounds of 17kHz (bit 0) and 18kHz (bit 1), inaudible, emitted by the speaker and read by the other phone's microphone at a short distance.
Every packet carries a TTL of 7 hops. If the message is not for you and the TTL is greater than 0, you re-send it to the nodes you have nearby (with a small random delay of 200-400ms to avoid collisions). If the destination is not connected, the packet is kept in a local queue and re-sent as soon as a new node appears. A temporary memory of already-seen messages prevents a packet from bouncing in an infinite loop.
Shared routes, bond activation, community review requests, and photos (fragmented into ~20KB chunks). Everything encrypted end to end — the mesh network can never read the content, it only transports it.
It works in the background (background service on Android, Background Modes: bluetooth-central + bluetooth-peripheral on iOS). The user keeps using the app normally; they never see the re-sending, except for the discreet indicator at the top.
A browser can only be Bluetooth "central" (connect to an already-existing device), never "peripheral" (advertise itself so others can find it) — it is a security restriction of the Web Bluetooth specification, not of this app. A native app is needed (Swift/CoreBluetooth on iOS, Kotlin/BLE on Android) for this architecture to really work.
The idea: that an app update spreads from phone to phone via Bluetooth/mesh network, like postcards, without each person needing internet to receive it. This is real and already exists in other contexts (such as some packages being updated on poor-connection networks) — but on the web it is impossible by design: a browser can never rewrite its own source code via Bluetooth, every code change must come from an HTTPS download from the server. In the native app it would indeed be possible: the first phone that has internet downloads the cryptographically signed update and relays it via BLE to the next one, which verifies it against the signature before installing it — never executing code that Poxtal did not sign.
Upload a photo, or take a new one with the camera.
Place seal obtained automatically when you visit this place. Seals cannot be modified.
Do you want to send this card to one of your contacts?
You have been 12 hours at this place. Do you want to open and accept it? It tells a fact about the person or the reason this place exists.
Choose whether the front of the postcard will be a real photo from your album or a postcard you already collected.
Select your photo — then complete the stamp box, required before uploading.