The complete code of the Python recipe is available on GitHub

Pretty tile avatars for subscribers

Rinaldo Nani
Variance Digital
Published in
6 min readOct 28, 2022

--

Give your users a custom artistic SVG icon.

When a user signs up to your site or app, you may automatically assign her a lovely custom tile, along with a nickname that can be easily remembered — and loosely connected to the tile.

This article describes a fast way to implement the “custom name + custom tile feature” in Python: we use this trick for our Flask applications and sites.

You can download the complete code of our demo “Minimal+User” Flask application from this public GitHub Repo. The “Minimal+User” site assigns custom names and tiles to the subscribing users. To see the demo follow this link.

1. SVG tiles: an example and its advantages

Usually, SVG image files do not contain information about the image’s individual pixels. Instead, they carry an XML text that describes the geometrical shapes that make up the picture. Figure 1 shows one of our SVG tiles and the content of its SVG representation (the ellipsis stands for polygons that have been left out from the diagram for brevity).

Fig.1 — An SVG tile and its XML text definition

When the browser needs to display an SVG image, it “draws” it in the defined place and at the declared size; this means that SVG images are resolution-independent.

Another advantage of SVG files is that they are typically lightweight; as they contain vectors and shapes in text format (instead of the data of all physical pixels), their size in bytes is usually tiny compared to high-resolution png-s or jpg-s.

If you create the SVG images with vector editing tools like Adobe Illustrator or Ink Scape, the elements that compose the image drawing will be represented with a shape SVG tag. And each shape will have fill and stroke color properties, as shown in Figure 1.

Given all the above, creating a custom tile is quite simple: get an SVG tile description (e.g., from the database) and change all its colors at pleasure. Then save the resulting modified tile’s SVG description as an SVG file on the cloud.

2. Our set of template tiles

We created a set of SVG tiles that the Flask app can use as templates: the Python code uses these SVG templates to create the customized tiles.

Our SVG templates are made using Adobe Illustrator. The SVG files saved by Illustrator contain a <style> tag with all the CSS classes used by the vector image. With the classes gathered in one place, replacing the image colors with Python is a breeze (see section 4).

You can get our template SVG tiles and use them as you like: they are stored in the database script of our “Minimal+User” Flask project here. Please read the README.md file for further instructions.

3. One table for the template tiles, one for the nouns

In the application’s database, we defined a table that contains the tile drawings in vector SVG format; each picture’s XML text file can fit in a text field of any database engine. We assigned a unique id to each SVG row.

In the same database schema, we have a table containing a list of words of three types:

  1. adjectives (type 1)
  2. animal names (type 2)
  3. web colors, with their names and hexadecimal color definition (type 3)

You can quickly grab lists of these words from the web, or you can get them from the database of the “Minimal+User” demo.

4. Create a nickname (with a Web color in it) and a custom tile (with a filename)

To create a nice nickname for our subscribing users, we can pick an adjective, an animal name, a number, and a color, all chosen randomly from the database table described in the previous section, then stick them together (separated by a hyphen). This will give us funny nicknames such as great-pony-395773-dark-salmon or lazy-hoopoe-948586-coral.

The pseudo-code to achieve this is almost banal:

def db_create_custom_name():   #0. Open db connection
...
#1. GET MIN AND MAX ID FOR ADJECTIVES
...
#1a. CREATE RANDOM ID FOR ADJECTIVE
rnd_adj_id = random.randint(min_adj_id,max_adj_id)
#2. GET MIN AND MAX ID FOR ANIMALS
...
#2a. CREATE RANDOM ID FOR ANIMALS
rnd_animal_id = random.randint(min_animal_id,max_animal_id)
#3. GET MIN AND MAX ID FOR COLORS
...
#3a. CREATE RANDOM ID FOR COLOR
rnd_color_id = random.randint(min_color_id,max_color_id)
#4 GET ADJECTIVE, NAME and COLOR
...
rnd_adj = record['nou_noun']
...
rnd_animal = record['nou_noun']
...
rnd_color_name = record['nou_noun']
rnd_color = "#"+record['nou_color']
#GET RANDOM NUMBER
rnd_number = create_numeric_otp()

#CREATE CUSTOM NICKNAME
custom_name = "{}-{}-{}-{}"
.format(rnd_adj,rnd_animal,rnd_number,rnd_color_name)
return custom_name, rnd_color

Note that the function returns the color code of the color name used to compose the nickname (the rnd_color variable). This particular color will be used as one of the custom tile’s colors 😎.

Now comes the custom tile part.

def db_create_custom_tile(custom_color):   #0. Open db connection
...
#1. COUNT TILES
...
num_tiles = count_col['count']

#2. SELECT ONE TILE RANDOMLY
...
user_tile = cur.fetchone()
#3. CREATE AN UNIQUE FILENAME FOR THE CUSTOM TILE
unique_filename = str(uuid.uuid4())+'.svg'
#4. GET SVG XML TEXT OF TILE
tile_text = user_tile['tle_svg']

#5. FIND ALL THE COLORS OF THE TILE
fills = re.findall(r'cls-\d+{fill:#\w+;}', tile_text)
allcolors = list(map(lambda x: re.findall('#\w+;',x)[0], fills))
#6. SUBSTITUTE ALL COLORS WITH RANDOM COLORS
# FIRST AND LAST COLORS ARE SPECIAL
r = lambda: random.randint(0,255)
for idx, c in enumerate(allcolors):
#THE FIRST COLOR IS THE CUSTOM NICKNAME COLOR!
if idx == 0:
tile_text = tile_text.replace(c, custom_color)
else:
randomcolor = '#{:02x}{:02x}{:02x}'.format(r(), r(), r())
tile_text = tile_text.replace(c,randomcolor)
#7. CHOOSE A RANDOM FLUE COLOR
fluecolors =["#c71585","#ff1493",...]
fluerandomcolor = random.choice(fluecolors)

#8. THE LAST OF THE TILE'S COLORS IS
SUBSTITUTED WITH A FLUE COLOR
tile_text = tile_text.replace(randomcolor,fluerandomcolor)
return unique_filename, tile_text

As you can see, to obtain the new tile, we substitute each color of the template tile with a new random color; but with a grain of salt:

  • the first color is set to the web color coming from the user’s nickname;
  • the last color is chosen from a list of “flou” colors that can be tweaked as you prefer.

The filename of the custom tile, along with the user nickname, will be saved in the database table containing user data. As an example, see how our db_create_user_entry() function does it.

6. Save the user’s custom tile in the cloud (e.g., Amazon S3 bucket)

Now that we have the custom tile's XML text and its future file name, we can save the tile to a cloud repository. Here is the snippet needed to save the tile on an Amazon S3 bucket.

import boto3, botocoredef gets3():
return boto3.client("s3",
aws_access_key_id=os.environ['AWS_ACCESS_KEY'],
aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'])
def write_tile_to_s3(filename, bucket_name, svgtext):
s3 = gets3()
s3.put_object(Body=svgtext, Bucket=bucket_name, Key=filename,
ContentType='image/svg+xml')

The boto3 package enables Python to upload (and delete) files to AWS S3 buckets; to make the snippet code work, you should install the package with pip (possibly in a virtual environment):

pip install boto3

Remember to update your requirements.txt file if you want to publish your application online. This file is already set up in our “Minimal+User” demo project.

Note: to use AWS S3 APIs, you’ll need the access key and secret you can obtain from the AWS console once you subscribe to Amazon Web Services.
Furthermore, to define the S3 bucket as “public” — so that anyone can see the files stored in it — you should set the bucket permission policies (and CORS) accordingly.
If you have trouble configuring AWS S3, contact us: we can help.

6. Use the tile in your HTML

Once the custom tile SVG file is saved on the cloud (and the SVG filename is associated with the user’s record in the database), one can use the tile image on any webpage using the usual HTML <img> tag, as in the code snipped below.

<img src=”[tile_url][tile_filename]” width=”64" height=”64">

If AWS S3 is used to store the SVG files, the [tile_url][tile_filename] will be the Object URL of the SVG file; the [tile_url] is usually retrieved from an environment variable of your Flask app, while [tile_filename] is usually fetched from the user’s related database record.

7. Conclusions

If you want to see the tile creation mechanism in action, go to our demo “Minimal+User” site and subscribe for a free ride. You will receive a custom tile and nickname. If you want to grab the complete Flask project code of the site, click here.

Please contact us if you have any suggestions on improving our code. By the way: we are adding new template tiles to the app database these days, so stay tuned.

--

--

Rinaldo Nani
Variance Digital

Algorithmist ▪ Software Engineer ▪ Project manager. I love maths and music + solving hard problems.