Miguel Piedrafita

Miguel Piedrafita

Currently working at Worldcoin and building hundreds of little projects.

About me

For years I thought I'd be an indie maker, y'know, booststrapping a few SaaS apps @levelsio-style. Then I discovered Ethereum and got really into decentralization and smart contracts. Lately, I've been looking more into ML, and trying to improve the Rust webdev ecosystem. Who knows what's next?

You might know me for
  • being 22
  • having purple hair
  • (almost) buying the US Constitution
  • building and launching something new every week of 2022
  • laravel, gen z mafia, web3 frens, indie maker circles, tpot

Currently in

Last Played

Everything* I've ever built

*

well, not *everything*, but still a pretty good list of things I've built/done/published over the past few years

My first SwiftUI app

After years of putting it off, I finally got to learning SwiftUI. This first app is a very simple "talk with AI" interaction, inspired by a demo from OpenAI's DevDay a few months ago. It's extremely simple, but I'm super happy with how it turned out!

View on GitHub

A Rust SDK for World ID

Most of the World ID integrations so far have been on the web or mobile, since that's what we have SDKs for. For everyone else, I took a stab at building a Rust crate (which can be called from Swift, Python, etc.) that can serve as a more universal bridge to the protocol.

View on GitHub
GitHub - m1guelpf/repair-json: Repair incomplete JSON (e.g. from streaming APIs or AI models) so it can be parsed as it's received.

github.com

GitHub - m1guelpf/repair-json: Repair incomplete JSON (e.g. from streaming APIs or AI models) so it can be parsed as it's received.

Working with streaming JSON in Rust

LLMs have gotten pretty good at generating structured data recently, but unlike with text you can't use the results in real-time, since the returned JSON isn't valid until the end of the response.

To solve this, I built a fast JSON syntax validator of sorts, which keeps track of the current context (are we inside a string, object, key, etc.) and can revert back to the latest valid state or complete the JSON to make it parseable.

let device = aranet::connect().await?;
let measurements = device.measurements().await?;

dbg!(measurements);
// [src/main.rs:6] measurements = SensorData {
//   со2: 962,
//   battery: 76,
//   humidity: 49,
//   status: GREEN,
//   pressure: 1017,
//   interval: 300s,
//   temperature: 25.75,
//   since_last_update: 127s,
// }

Monitoring air quality with Rust.

I've owned an Aranet4 CO₂ monitor for a while now, and while the device itself is great, it's not compatible with any smart home systems.

I wanted to get push notifications when the CO₂ levels in my room were too high, so I reverse-engineered the BLE protocol it uses and built a simple Rust library to interact with it.

View on GitHub
use silhouette::facade::Container;

struct DBPool {}
struct DBConnection {}

// will always use the same pool
Container::singleton(&|_| DBPool::new())?;

// will resolve a new connection each time
Container::bind(&|container| -> DBConnection {
    let shared_pool = container.resolve::<DBPool>().unwrap();

    shared_pool.get_conn()
})?;

// somewhere else in your app...
let connection: DBConnection = Container::resolve()?;

Exploring dependency injection in Rust.

Dependency injection is one of my favourite patterns (it's also the secret sauce behind Laravel), but Rust's type system and borrow checker make it impossible to fully implement.

Nevertheless, I wanted to see how far I could get, so I built a super simple service container that lets you register and resolve services, with support for singletons and closures. No interfaces tho 😅

View on GitHub
use epicenter:: { Event, AsyncDispatcher };

#[derive(Debug, Event)]
struct ExampleEvent { }

// There'a also a SyncDispatcher you can use
let mut dispatcher = AsyncDispatcher::new ();

// Register a callback to run when an event is dispatched
// This gets access to the event, so it can retrieve data from it!
dispatcher.listen(| event: ExampleEvent | async move {
    // ...
}).await;

// Dispatch an event to all listeners
dispatcher.dispatch(& ExampleEvent {}).await ?;

An elegant event listener package for Rust.

When building a few of my last Rust crates, I found myself wanting to provide a simple way to let callers hook into certain events. While there are a few event dispatcher crates out there, none of them were simple and elegant enough, so I decided to build my own.

View on GitHub
use flysystem::{Filesystem, adapters::{S3Adapter, s3}};

#[tokio::main]
async fn main() {
    // instantly swap between storage backends (like S3/Local/FTP)
    // by changing the type here 👇👇👇
    let mut cache = Filesystem::<S3Adapter>::new(s3::Config {
        region: env::var("S3_REGION").ok(),
        bucket: env::var("S3_BUCKET").unwrap(),
        endpoint: env::var("S3_ENDPOINT").unwrap(),
        access_key: env::var("S3_ACCESS_KEY").unwrap(),
        secret_key: env::var("S3_SECRET_KEY").unwrap(),
    }).await?;

    filesystem.write(Path::new("my-first-file.txt"), "Hello, world!").await?;
}

A filesystem abstraction layer for Rust.

Continuing on the trend of building packages missing from the Rust ecosystem, I decided to try my hand at rewriting PHP's Flysystem library in Rust. After a few days of tinkering I had something extensible and easy to use, and with full test coverage!

View on GitHub
use amnesia::{Cache, drivers::RedisDriver};

#[tokio::main]
async fn main() {
    // instantly swap between cache backends (like DynamoDB/MySQL/Postgres)
    // by changing the type here 👇👇👇
    let mut cache = Cache::<RedisDriver>::new(RedisConfig {
        redis_url: "..."
    }).await?;

    // get `test-value` from the cache
    // or store it for 10 seconds if it's not there yet
    let my_value = cache.remember(
        "test-value",
        Duration::from_secs(10),
        my_value
    ).await?;

    // aaaand it's gone
    cache.forget("test-value").await?;
}

An expressive Rust library for interacting with a cache.

Lately, I've been trying to build a more intuitive ecosystem of webdev-related packages. I needed to store some things on Redis for an upcoming project, so I thought I'd take some time to upgrade the DX around caching in general.

View on GitHub

World ID 2.0

After many months of work, we're releasing the next generation of World ID. I got to rebuild the SDK from scratch and design a new way to connect with the World App, which has made everything more reliable and private.

We also launched a bunch of pre-built integrations, like Telegram or Minecraft (which was super fan to debug). Make sure to check out the announcement for all the details!

Read the announcement

A personal wearable AI

I recently flew to SF to help my friend Avi announce his startup to the world. He's been working on this necklace that listens in on all your conversations and has full context on everything going on in your life, which allows it to give you hyper-targeted advice and answer your questions in a way no other AI assistant can.

He's done an amazing job building the prototype, and on my last night before flying back I offered to pull an all-nighter and "upgrade" his backend with a focus on scalability. I managed to make it more than 10x faster and clean up the code quite a bit, and became the second human ever to own a Tab!

Watch Avi introduce Tab

Building the ultimate Mario game

Still on my journey to get good™ at YouTube, I've made another video! This time, it tries to explain how transformer networks work, with the excuse of using one to generate Super Mario levels.

I'm super happy with how everything turned out, and I hope you'll enjoy it!

Watch on YouTube

An example Cog model

use cog_rust::Cog;
use schemars::JsonSchema;
use serde::{Serialize, Deserialize};

struct MyModel { ... }

impl Cog for MyModel {
    type Request: Deserialize + JsonSchema;
    type Response: Serialize + JsonSchema;

    /// Setup the model
    async fn setup() -> Result<Self>;

    /// Run a prediction on the model
    fn predict(&self, input: Self::Request) -> Result<Self::Response>;
}

cog_rust::start!(MyModel);

My Rust ML library is finally ready!

When I started working on a Rust version of Cog (Replicate's Python library to dockerize ML models) I set the goal of running Stable Diffusion on Replicate with no external code. Almost two months later, it finally works!

This is probably the most complex codebase I've ever worked on, and I still have a lot of ideas on how to make it better, but I thought hitting this milestone was a good time to mark it production-ready.

View on GitHub

The quickest way to commit your code

Commit is a simple macOS app, which you can invoke with a keyboard shortcut. It'll open a window where you can write a commit message, and then press enter to commit it.

It was inspired by this TailwindUI template, which imagines a fake app that does the same thing. I thought it was a cool idea, so I decided to build it!

Download on GitHub
GitHub - m1guelpf/Chess-Challenge: My entry for Sebastian Lague's C# Chess Bot Challenge

github.com

GitHub - m1guelpf/Chess-Challenge: My entry for Sebastian Lague's C# Chess Bot Challenge

A Chess bot in C#

Sebastian Lague recently announced a chess coding challenge, where you're given a C# framework that manages the board, generates moves, etc. and you have to write a "brain" for a chess bot.

While I'm not particularly good at C# (and know next to nothing about building chess bots), I thought it'd be interesting to participate. Definitely not the prettiest bot in the competition, but learned a lot while building it!

Taking the pain out of running AI models locally

Local models keep getting more and more powerful, but the experience of running them still sucks. I've been working on Dyson, a self-hosted Replicate of sorts, which makes running a new model as easy as writing its name and using the auto-generated interface or API.

It's very different from what I'm used to (and has a surprisingly big amount of devops, which I didn't know anything about before), but I'm slowly making progress!

View on GitHub
GitHub - m1guelpf/tinyvector: A tiny embedding database in pure Rust.

github.com

GitHub - m1guelpf/tinyvector: A tiny embedding database in pure Rust.

A tiny vector database in Rust

After seeing my friend Will build a tiny embedding database in ~500 lines of code with python, sqlite and numpy, I thought it'd be fun to try and build something similar in Rust.

I ended up rewriting the entire thing from scratch (dropping sqlite and numpy on the process) and storing everything on memory. After some performance optimizations, it was good enough to replace Pinecone on some personal projects!

use cog_rust::Cog;
use anyhow::Result;
use schemars::JsonSchema;
use async_trait::async_trait;

struct ExampleModel {
    prefix: String,
}

#[derive(serde::Deserialize, JsonSchema)]
struct ModelRequest {
    /// Text to prefix with 'hello '
    text: String,
}

#[async_trait]
impl Cog for ExampleModel {
    type Request = ModelRequest;
    type Response = String;

    async fn setup() -> Result<Self> {
        Ok(Self {
            prefix: "hello".to_string(),
        })
    }

    fn predict(&self, input: Self::Request) -> Result<Self::Response> {
        Ok(format!("{} {}", self.prefix, input.text))
    }
}

cog_rust::start!(ExampleModel);

Rust containers for Machine Learning

In the past I've used Cog (a Python library by Replicate) to very quickly build and deploy new models. As the state of non-Python models slowly advances (mostly thanks to @ggerganov), I thought a Rust version could unlock extra performance.

The library is still very much a work in progress, but it's already usable locally!

View on GitHub

web3 app starter

While working on a new project, I realized that everything I had built so far could be used as a template for other projects, so I decided to make it into a starter kit.

It's a Next.js app (using the new App Router and server actions) that includes Sign in with Ethereum, a basic UI and support for teams (letting you assign roles, invite people, etc.).

View on GitHub

New website!

I've felt like my old website didn't really represent who I am for a while now, and after months of trying to come up with a design I liked, I finally managed to find something unique enough.

I'll keep tweaking and adding stuff (especially to the timeline, there's years of stuff missing), but I wanted to get it out there before I started overthinking it again. Hope you like it!

Share your thoughts on Twitter
enstate.rs - querying ens information should be easy.

An API for ENS data

I really like the idea of ENS being "the universal profile", which you can set up once and every other app can follow.

To make this a little easier, I teamed up with my friend Luc to build a dead-simple API that returns all relevant attributes for an ENS name.

View on GitHub

My first real attempt at a YouTube video

I've been wanting to make YouTube videos for a while, but never really found the time to do it. A week ago I decided to challenge myself to finish a video in a week (or shave my head), and managed to do it!

The video shows how I gave GPT-4 control over a browser and taught it to browse the web, with a fun tone and a bunch of jokes. Go watch it!

Watch the video

A new design for the Worldcoin Docs

After launching World ID I felt like the docs needed a fresh coat of paint, so I deleted the previous repo and started again from scratch. A few hours later, the new site was live with new design, new content, and a new domain!

See the docs
Introducing World ID and SDK

worldcoin.org

Introducing World ID and SDK

World ID is a new privacy-first protocol that brings global proof of personhood to the internet.

Announcing World ID

Today we're launching World ID. Sybil resistance is proving to be more important than I ever thought, and this is a foolproof solution, working on and off-chain that you can integrate in minutes.

We've been working to make World ID not only the most robust on-chain option, but also incredibly easy to integrate outside of crypto. For example, "Sign in with Worldcoin" allows regular web apps to become sybil-resistance in the same effort it takes to "Sign in with Google" ⚡

That means, if you're building "regular" apps with Next.js, Laravel, or anything else, you can integrate World ID in just a few lines of code. Actually, thanks to services like Auth0, you don't need code at all! Just add Worldcoin from the dashboard and you're good to go 😁

If you haven't gotten orb'd yet (or don't want to), we're also adding a phone signal to the app, which allows you to anonymously prove you have a valid phone number and a unique device, a weaker version of sybil-resistance but still much better than nothing.

ChatGPT for your docs

While visiting my friends from Hop, one of them mentioned it was crazy no one had built a tool that let you train ChatGPT on your app's documentation, so of course I decided to build it.

A few days (and lots of Rust) later, Clippy (MSFT don't sue plz) can "learn" your docs in ~5min and answer questions about them.

Baby's first Transformer model

Built my first Transformer model (trained on Shakespeare's works) following Andrej Karpathy's newest video lecture. It's 2:30h packed with deep knowledge, and while I definitely didn't understand everything, I learned a lot and getting the model working felt like magic ✨

Watch the lecture

An iOS widget for Worldcoin

Built an iOS widget with Scriptable, showing real-time Worldcoin onboarding stats! Uses internal APIs, so unfortunately can't share the code, but hopefully we have some public endpoints soon? 👀

Is This Image NSFW?

nsfw.m1guelpf.me

Is This Image NSFW?

An extremely fast machine learning NSFW image filter, powered by open-source models.

A mature content filter using Stable Diffusion

The Stable Diffusion safety filter has always been a mystery to me. It's not documented anywhere, and overall pretty accurate. I recently came across a paper by a group of researchers that had the same questions I did. They managed to reverse-engineer not only the logic but also the types of content the filter tries to match. Turns out, it's much simpler than expected!

Stable Diffusion already has a way of figuring out which concepts an image is closest to (this is a core part of generating images), using OpenAI's CLIP model. So you can use it to measure how close the generated image is to a list of "sensitive" concepts.

I modified the example code proposed in the paper (repo below), and deployed it to Replicate. The result: an API that can check images for adult content in less than half a second, for ~$0.00022/image.

View the code
Search your favorite podcasts by topic, not quotes.

podcast-search.m1guelpf.me

Search your favorite podcasts by topic, not quotes.

Presenting a new era of search for podcasts, allowing you to search a complete transcript of all episodes semantically.

Contextual search for podcasts

I've been looking into semantic search this last week, and decided to build a simple demo. It indexes the Indie Hackers podcast (which I transcribed using Whisper) and lets you search through all episodes by topic of conversation. Also had lots of fun building the UI!

GitHub - m1guelpf/lil-http-rs: A Rust web framework with no external dependencies

github.com

GitHub - m1guelpf/lil-http-rs: A Rust web framework with no external dependencies

Building a web framework from scratch 🦀

I've been learning Rust recently, and built a zero-dep HTTP server to practice (establishing TCP connections, manually parsing HTTP payloads and crafting responses, etc.). After that was finished, I kept going for a bit and built a router and some helpers to the point where it was more of a lil framework.

Wouldn't recommend using it in prod, but I'm super happy with how the DX turned out.

Copilot, but for your terminal

After failing to remember the command to check the size of a directory for the 100th time (and looking for yet another excuse to build something in Rust), I took on building a simple CLI that could bring the Copilot experience to the terminal. Works great for things like ffmpeg!

Try it out

Adding live output to my ChatGPT Telegram bot

One of the things that's made ChatGPT really magical is its ability to show you what it's thinking in real time. While I had originally skipped on this while building my Telegram bot (since Telegram doesn't support live updates), I ended up finding a hacky way to make it work!

Try it out

A Telegram bot for ChatGPT

I got tired of opening the ChatGPT website every single time I needed to ask something, so I reverse-engineered the API and built a Telegram bot that lets you chat with it directly from the app!

Try it out

A better ChatGPT interface

ChatGPT might be one of the most impressive things I've seen in a while, but its interface is a bit lacking. I decided to try my hand at building a better one, and ended up with possibly one of the most polished things I've ever made.

Deploying Stable Diffusion models to Replicate

I've been playing a lot with fine-tuned Stable Diffusion models recently and deploying them to Replicate for blazing-fast inference, so I made a quick tutorial showing you how to easily deploy any SD model (no ML knowledge required).

Watch on YouTube

Using GPT-3 to write commit messages

After someone at work told me off for naming all my commits "wip", I decided to build a tool that automatically writes the commit messages for you.

Try it out

Script-writing app progress update

I've continued to work on Scripty, my lil script-writing app (hoping to release it soon), here's a few design details from the prototype.

Feels really crazy how fast I can go from "i wish this existed" to a prototype, coding really is a magical skill ✨

Get on the waitlist
A screenshot of a fictional app (called Scripty) is shown with a slight 3D tilt on a purple background. The screenshot shows a web app with a 3-column layout. The first column shows the navigation (with items "Script", "Scenes", "Inspiration", "Feeling Stuck?", and "All Projects"), while the second shows an editor view with some text. Sections of the text are highlighted with different background colors, to indicate the scene. On the right column, an "Edit scene" menu is shown, with some form fields ("name", "highlight color" and "description"), and a list of scene appearances.

Concept for a script-writing app

I've been writing some scripts for videos I wanna record recently, which usually has me thinking about both the script and editing details at the same time.

I tried to find something that would let me annotate both of these things at the same time, but couldn't find anything, so I made a concept for an app that allows you to define both the script and the scenes in the same place.

Get on the waitlist

Explaining web3 to a non-crypto friend

I had to improvise an explanation for what "web3" means for a non-crypto friend recently, and thought it might make a useful resource for others too, so I turned it into a lil video.

New World ID docs

When we started working on World ID, we used Gitbook for the docs. With a little more time in our hands, we decided to move to a fully-custom docs site, and it turned out pretty nice!

Check them out!

Image support for Lens Reflect

Finally managed to add image support to Reflect! After you enable the images option from your dashboard, your Lens posts will keep their images when cross-posted to Twitter.

Try it out!
// Reference: https://replicate.com/m1guelpf/whisper-subtitles

fetch('https://api.replicate.com/v1/predictions', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        Authorization: `Token ${process.env.REPLICATE_API_TOKEN}`,
    },
    body: JSON.stringify({
        version: '7f686e243a96c7f6f0f481bcef24d688a1369ed3983cea348d1f43b879615766',
        input: { audio_path: 'https://path/to/audio.mp3', format: 'srt' },
    }),
})

A simple API for Whisper

Need an API to quickly transcribe some audio? I just pushed a version of OpenAI's Whisper specialized in generating subtitles (both SRT and VTT) to Replicate, which lets you transcribe audio in the cloud with no markup from the compute cost!

Try it out!
How Twitter hacked an AI (and how to prevent it)

www.youtube.com

How Twitter hacked an AI (and how to prevent it)

Last week, a job board company decided to make a Twitter bot that would reply to tweets about remote work automatically. It didn't work out great for them......

My first video

Yesterday I promised I'd stop procrastinating on video content and make a video on something. It's super basic (me talking to a camera), the editing is somewhat annoying, and could generally be improved A LOT, but it's here, and the next one will be better.

✨ Stable Diffusion is amazing, but unfortunately it isn't trivial to setup (especially for people without good GPUs). Instead, I made a Twitter bot that turns any reply to this tweet into an image, using SD! Let's see what you can come up with! 👇

A Stable Diffusion Twitter bot

Stable Diffusion is amazing, but unfortunately it isn't trivial to setup (especially for people without good GPUs). To share it with everyone, I made a Twitter bot that turns any tweet reply into an image, using SD.

Dynamic location for my website

As part of my quest to make my website more personal, I added a map showing where I am. It dynamically updates the location every day when I wake up, generates an Apple Maps screenshot, and a low-res placeholder.

Here's how I built it

"Now Playing" tile for my website

I've been trying to make my website feel a bit more personal, and I thought a peek into my music would be a fun start, so I built a real-time Spotify tile that shows what I'm listening to at the moment.

Human verification for Lens Protocol

Social has always has a big problem with bots & spam. Together with Lens Protocol we worked on a simple solution: Have users verify themselves as human in a completely anonymous way, using World ID. The human status is then made available to all apps via the Lens API.

Prototype for ⌘K authentication

Still from a project I never got to release, which used a ⌘K menu for wallet management.

Twitter cross-posting for Lens

With new social networks come new possibilities, but also the hassle of manually cross-posting content. To fix this, I built a simple tool that automatically tweets your Lens posts.

Lenster for iOS

I've been using Lenster a lot, and was getting tired of using Safari all the time, so I wrapped it into its own little app.

Join the Testflight
Lens Leaderboard: Most followed, active, collected & shared profiles

leaderboard.withlens.app

Lens Leaderboard: Most followed, active, collected & shared profiles

Open protocols offer new levels of transparency. This leaderboard uses 100% public data to rank notable profiles on the Lens Protocol.

A leaderboard for Lens

With every new social network, it's always interesting to keep track of the most active users and see how engagement evolves. Fortunately, Lens Protocol makes this super easy, since all the data is on-chain and indexed. So I built a little tool to look over the metrics.

Cleaning up my Twitter timeline

My timeline has been a bit of a mess lately, so I built a tool to improve it. It helps you go through every user you follow, view their most recent tweets and some useful stats (like % of RTs, tweets/day, time since last activity, etc.), then choose to unfollow or hide their retweets from your feed.

Recording a TV documentary

I've been helping out with a TV documentary about the future of tech for the biggest news channel in Spain. Today was recording day!

Running an Ethereum archive at home

Finally managed to get an Ethereum archive node running at home, and point all my wallets & apps to it. Self-sovereignty feels great, and RPC calls are much faster too!

Explaining crypto, Ethereum, NFTs & more FROM SCRATCH

www.youtube.com

Explaining crypto, Ethereum, NFTs & more FROM SCRATCH

Over the last few months, I went from knowing nothing about crypto to getting a job at a crypto startup. Then, I decided to rely my knowledge to a non-techni...

A 1h web3 crash course, for non-technical people

A few months ago, I made a stream where I got a non-technical friend and explained everything crypto to them, from blockchains and PoS, to smart contracts, ENS & more. I finally had time to edit the 5h of stream into a consumable video.

Making web apps in Solidity

Have you ever wanted to build a web app in Solidity? Me neither, but I built a barely-working server for it anyways.

View on GitHub

Animated fractal experiments

Played around with some fractal simulations now that I finally have a M1. Above is a Mandelbulb, a 3D version of the Mandelbrot set

View the source
We didn't get the Constitution, but we made history nonetheless. We broke records for the largest crowdfund for a physical object and most money crowdfunded in 72h, which will of course be refunded to everyone who participated. To all our 17,437 contributors, THANK YOU ❤️

ConstitutionDAO

Last month, my friends and I embarked on the crazy journey of trying to buy a copy of United States' Consitution. We built the DAO in less than a week and raised $42M in 4 days. Didn't end up winning, but it was a hell of a ride.

necromint.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "solmate/tokens/ERC721.sol";

struct Ghost {
    address contractAddress;
    uint256 tokenId;
}

contract Necromint is ERC721 {
    uint256 private _tokenIds;

    mapping(uint256 => Ghost) internal _ghostMap;
    mapping(bytes32 => bool) internal _uniqueMap;

    constructor() ERC721("Necromint", "DEAD") {}

    function resurrect(ERC721 spirit, uint256 soul) external returns (uint256) {
        uint256 tokenId = _tokenIds++;
        Ghost storage ghost = _ghostMap[tokenId];

        require(tokenId < 6669, "max supply");
        require(!_uniqueMap[keccak256(abi.encodePacked(spirit, soul))], "already resurrected");
        require(spirit.ownerOf(soul) == address(0x000000000000000000000000000000000000dEaD), "token not in cementery (yet?)");

        ghost.tokenId = soul;
        ghost.contractAddress = address(spirit);
        _uniqueMap[keccak256(abi.encodePacked(spirit, soul))] = true;

        _mint(msg.sender, tokenId);

        return tokenId;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_ownerOf(tokenId) != address(0), "token does not exist");
        Ghost memory ghost = _ghostMap[tokenId];

        return ERC721(ghost.contractAddress).tokenURI(ghost.tokenId);
    }
}

Necromint contract

Built an ERC721 contract that allows you to resurrect burned NFTs, inspired by Dom Hofmann

View on Etherscan

A WalletConnect iOS Bridge

Made a little iOS/iPadOS app that lets you use WalletConnect on sites where only MetaMask is supported.

Join the TestFlight

Roam Research iOS app

Got tired of waiting for a Roam Research app so I built my own! It comes with a native "Share to Roam" extension so you can finally send notes to Roam from the native iOS menu.

Join the TestFlight

DM Newsletters on Twitter

While playing around with the Twitter API, I discovered a hacky way to bring newsletters into the platform using a DM feature meant for business chats.

View on Twitter

Spoke at Laravel Worldwide Meetup

Gave a talk about different methods of authentication for Laravel at the Laravel Worldwide Meetup. Was a lot of fun!

Watch on YouTube

3D experiments

Played around with physics-based animations in Blender. Not super fancy-looking but hey, physics!

A WebAuthn Laravel package

Built a simple Laravel package that makes integrating WebAuthn into your app a breeze.

View on GitHub

Landing page design

A landing I designed for a product that never ended up getting announced. I designed this in Sketch, taking inspiration from the old Tuple and Level landing pages, and then built it with Tailwind CSS.

A new book-reading experience

To celebrate a few months with my girlfriend, I bought her an eBook. However, she doesn't have an eReader, so I built a simple web app to read it on following the stories format.

See the process

Shortcut macOS app

I wanted a desktop app for Shortcut (previously Clubhouse), but they aren't planning to release one soon, so I made it myself.

Neumorphic Sitesauce prototype

Over the last few days, I scratched the whole Sitesauce codebase (while keeping a copy on git obviously) and started over, focusing on the best UI & UX I could provide.

View full redesign

Reverse-engineering Byte

Spent some time reverse-engineering the Byte API, and managed to upload a video from outside the app!

Sitesauce UI refresh

I took some time this weekend to rebuild the entire Sitesauce UI from scratch (for like 3rd time!). Happy with this iteration so far.

Skeuomorphic credit card input

A very unique credit card input for Sitesauce (using Stripe Elements behind the scenes). Didn't end up making it onto the final product, but I still love it.

🎉 I'm incredibly excited to finally unveil what I've been working on for the past month. Sitesauce generates static sites from ANY dynamically-generated site and keeps them updated. Learn more and sign up for early access 👇

Announcing Sitesauce

Sitesauce generates static sites from ANY dynamically-generated site and keeps them updated. I've been working on it for over a month now, and I'm super excited to see where it goes!

Secret project prototype

Secret project video update: Been working on polishing UX & onboarding experience. Hoping to announce it very soon!

My first ever (un)conference talk!

I gave my first talk ever at the LaraconEU Unconference, and it was a great experience. Maybe I'll be on the main stage next year?

Custom backgrounds

Designed some new backgrounds for my devices, showing all the logos from past projects and my branding ✨

A Chrome extension to focus on your email

Inspired by Christian Genco, I buily a simple Chrome extension that strikes out the text of every single email except for the first one, forcing you to actually focus instead of just skimming through them.

Install extension

A theme uploader for Ghost

A Ghost theme marketplace prototype that could directly upload and update Ghost themes using undocumented API endpoints. Built in under two hours while streaming!

Launchpad OBS controls

Managed to get a really cool scene switching setup with my launchpad, using MIDI to control OBS Studio. I can now switch scenes and toggle sources with the push of a button!

Blog redesign prototype

An early version of my website's redesign which I ended up discarding.

Things web logger

I LOVE Things, but it's only available for iOS devices and I wanted to add tasks from my school Chromebook, so I made a little PWA that lets you add tasks from any device.

View on GitHub

Blogcast onboarding prototype

Built a nice onboarding for Blogcast, which explains the service and guides you while adding your first article, importing and enabling sync.

Snaptier designs

Snaptier was an automation project I worked on with some friends. We ended up shutting it down after a few months, but the designs were pretty cool.

Turn your blog into a podcast

Blogcast uses advanced text-to-speech technology to turn your blog into a podcast. I set myself the goal of going from idea to first paying customer in less than a week, and I'm happy to say I did it!

View on Product Hunt

Website redesign

Redesigned my website yet again, this time with a much cleaner look and cards for the articles. Also, dark mode!

Blogcast UI

Finally finished working on the UI flow for my new article-to-audio product! Still things to tweak, but here's an early preview.

A better Patreon for makers

Built a landing page for a product that never ended up launching. It was supposed to be a better Patreon for makers, with better integrations and an actually usable API.

An extension to toggle CSS from a website

I challenged myself to build something in an hour, and the result was a very simple Chrome extension that let you disable CSS on a website. It's now available on the Chrome Web Store!

Install extension

Personal Dashboard

A dynamic dashboard showing my calendar, Twitter interactions, current music, and more. Built with Laravel and Vue.js.

Video Embeds for Statamic

My second Statamic addon, which lets you embed videos from YouTube, Vimeo, and Wistia. It also supports custom embeds, and is fully configurable.

Beautiful docs for everyone

Since last summer, I've been working in my first real product. It aims to help everyone create beautiful documentation for their projects. Try it out!

{{-- Tired of doing this? --}}

@if (Auth::check())
    @include('super-secret-stuff')
@else
    @include('nothing-to-see-here')
@endif

{{-- Maybe it's even worse... --}}

@if (Auth::guard('api')->check())
    @include('super-secret-stuff')
@endif

{{-- Now you can simply --}}

@auth
    @include('super-secret-stuff')
@endauth

@auth('api')
    Yay, Auth Guards!
@endauth

Contributed to the Laravel framework

Added an @auth Blade directive, so you can easily check if a user is logged in or not.

View on GitHub

My first 3DS homebrew

Finally managed to get DevKitPro working, and write my first 3DS homebrew!