ai-startup-skills
创业公司做 AI 产品的 7 步 Agent Skill 合集:验证 → BP → 政策 → 路演 → 获客 → 定价 → 注册。
Translation pending
A city built 24/7 by Blockies, the builders of Base. Every $10 of $BLOCKY brings a Blocky: it builds the city, and it's an NFT you claim once trading opens.
OtherGitHub @madebyshunOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A live, watch-only voxel city tied to the $BLOCKY token on Base.
$BLOCKY a wallet buys (added up per wallet) brings one Blocky to the city by blimp (usdPerBlocky in src/config.js; each buy counts at the price of its day, so changing it only affects later buys): Blocky #1, #2, ... with at most 10,000 in the city at once. A Blocky held 6 hours is a citizen: an NFT its wallet claims (BaseCity Blockies, BCB, see below). Only 10,000 NFTs can ever exist: first come, first claimed. Big buys arrive in batches. A single buy of $1,000+ also builds a Whale Fountain signed with the wallet, and jumps the build queue.$BLOCKY balance (tokens it had before count too) must cover it, so sell half of what it bought and the newest half of its newcomers leave (tokens moved away count as sold); freed places go to the next wallets in line (a waitlist once the city is full). Opening day is when unlockUsd has been bought in total (the HUD's "Bought"); it is 0, so trading opened at the first update after it was set: from then a Blocky held citizenDays (0.25: 6 hours) is a citizen for good, whatever the wallet does, and an NFT it can claim. Held tokens cover newcomers first, so citizens free the rest. Both settings can be lowered any time (lowering unlockUsd opens trading at the next update), never raised after launch.api/_names.js reads the primary name from ENS's L2 reverse registrar on Base (ENSIP-19, where names are set since 2025), else the older Basenames resolver, and only keeps names that resolve back to the wallet (the name's resolver from the Base registry, its Base address record, else its plain one). Contract addresses are in basenames in src/config.js. Names are cached in KV (new wallets right away, known ones re-checked daily) and sent with /api/colony as names.avenue in src/config.js; projects: src/projects.js): numbered plots kept for Base projects' headquarters. A free plot shows "BASE AVENUE · PLOT n · Your project's HQ here" (and adContact / xHandle, which its sign links to). Add a project with one line in src/projects.js (the file explains every field): its plot, its goal at (Blockies), the day it was added (its HQ is never built before then, so adding one never changes what the city already built), colours, style (tower, campus, spire, dome) and logo (one drawn in code, LOGOS in src/city.js, or a square image in public/logos/). Until its goal its plot shows COMING SOON; then the crew builds the HQ like a landmark, and its signs link to the project. The gallery (/gallery.html?only=hq) shows every style. Landmarks are spaced out (landmarkEvery: at most one in every 3 projects), so homes keep going up even when many goals unlock at once.whaleTiers in src/config.js): one buy of $1k+ builds a Whale Fountain, $2.5k+ a Whale Tower, $5k+ a Whale Skyscraper, ahead of everything else; towers go downtown (a free lot within 3 rings of Town Square, else in place of the oldest home, shop or office there). Each carries its whale's Basename (or address) on its crown, clickable to the wallet. The name stays while the wallet keeps at least half the Blockies it had right after the buy (CitySim.whaleNames, from departure times); sell more and the building goes dark, FOR SALE, and the next whale of its size or bigger takes it over (a new tower on that lot). The log, toasts and ticker say so.departures in src/config.js, CitySim.depart in src/sim.js): Blockies that leave take the blocks they placed on the current construction site with them (the HUD and the log say how many), so the site takes longer. A big exit, ruinAt (20) or more Blockies at the same moment, leaves the newest home, shop or office abandoned (one per 20, at most maxRuins): grey, dark, boarded up and taped off, until the crew rebuilds it as the same kind of building, ahead of everything but whale fountains. Landmarks, parks and fountains are never touched. All of it follows from the departure times, so every visitor sees the same city.sites in src/config.js) and splits the crew between them. A crew's speed grows with the square root of its skill (4× the skill = 2× faster), so smaller crews on more sites build more in total, and bigger buildings take longer by tier (buildTime in src/config.js: ×3 small, ×4 mid, ×5 large, ×6 towers and skyscrapers; landmarks, fountains, land and the metro have their own). With ~100 Blockies a cottage takes ~9 min, apartments ~1.5 h, a skyscraper ~13 h. A new city gets a head start (launchBoost): its first project takes 8% of the time and each next one a bit more, up to the full time from the 80th, so with the 100 reserve Blockies the first buildings are up in minutes and ~50 in the first day. The HUD shows the time left, the next community goal and how many of the 10,000 Blockies are left. Land expansions and landmarks unlock at Blocky counts (10, 30, 75, … for land; 15 for Builder HQ, 100 for the airport, 1,000 for the metro, …). Up to ~120 Blockies walk the streets at once (the founder, the Base Builders, the first 20 OGs, every Legendary and the newest arrivals); all of them build.legends in src/config.js (joined: 'YYYY-MM-DD' to start later). gallery.html?only=legends shows them all, ?only=Jesse,Ahaan Raizada just those. Each one is in the Blocky viewer too, by name (/b/jesse).rollSeed in src/ledger.js), so nobody can know or snipe a rare number before buying and anyone can check it afterwards: Common 70%, Uncommon 22% (Shades, Base Cap), Rare 7% (Gold Hard Hat, Laser Eyes, Astronaut), Legendary 1% (Diamond Skin, Crown). Rare ones walk the city, get a toast and fireworks when they arrive, and show on their card and PFP. Odds live in rarity in src/config.js; gallery.html?only=rare shows them./builders.html, linked from the HUD): every Base Builder's profile with a voxel PFP, title, live stats (hours building, blocks placed, share of the city, skill, building since) in a profile you can link to (/builders.html#jesse) and share on X, and a Download PFP button (1024×1024 PNG with a small BaseCity tag). Clicking any Blocky in the city shows its PFP too, so every buyer can download the Blocky their buy brought. Add x (handle) or bg (PFP colour) to a legend in src/config.js.gallery.html shows every design and Blocky side by side; ?only=blockies or ?only=coaster,ferris to zoom in.api/live.js). Each open tab checks in every 2 minutes while it's visible; visitors are a hash of their IP in Redis HyperLogLogs (one per 2 minutes, one for all time), so no address is stored, a reload counts once and random ids can't inflate it. About one KV command per viewer per 2 minutes.blocky.html, src/viewer.js, at /b/N, or /b/jesse for a Base Builder): any Blocky by its number, or a Base Builder by name (suggested as you type), head to toe in 3D (drag to turn it) doing what Blockies do in the city (src/dance.js: Idle, Walk, Run, Carry a block, Build, Wave) or a dance (Bounce, Sway, Spin, Cheer), each a loop posed on the Blocky's rig; with its rarity, trait, role, status, owner, arrival and blocks placed (a Base Builder: office, who they are, building since, blocks placed). ◀ ▶ (arrow keys) and Random. Downloads: one loop of the move as a 480 px GIF (gifenc), a 2048 px full-body PNG, the same without background, the PFP and a 1500×500 X header. Numbers not reached yet say how to bring the next one.recap.html, src/recap.js): what the city did each day (24 h from its start), replayed from the same ledger: Blockies in the city and the day's change, arrivals (Legendary and Rare), departures, buildings finished, blocks placed, landmarks, whale builds and land, the day's rarest arrivals and its hardest-working buyer's Blocky. A 16:9 card to screenshot, a prefilled post for X, ?day=N for any day (the last full day by default). The post links to /r/N (vercel.json rewrites it to api/recap.js): a page whose X card is that day's recap as a 1200×675 PNG, drawn on the server from the same numbers (src/recap-data.js, satori + resvg), and that sends people on to the recap. ⬇ Save image makes the image from the card on the page (html-to-image, 2400×1350); on phones, Share attaches it to the post.og:url, a 1200×630 image with absolute URLs from siteUrl, twitter:site from xHandle): public/og.png for the city, og-builders.png, og-blockies.png and og-claim.png for the Builders, Blockies and Claim pages. In the pages, %SITE% and %X% are filled in at build time (vite.config.js).isReserve in src/sim.js) and get named woods districts. Weights per zone live in CATALOG (w: [downtown, midtown, suburbs, outskirts]).CitySim.redevelop in src/sim.js; npm test checks the crew never runs out of work.expandNeeds in src/config.js). Until then the city waits, which is where new buys come in.$BLOCKY's 24h price change: storm with lightning (≤ -15%), rain, cloudy, sunny, and a fireworks bull run (≥ +15%). Buys of 10+ Blockies fire a volley over the Statue of Blockerty, whales fire three. ?weather=storm forces a look for recording.$BLOCKY's price and 24h move, the token it trades against (NVDAc, priced from the pool) and any STOCK_TOKENS. A gold bull stands out front while $BLOCKY is up over 24h, a bear when it is down.src/cats.js, HQ style cats).metro in src/config.js.sponsors in src/config.js ({ name, tagline, color, logo?, url, sponsored? }); clicking a board opens its link.P hides the panels and holds the camera still (Esc to exit); The camera holds still by default; R or ⟳ turns a slow auto-rotate on (remembered). ?photo starts in photo mode, ?spin / ?still force rotation on / off.offices in src/config.js): every Base Builder holds a city office (office on each legend): Jesse (founder of Base) is the Mayor, Brian (CEO of Coinbase) the Governor, then the Speaker, Treasurer, Chief Architect, Fire Chief, Night Mayor and more. Offices show on the Blocky card (★ MAYOR · CITY COUNCIL), the leaderboard, the Base Builders page (ordered by rank), cinematic captions and the news ticker (each office has a duty line). Each office has a home (landmarks or building types): once one stands, its holder spends most breaks there ("At Town Square").src/cinematic.js): 🎬 Cinematic (or F, or 🎬 Film on a Blocky's card) swaps the isometric view for a film camera: a perspective lens, a real sky with the sun and moon, bloom (the windows glow at night) and depth of field on the subject. Shots change by themselves (Auto) or with ◀ ▶: a close-up of a Blocky, a high tracking shot following one, the construction site from above, the skyline from out of town, a drone flyover, a crane shot up the tallest building, the river. A spring-arm camera keeps buildings, trees, the metro and other Blockies from blocking the star, and cuts away if they do. Light presets (Golden hour, Night, Noon, Live; only your view, the city keeps its clock), frames for every feed (2.39:1, 16:9, 1:1, 9:16), and captures with the caption and the BaseCity watermark: 📸 a photo (2400 px on the long edge) and ⏺ a 10-second clip (MP4 where the browser can, else WebM), with Share (the phone's share sheet) and Save.| Page | What |
|---|---|
/ | The city, live. Click any Blocky for its card, PFP and NFT page. |
/collection.html | The Blockies: every Blocky with filters (rarity, trait, in the city / left), search by #number, name or wallet, top holders, and a card per Blocky (/collection.html#206) with its NFT portrait, stats, PNG download and OpenSea / Basescan links. |
/claim.html | Claim: connect the wallet that bought (browser wallets via EIP-6963, Coinbase Smart Wallet / Base App via the Coinbase Wallet SDK), see its Blockies, claim them 50 per transaction. The buyer pays the gas. ?address=0x… opens a wallet. |
/builders.html | Base Builders: profiles, live stats and downloadable voxel PFPs. |
/about.html | How it works: the rules, rarity odds, goals, contracts, FAQ. |
/deploy.html | Owner tool (not linked): deploys the NFT contract from your browser wallet. |
contracts/BaseCityBlockies.sol: ERC-721 + ERC-2981 (5% royalty to the treasury) + ERC-4906, OpenZeppelin 5.
src/ledger.js, run by api/colony.js) decides which wallet brought which Blocky and when it becomes a citizen (citizenAt: not before opening day, L.openedAt). api/claim.js signs an EIP-712 claim for the wallet's citizens not claimed yet; the wallet sends claim(ids, deadline, signature) itself and pays the gas. Only the wallet named in the signature can use it; signatures last 30 minutes.$10 of $BLOCKY for 6 hours, which keeps instant buy-and-dump from farming them. The contract mints at most MAX_SUPPLY (10,000), ever.MAX_SUPPLY, set at deploy, the same as the city's cap); the claim API never signs a claim the contract can't mint.nft.reserve in src/config.js, or TEAM_RESERVE_WALLET / TEAM_RESERVE_COUNT): citizens from opening day, never sent away by the hold rule, counted in the 10,000, disclosed on the About page and as Origin: Team reserve in their metadata. Set the count to 0 for none.api/nft/[id].js: /api/nft/206 (name, rarity, trait, role, status: Newcomer / Citizen / Left the city, citizen since, blocks placed, arrival date), /api/nft/206.svg (the portrait, drawn from the same 3D model by src/voxel-svg.js, cached for a year), /api/nft/collection (contractURI).setSigner (rotate the claim key if it ever leaks), setBaseURI (also asks marketplaces to refresh, ERC-4906: call it if the domain changes after deploy), setContractURI, setRoyalty.cd contracts && npm install && npm test compiles (solc 0.8.26, Cancun), runs the contract tests on an in-memory Base and an end-to-end test of the claim and metadata APIs against it. contracts/out/ holds the artifact (ABI + bytecode, used by /deploy.html) and the Standard JSON Input for Basescan verification.npm install
cp .env.example .env.local
npm run dev # http://localhost:5173, also serves /api/colony, /api/claim, /api/live and /api/nft/* locally
# (installs any dependency a git pull added before it starts)
npm run build
Locally the API reads trades from GeckoTerminal like production; without KV the ledger lives in memory and starts empty. If the live API is unreachable, the pages fall back to demo data.
URL flags: ?demo fakes 3 days of history and then a trade every 30s (a $1,000 whale at 2 minutes, a seller at 3.5 minutes); ?speed=600 fast-forwards the city clock for timelapse videos; ?weather=bull forces the weather; ?photo starts in photo mode. Combine them: /?demo&speed=600&photo.
KV_REST_API_URL / KV_REST_API_TOKEN). Required in production.KV_KEY to a new name (e.g. basecity-v1): a new key means a fresh ledger, so the city starts from empty land with only the team reserve (100 / 10,000, or 0 with no reserve) and only buys from now on count. Optionally set LAUNCH_TIME_MS (ms timestamp) to the launch moment. Do not set BACKFILL_HOURS.BASE_RPC_URL to your own Base RPC (Alchemy, QuickNode, …): the API reads every trade's receipt (the real wallet, and the block hash that seeds rarity) and checks holders' balances. A trade whose receipt can't be read yet waits, with every trade after it, for up to 10 minutes rather than count for the bundler; and one serverless instance at a time updates the ledger (a KV lock), so a Blocky number never goes to two wallets./api/colony)./deploy.html with the dev wallet (0x8eBA…C34D), click Generate a signer key, copy the key, deploy. Then in Vercel set NFT_CONTRACT (the new address), CLAIM_SIGNER_KEY (the key) and SITE_URL (your domain), and redeploy: claims open. Claims stay closed on Vercel without KV (every instance must sign from the same ledger)./api/colony every minute. The ledger only updates when the API runs, and the trade feed keeps just the last 300 trades of the pool, so a quiet night without visitors must not drop buys.Import the repo; Vercel detects Vite and serves api/*.js as serverless functions.
Environment variables (see .env.example):
| Var | What |
|---|---|
KV_REST_API_URL / KV_REST_API_TOKEN | Upstash Redis (Vercel KV). Required in production: stores the ledger (every Blocky, its wallet and seed, departures, the waitlist) so every visitor sees the same city. |
KV_KEY | Name of the stored ledger (default blocky:colony). A new name starts a fresh city at 0 / 10,000. |
LAUNCH_TIME_MS | When the city starts from empty land and buys start counting. Default: the first time the API runs. |
BASE_RPC_URL | Base RPC for receipts, balance checks and the NFT contract (default: the public mainnet.base.org, rate limited). |
NFT_CONTRACT | The BaseCity Blockies contract (from /deploy.html). Claims open when this and CLAIM_SIGNER_KEY are set. |
CLAIM_SIGNER_KEY | Private key that signs claims; its address is the contract's signer. Server only, never commit it. |
OPENSEA_API_KEY / OPENSEA_SLUG | Optional: reads the collection's floor and listings on OpenSea for the claim page's suggested prices and low-listing warnings (src/pricing.js; slug default nft.openseaSlug). Without a key, suggestions use a fixed $15 of ETH. The key also lets holders list on OpenSea from the claim page (src/listing.js, OpenSea's SDK; api/opensea.js relays only BaseCity Blocky listings, at /api/os/*, so the key never reaches the browser). |
SITE_URL | Your domain, e.g. https://basecity.xyz: NFT metadata links, share links and share images. |
USD_PER_BLOCKY / MAX_SUPPLY / WHALE_USD / UNLOCK_USD / CITIZEN_DAYS | Optional overrides of usdPerBlocky (10), supply (10000), whaleUsd (1000), unlockUsd (0: open) and citizenDays (0.25: 6 hours) in src/config.js; keep them in sync. |
MIN_BUY_USD | Ignore dust buys (default $1). |
HOLD_CHECK_MINUTES |
src/config.js: city name, ticker, token links, $ per Blocky, supply, rarity odds, Base Builders, billboards, blocksPerHour, day length, land size and expansion thresholds, landmark milestones.src/sim.js: Blocky roles and work rates, the river, the building catalog and the deterministic build plan (landmarks, buildings, land expansions).src/city.js: voxel designs, land/river/bridges, progressive roads, construction sites, day/night.src/vehicles.js: cars, buses, boats and service patrols; src/fleet.js: the service vehicles.src/metro.js: the elevated metro loop, its stations and the train.src/pfp.js: voxel PFP renderer (WebGL); src/voxel-svg.js: the same Blocky as an SVG (NFT images, collection pages).src/ledger.js: the Blocky ledger (buys, the hold rule, the waitlist, rarity seeds), shared by the API and demo mode.builders.html, collection.html, claim.html, about.html with src/site.js + src/site.css (nav, footer, shared styles).src/agents.js: the AI agent drones.src/cats.js: Cat Town's cats and the plaza's statue.src/music.js: the city's lo-fi music, played live with the Web Audio API (no audio files): ♪ Music or M. It gets darker at night and quieter in the rain.src/votes.js, api/vote.js, /vote.html: the citizens' vote. Holders of BaseCity Blockies NFTs pick what the city builds next, 1 NFT = 1 vote (the team's reserve and grants don't vote), signed for free (smart wallets too), counted per NFT in KV. The round lives in vote in src/config.js; the winner goes into src/projects.js by hand when it ends.src/citizens.js: builders walking the roads, hauling and placing blocks.No game server. The crew's speed only changes when a builder arrives (blocksPerHour × √(total skill)), so total blocks placed is a piecewise-linear function of time. The city plan is a fixed, seeded sequence of buildings; each starts when the previous one is done and finishes once the crew has placed its cost in blocks. Any browser that knows every Blocky's arrival and departure (from /api/colony + KV) computes the exact same skyline, including when each building was completed.
How often holders' $BLOCKY balances are checked (default 15). |
RESOLVE_WALLETS | 0 to skip reading receipts (then smart-wallet buys count for the bundler and rarity seeds from the tx hash). Default on. |
POOL_ID | The BLOCKY/NVDAc Uniswap v4 pool. Trades are read from its public GeckoTerminal feed. |
STOCK_TOKENS | Optional: comma-separated addresses of more tokenized stocks on Base for the Stock Exchange ticker. |
BACKFILL_HOURS | Testing only: also count trades from the last N hours (the feed covers ~24h). |
COUNT_MODE | buys (default). fees: creator fees bring Blockies instead (FEE_WALLET, EXCLUDE_TOKENS, FEES_URL, FEES_USD_OVERRIDE, FEES_OFFSET_USD, FEE_TOKENS). |