Building the Future of Web3 Freelancing: Escrow Protection, Anti-Abuse Gating, and Mobile Network Hardening on HivePostify
Over the past few weeks, HivePostify reached a point that had been in progress for a while. What started as a decentralized blogging and publishing front-end on the Hive blockchain is now growing into a Web3 freelancing and services marketplace.
More creators and freelancers are joining. Thousands of pages are already indexed across major search engines. That growth shifted the focus from publishing alone to the real problems of online hiring: security, spam, transparent escrow, and mobile performance on networks that do not behave like a clean office broadband line.
This update covers the decisions behind the latest release, the problems that showed up in production, and the code that shipped. It is not a product pitch. It is what changed.

Decoupling Services into Two Distinct Engines: Gigs vs Custom Jobs
One of the first design questions on a freelancing platform is how work should be offered. Fiverr-style products are packaged services. Upwork-style products are client requests. Those are not the same search.
The first marketplace prototype put both into one tabbed view. It looked tidy in the mock. It failed in real use. People looking for a fixed package and people looking for a custom bid were fighting the same screen.
Service Gigs (/marketplace):
Freelancer-driven. The freelancer sets fixed packages (Basic, Standard, Premium), states delivery time, and the buyer purchases a ready offer.
Job Board (/jobs):
Client-driven. The client describes a custom problem, sets a target budget in USD / AHPT, and freelancers send tailored proposals.
Putting them in one interface created clutter. Filters meant different things depending on which tab was open. They are now two discovery engines, each with its own route, search, and flow. Both still sit on the same wallet and the same escrow ledger. The split is in the product, not in the money path.
+-----------------------------------+
| HivePostify Engine |
+-----------------------------------+
|
+-------------------------+-------------------------+
| |
v v
+-----------------------+ +-------------------+
| Gigs (/marketplace) | | Jobs (/jobs) |
| - Fixed tier pricing | | - Custom RFPs |
| - Direct purchase | | - Bids & Escrow |
+-----------------------+ +-------------------+
| |
+-------------------------+-------------------------+
v
+-----------------------------+
| Postify Wallet & Escrow |
| Dynamic Settings & Ledger |
+-----------------------------+
The practical result is simpler navigation. A buyer who wants a logo package does not land in a bid board. A client who wants a custom build does not have to pretend it is a gig.
Anti-Abuse & Spam Protection: Account Verification Middleware
Open job boards attract the usual noise: scrapers, unverified accounts posting fake offers, and low-effort proposal spam. The job board should not be a place where confirmed users have to filter garbage before they can work.
The gate sits at the API route. A project cannot be published, and a proposal cannot be submitted, unless the account is confirmed. That check runs against the SignupTicket ledger before the request goes any further:
// Middleware: Verify confirmed standing before allowing jobs/proposals
async function checkUserPermission(username) {
if (!username) return { allowed: false, error: 'Authentication required' };
const ticket = await SignupTicket.findOne({
$or: [
{ hiveUsername: username.toLowerCase().trim() },
{ freshEmailUsername: username.toLowerCase().trim() }
]
});
if (!ticket) {
return { allowed: false, error: 'Account verification record not found.' };
}
// Block pending or unconfirmed trial accounts from posting or bidding
if (ticket.status !== 'confirmed') {
return {
allowed: false,
error: 'Your account is currently pending verification. Only confirmed accounts can post projects or submit proposals.'
};
}
return { allowed: true, ticket };
}
On the frontend, an Axios interceptor catches the 403 and shows a plain notice that points the user to verification. A dead button was not the goal. Trial or pending accounts posting jobs was not the goal either. Confirmed standing is the minimum bar for publishing or bidding.
Escrow Architecture: Fixed-Price Milestones & Dynamic Platform Fees
Why hourly billing was dropped
The first schema had an hourly option. After looking at how disputes actually happen, hourly billing was removed and fixed-price contracts stayed.
Hourly work either needs a desktop tracker, which does not belong on a user's machine, or it needs manual time logs, which turn into arguments. Fixed price with escrow is clearer for both sides:
- Scope and bid amount are locked before work starts.
- The agreed funds are reserved from the buyer's internal balance ($1 AHPT = $1.00 USD).
- Funds move only after the buyer checks the deliverable and approves it.
Fees come from settings, not from hardcoded controllers
Earlier builds had fee percentages written into a few controllers. That works until a number needs to change without a redeploy. The hire path (/api/jobs/proposals/:proposalId/hire) now reads MarketplaceSettings and supports a flat fee or a tiered fee:
// Dynamic Fee Calculation from centralized MarketplaceSettings
const settings = await MarketplaceSettings.findOne();
let platformFeePercentage = settings?.platformFee?.percentage || 0;
if (settings?.platformFee?.type === 'tiered' && settings.platformFee.tiers?.length > 0) {
const tier = settings.platformFee.tiers.find(
t => agreedPrice >= t.minAmount && agreedPrice <= t.maxAmount
);
if (tier) platformFeePercentage = tier.percentage;
}
const platformFee = parseFloat(((agreedPrice * platformFeePercentage) / 100).toFixed(2));
const sellerEarnings = parseFloat((agreedPrice - platformFee).toFixed(2));
The fee rule lives in one place. A percentage change does not require a new build.
Solving Real-World Mobile Networking: Conquering ERR_CONNECTION_RESET under HTTP/3
This one took longer than the marketplace split. Some users on mobile 4G/LTE, and some on iOS Safari, were hitting intermittent ERR_CONNECTION_RESET. Desktop broadband was fine. The bug only showed up on certain carrier paths.
Two things were stacking:
- Path MTU black holes. A lot of mobile networks, especially where CGNAT and LTE tunnels are in the path, run an MTU under 1500 bytes. 1420 and 1380 showed up often. Large TLS 1.3 handshakes and HTTP/3 (QUIC) datagrams were getting dropped. The routers were not sending ICMP Fragmentation Needed, so the client just saw a reset.
- Nginx header buffers. Mobile Safari sends long client hints and user-agent data. Cloudflare adds its own headers on the way in. Default
client_header_buffer_sizeof 1k was enough to reset the socket under that load.
HTTP/3 and TLS 1.3 were not turned off to hide the bug. The fix went into the kernel and the proxy:
# Enable Linux Kernel TCP MTU Probing
# Automatically detects path MTU to prevent packet drop resets
sysctl -w net.ipv4.tcp_mtu_probing=1
sysctl -w net.core.somaxconn=2048
Nginx:
# Expanded client header and proxy buffers for modern mobile browsers
client_header_buffer_size 16k;
large_client_header_buffers 8 64k;
client_body_buffer_size 128k;
proxy_buffer_size 128k;
proxy_buffers 8 256k;
proxy_busy_buffers_size 256k;
keepalive_timeout 75s;
keepalive_requests 1000;
With MTU probing on and the buffers raised, those mobile sessions stopped dropping. The page loads on the same carriers that were failing before.
Defensive UI: Preventing Layout Fragmentation
Job briefs are messy. People paste code, long URLs, and unbroken strings. A normal flex or grid card will overflow sideways if that is left unchecked.
Defensive wrapping is now on job cards and scope views:
<div
className="text-slate-700 dark:text-slate-300 leading-relaxed text-sm"
style={{
whiteSpace: 'pre-wrap',
wordBreak: 'break-word',
overflowWrap: 'anywhere'
}}
>
{job.description}
</div>
overflowWrap: 'anywhere' plus min-w-0 on the parent keeps the text inside the card. It is a small rule. It stops a single URL from breaking the layout on a phone.
What's Ahead for HivePostify
The freelancing pipeline is still in progress. Next on the list:
- Milestone-based escrow releases. Multi-week jobs should be able to pay in stages, not only at the end.
- On-chain reputation attestations. Completed ratings and feedback written into Hive custom JSON, so trust is not only inside the database.
- Deliverable file exchange. In-app upload and preview so a client can sign off without leaving the job.
Decentralized software only works if the boring parts are solid: who can post, where the money sits, and whether the site loads on a normal mobile network. Feedback from Hive developers is welcome on the split between gigs and jobs, the verification gate, and the escrow fee model.
HivePostify is live at hivepostify.com.
Feedback and collaboration are welcome in the comments.