{"id":15285780,"url":"https://github.com/emarifer/gocms","last_synced_at":"2025-07-24T15:32:31.661Z","repository":{"id":223661755,"uuid":"760455443","full_name":"emarifer/goCMS","owner":"emarifer","description":"goCMS is a headless CMS (Content Management System) written in Golang using Gin framework + \u003c/\u003eHtmx \u0026 A-H Templ, designed to be fast, efficient, and easily extensible. It allows you to create a website or blog, with any template you like, in only a few commands.","archived":false,"fork":false,"pushed_at":"2024-03-26T12:03:37.000Z","size":296,"stargazers_count":21,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-01T11:50:26.934Z","etag":null,"topics":["clean-architecture","cms","dependency-injection","error-middleware","gin-framework","gin-gonic","go","golang","hateoas","headless-cms","htmx","layered-architecture","response-caching","server-side-rendering","templ"],"latest_commit_sha":null,"homepage":"","language":"Go","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/emarifer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2024-02-20T13:04:08.000Z","updated_at":"2025-02-25T08:51:14.000Z","dependencies_parsed_at":"2024-03-26T13:27:34.706Z","dependency_job_id":"c77999c3-e2b6-45e5-adb6-7c6a995060ca","html_url":"https://github.com/emarifer/goCMS","commit_stats":null,"previous_names":["emarifer/gocms"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/emarifer/goCMS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2FgoCMS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2FgoCMS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2FgoCMS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2FgoCMS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emarifer","download_url":"https://codeload.github.com/emarifer/goCMS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2FgoCMS/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266862606,"owners_count":23996866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-24T02:00:09.469Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["clean-architecture","cms","dependency-injection","error-middleware","gin-framework","gin-gonic","go","golang","hateoas","headless-cms","htmx","layered-architecture","response-caching","server-side-rendering","templ"],"created_at":"2024-09-30T15:07:35.952Z","updated_at":"2025-07-24T15:32:31.321Z","avatar_url":"https://github.com/emarifer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \n\u003ch1 align=\"center\"\u003egoCMS\u003c/h1\u003e\n\n\u003cimg src=\"doc/cms-logo.png\" width=\"55%\"\u003e\n\n\u003chr /\u003e\n\n\u003cp style=\"margin-bottom: 8px;\"\u003e\n\ngoCMS is a headless CMS (Content Management System) written in Golang using Gin framework + \u003c/\u003eHtmx \u0026 A-H Templ, designed to be fast, efficient, and easily extensible. It allows you to create a website or blog, with any template you like, in only a few commands.\n\n\u003c/p\u003e\n  \n![GitHub License](https://img.shields.io/github/license/emarifer/url-shortener-echo-templ-htmx) ![Static Badge](https://img.shields.io/badge/Go-%3E=1.22-blue)\n\n\u003c/div\u003e\n\n\u003chr /\u003e\n\n## Features 🚀\n\n- [x] **Headless Architecture:** Adding pages, posts, or forms should all\n  be done with easy requests to the API.\n- [x] **Golang-Powered:** Leverage the performance and safety of one of the\n  best languages in the market for backend development.\n- [x] **SQL Database Integration:** Store your posts and pages in SQL databases for reliable and scalable data storage.\n- [x] **Centralized HTTP error handling:** The user receives feedback about the Http errors that their actions may cause, through the use of middleware that centralizes the Http errors that occur.\n- [x] **Caching HTML responses from endpoints:** Own implementation of an in-memory cache that stores HTML responses for 10 minutes in a map with mutex lock R/W access.\n- [x] **Live Reload:** through the use of `air`.\n- [x] **Possibility for the user to add their own plugins written in `Lua`:** this feature allows you to customize the admin application at runtime.\n- [ ] **Post**: We can add, update, and delete posts. Posts can be served\n  through a unique URL.\n- [ ] **Pages**: TODO.\n- [ ] **Menus**: TODO\n  \n\u003cbr /\u003e\n\n\u003e[!IMPORTANT]\n\u003e***The Go language uses [html/template](https://pkg.go.dev/html/template) package to render HTML. In this application we have used the [a-h/templ](https://github.com/a-h/templ) library instead. The main difference is that templ uses a generation step to compile the files .templ into Go code (as functions). This means that the templates are type-safe and can be checked at compile time. This amazing library implements a templating language (very similar to JSX) which allows you to write code almost identical to Go (with expressions, control flow, if/else, for loops, etc.) and have autocompletion. For all these reasons, calling these templates from the controllers side will always require the correct data, minimizing errors and thus increasing the security and speed of our coding.***\n\n## Installation\n\nEnsure you have Golang installed on your system before proceeding with the installation.\n\n```bash\ngo get -u github.com/emarifer/gocms\n```\n\n### Example - Running the App (user application) manually\n\nFirst, make sure you have the necessary executable binaries to run and work with the application.\n\n```bash\nmake install-tools\n```\n\nAfter that, with the `MariaDB` database engine running, with the idea of populating the database with some sample data, make sure to run the migrations with the previously installed `Goose` tool. We recommend creating a database called `cms_db` and running the following command:\n\n```bash\nGOOSE_DRIVER=\"mysql\" GOOSE_DBSTRING=\"root:root@/cms_db\" goose up\n```\nReplace the database connection string with the appropriate string\ndependending on where your database is.\n\nAfter you've replaced the default template files with your prefered\ntemplate, simply build and start the app with the following commands.\n\n```bash\ngo mod tidy \u0026\u0026 go build -ldflags=\"-s -w\" -v -o ./tmp/gocms ./cmd/gocms \u0026\u0026 ./tmp/gocms\n```\n\nAlternatively, the `air` command will allow us to start the user application (also creating the admin application executable), having, however, with said command the possibility of hot reloading after any change in the user/admin applications code.\n\nThis will start `goCMS` on `http://localhost:8080`. If we have used the `air` command we can start the admin application with the `make run` (on `http://localhost:8081`) command. You can customize the configuration by providing the necessary environment variables.\n\n```bash\n# e.g.\n\nDATABASE_PORT=3306 ./tmp/gocms-admin\n```\n\nFor more information, see the [configuration settings](#configuration).\n\n### Example - Running with Docker Compose (user \u0026 admin applications)\n\nIn this case the only requirement is to have `Docker` installed and running.\n\nTo create the image and the `Docker` containers and start the application you only need to run the following command in the project folder:\n\n```bash\nmake run-containers\n```\nThe above will create an Ubuntu:jammy image and, within that OS, will install Golang, Goose, A-H.Templ and Air. Next, from said image and the mariadb:jammy image, you will create and start two containers: one containing the `goCMS` app, serving on port `8080`, and another one serving the `mariadb` database internally. This will also run the migrations automatically to setup the database!\n\nTo stop and eliminate both containers we will execute the following in another terminal:\n\n```bash\ndocker compose down # to stop and remove containers (run in another terminal)\n```\n\nIf we do not plan to delete the containers with the idea of continuing to reuse them, we will simply press `Ctrl+C` in the same terminal. This will stop the containers without deleting them. The next time we want to start the application we will run `make run-containers` again.\n\nAs long as we have created/run the aforementioned containers, the management application executable file will have been created. To start it (within `Docker`), simply run the following commands:\n\n```bash\ndocker exec -it docker-gocms-1 sh # to enter the `docker-gocms-1` container\n\ncd gocms \u0026\u0026 make start-admin-container # to enter the project folder (inside the container) and start the admin application\n```\n\n\u003e[!NOTE]\n\u003e***the above serves the application in `http://localhost:8081`.***\n\n## Architecture\n\nCurrently, the architecture of `goCMS` is still in its early days.\nThe plan is to have two main applications: the public facing application\nto serve the content through a website, and the admin application that\ncan be hidden, where users can modify the settings, add posts, pages, etc.\n\n## Configuration\n\nThe runtime configuration can be done through a [toml](https://toml.io/en/) configuration file or by setting the mandatory environment variables (*fallback*). This approach was chosen because configuration via toml supports advanced features (i.e. *relationships*, *arrays*, etc.). The `.dev.env`-file used only for the `goose up` command, they are not needed for `Docker` files.\n\n### `.toml` configuration\n\nThe application can be started by providing the `config` flag which has to be set to a toml configuration file. The file has to contain the following mandatory values:\n\n```toml\nwebserver_port = 8080 # port to run the webserver on\nadmin_webserver_port = 8081 # port to run the webserver (admin) on\ndatabase_host = \"localhost\" # database host (address to the MariaDB database)\ndatabase_port = 3306 # database port\ndatabase_user = \"root\" # database user\ndatabase_password = \"my-secret-pw\" # database password\ndatabase_name = \"cms_db\" # name of the database that is created through `Docker`\nimage_dir = \"./media\" # directory to use for storing uploaded images\n\n# optional: directives containing the name and path of user-supplied `Lua` plugins\n# e.g.\n\n[[shortcodes]]\nname = \"img\"\n# must have function \"HandleShortcode(arguments []string) -\u003e string\"\nplugin = \"plugins/image_shortcode.lua\"\n```\n\n\u003e[!NOTE]\n\u003e***The above configuration values are used to start the local development database, in addition to the user/admin application ports, media storage folder, or optionally, admin plugins directives.***\n\n### Environment variables configuration (fallback)\n\nIf chosen, by setting the following environment variables the application can be started without providing a toml configuration file (although a file of this type is necessary to establish the directives of user plugins written in `Lua`). \n\n- `WEBSERVER_PORT` port the application should run on\n- `ADMIN_WEBSERVER_PORT` the same as the previous one but for the admin app\n- `DATABASE_HOST` should contain the database addres, e.g. `localhost`\n- `DATABASE_PORT` should be the connection port to the db, e.g. `3306`\n- `DATABASE_USER` is the database username.\n- `DATABASE_PASSWORD` needs to contain the database password for the given user.\n- `DATABASE_NAME` sets the name of the database `goCMS` will use.\n- `IMAGE_DIRECTORY` directory images should be stored to if uploaded to `goCMS`\n\nTo the above (as we have already mentioned), we would have to add an environment variable (`CONFIG_FILE_PATH`) that contains the path to a `.toml` file that contains the directives for the plugins (`Lua` scripts) that the user wants add. This file would have the form:\n\n```toml\n# e.g.\n\n[[shortcodes]]\nname = \"img\"\n# must have function \"HandleShortcode(arguments []string) -\u003e string\"\nplugin = \"plugins/image_shortcode.lua\"\n```\n\n## Development\n\nTo facilitate the development process, `Docker` is highly recommended. This way you can use `docker/mariadb.yml` to configure a predefined MariaDB database server. The file `mariadb.yml` creates the database `cms_db`.\n\n```bash\n$ make start-devdb\n```\n\nTo populate the aforementioned db with some sample data you can use this command:\n\n```bash\n$ make run-migrations\n```\n\n## License\n\n`goCMS` is released under the MIT License. See LICENSE for\ndetails. Feel free to fork, modify, and use it in your projects!\n\n---\n\n## Happy coding 😀!!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarifer%2Fgocms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femarifer%2Fgocms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarifer%2Fgocms/lists"}