{"id":21988886,"url":"https://github.com/alessandro-salerno/htmc","last_synced_at":"2026-03-02T13:02:51.313Z","repository":{"id":258404325,"uuid":"858852511","full_name":"Alessandro-Salerno/htmc","owner":"Alessandro-Salerno","description":"Ever wanted to code a website in C? No? Well, now you can!","archived":false,"fork":false,"pushed_at":"2024-11-22T23:16:57.000Z","size":14942,"stargazers_count":19,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-30T12:15:27.429Z","etag":null,"topics":["backend","c","cgi","cli","dynamic-linking","dynamic-webpages","dynamic-websites","frontend","go","golang","html","html5","http-server","hypertext-preprocessor","linux","mit-license","shared-object","unix","web-server"],"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/Alessandro-Salerno.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-09-17T16:38:08.000Z","updated_at":"2025-01-12T18:23:17.000Z","dependencies_parsed_at":"2025-04-30T12:07:23.286Z","dependency_job_id":null,"html_url":"https://github.com/Alessandro-Salerno/htmc","commit_stats":null,"previous_names":["alessandro-salerno/htmc"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Alessandro-Salerno/htmc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2Fhtmc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2Fhtmc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2Fhtmc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2Fhtmc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alessandro-Salerno","download_url":"https://codeload.github.com/Alessandro-Salerno/htmc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alessandro-Salerno%2Fhtmc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30003475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T12:19:43.414Z","status":"ssl_error","status_checked_at":"2026-03-02T12:19:02.215Z","response_time":60,"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":["backend","c","cgi","cli","dynamic-linking","dynamic-webpages","dynamic-websites","frontend","go","golang","html","html5","http-server","hypertext-preprocessor","linux","mit-license","shared-object","unix","web-server"],"created_at":"2024-11-29T19:26:12.969Z","updated_at":"2026-03-02T13:02:51.294Z","avatar_url":"https://github.com/Alessandro-Salerno.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"[contributors-shield]: https://img.shields.io/github/contributors/Alessandro-Salerno/htmc.svg?style=flat-square\n[contributors-url]: https://github.com/Alessandro-Salerno/htmc/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/Alessandro-Salerno/htmc.svg?style=flat-square\n[forks-url]: https://github.com/Alessandro-Salerno/htmc/network/members\n[stars-shield]: https://img.shields.io/github/stars/Alessandro-Salerno/htmc.svg?style=flat-square\n[stars-url]: https://github.com/Alessandro-Salerno/htmc/stargazers\n[issues-shield]: https://img.shields.io/github/issues/Alessandro-Salerno/htmc.svg?style=flat-square\n[issues-url]: https://github.com/Alessandro-Salerno/htmc/issues\n[license-shield]: https://img.shields.io/github/license/Alessandro-Salerno/htmc.svg?style=flat-square\n[license-url]: https://github.com/Alessandro-Salerno/htmc/blob/master/LICENSE.txt\n\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n![](https://tokei.rs/b1/github/Alessandro-Salerno/htmc)\n\n\u003cbr\u003e\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\".github/htmc-logo.svg\" height=\"120\"\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n# What is htmc?\nhtmc is a tool that allows you to easily integrate C code in your HTML pages and vice versa. Files ending in `.htmc` can be used to describe the structure of a page statically in HTML and dynamically in C, much like other hypertex preprocessors such as [PHP](https://www.php.net/).  Regular C source files can also be compiled with htmc and used to generate fully dynamic web pages.\n\n# Why use htmc?\nhtmc uses [GCC](https://gcc.gnu.org/) and the [GNU Linker](https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html) to generate highly optimized native binaries that can be cached and run on demande via htmc. **In theory**, this allows for much faster execution* compared to many common [interpreted languages](https://en.wikipedia.org/wiki/Interpreter_(computing)) like PHP, Python, and JavaScript. \n\nWriting web code in C can also be a fun challenge or academic exercise. Given enough tinkering, you can get htmc to do everything you need in a dynamic web page or HTTP API endpoint.\n\n\\* _The performance of code executed through htmc has not been tested yet. Also, most important optimizations have yet to be implemented as they stricly require htmc to integrate a web server of its own._\n\n# Ways to use htmc\nhtmc is built to support multiple usecases. As of now, htmc can be used:\n1. As a CLI tool\n2. As a [CGI](https://it.wikipedia.org/wiki/Common_Gateway_Interface) script\n3. As a static library (using headers from the `include` directory and `libhtmc.a`)\n\nThe recommended mode for serving web content is CGI as it allows for easy integration with existing web software.\n\n## Integrated web server\nCGI is known to be old and slow, hence why htmc will get its own web server at some point. The integrated web server will use preallocated [arenas](https://www.rfleury.com/p/untangling-lifetimes-the-arena-allocator), memory and network optimizations to maximize execution speed and minimize overhead, hopefully.\n\n# How to use htmc easily\n\n\n\u003cdetails\u003e\n    \u003csummary\u003eRequirements\u003c/summary\u003e\n\n\u003cbr\u003e\n    \n- Modern GCC Compiler or equivilent\n- Decently recent version of the GNU Linker or equivilent\n- GNU + Linux or other compatible Linux-based systems\n\n**NOTE:** As of now replacing GCC or GNU Linker with other software is not encouraged. Some commandline options specified by htmc may be different in other compilers/linkers.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eHow to use libhtmc\u003c/summary\u003e\n\n\u003cbr\u003e\n\nlibhtmc contains all htmc functions. The library can be used in other native programs to integrate htmc, but also includes an interface to interact with the htmc runtime and manipulate HTML code\n\n| Function interface | Description |\n| - | - |\n| `void  htmc_bind(htmc_handover_t *handover)` | Binds an `htmc_handover_t` pointer to the current htmc execution unit |\n| `int   htmc_printf(const char *fmt, ...)` | Writes a formatted string to the HTML page |\n| `int   htmc_vpprintf(const char *fmt, va_list args)` | Writes a formatted string to the HTML page |\n| `int   htmc_puts(const cahr *s)` | Write a plain-text string to the HTML page (faster than `htmc_printf`) |\n| `int   htmc_query_scanf(const char *fmt, ...)` | Reads values from HTTP query arguments |\n| `int   htmc_query_vscanf(const char *fmt, va_list args)` | Reads values from HTTP query arguments |\n| `int   htmc_form_scanf(const char *fmt, ...)` | Reads values from HTTP body arguments in POST requests |\n| `int   htmc_form_vscanf(const char *fmt, va_list args)`  | Reads values from HTTP body arguments in POST requests |\n| `int   htmc_error(const char *fmt, ...)` | Throws a formatted error message |\n| `void *htmc_alloc(size_t size)` | Returns a `void *` to a memory buffer of the requested size or `NULL` if it fails |\n| `void  htmc_free(void *ptr)` | Frees a memory buffer allocated with `htmc_alloc` |\n\n\u003c/details\u003e\n\n\n## CGI web server\nThe easiest way to use htmc is to create a simple CGI web server in a high level language and invoke htmc when handling requests. In this example, [Golang](https://go.dev/) is used as it's one of the simplest native languages that supports these features out of the box. A Golang web server is included in this repository.\n\n1. Downlaod the latest `htmc-cgi-ws` for Linux from [here](https://alessandro-salerno.github.io/htmc/bin/htmc-cgi-ws)\n2. Create a directory for the server and move `htmc-cgi-ws` into it\n3. Make sure that `htmc-cgi-ws` is recognized as an executable\n```\nchmod +x ./htmc-cgi-ws\n```\n4. Run `htmc-cgi-ws` as super user (if needed) and follow the instructions on screen\n```\n[alevm@alevm ws]$ sudo ./htmc-cgi-ws \nYou're missing some important htmc files, proceed with the download? [Y/n]: Y\nDownloading \u003chttps://alessandro-salerno.github.io/htmc/bin/htmc\u003e to ./bin/htmc ... Done!\nDownloading \u003chttps://alessandro-salerno.github.io/htmc/bin/libhtmc.a\u003e to ./bin/libhtmc.a ... Done!\nDownloading \u003chttps://alessandro-salerno.github.io/htmc/include/libhtmc/libhtmc.h\u003e to ./include/libhtmc/libhtmc.h ... Done!\nDownloading \u003chttps://alessandro-salerno.github.io/htmc/examples/index.htmc\u003e to ./index.htmc ... Done!\nListening on localhost:80\n```\n5. An example page should now be available at `localhost/index.htmc`\n\n# How to build htmc\n\n\u003cdetails\u003e\n    \u003csummary\u003eRequirements\u003c/summary\u003e\n\n\u003cbr\u003e\n    \n- C compiler compatible with C23 (C2x)\n- Linker that supports LTO\n- Make\n- Go\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eExpected behaviour\u003c/summary\u003e\n\n\u003cbr\u003e\n    \n```\nCompiling for linux\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/cli.c -o obj/common/cli.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/compile.c -o obj/common/compile.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/emit.c -o obj/common/emit.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/libhtmc/impl/base-impl.c -o obj/common/libhtmc/impl/base-impl.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/libhtmc/impl/debug-impl.c -o obj/common/libhtmc/impl/debug-impl.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/libhtmc/libhtmc.c -o obj/common/libhtmc/libhtmc.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/load.c -o obj/common/load.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/log.c -o obj/common/log.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/main.c -o obj/common/main.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/parse.c -o obj/common/parse.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -flto -c src/common/util.c -o obj/common/util.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/cli.c -o lib/common/cli.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/compile.c -o lib/common/compile.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/emit.c -o lib/common/emit.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/libhtmc/impl/base-impl.c -o lib/common/libhtmc/impl/base-impl.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/libhtmc/impl/debug-impl.c -o lib/common/libhtmc/impl/debug-impl.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/libhtmc/libhtmc.c -o lib/common/libhtmc/libhtmc.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/load.c -o lib/common/load.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/log.c -o lib/common/log.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/main.c -o lib/common/main.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/parse.c -o lib/common/parse.o\ngcc -O2 -std=c2x -Wno-unused-parameter -Iinclude/ -DEXT_HTMC_BUILD=\"\\\"24.10.09\\\"\" -fPIC -g -w -c src/common/util.c -o lib/common/util.o\ngcc -flto obj/common/cli.o obj/common/compile.o obj/common/emit.o obj/common/libhtmc/impl/base-impl.o obj/common/libhtmc/impl/debug-impl.o obj/common/libhtmc/libhtmc.o obj/common/load.o obj/common/log.o obj/common/main.o obj/common/parse.o obj/common/util.o -o bin/htmc\nar rcs bin/libhtmc.a lib/common/cli.o lib/common/compile.o lib/common/emit.o lib/common/libhtmc/impl/base-impl.o lib/common/libhtmc/impl/debug-impl.o lib/common/libhtmc/libhtmc.o lib/common/load.o lib/common/log.o lib/common/main.o lib/common/parse.o lib/common/util.o\ncd cgi-ws \u0026\u0026 go build -o ../bin/htmc-cgi-ws\nFinished!\nalessandrosalerno@MacBook-Pro-di-Alessandro-3 htmc %\n\n\n\n```\n\n\u003c/details\u003e\n\n1. Clone this repository\n```\ngit clone https://github.com/Alessandro-Salerno/htmc\n```\n2. Enter the repository's directory\n```\ncd htmc/\n```\n3. Use the make command to build htmc\n```\nmake\n```\n\n**NOTE:** The default make target is `all`. Alternative make targets are:\n```bash\nmake htmc         # Build ONLY the executable\nmake libhtmc      # Build ONLY the library\nmake htmc-cgi-ws  # Build ONLY the CGI Web Server\n```\n\n# Screenshot\n\n\u003cimg src=\".github/screenshots/screenshot1.png\"\u003e\n\n# License\nhtmc is distributed under the terms of the MIT license. See [LICENSE](LICENSE) for more information.\n\n# Credits\nThis project was initially inspired by [PKD667/cweb](https://github.com/PKD667/cweb).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessandro-salerno%2Fhtmc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessandro-salerno%2Fhtmc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessandro-salerno%2Fhtmc/lists"}