Expand my Community achievements bar.

SOLVED

How to best host fonts in AEM?

Avatar

Level 4
Level 4

Hey guys,

 

We received Libre Franklin fonts (.ttf) files which we want to include in our codebase.

I am trying to add them to path - ui.apps/src/main/content/jcr_root/apps/project/clientlibs/clientlib-site/resources but get the below prompt -

 

The following paths are ignored by one of your .gitignore files:
ui.apps/src/main/content/jcr_root/apps/project/clientlibs/clientlib-site
hint: Use -f if you really want to add them.
hint: Turn this message off by running
hint: "git config advice.addIgnoredFile false"

 

Should I change my gitignore config or move it at some other location?

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hey @_CL ,

I think you should place it in ui.frontend module - Give this blog by @Imran__Khan  a read AEM ui.frontend module Complete Guide
Quoting from the above - 
dist → This contains front end fonts, images and minified version of JS and CSS files. npm run dev build command helps us to move/copy files from ui.frontend/src to ui.frontend/dist and ui.apps folder.

Rohan_Garg_0-1727275776147.png


Hope this helps!

View solution in original post

8 Replies

Avatar

Correct answer by
Community Advisor

Hey @_CL ,

I think you should place it in ui.frontend module - Give this blog by @Imran__Khan  a read AEM ui.frontend module Complete Guide
Quoting from the above - 
dist → This contains front end fonts, images and minified version of JS and CSS files. npm run dev build command helps us to move/copy files from ui.frontend/src to ui.frontend/dist and ui.apps folder.

Rohan_Garg_0-1727275776147.png


Hope this helps!

Avatar

Level 4
Level 4

thanks @Rohan_Garg, what is the disadvantage of putting it directly in /apps/project/clientlibs?

Avatar

Community Advisor

It will get overridden when ui.frontend files are put in the ui.apps folder.

aem-clientlib-generator plugin moves all compiled CSS, JS and other resources into the ui.apps module.

Avatar

Community Advisor

In my opinion, best way to embed a custom font for an AEM project is to store web-safe font files directly into a client library; self hosted. The fonts are then referenced by the CSS stylesheet, where the font file paths are the proxied client libraries URI. Using the CSS rule, @Font-face, we are able to configure custom fonts for an AEM project. Also, serving fonts directly from AEM allows you to apply performance improvements, in caching mechanisms on the browser and CDN.

 

Once you have added resources into the ui.frontend, the code compilation is expected to export the client library under /apps/sourcedcode/clientlibs/*. From here, ensure that your client library is enabled with allowProxy="{Boolean}true". From here, you should be able to call the proxied paths.

inspect_element_0-1727279632504.png


Usage in ui.frontend .scss files, example:

 

 

 

  @Font-face {
    font-family: "Roboto";
    src: url("/etc.clientlibs/sourcedcode/clientlibs/clientlib-site/resources/fonts/roboto-bold.otf") format("truetype");
    font-style: normal;
    font-weight: 700;
  }

  @Font-face {
    font-family: "Roboto";
    src: url("/etc.clientlibs/sourcedcode/clientlibs/clientlib-site/resources/fonts/roboto-medium.otf") format("truetype");
    font-style: normal;
    font-weight: 500;
  }

  @Font-face {
    font-family: "Roboto";
    src: url("/etc.clientlibs/sourcedcode/clientlibs/clientlib-site/resources/fonts/roboto-regular.otf") format("truetype");
    font-style: normal;
    font-weight: 300;
  }

 

 

 

 

CDN Rules for WOFF (from WKND Project):

 

 

<LocationMatch "^/etc\.clientlibs/.*\.(?i:js|css|ttf|woff2)$">
        Header set Cache-Control "max-age=2592000,stale-while-revalidate=43200,stale-if-error=43200,public,immutable" "expr=%{REQUEST_STATUS} < 400"
        Header set Age 0
    </LocationMatch>

 

 

https://github.com/adobe/aem-guides-wknd/blob/a5915afb2f48a602bbe8ea24680dd8fe81962198/dispatcher/sr...

This configuration uses an <LocationMatch> directive to apply specific HTTP headers for certain file types in the specified path (/etc.clientlibs/). Here’s a summary of what each part does:

  1. LocationMatch: This block applies to URLs that match the regular expression pattern, specifically files with extensions .js, .css, .ttf, or .woff2, case-insensitively.

  2. Header set Cache-Control: This sets caching headers for the matched resources:

    • max-age=2592000: Caches the response for 30 days.
    • stale-while-revalidate=43200: Allows the stale cached response to be served for 12 more hours while fetching a fresh one.
    • stale-if-error=43200: Allows serving the cached response for 12 hours if an error occurs during the fresh fetch.
    • public: Indicates that the response can be cached by any cache.
    • immutable: Suggests that the resources won’t change, allowing for long-term caching.
  3. Header set Age 0: Sets the Age header to 0, indicating that the response is fresh and has not been in cache.

 

Useful blog articles:

3 Different Ways to Embed Custom Fonts in AEM Sites - Sourced Code

How to Serve Static Assets in AEM as Client Library Resources - Sourced Code

P.S, you can literally clone exactly what the WKND project is doing, as this is the proper way to implement exactly what I have mentioned above: aem-guides-wknd/ui.frontend/src/main/webpack/resources/fonts at main · adobe/aem-guides-wknd · GitHu...

Avatar

Level 4
Level 4

hey @BrianKasingli , thanks for the detailed reply - one query - should I directly place the files in /apps/project/clientlibs or in ui.frontend as @Rohan_Garg has suggested?

Avatar

Community Advisor

Hey @_CL , its best practice to place resource files into the ui.frontend. Please copy exactly what the WKND project is doing here, and this is the way to do it https://github.com/adobe/aem-guides-wknd/tree/main/ui.frontend/src/main/webpack/resources/fonts



The disadvantage of hard coding the resources under /apps/my-site/clientlibs/clientlib-site/resources/* is that whenever your code is re-compiling code, then whatever you place in there will be gone... this is because the ui.frontend uses the clientlib-generator, which will re-produce /apps/my-site/clientlibs/clientlib-site on maven build.