Skip to content

Image storages

This document outlines the standard practices for image management within our project.

For image format guidelines, optimization recommendations, and workflow with designers, see Image Guidelines for Designers.

Image storages

There are two main storages:

  1. This git repository, resources/img directory (processed by Vite::asset()). For:
    • UI elements (icons, logos, backgrounds)
    • Default images (stubs)
    • Any small images that are part of the application's core design
  2. AWS S3 ixdf--images bucket (s3-images filesystem disk). For:
    • User-uploaded content (profile pictures, images for entities stored in Database (example: courses))
    • High-resolution images (to avoid git repo bloat)
    • Large images (>1Mb) (to avoid git repo bloat)
    • Cache for generated images (e.g., certificates)
    • Images that change frequently (to avoid git repo bloat)
    • Images used in emails and other notifications (persistent URLs)

While using this repository is easier for the development process, we should avoid storing large images here to prevent the repository from becoming bloated.

Store Decision Matrix

ScenarioStorage Option
Small, static UI elementsGit Repository
Large images (>1MB)AWS S3 (ixdf--images)
User-uploaded contentAWS S3 (ixdf--images)
Frequently changing imagesAWS S3 (ixdf--images)
Images needed in emails with persistent URLsAWS S3 (ixdf--images)
Part of application's core designGit Repository
Downloadable images, docs and archivesAWS S3 (ixdf--assets)

CDN

Both stores are connected to CDNs (CloudFront) to ensure optimal performance:

  • assets.interaction-design.org domain Vite assets (stored in GitHub repo and then distributed via our CDN (E1UQEIYQ3OG2MM Distribution ID))
  • public-images.interaction-design.org for s3-images disk (ixdf--images bucket)

You don't need to add the domain to the URL, these functions will do it for you:

  • Vite::asset() for Vite assets. Example: Vite::asset('resources/img/pictograms/member-placeholder.svg')
  • public_img_url() for s3-images disk. Example: public_img_url($member->picture_pic_url)

Vite

Vite::asset('resources/img/pictograms/member-placeholder.svg') output examples from different envs:

URLenv
http://localhost/build/assets/idf-member-CvAHbb8S.svglocal
https://staging.ixdf.dev/build/assets/idf-member-CvAHbb8S.svgstaging
https://assets.interaction-design.org/build/assets/idf-member-CvAHbb8S.svgproduction

Production URLs are served by CloudFront CDN, because of the ASSET_URL .env variable.

Hash part of the URL (-CvAHbb8S) is generated based on the file content (checksum) and thus changed only when the file content is changed.

Vite::asset vs. @vite

Please don't confuse Vite::asset() calls with @vite('resources/pcss/pages/uxArticle.css') Blade directive. The first one generates a URL for an asset file, while the second one generates <link> or <script> tag with an URL inside (it does even more, like resource prefetch tags, but it's out of the topic of this doc).

Other storages

There are some other places where we store images:

  1. Other deprecated S3 buckets (mostly idf--assets that is linked to the public-media.interaction-design.org domain and s3 disk, also connected to the ImageKit).
  2. CSS using url('data:image.... Rarely used, please avoid using it.
  3. HTML using <img src="data:image...">, usually to inject SVG. Rarely used, please avoid using it.

Legacy note

There is one legacy trick we use for historical reasons on nginx level: redirect all /images/* requests to the public-media.interaction-design.org domain:

shell
# Redirecting assets to the CloudFront distribution (CDN)
rewrite ^/(images)/(.*)$ https://public-media.interaction-design.org/$1/$2 redirect;

This allows not specifying domain for such URLs in the codebase, but is considered a bad practice and should be avoided in new code.