LUKSO
No coding experience required

Build Your First LUKSO Grid Mini App

A complete beginner's guide — from zero accounts to a live, interactive app on your Universal Profile. Built with AI. No code needed.

~60 min
Time needed
3 free
Accounts required
0 lines
Code written by you
LUKSO Universal Profile Grid examples showing customized mini app layouts
1

Before You Start — Understanding The Grid

What Is The Grid?

Every Universal Profile on LUKSO has a section called The Grid. Think of it like the home screen on your phone — you can add widgets like a weather app, a clock, or a photo slideshow. The Grid works the same way, but for your blockchain identity.

The Grid is a customizable area on your Universal Profile page where you can embed mini apps — small interactive websites that live right on your profile. Anyone who visits can see and interact with them.

What Is a Mini App?

A mini app is just a website — a small one, designed to fit in a card-sized space on your Grid. Here's the good news: you don't need to know how websites work. An AI tool will build the entire thing for you based on what you tell it in plain English.

What You'll End Up With

1A custom mini app — a small website built by AI to your spec
2That app published online — live on the internet with its own URL
3That URL added to your Grid — showing on your Universal Profile

The whole journey: Build it → Publish it → Add it to your profile.

Time estimate

45–60 minutes if things go smoothly. Up to 90 if this is your first time with tools like these. Don't rush it.

One important rule: HTTPS only

Your mini app's URL must start with https:// (not http://). The Grid requires it for security. Vercel gives you HTTPS automatically.

Before You Continue, You'll Need:

A Universal Profile on LUKSO (create one free)
A Google account (for Bolt.new)
A GitHub account — github.com
A Vercel account — vercel.com
Chrome or Brave browser (required for UP Extension)
About 60–90 minutes of free time

Note: If your app uses the LUKSO Relayer API, users can transact without needing LYX for gas. Adding your mini app to the Grid still requires a small gas fee from your own account.

2

Building Your Mini App with AI

Why Bolt.new?

Everything runs in your browser — no downloads, no installation
Describe what you want in plain English and it writes all the code
See a live preview instantly as it builds
Can publish your app directly from the same window

Official LUKSO mini app template available

The LUKSO team maintains an official Next.js mini app template with up-provider, erc725.js, and web-components pre-configured.

View on GitHub →

Cursor tip: rename the template README.md to .cursorrules for better AI assistance in Cursor.

Other options like Lovable, v0, or Replit work too — Bolt.new is recommended for its zero-install browser experience and instant preview.

Getting Started

1Go to bolt.new in your browser
2Click "Sign in" and use your Google account
3You'll see a big text box — "What do you want to build?"

The Starter Prompt

Copy the entire block below and paste it into Bolt.new. Don't change anything — just paste and hit Enter.

Starter Prompt — Copy and paste into Bolt.new
Build me a single-page web app that works as a LUKSO Universal Profile mini app with wallet connection. Here are the exact requirements:

WHAT IT DOES:
- Shows a "Connect your Universal Profile" button on first load
- When clicked, it connects using the official UP Provider package
- After connecting, it reads and displays the connected user's profile: name, bio/description, and profile picture
- Also shows the connected wallet address (shortened: first 6 + last 4 chars)
- Shows follower count via the Envio indexer
- Shows a "Disconnect" button after connecting

SETUP — Install these official LUKSO packages via npm:
- @lukso/up-provider: for UP wallet connection on the Grid (EIP-1193 compatible provider)
- @erc725/erc725.js: for fetching ERC725Y profile data (decodes VerifiableURI, resolves IPFS automatically)
- @lukso/lsp-utils: for high-level helpers like getProfileMetadata()
- @lukso/web-components: for pre-built branded profile UI components (e.g. <lukso-profile-preview>)
- ethers: for blockchain interaction

Reference template: https://github.com/lukso-network/miniapp-nextjs-template

HOW TO CONNECT (using @lukso/up-provider — NOT raw window.lukso):
import { createClientUPProvider } from '@lukso/up-provider';

const provider = createClientUPProvider();
// provider is EIP-1193 compatible — works with ethers.js BrowserProvider
// To get accounts:
const accounts = await provider.request({ method: 'eth_requestAccounts' });
// accounts[0] is the connected Universal Profile address

// If provider is not available, show: "Please open this in the LUKSO Grid or install the UP Extension"
// Do NOT use window.lukso or window.ethereum directly — always use createClientUPProvider()

Reference: https://docs.lukso.tech/learn/dapp-developer/getting-started
Reference: https://www.npmjs.com/package/@lukso/up-provider

HOW TO FETCH PROFILE DATA (using @erc725/erc725.js + @lukso/lsp-utils — NOT manual ABI calls):
import { getProfileMetadata } from '@lukso/lsp-utils';

// getProfileMetadata(address, provider) returns { name, description, profileImage, backgroundImage, tags }
// It handles all ERC725Y decoding, VerifiableURI parsing, and IPFS resolution internally
// IPFS gateway: https://api.universalprofile.cloud/ipfs/

// Alternative: use ERC725.js directly for more control:
import ERC725 from '@erc725/erc725.js';
import lsp3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json';

const erc725 = new ERC725(lsp3ProfileSchema, address, 'https://rpc.mainnet.lukso.network', {
  ipfsGateway: 'https://api.universalprofile.cloud/ipfs/',
});
const profileData = await erc725.fetchData('LSP3Profile');
// profileData.value.LSP3Profile contains { name, description, profileImage, backgroundImage, tags }

// Do NOT manually call getData(bytes32[]) or decode VerifiableURI by hand — the libraries handle this.

Reference: https://docs.lukso.tech/standards/metadata-detection
Reference: https://www.npmjs.com/package/@erc725/erc725.js
Reference: https://www.npmjs.com/package/@lukso/lsp-utils

PROFILE UI (using @lukso/web-components):
import '@lukso/web-components';

// Use <lukso-profile-preview address="0x..." /> for an instant branded profile card
// The component handles fetching and rendering profile data automatically
// You can also build a custom card using the data from getProfileMetadata()

Reference: https://www.npmjs.com/package/@lukso/web-components

ALSO FETCH FOLLOWER COUNT (via Envio indexer):
// Note: The Envio indexer is currently free but may become a paid service in the future.
fetch('https://envio.lukso-mainnet.universal.tech/v1/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: `query { followerCount: Follow_aggregate(where: {followee: {_eq: "${address}"}}) { aggregate { count } } }` })
})
Reference: https://github.com/lukso-network/tools-lsp-utils

DESIGN:
- LUKSO brand colors: magenta #FE005B as accent color, dark background (#0a0a0a), white text
- Clean, modern card layout centered on the page
- Profile picture in a large circle (120px) with a subtle magenta ring
- Name in large bold font, description in smaller muted text
- Address displayed in a monospace code style with subtle background
- "Connect" button: magenta #FE005B background, white text, rounded-full, with wallet icon
- Mobile responsive
- Must work when embedded in an iframe (LUKSO Grid context)

UX DETAILS:
- Before connecting: centered connect button with LUKSO logo/icon and tagline "Connect your Universal Profile"
- After connecting: profile card slides in with avatar, name, bio, address, follower count
- Loading state: subtle pulsing skeleton while fetching profile data
- Error state: friendly message if connection fails or profile not found

Wait and Watch

1Wait 30–60 seconds. The AI is writing your entire app.
2Watch the right side of the screen — a live preview will appear.
3If the preview looks blank, click the refresh icon above the preview panel.

Customize It

Keep chatting with Bolt.new to change anything. Each message updates the code and preview instantly.

"Make the background dark and the text white"
"Make the profile picture bigger"
"Add a gradient background from black to dark purple"
"Change the font to something more modern"

If you see a profile name, description, and picture — congratulations. You just built a blockchain app without writing a single line of code.

💡 Not sure what to build?

Browse 12 community mini app ideas — from a tip jar to an NFT gallery to a live follower counter.

Mini Tip JarNFT GalleryFollower Counter+9 more
Browse Ideas →
3

Publishing Your App Online

Your app looks great in Bolt.new's preview — but that preview is temporary. To add it to your Grid, you need a permanent public URL. That's what "deploying" means: putting your app on the internet for real.

EASIESTOption A: Deploy Directly from Bolt.new
1Look for the "Deploy" button in the top-right area of Bolt.new
2Follow the prompts to connect a hosting account if asked — it's free
3Click Deploy and wait ~30 seconds
4You'll get a URL like https://your-app-name.vercel.app or similar
5Copy that URL and open it in a new tab to verify it works

✓ If this worked, skip to "Test Your URL" below.

RELIABLEOption B: Export to GitHub → Deploy on Vercel
1In Bolt.new, look for "Export to GitHub" — this saves your project to a GitHub repository
2Go to vercel.com and sign in with your GitHub account (free, no credit card)
3Click "Add New Project""Import Git Repository"
4Select the repo Bolt.new just created
5Click Deploy and wait ~1 minute. You'll get a URL like https://your-project.vercel.app

Test Your URL Before Moving On

Open the URL in a new browser tab — does it load?
Test the profile search — does it fetch LUKSO data?
Try it on your phone — does it look good on mobile?

Save your URL. Email it to yourself or put it in your notes. You'll need it in the next step.

4

Adding Your App to Your Universal Profile Grid

What You Need

🌐The UP Browser Extension installed in Chrome or Brave — search "LUKSO Universal Profile" in the Chrome Web Store
👤Your Universal Profile logged into the extension
🔗Your mini app's HTTPS URL from the previous section
💎A small amount of LYX in your profile (less than 0.01 LYX for the transaction fee)

Adding Your App via universaleverything.io

2Click "Connect" in the top-right and connect your Universal Profile via the browser extension
3Navigate to your own profile
4Scroll down to the Grid section
5Click the "Edit Grid" button or "+" icon
6Click "Add widget" or "Add mini app"
7Paste your app's URL (e.g., https://your-app.netlify.app)
8Give it a name if you'd like, and choose a size (medium is a good start)
9Click Save
10The UP Browser Extension will pop up — approve the transaction (costs less than 0.01 LYX)
11Wait ~10 seconds for the blockchain to confirm
12Refresh the page — your mini app should now appear in your Grid!

What does the transaction actually do?

When you add a mini app to your Grid, you're saving that URL directly to your Universal Profile's on-chain data. That's why the extension asks you to approve — you're writing data to the blockchain. This costs a tiny amount of LYX (gas fee).

Verify It Worked

Visit your profile on universaleverything.io
Scroll to the Grid section
Your mini app should be visible as an embedded card
Click into it — it should be fully interactive

Anyone who visits your profile now sees your mini app. You just added a custom, interactive widget to your on-chain identity. 🎉

5

Troubleshooting, Pitfalls & Next Steps

The 11 Most Common Beginner Mistakes

Save Your Work (Do This Now)

1.In Bolt.new, click the Download/Export button to save a ZIP file.
2.Go to github.com/new and create a repository called my-grid-app.
3.Upload the files from the ZIP using GitHub's "Upload files" button.
4.Your code is now safe and accessible from anywhere.

What Comes Next

Beginner
  • Static profile showcase — what this guide built
Intermediate
  • Token balance display (LSP7)
  • Live LYX price widget
  • Mini social feed from Forever Moments
  • Gasless transactions via Relayer API (no LYX needed for users)
  • @lukso/web-components profile cards
Advanced
  • Interactive tip jar (send LYX button)
  • Custom smart contract frontend
  • LSP7/LSP8 token interfaces
  • Smart contract development with lsp-smart-contracts
  • Foundry template for Solidity contracts

Mini Glossary

URLA web address — the text in your browser's address bar (like https://example.com).
DeployUploading your app to a hosting service so anyone on the internet can visit it.
Repository (Repo)A folder on GitHub that stores your project's code.
FrontendWhat users see in their browser (HTML, CSS, JavaScript) — this guide only needs frontend.
iframeA window inside a webpage that displays another webpage — how the Grid shows your mini app.
TransactionA signed action on the blockchain that costs a small fee (gas).
LYXLUKSO's native currency — needed in small amounts for transaction fees.
ERC725YThe storage system for your Universal Profile — a database attached to your profile.
LSP28The standard that defines how the Grid works on Universal Profiles.
RPC EndpointThe address your app uses to talk to the LUKSO blockchain.
6

Your First Real Build: A Profile Viewer

You've learned the full pipeline: build → deploy → add to Grid. Now let's build something that actually reads live data from LUKSO. This mini app lets anyone enter a Universal Profile address (or username) and see their name, bio, avatar, and follower count — all fetched directly from the blockchain and IPFS.

What You'll Learn

Reading ERC725Y Data
How erc725.js and lsp-utils fetch profile data from Universal Profiles
Using Official LUKSO Libraries
up-provider for wallet connection, erc725.js for data, web-components for UI
Fetching from IPFS
Retrieving profile images and metadata from decentralized storage
Displaying LSP3 Profile Data
Rendering name, bio, avatar, and social data from the LSP3 standard

How the Profile Viewer Works

1User enters a UP address (0x...) or username into the search bar
2If it's a username, resolve it to an address via the Envio GraphQL indexer
3Call getData() on the Universal Profile contract to read the LSP3Profile key (ERC725Y)
4Decode the VerifiableURI to get the IPFS link to the profile's JSON metadata
5Fetch the JSON from IPFS and display: name, bio, avatar image, and follower count
Profile Viewer Prompt — Copy and paste into Bolt.new
Build me a single-page web app that works as a LUKSO Universal Profile Viewer. Here are the exact requirements:

WHAT IT DOES:
- Shows an input field where users can enter a Universal Profile address (0x...) or a UP username
- Has a "View Profile" button that fetches and displays the profile
- Displays: profile name, bio/description, profile picture (avatar), and follower count
- Also shows the full address in a monospace code style
- Optional wallet connection button for Grid context

SETUP — Install these official LUKSO packages via npm:
- @lukso/up-provider: for UP wallet connection on the Grid (EIP-1193 compatible provider)
- @erc725/erc725.js: for fetching ERC725Y profile data (decodes VerifiableURI, resolves IPFS automatically)
- @lukso/lsp-utils: for high-level helpers like getProfileMetadata()
- @lukso/web-components: for pre-built branded profile UI components (e.g. <lukso-profile-preview>)
- ethers: for blockchain interaction

Reference template: https://github.com/lukso-network/miniapp-nextjs-template

HOW TO RESOLVE USERNAMES:
If the input doesn't start with "0x", treat it as a username and resolve it via Envio GraphQL:
// Note: The Envio indexer is currently free but may become a paid service in the future.
fetch('https://envio.lukso-mainnet.universal.tech/v1/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: `query { Profile(where: {name: {_eq: "${username}"}}) { id name } }` })
})
The "id" field in the response is the profile address.

HOW TO FETCH PROFILE DATA (using @erc725/erc725.js + @lukso/lsp-utils — NOT manual ABI calls):
import { getProfileMetadata } from '@lukso/lsp-utils';

// getProfileMetadata(address, provider) returns { name, description, profileImage, backgroundImage, tags }
// It handles all ERC725Y decoding, VerifiableURI parsing, and IPFS resolution internally
// IPFS gateway: https://api.universalprofile.cloud/ipfs/

// Alternative: use ERC725.js directly for more control:
import ERC725 from '@erc725/erc725.js';
import lsp3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json';

const erc725 = new ERC725(lsp3ProfileSchema, address, 'https://rpc.mainnet.lukso.network', {
  ipfsGateway: 'https://api.universalprofile.cloud/ipfs/',
});
const profileData = await erc725.fetchData('LSP3Profile');
// profileData.value.LSP3Profile contains { name, description, profileImage, backgroundImage, tags }

// Do NOT manually call getData(bytes32[]) or decode VerifiableURI by hand — the libraries handle this.

PROFILE UI (using @lukso/web-components):
import '@lukso/web-components';

// Use <lukso-profile-preview address="0x..." /> for an instant branded profile card
// The component handles fetching and rendering profile data automatically
// You can also build a custom card using the data from getProfileMetadata()

HOW TO FETCH FOLLOWER COUNT:
// Note: The Envio indexer is currently free but may become a paid service in the future.
fetch('https://envio.lukso-mainnet.universal.tech/v1/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: `query { followerCount: Follow_aggregate(where: {followee: {_eq: "${address}"}}) { aggregate { count } } }` })
})

OPTIONAL — WALLET CONNECTION (using @lukso/up-provider — NOT raw window.lukso):
import { createClientUPProvider } from '@lukso/up-provider';

const provider = createClientUPProvider();
// provider is EIP-1193 compatible
const accounts = await provider.request({ method: 'eth_requestAccounts' });
// When connected, auto-fill the input with accounts[0] and load their profile
// This makes it work as a Grid mini app too
// Do NOT use window.lukso or window.ethereum directly — always use createClientUPProvider()

DESIGN:
- LUKSO brand colors: magenta #FE005B as accent, dark background (#0a0a0a), white text
- Clean search bar at the top with the input and button side by side
- Profile card below: avatar in a large circle (120px) with magenta ring, name bold, bio muted, address monospace
- Follower count shown with a small people icon
- Mobile responsive, works in iframe (Grid context)
- Loading: pulsing skeleton placeholders
- Error: friendly message if profile not found

Try It Live — Find a Profile Address

Need a Universal Profile address to test with? Browse real profiles on Universal Everything to find one. Click on any profile, copy their address from the URL bar, and paste it into your Profile Viewer.

Browse Universal Profiles

Pro Tips for This Build

  • If you get CORS errors, switch the RPC to https://42.rpc.thirdweb.com
  • The IPFS gateway api.universalprofile.cloud/ipfs/{CID} is the most reliable for LUKSO profile data
  • Use @lukso/up-provider for wallet connection so it works as a Grid mini app
  • Once it works, deploy to Vercel and add it to your Grid — you've now built a real LUKSO dApp