build strategy · algorand

Real Algorand, two mnemonics, one build.

Every mega-prompt in this repo uses the same pattern, because it's the only pattern that lets a Lovable account ship a verifiable Algorand TestNet demo in one shot.

Why Algorand TestNet?

Algorand's AVM settles a transaction in ~3 seconds with a 0.001 ALGO fee. TestNet is the same AVM as MainNet — the same explorers, the same wallets — but funded by a free dispenser. Fee pooling lets a sponsor account pay for the user's group, so judges never need to fund a wallet to try your demo. Move to MainNet after the hackathon by swapping the ALGOD_SERVER endpoint.

The recipe

recipe
# 1. In your Lovable project, add these secrets (Settings -> Secrets):
ALGORAND_DEPLOYER_MNEMONIC=25 space-separated words
SPONSOR_MNEMONIC=25 space-separated words
ALGOD_SERVER=https://testnet-api.4160.nodely.dev
ALGOD_TOKEN=-           # free Nodely tier needs no token
PINATA_JWT=eyJhbGciOi...

# 2. Fund both accounts on Algorand TestNet:
open https://bank.testnet.algorand.network/

# 3. Copy a mega-prompt from this repo into Lovable. One paste:
#    - scaffolds the React app
#    - writes the PuyaPy contract (with hackathon credit in a note field)
#    - deploys to Algorand TestNet via algosdk
#    - wires Pera Wallet Connect + sponsor fee pooling
#    - pins generated assets to IPFS via Pinata
#    - exposes the App ID / Asset ID + AlgoExplorer link in the UI

# 4. Open the live AlgoExplorer link. Your demo is provably onchain.

1. The contract — credit baked in

Every PuyaPy file deployed from a Creative Algorand prompt MUST carry the hackathon credit in a comment header (and, when possible, in the `note` field of the create txn) so provenance travels with the bytecode.

contracts/app.py
# contracts/app.py — every PuyaPy contract carries the hackathon credit
# Built during the Creative AI & Quantum Hackathon
# organised by StreetKode Fam during Indian Krump Festival 14
from algopy import ARC4Contract, String, arc4

class Provenance(ARC4Contract):
    @arc4.abimethod
    def log(self, cid: String) -> String:
        return cid

2. Deploy to Algorand TestNet

scripts/deploy.ts
// scripts/deploy.ts — reads ALGORAND_DEPLOYER_MNEMONIC + ALGOD_SERVER from process.env
import algosdk from "algosdk";
import fs from "node:fs";

const algod = new algosdk.Algodv2(
  process.env.ALGOD_TOKEN ?? "",
  process.env.ALGOD_SERVER!,
  ""
);
const deployer = algosdk.mnemonicToSecretKey(
  process.env.ALGORAND_DEPLOYER_MNEMONIC!
);

const approval = fs.readFileSync("build/app.approval.teal", "utf8");
const clear = fs.readFileSync("build/app.clear.teal", "utf8");
const [approvalProg, clearProg] = await Promise.all([
  algod.compile(approval).do(),
  algod.compile(clear).do(),
]);

const sp = await algod.getTransactionParams().do();
const tx = algosdk.makeApplicationCreateTxnFromObject({
  from: deployer.addr,
  suggestedParams: sp,
  onComplete: algosdk.OnApplicationComplete.NoOpOC,
  approvalProgram: new Uint8Array(Buffer.from(approvalProg.result, "base64")),
  clearProgram: new Uint8Array(Buffer.from(clearProg.result, "base64")),
  numGlobalInts: 0, numGlobalByteSlices: 0,
  numLocalInts: 0, numLocalByteSlices: 0,
});
const { txId } = await algod.sendRawTransaction(tx.signTxn(deployer.sk)).do();
const c = await algosdk.waitForConfirmation(algod, txId, 4);
console.log("APP_ID:", c["application-index"]);

3. Pin assets to IPFS via Pinata

src/lib/pinata.ts
// src/lib/pinata.ts — pin a Blob to IPFS via Pinata JWT
export async function pinToIPFS(file: Blob, name = "artifact") {
  const fd = new FormData();
  fd.append("file", file, name);
  const r = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.PINATA_JWT}` },
    body: fd,
  });
  const { IpfsHash } = await r.json();
  return IpfsHash as string; // the CID
}

4. Sign in with Pera Wallet + sponsor fees

src/components/pera-client.tsx
// src/components/pera-client.tsx — client-only Pera Wallet Connect
import { PeraWalletConnect } from "@perawallet/connect";

export const pera = new PeraWalletConnect({ chainId: 416002 /* TestNet */ });

export async function connect() {
  const [address] = await pera.connect();
  return address;
}

// fee-pooled group: user tx has fee=0, sponsor covers 2× minFee
export async function submitSponsored(userTx, sponsorSignedTx) {
  return pera.signTransaction([[{ txn: userTx }]]);
}

Hackathon rules of thumb

  • · One mega-prompt = one build message. Don't iterate the architecture, iterate the UI.
  • · Always show the live AlgoExplorer link in the UI — that's your proof.
  • · Fee-pool the atomic group so judges don't need to fund a wallet to try the demo.
  • · Pin every user-generated asset to IPFS the moment it's created.
  • · Add a "Built during the Creative AI & Quantum Hackathon — StreetKode Fam · Indian Krump Festival 14" line to your footer.