DEV Community

Daniel Ioni
Daniel Ioni

Posted on

Why I Built a Separate NFT Template for MyZubster (and How It Integrates)

Why I Built a Separate NFT Template for MyZubster (and How It Integrates)

The Problem: Monero Doesn't Have Native NFTs

Monero is the gold standard for private, fungible cryptocurrency. Its blockchain is designed to be untraceable and confidential – which is exactly what makes it great for payments, but also what makes it incompatible with traditional NFTs.

When I started building MyZubster, I wanted to add NFT functionality to the platform. But I faced a fundamental challenge: Monero doesn't support NFTs natively.

Enter Tari – Monero's official sidechain designed specifically for digital assets like NFTs, tickets, and loyalty points.

The Solution: Tari, Monero's Official Sidechain

Tari is a merge-mined sidechain to Monero, built by ex-Monero maintainers. It offers:

  • Privacy by default (MimbleWimble protocol)
  • Smart contract support (via templates in Rust)
  • Security inherited from Monero's mining network
  • Scalability with a two-token model (XTM for mining, XTR for dApps)

This made Tari the obvious choice for MyZubster's NFT functionality.

The Decision: Why a Separate Template?

I could have embedded the NFT logic directly into MyZubster's backend. Instead, I chose to build a separate, standalone NFT template called tari-nft-template. Here's why:

1. Reusability Across Projects

The template is not tied to MyZubster. Any developer or project can use it to create NFT collections on Tari, without having to adopt the entire MyZubster ecosystem.


bash
docker pull myzubster/tari-nft-template:latest
2. Easier Testing and Maintenance

A focused codebase is easier to test, debug, and maintain. The template is written in Rust with tari_template_lib, and follows a clean, minimal API:
rust

pub fn new(name: String, symbol: String) -> Component<Self> {
    let nft_resource = ResourceBuilder::non_fungible()
        .metadata("name", name.clone())
        .metadata("symbol", symbol.clone())
        .metadata("description", "A Tari NFT Collection")
        .build();
    // ...
}

pub fn mint(&mut self, id: NonFungibleId, immutable_data: String, mutable_data: String) -> Bucket {
    let manager = self.nft_vault.get_resource_manager();
    // ...
}

3. Open Source for the Community

By keeping the template public and open-source (BSD-3-Clause), I'm contributing back to the Tari and Monero ecosystem. Other developers can:

    Fork it for their own projects

    Contribute improvements and bug fixes

    Learn from the implementation

4. Separation of Concerns

MyZubster is a complex ecosystem with:

    A skills marketplace

    A payment gateway

    An Android app

    An admin panel

    A React dashboard

Adding NFT logic directly into the monolith would have made the codebase harder to manage. By keeping the NFT logic separate, I can:

    Update the NFT template independently

    Roll back changes without affecting the rest of MyZubster

    Reuse the same template in future projects

5. Dockerized for Easy Deployment

The template is containerized and published on Docker Hub:
yaml

services:
  backend:
    image: myzubster/tari-nft-template:latest
    ports:
      - "8080:8080"

This makes it plug-and-play for any developer.
How It Integrates with MyZubster

The integration is designed to be seamless, following a microservices-inspired approach:
Architecture Overview
text

[React Frontend] → [Gateway API] → [Rust NFT Template (Docker)]
                       ↓
                 [Marketplace API]
                       ↓
                 [SQLite Database]

1. The Template Exposes a REST API

The Rust backend (tari-nft-template) runs as a standalone service, exposing HTTP endpoints:
rust

// src/api.rs
async fn get_orders(State(state): State<AppState>) -> Json<serde_json::Value> {
    // Fetch orders from SQLite
    Json(json!({ "orders": orders }))
}

2. The Gateway Routes NFT Requests

MyZubster's Node.js gateway (gateway/) acts as a reverse proxy:
javascript

app.use('/api/nft', require('./routes/nft'));

3. The Frontend Calls the Gateway

The React dashboard (myzubster-frontend/) calls the gateway's /api/nft endpoints:
typescript

const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';

const response = await fetch(`${API_URL}/api/nft/mint`, {
    method: 'POST',
    body: JSON.stringify({ id, immutableData, mutableData }),
});

4. The Mobile App (Android) Uses the Same APIs

The Kotlin app (myzubster/) also calls the gateway, ensuring consistency across platforms:
kotlin

// Android (Kotlin)
val response = client.get("http://localhost:4000/api/nft/collections")

Benefits for the Community

By separating the NFT template, I've created a public good that benefits the entire Tari ecosystem:
1. A Ready-to-Use NFT Template

Developers can launch their own NFT collections on Tari in minutes:
bash

git clone https://github.com/DanielIoni-creator/tari-nft-template.git
cd tari-nft-template
cargo build
docker build -t my-nft .
docker run -p 8080:8080 my-nft

2. A Reference Implementation

The template serves as a learning resource for developers new to Tari and Rust smart contracts.
3. A Testbed for Innovation

The template is a sandbox where developers can experiment with new NFT features (royalties, whitelist, limited editions) without affecting their main projects.
4. Cross-Project Compatibility

Because the template is decoupled, it can be integrated into any project – not just MyZubster.
Repository Structure

The MyZubster ecosystem is organized as follows:
Repository  Purpose Visibility
MyZubster   Main ecosystem (private)    🔒 Private
tari-nft-template   NFT template for Tari   🌍 Public
myzubster-assets    Images and resources    🌍 Public
myzubster   Android app (Kotlin)    🌍 Public (fork)
Future Development
Feature Status  Timeline
NFT Royalties   📝 Planned    Q3 2026
Whitelist Minting   📝 Planned    Q3 2026
Batch Minting   🔬 Research   Q4 2026
IPFS Metadata   🔬 Research   Q4 2026
Conclusion

Building a separate NFT template for MyZubster wasn't just a technical decision – it was a strategic one. It allowed me to:

    Keep the codebase maintainable

    Contribute back to the Tari community

    Enable reusability across projects

    Create a public good that outlasts MyZubster itself

If you're building on Tari or Monero, I hope this template serves as a useful starting point. And if you're curious about the integration, feel free to explore the code, open an issue, or reach out.
📬 Connect with Me

    📖 Dev.to: https://dev.to/danielioni

    🐦 Twitter: https://x.com/myzubster

    💼 LinkedIn: https://linkedin.com/in/daniel-ioni-62b2b9423/

    🐙 GitHub: https://github.com/DanielIoni-creator

Built with ❤️ for the Monero and Tari community.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)