{"id":18965546,"url":"https://github.com/celliesprojects/use_google_fonts_locally","last_synced_at":"2026-04-29T10:34:32.580Z","repository":{"id":87569242,"uuid":"550751133","full_name":"CelliesProjects/use_google_fonts_locally","owner":"CelliesProjects","description":"In this example we are going to serve the Google Roboto font from your ESP32 instead of through the Google API. This means downloading the font files, renaming them, converting to C-style header files and finally use them with ESPAsynWebServer.","archived":false,"fork":false,"pushed_at":"2022-10-15T08:48:29.000Z","size":93,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-02T08:26:47.553Z","etag":null,"topics":["arduino-sketch","esp32","esp32-arduino","espasyncwebserver","google-fonts","local-storage","woff2"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CelliesProjects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-13T09:11:42.000Z","updated_at":"2025-01-22T15:22:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"2a5977f6-2a6f-494e-b16b-fcf50858b3bc","html_url":"https://github.com/CelliesProjects/use_google_fonts_locally","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CelliesProjects/use_google_fonts_locally","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CelliesProjects%2Fuse_google_fonts_locally","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CelliesProjects%2Fuse_google_fonts_locally/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CelliesProjects%2Fuse_google_fonts_locally/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CelliesProjects%2Fuse_google_fonts_locally/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CelliesProjects","download_url":"https://codeload.github.com/CelliesProjects/use_google_fonts_locally/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CelliesProjects%2Fuse_google_fonts_locally/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32422048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T06:29:02.080Z","status":"ssl_error","status_checked_at":"2026-04-29T06:29:00.631Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino-sketch","esp32","esp32-arduino","espasyncwebserver","google-fonts","local-storage","woff2"],"created_at":"2024-11-08T14:29:59.001Z","updated_at":"2026-04-29T10:34:32.561Z","avatar_url":"https://github.com/CelliesProjects.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to host Google fonts from your ESP32 with ESPAsyncWebServer\n\nIn this example we are going to serve the Google Roboto font from your ESP32 instead of through the Google API. This means downloading the font files, renaming them, converting to C-style header files and finally use them with ESPAsynWebServer.\n\nA simple example sketch on how to set up the HTML files and [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) is included.\n\n## Steps needed\n\n1. Locate the font on [https://fonts.google.com/](https://fonts.google.com/). \n\n2. You will need to download the font through the Google font API which can be found at `https://fonts.googleapis.com/css2`.\u003cbr\u003e\nSee [https://developers.google.com/fonts/docs/css2](https://developers.google.com/fonts/docs/css2). No account is needed to download the font files.\n\n3. Open the link [https://fonts.googleapis.com/css2?family=Roboto](https://fonts.googleapis.com/css2?family=Roboto) in your browser and locate your local font variants. \nIn this case `latin` and `latin-ext`. (Western alphabet and western accented letters) \n\n4. Download the files linked to in the line `src: url()` to the folder where your sketch is.\nThese are for Roboto `https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2` for latin-ext and `https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2` for latin.\n\n5. Rename the files to some easier names to remember, I used `Roboto-latin.woff2` and `Roboto-latin-ext.woff2`.\n\n6. Copy the complete CSS `@font-face{}` section containg the desired variants to the CSS section of the HTML file hosted on the ESP32. Change the `src: url` lines like below:\n```css\n/* latin-ext */\n@font-face {\n  font-family: 'Roboto';\n  font-style: normal;\n  font-weight: 400;\n  src: url(/Roboto-latin-ext.woff2) format('woff2');\n  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Roboto';\n  font-style: normal;\n  font-weight: 400;\n  src: url(/Roboto-latin.woff2) format('woff2');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n```\n\n7. To be able to use the font files in your project you have to convert the font files to C-style header files with `xxd`:  \n`xxd -i inputfile \u003e outputfile`.\u003cbr\u003e  \nThis will become `xxd -i Roboto-latin.woff2 \u003e Roboto-latin.h` for the `latin` file and `xxd -i Roboto-latin-ext.woff2 \u003e Roboto-latin-ext.h` for the `latin-ext` file.  \nThis works on most Linux installs, if you are using Windows you have to find an alternative to `xxd`.\n\n8. In the generated files, change the first line to `const unsigned char Roboto_latin_woff2[] ...` and the last line to `const unsigned int Roboto_latin_woff2_len ...;`   \nBecause if you don't declare the array as a `const`, it will end up in RAM memory instead of in FLASH memory.  \nYou will have to do this for all files hosted on your ESP32. (`index.htm` and both `*.woff2` files)\n\n9. Include `Roboto-latin.h` and `Roboto-latin-ext.h` in your sketch. See below.\n\n10. Set up ASyncWebServer to use the `Content-Type` header `application/x-font-woff2` when serving these files.\u003cbr\u003e\nUse the [`request-\u003ebeginResponse_P()`](https://github.com/me-no-dev/ESPAsyncWebServer#send-binary-content-from-progmem) function to serve data from flash memory.\n```c++\n#include \"index_htm.h\"\n#include \"Roboto-latin.h\"\n#include \"Roboto-latin-ext.h\"\n...\n...\nvoid setup() {\n    ...\n    ...\n    static AsyncWebServer http_server(80);\n    static const char* CONTENT_TYPE_HTML {\"text/html\"};\n    static const char* CONTENT_TYPE_WOFF2 {\"application/x-font-woff2\"};\n\n    http_server.on(\"/\", HTTP_GET, [](AsyncWebServerRequest * const request) {\n        AsyncWebServerResponse* const response = request-\u003ebeginResponse_P(200, CONTENT_TYPE_HTML, index_htm, index_htm_len);\n        request-\u003esend(response);\n    });\n\n    http_server.on(\"/Roboto-latin-ext.woff2\", HTTP_GET, [](AsyncWebServerRequest * const request) {\n        AsyncWebServerResponse* const response = request-\u003ebeginResponse_P(200, CONTENT_TYPE_WOFF2, Roboto_latin_ext_woff2, Roboto_latin_ext_woff2_len);\n        request-\u003esend(response);\n    });\n\n    http_server.on(\"/Roboto-latin.woff2\", HTTP_GET, [](AsyncWebServerRequest * const request) {\n        AsyncWebServerResponse* const response = request-\u003ebeginResponse_P(200, CONTENT_TYPE_WOFF2, Roboto_latin_woff2, Roboto_latin_woff2_len);\n        request-\u003esend(response);\n    });\n...\n    ...\n```\n\n## That's it\n\nIncluded are the files used in this example. The example sketch will set up a simple webserver and show some text in the locally hosted `Roboto` font.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcelliesprojects%2Fuse_google_fonts_locally","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcelliesprojects%2Fuse_google_fonts_locally","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcelliesprojects%2Fuse_google_fonts_locally/lists"}