Kevin Wolkober (@kevinwo) • Hey
Product & engineering versatilist jazzed about NFTs and mobile. Prev: Unfold, Squarespace. Developer DAO member. I also make cocktails and an occasional go
Publications
- TIL you can charge an iPhone with an iPad - USB-C to Lightning cable and you’re good to go
- "Anxiety Monsters" is a new series from @cybershakti.lens, and the first animated piece is titled "DUMBO". I think the intention of the series is great, aiming to create more conversations and awareness around the subject of anxiety. Thank you Cyber Shakti for sharing this piece with me!
https://rarible.com/token/0x3c504dff2cac1266605847e5999731d5c88e60fb:1
- Just minted my handle on @talentlayer.lens
https://claim.talentlayer.org/profile/kevinwo
(Thanks for the heads up @gotenks.lens !)
- Someone lost a balloon at Grand Central 🎈
- The sunset blues hit me just right somehow yesterday, and so I snapped this and stared out window for awhile.
- Ultimately with artists you need to show that their time invested here is well spent. I genuinely feel Lens could be social media and the store, all in one. You would no longer have to announce that your song is available on Spotify and try to send people there; you could just make it available to collect right here on Lens. If artists could see reach combined with that means to transact, this place would instantly become somewhere they shouldn't ignore.
As for labels, I think their needs are more basic: they want to know they can connect with fans and generate revenue. But Lens can absolutely do that too.
- At Blockchain NYC’s DeFiCon today. My head’s been in NFT land for so long, so learning more about DeFi!
Interesting question posed by one of the speakers today: Will stablecoins have USDnullT TVL in 5 years? (I think so)
- Is there a Lens NYC group out there (online or offline)? Or any plans for a Lens meetup at NFT.NYC this year? I want to meet and talk shop with others building on Lens!
- gm! is this thing on? 🎙️
- When I moved to NYC 15 years ago, I didn’t know anyone. A friend mentioned a website called Meetup at the time. At the first event I went to I met others and made a short film together over 48 hours. That one event led to:
1. Making a fun film
2. Meeting one of my best friends
3. Joining a sketch comedy group
4. Living in Taiwan and learning Mandarin
5. Meeting my wife
6. A ton of other things and people I’m grateful for
The next time you consider talking yourself out of going to an event you thought looked fun, consider the ripple effects - just one event could lead to a ton of important life stuff!
- Today at the Shedd Aquarium. Bioluminescence in sea creatures amazes me.
- Seeing this today at the Shedd, my brain naturally went to NFTs. Only a matter of time until these are digital.
- Day 30: The end. Wrapped up some final auth tweaks on the last day of my first exercise building on @lensprotocol and @lensapi.lens – HttpOnly cookies for JWTs! The Pods beta is ready to launch, pending the app getting whitelisted for broadcast by the Lens team, and then I'll share out the link.
I hope this log was helpful for some interested in building on Lens and/or with React/Next.js frontends! I'll either continue developing on Pods if people find it useful, or will explore, build on, and share another NFT-related project next!
- Day 29: Set up a basic tabbed interface for mobile. The drafts and queue side-by-side is a bit too tight for small screens, so I implemented tabs to separate and view them more clearly. I observe the window size changes and render both drafts and queue on wider screens.
Tabs out-of-the-box brought to you by react-tabs from the React Community! https://github.com/reactjs/react-tabs
- Day 28: Finished refresh token implementation. Sessions should automatically extend when you return to Pods after 30 minutes. By the way, did you know the JSON Web Token standard was first published in 2010? I didn't! https://en.wikipedia.org/wiki/JSON_Web_Token
- Tiny feature request for @orbapp.lens – tap device screen top (e.g. the notch) on iOS to auto-scroll to the top of my feed 😁
- Building an iOS app? Doing stuff with NFTs? Hit me up if you want to talk shop or need help navigating all things Apple and App Store rules! Happy to chat and learn about what you’re working on.
- Day 27: Started work to persist login. Lens access tokens expire after 30 minutes from issue, so we need to rotate refresh tokens to keep the session going with new access tokens. LogRocket has a great article on persistent login and tokens! https://blog.logrocket.com/persistent-login-in-react-using-refresh-token-rotation/
To review, here's also Lens authentication docs I shared previously with details on login and JWT token for app implementation: https://docs.lens.xyz/docs/authentication
- Day 26: Added WalletConnect support. I had been working with a browser-injected wallet via MetaMask, but there are of course all kinds of wallets out there, hot and cold, desktop and mobile. Expanded wallet support enables as many people as possible to access and use Pods.
Web3Modal makes it really easy to support most major wallets out of the box with fairly straightforward configuration via wagmi: https://github.com/WalletConnect/web3modal
- Day 25: Added menu popover. A tiny update today, but an important one. Users need to be able to access their account and sign out! Only support for login with default profile, but might support multiple profiles in the future. Profile link opens your profile on Lenster for now.
The Tippy.js library and React component support did the job for getting our menu popover quickly up and running! https://github.com/atomiks/tippyjs-react
- Day 24: Tweaked and fixed various things around deployment and database connection. If you're feeling brave, the alpha preview is now available *for testnet profiles only*. No promises yet on stability! 😅 https://preview.onpods.xyz/
- Day 23: Added placeholder loading animation for post lists and truncated post content preview. Will start with a three-line limit for text and see what people think. Edit to see and modify the whole post. Next will tackle empty state, and should be ready to share staging site.
The placeholder loading animation is driven by the excellent react-content-loader library! https://github.com/danilowoz/react-content-loader
- Swapping Sunday rest day for today, and reconnecting with childhood. Many nights of Goldeneye and Pizza Hut back in the day.
- This is exactly what @wav3s.lens is doing on Lens 🔥
- Rewards programs like Starbucks Odyssey are already beginning to introduce the concept of digital ownership via NFTs, but what excites me most is the ability to reduce friction in partnerships between brands:
“Examples of this interoperability exist today but are limited by Web2 technology that requires collaborations to be manual, time-consuming and bi-directional (meaning that Brand A must negotiate a deal with Brand B and pursue a timely and expensive systems integration in order to collaborate).”
https://www.coindesk.com/consensus-magazine/2023/01/26/web3-loyalty-programs-are-a-trojan-horse-for-good-crypto-policy
By end of 2023, I bet we see significantly more people participating in more mature programs beyond Starbucks as more brand integrations happen.
- Day 22: Added notification after successful publish. At first I thought, "Success needs an array of fireworks, or maybe a shooting star." Then I remembered I didn't need to go crazy with expressing the majesty of success for getting out a post and a link to follow the tx status.
These notifications took just a few lines of code to implement with react-toastify, a nicely designed and highly configurable toast library. https://github.com/fkhadra/react-toastify
- Day 21: Completed first deployment. Normally testing a deployment is something best done near the beginning of a project to avoid juggling many potential issues/errors later on. However, I got excited with digging into this prototype, and decided to tackle deployment now.
I'm newer on the TypeScript scene, and so deferred various type and syntax fixes until now. Between Visual Studio Code highlighting and Next.js type validation via npm run build, I finally tweaked my way into getting a valid build up and running on Vercel! vercel.com
For managing my PostgreSQL remote database, I'm using Supabase, which got me up and running quickly with my deployment! supabase.com
- Day 20: Filtered post content by search text and added error handling/alerts. Search will be pretty basic on the frontend for now. Can spice it up more in the future when supporting things like organization by campaign, and other post attributes, like collect type, audience, etc.
- I pull all my motivational quotes from cough drops now.
- Day 19: Implemented contextual delete and publish to Lens. The delete modal from before wasn't the right fit as it became unclear which post was intended to be confirmed for delete. The publish to Lens now works from the queue, completing the entire path from draft to publish!
I'm using React Spinners for the progress indicators. There are some sizing issues and polish to work out yet, but I'll circle back after finishing the remaining key areas, if there's time. Still aiming for launch within eleven more days! https://mhnpd.github.io/react-loader-spinner/
- Are you a **specialist**, **generalist** or **versatilist**?
Specialist = expert in a focussed area
Generalist = broad based of knowledge across many areas
Versatilist = adept in various areas according to needs
Great article exploring this idea here - https://nesslabs.com/specialist-generalist-versatilist
- Lunar New Year is here – Happy Year of the Rabbit! 🧧🎉 新年快樂!
- Day 18: Can now edit a post and move it from the queue back to draft. Most basic management functions are in place now. Off tomorrow, but will likely next complete the publish flow, and reconnect our previous Lens post publishing logic with the send button in the queue.
- Day 17: Deleting/queuing posts is a go. You can queue a post for an intended publish date, separating your in-progress work from your ready-to-go stuff. You'll still have to hit publish yourself until Lens supports scheduled publishes, but hey, at least you'll be more organized!
- Day 16: Added creating a post via modal. I took the form previously used for creating a post directly on Lens, and injected it into a modal. Creation now routes instead to our Postgres DB. Over the next couple days I'll implement similar modals for managing and deleting posts.
For the create modal, I'm using the excellent modal library, Rodal! It makes it super easy to get an animated modal going quickly, and has some nice customization options. https://github.com/chenjiahan/rodal
I forgot to also mention yesterday that I'm using Font Awesome icons via React Icons. Also easy to implement and look great. https://react-icons.github.io/react-icons/
- Day 15: Added buttons o' plenty! Getting closer to what the initial UI will really look like. A simple start, you'll be able to manage post drafts, move them to a publish queue, and when you're ready, send 'em to Lens! Halfway through the exercise now, aiming for V1 by day 30.
- Day 14: Settled on a simple two-column UI to start. The most fundamental part of this little app is drafting up content, and queuing it to publish to Lens. Nicer UI and more to come. Anyone have a favorite icon library for edit/delete/other standard buttons?
- Day 13: Sketched out a few different ideas for initial organizer UI. Landed on starting with a simple drag n' drop card layout to let you queue posts by category. React DnD will do the job when I'm ready (https://react-dnd.github.io/react-dnd). Off keys the next two days to play the other DnD.
- Day 12: Connected draft creation to database, with basic storage of HTML post content.
I'm at a fork in the road of my mind:
Do I next improve the UI to better illustrate draft organization, or do I further develop the underlying data (collect type, publication type, tags, etc.) we want to organize?
- Day 11: Set up a good ol' fashioned database with PostgreSQL, using Prisma as a nice ORM on top. We'll be first storing posts there before sending them off to Lens for publishing. Attached is a peek at the initial schema. Nothing fancy to start. Will walk through it in a later post.
This very comprehensive guide from Vercel got me up and running with setup and rendering in the UI. Will share UI bits tomorrow, with more to follow probably on Saturday around auth with Lens and using a user's wallet address to store and access records. https://vercel.com/guides/nextjs-prisma-postgres
- Day 10: Huzzah! Published a first post via @lensapi.lens on @lensprotocol! Altogether now, to recap the whole process:
1. Enter text
2. Build post metadata
3. Upload it to IPFS
4. Generate typed data representing the post
5. Sign it with a wallet
6. Send broadcast ID + signature to Lens
7. Published!
An ID comes back in the response when requesting typed data from the Lens API for a post. After signing the typed data with a wallet, we now send the ID plus the signature to Lens so it can relay a transaction, creating a post on our behalf – gas-free! https://docs.lens.xyz/docs/broadcast-transaction
Now that we have the basic flow for creating a post in place, gears will shift to building out more of the application. Next time we'll start looking at drafting and storing posts in our app's database prior to publish.
- Day 9: Finally signed the create post request typed data with a browser wallet! We now have all the pieces of data we need to publish our post, and will move forward with that tomorrow.
The @wagmi_sh library makes it easy to sign the data in the way we need. Breaking out domain, types, and value from the typed data generated by the Lens API, we can use wagmi's interface for signing typed data to generate a signature. https://wagmi.sh/core/actions/signTypedData
Today I also briefly got stuck on a tricky issue with Next.js UI hydration and wagmi, and found this excellent post explaining how to work around it! (TL;DR: manually check if a component has mounted before returning it when wrapping with WagmiConfig) https://codingwithmanny.medium.com/understanding-hydration-errors-in-nextjs-13-with-a-web3-wallet-connection-8155c340fbd5
- GM from cheesy 2017 frames and edits! Hope everyone has a killer week ⚡️
1 WMATIC // Edition of 5 // 65% referral
- Day 8: Briefly started investigating signing the post request typed data. There are many different methods and libraries to sign data. "eth_signTypedData" is the method we want, but there are a few different versions. MetaMask has a good rundown on signing data: https://docs.metamask.io/guide/signing-data.html
I also got sidetracked in investigating the wagmi library as both the wallet account connection and signing management. I've previously rolled my own, but this modern take with React Hooks seems much better! https://wagmi.sh
Will continue tomorrow aiming to finish at least getting wagmi setup for connection management, and then see if I can chip away at actually signing.
- Chasing waterfalls today. Day 8 will resume tomorrow.
- Day 7: Generated EIP-712 typed data representing the post request. The typed data will be sent to the user's wallet for signing, and then we'll send the request + signature up to Lens to finally publish our post. Looking to knock down signing tomorrow.
You can see an example of creating typed data and signing it for a post on the Lens API examples repo. The example uses ethers to sign the message. However, we're going to go a different route, querying a browser-connected wallet to perform the signing. https://github.com/lens-protocol/api-examples/blob/master/src/publications/post.ts
7 days in now, and you might be wondering, "Is this just going to be a simple posting app for Lens?" Nay! Once we get the basic posting process understood and implemented, we're going to start to take a turn at breaking these steps apart for a slightly different purpose...
- Day 6: Fetched the Lens profile data for wallet-connected user. Only a tiny bit of time to tinker today, so got to the point of fetching a profile, which we'll need to eventually send up along with our metadata in our create post request.
The profile data is naturally used to identify who the post belongs to after publish. We also additionally pull the user's handle to include in the post name when collected, but also whether or not the user uses a dispatcher. More on that another day! https://docs.lens.xyz/docs/get-default-profile
- Major hats off to @lensprotocol and the @lensapi.lens team for building such great documentation. Between the explanations and the many examples, it's been nice and straightforward to diving into building on Lens! 🙏
- Day 5: Formatted and uploaded post metadata to IPFS upon hitting the Publish button. These are just the first two steps I mentioned on Day 4 to publish a post. At this point, we have a content identifier for our metadata, and we'll send that up tomorrow in our post request.
Attached is an example of post metadata content. Since we're only handling text posts to start, we use the user-submitted text for the rendered post content shown on any Lens frontend, as well as for the description seen on a marketplace when this post is collected as an NFT.
The metadata_id can be any unique string, so a UUID should be sufficient. The name corresponds to what is displayed for the name of an NFT representing the post when collected. For now, we'll just use the format "Post by {the Lens handle of the user}".
- Businesses and brands are about to become customers of their customers. I don’t think this has fully sunk in with people yet. In September 2021 and April 2022 I used these examples for what happens when Instagram goes full web3: