Hayden Bleasel


Share and find inspiration from AI-generated art.

Published on Sep 16, 20234 min read

In January 2023, I launched an app for sharing and finding inspiration from AI-generated art. It was called Desync.art. Today, Desync is moving to a new home with my friends at Surge Studio — a digital product studio. This is a short retrospective of the project and my experience so I can learn from it, using the lessons to guide my decisions going forward.

The idea for Desync stemmed from a private Discord channel I had with a few friends. We would use Midjourney to generate art and share it with each other. It was a fun way to see what the AI was capable of and to share our favorite pieces. I wanted to create a place where the focus was on the prompt so others could generate their own similar art.

You could upload your best creations from DALL-E, Midjourney and Stable Diffusion along with the prompt. It would be featured on a continuously updating feed of art on the homepage, as well as on your personal profile. You could also follow other users and like their art.

The ProductHunt launch was relatively small but it was a good way to get feedback from the community. I was able to get a few users to upload their art and I was able to see what they liked and didn't like about the platform. I also got a few ideas for features that I could add.

From a technical perspective, the frontend was easy enough (file upload, feed, profile, etc.) but the backend was a bit more challenging. While I'm no stranger to file uploads, having to set up an entire AWS account for S3 and deal with their presigning, IAM and permissions approach was painful. While the pricing was good, the sheer weight of the AWS ecosystem was a bit much for the standard Beskar rapid-iteration stack.

One thing I was happy with was my setup for automatic image optimization. Images generated by Midjourney are output as PNGs which, given the subject of the images, is suboptimal. I set up a Lambda function that would listen for new images in the S3 bucket and convert them to JPEGs using Python. This was a great way to learn more about Lambda and S3 events.

import boto3
from PIL import Image
s3 = boto3.client('s3')
def lambda_handler(event, context):
  # Get the name of the S3 bucket and the key of the object
  bucket = event['Records'][0]['s3']['bucket']['name']
  key = event['Records'][0]['s3']['object']['key']
  # Create local image refs
  png = '/tmp/image.png'
  jpg = '/tmp/image.jpg'
  # Download the PNG image from S3
  response = s3.download_file(bucket, key, png)
  # Create a jpg_key
  jpg_key = key.replace('.png', '.jpg')
  # Open the PNG image and convert it to JPG
  with Image.open(png) as png_image:
      png_image.convert('RGB').save(jpg, 'JPEG', quality=95, optimize=True)
      # jpg_image = png_image
  # Save the JPG image back to S3
  s3.upload_file(jpg, bucket, jpg_key, ExtraArgs={'ContentType': 'image/jpeg'})
  # Delete the original PNG
  s3.delete_object(Bucket=bucket, Key=key)

Even this simple function was painful because I had to create a "layer" in the Lambda containing Pillow - the Python library containing the Image utility I needed. Additionally, I setup a CloudFront distribution to serve the images from S3 and cache them to reduce the load on the S3 bucket.

Interestingly, my main takeaway from building this was that there needs to be a "Vercel of S3" — a file storage solution that abstracts the complexity of a raw file storage solution like S3 and provides a simple, developer-friendly interface. Plus, if it could run on the Edge, that would be even better. Then, lo and behold, Vercel announced Blob Storage, so I migrated the images over to that.

Anyway, after much thought, I handed the keys for Desync over to Surge Studio. It fits well with their existing apps that focus on AI image generation and prompt engineering.

If I were to start again, I'd probably focus on the following things: improving the ability to share, adding the ability to generate images in-app (no Midjourney API yet 😭). The primary challenge then will likely be the lack of advantage over an existing media sharing platform with a strong distribution network, like Instagram.

That's all for now, hope you enjoyed my little write-up.

Lessons Learned:

  • Don't use AWS lol.
  • I quite like writing Python in Lambdas. But locally, package management and Python binaries are a nightmare compared to Node / NPM.
  • Anything requiring user-generated content is both a blessing and a curse.
  • People tend to want a holistic experience, not a last-mile solution.