A decentralized permit platform that lets citizens upload building documents (PDFs), track their permit status, and — after approval — publish verifiable permit records on-chain, generate QR evidence, mint NFTs, and optionally launch property tokens for community investment.
Inspiration
A small story When a young family in our neighborhood waited months for a simple renovation permit, they lost savings, time, and sleep. The father missed work to chase clerks; the mother worried whether the project would ever be approved. That frustration — the human cost of slow bureaucracy — is why we built Web3 Building Permit. We wanted an open, auditable, and grief-free way for people to prove the legitimacy of a permit and unlock new ways to fund and share the value of property projects.
Why this matters Traditional permitting is opaque and centralized. This delays projects, enables disputes, and blocks alternative financing. By using cryptographic proofs, IPFS storage and blockchain anchors, we reduce friction, increase trust, and create new financial pipelines (NFTs / property tokens) for developers and communities.
What it does
Core user flows
- Submit Permit: User fills Owner Name and Property Location, uploads PDF-only documents, and submits.
- Track Permit Status: Applicants can check permit progress (Pending / Approved / Rejected) via permit ID.
- Admin Review: Admin panel lists all permits; admin can Approve or Reject. Approvals kick off encryption, IPFS upload, and on-chain registration.
Post-approval features
- Secure Storage: Files are AES-GCM encrypted, uploaded to IPFS (Pinata). The AES key is stored per-permit (Base64 or wrapped with RSA if needed).
- On-Chain Record: A short permit record (owner, location, IPFS CID, tx hash) is stored on-chain (Sepolia testnet in demo).
- QR & NFT: App generates QR PNGs containing permit verification text + visible permit ID; metadata is saved locally. Optionally mint NFT with that metadata.
- Optional Funding: After tokenization, the project owner can open a token sale (ERC-20 coin launch) tied to the approved permit — enabling community investment.
How it works (technical breakdown)
Frontend
- Stack: HTML + Bootstrap (responsive), small JS modules using Fetch API for async requests.
- UX: Single-page admin & applicant flows, immediate feedback on upload, permit list, and one-click decrypt & download.
Backend
Framework: Flask endpoints for:
/submit_permit— handle uploads, store temp file, create log entry./update_permit_status/<id>— Approve/Reject; on approve it encrypts file, uploads to IPFS, stores AES key and on-chain info./get_logged_permitsand/track_permit/<id>— return permit log or single permit status./generate_qrs,/qr_gallery— QR generation and UI for QR gallery./nft_mint/<id>— mint NFT using local metadata or third-party SDK.
Storage & Files
- Local logs:
permit_log.jsonholds all permit metadata and statuses (persisted). - Static assets: QR images saved under
static/qrcodes/permit_<id>.png. Metadata JSON saved understatic/metadata/. - IPFS: AES-encrypted file uploaded to Pinata; result CID stored in
permit_log.jsonand on-chain.
Encryption & Keys
- Encryption: AES-GCM (AES-256 with 12-byte IV). Ciphertext stored as
iv + ciphertext. - Key handling: AES key optionally wrapped with admin RSA public key (OAEP/SHA256) or stored Base64 depending on your security model.
Blockchain & NFT
- Smart contract: Simple
PermitNFTcontract (ERC721-based) deployed to Sepolia for demo minting. - Mint flow: Generate metadata JSON with
imagepointing to QR image hosted on IPFS or local static, then call the contractmintNFT(to, tokenURI). - Optional: ERC-20 token factory for property coins or using third-party NFT lazy-minting via Alchemy/Thirdweb.
Architecture diagram (conceptual)
- User → Upload PDF → Flask
/submit_permit→permit_log.json(Pending). - Admin →
/update_permit_status/<id>Approve → Encrypt file → Upload to IPFS → Savecid&ipfs_url→ Store on-chain (tx_hash). - Server → Generate QR + metadata → Optionally mint NFT using
tokenURI(metadata path or IPFS). - Optional: Deploy ERC-20 token and open sale UI to let the public buy project tokens.
Security considerations
- Encryption: AES-GCM ensures confidentiality and integrity for stored documents. IVs are unique per file.
- Key storage: Never commit private keys to repo. Use RSA wrapping for AES keys if you want admin-only unwrapping. Or keep AES keys ephemeral and provide secure admin tools to decrypt locally.
- On-chain exposure: Only store small, non-sensitive permit metadata on-chain (CID, hashes, minimal fields). Large docs remain off-chain encrypted.
- Server hardening: Use HTTPS (Let's Encrypt), proper file permissions for
static/and logs, and run Flask behind Gunicorn + systemd + Nginx.
UX & design highlights
- Responsive layout (Bootstrap) for mobile-friendly uploads and admin actions.
- Progress indicators for uploads & IPFS pinning.
- One-click decrypt & download that performs AES-GCM decryption in the browser using the stored AES key.
- QR images include a visible Permit ID below the code for human readability.
Challenges we ran into
- Key handling trade-offs: Balancing developer convenience (Base64 AES keys stored in log) vs production security (RSA key wrapping).
- Solidity/imports: Getting OpenZeppelin imports to compile in local solc (
node_modulesvs single-file flattening). - RPC & gas issues: Handling
replacement transaction underpricedandalready knownerrors; managing nonces and gas price strategy. - Static serving: Nginx permission issues for
static/qrcodes(file ownership + SELinux / user permissions bugs on deployment). - Python environment: Library compatibility pitfalls (web3, eth-abi, third-party SDKs) across Python versions.
Accomplishments we’re proud of
- End-to-end encrypted upload → IPFS → on-chain flow.
- Auto QR generation with visible IDs (skip-regeneration if files exist).
- Local metadata generation and successful NFT minting on Sepolia.
- Production-ready deployment setup: Gunicorn + systemd + Nginx with static aliasing.
- UX features: decrypt in-browser, copy wrapped key, toast messages, mobile UI.
What we learned
- Real-world web3 is as much about tooling (solc, ABI, RPC providers) as about smart contract code.
- UX matters: people need clear progress and short error messages — long stack traces confuse non-technical users.
- File permissions and server config are common deployment gotchas.
- Pinning metadata and images before minting avoids broken token URIs.
What's next / Roadmap
Short term
- Add multisig approvals for high-value permits (e.g., 2-of-3 admin signoff).
- Support IPFS fallback + metadata pinning checks.
- Add email/webhook notifications for status changes.
Mid term
- Launch an ERC-20 property token template and a minimal sale UI (buy/sell).
- Integrate on-chain escrow & vesting for investor funds raised via property tokens.
- Add KYC onboarding for token sales.
Long term
- DAO governance for community-funded projects (voting, revenue share).
- Analytics dashboard: permit volumes, tokens issued, funds raised.
- Marketplace integration to list NFTs on OpenSea (mainnet flow and metadata standards compliance).
How to demo / run online (quick)
visit - https://nebulix.tech/
Built With
- blockchain
- python
- web3
Log in or sign up for Devpost to join the conversation.