{"id":20621454,"url":"https://github.com/emarifer/url-shortener-echo-templ-htmx","last_synced_at":"2025-10-12T20:09:03.169Z","repository":{"id":218216091,"uuid":"745619418","full_name":"emarifer/url-shortener-echo-templ-htmx","owner":"emarifer","description":"Go/Echo+Templ+Htmx: Url Shortener App","archived":false,"fork":false,"pushed_at":"2024-01-27T20:21:47.000Z","size":764,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-15T12:18:22.227Z","etag":null,"topics":["authentication-middleware","clean-architecture","dependency-injection","echo-framework","error-handling","error-middleware","go","golang","hateoas","htmx","hyperscript","layered-architecture","link-shortener","restful","server-side-rendering","session-middleware","tailwindcss","templ","templating-language","url-shortener"],"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,"publiccode":null,"codemeta":null}},"created_at":"2024-01-19T18:16:12.000Z","updated_at":"2025-02-26T05:52:15.000Z","dependencies_parsed_at":"2024-01-27T21:32:49.369Z","dependency_job_id":"0d698345-3d6f-46a2-8ac7-998a6290e211","html_url":"https://github.com/emarifer/url-shortener-echo-templ-htmx","commit_stats":null,"previous_names":["emarifer/url-shortener-echo-templ-htmx"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/emarifer/url-shortener-echo-templ-htmx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2Furl-shortener-echo-templ-htmx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2Furl-shortener-echo-templ-htmx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2Furl-shortener-echo-templ-htmx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2Furl-shortener-echo-templ-htmx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emarifer","download_url":"https://codeload.github.com/emarifer/url-shortener-echo-templ-htmx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarifer%2Furl-shortener-echo-templ-htmx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279012794,"owners_count":26085187,"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-10-12T02:00:06.719Z","response_time":53,"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":["authentication-middleware","clean-architecture","dependency-injection","echo-framework","error-handling","error-middleware","go","golang","hateoas","htmx","hyperscript","layered-architecture","link-shortener","restful","server-side-rendering","session-middleware","tailwindcss","templ","templating-language","url-shortener"],"created_at":"2024-11-16T12:17:54.864Z","updated_at":"2025-10-12T20:09:03.137Z","avatar_url":"https://github.com/emarifer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \n\u003ch1 align=\"center\"\u003eShortify\u003c/h1\u003e\n\n\u003cimg src=\"doc/banner.png\" width=\"100%\"\u003e\n\n\u003chr /\u003e\n\n\u003cp style=\"margin-bottom: 8px;\"\u003e\n\nA Full Stack Url Shortener App using Golang's Echo framework + \u003c/\u003eHTMX \u0026 Templ.\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.18-blue)\n\n\u003c/div\u003e\n\n\u003chr /\u003e\n\n## 🤔 What Stack have we used?\n\nIn the implementation of this application we have used the following technologies:\n\n- ✅ **Bootstrapping**: [Go programming language (v1.21)](https://go.dev/)\n- ✅ **Backend Framework**: [Echo v4.11.4 ](https://echo.labstack.com/)\n- ✅ **Auth \u0026 Session middleware**: [Echo Contrib Session](https://github.com/labstack/echo-contrib/)\n- ✅ **Dependency Injection**: [Fx - dependency injection system for Go](https://uber-go.github.io/fx/)\n- ✅ **Database**: [PostgreSQL](https://www.postgresql.org/)\n- ✅ **Styling**: [TailwindCSS + DaisyUI](https://tailwindcss.com)\n- ✅ **Frontend interactivity**: [\u003c/\u003eHtmx + _Hyperscript](https://htmx.org/)\n- ✅ **Templating Language**: [\u003c/\u003eTempl - build HTML with Go](https://templ.guide/)\n- ✅ **Popup Boxes (Alerts)**: [Sweetalert2 - responsive \u0026 customizable replacement for JavaScript's popup boxes](https://sweetalert2.github.io/)\n  \n\u003cbr /\u003e\n\n\u003e[!NOTE]\n\u003e***The use of [\u003c/\u003ehtmx](https://htmx.org/) allows behavior similar to that of a SPA, without page reloads when switching from one route to another or when making requests (via AJAX) to the backend. Likewise, the [_hyperscript](https://hyperscript.org/) library allows you to add some dynamic features to the frontend in a very easy way.***\n  \n\n\u003e[!IMPORTANT]\n\u003e***In this application, instead of using the [html/template](https://pkg.go.dev/html/template) package (native Golang templates), we use the [a-h/templ](https://github.com/a-h/templ) library. This amazing library implements a templating language (very similar to JSX) that compiles to Go code. Templ will allow us to write code almost identical to Go (with expressions, control flow, if/else, for loops, etc.) and have autocompletion thanks to strong typing. This means that errors appear at compile time and any calls to these templates (which are compiled as Go functions) from the handlers side will always require the correct data, minimizing errors and thus increasing the security and speed of our coding.***\n\n---\n\n## 🖼️ Screenshots:\n\n\u003cdiv align=\"center\"\u003e\n\n###### Home \u0026 Login Pages with success alert:\n\n\u003cimg src=\"doc/screenshot-01.png\" width=\"35%\" align=\"top\"\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cimg src=\"doc/screenshot-02-v.2.png\" width=\"35%\"\u003e\n\n###### Short link creator Page and Dashboard Page with alerts:\n\n\u003cimg src=\"doc/screenshot-03.png\" width=\"35%\" align=\"top\"\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cimg src=\"doc/screenshot-04-v.2.png\" width=\"35%\"\u003e\n\n###### Dashboard Page with alert and Short Link Update Modal:\n\n\u003cimg src=\"doc/screenshot-05.png\" width=\"35%\" align=\"top\"\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cimg src=\"doc/screenshot-06.png\" width=\"35%\"\u003e\n\n###### Centralized HTTP error handling:\n\n\u003cimg src=\"doc/screenshot-07.png\" width=\"40%\" align=\"top\"\u003e\n\n\u003c/div\u003e\n\n---\n\n## 📦 Project structure\n\n```\n- assets\n  |- css\n  |- img\n- database\n- encryption\n- internal\n  |- api\n    |- dto\n  |- entity\n  |- model\n  |- repository\n  |- service\n- postgresdb_init\n- settings\n- timezone_conversion\n- views\n  |- auth_views\n  |- components\n  |- errors_pages\n  |- layout\n  |- links_views\n```\n\n\u003cbr /\u003e\n\n\u003cimg src=\"doc/flow.svg\" width=\"100%\"\u003e\n\n\u003cbr /\u003e\n\n\n\u003e[!NOTE]\n\u003e***In this application, we have tried to apply a [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) pattern. The architecture follows a typical \"onion model\" where each layer doesn't know about the layer above it, and each layer is responsible for a specific thing. Although the application is extremely simple, we use this pattern to illustrate its use in more complex applications. Layering an application in this way can simplify code structure, since the responsibility of each type is clear. To ensure that each part of the application is initialized with its dependencies, each struct defines a constructor (the New function in this example). Related to the latter, we have used a dependency injector ([Fx](https://uber-go.github.io/fx/) from uber-go), which helps to remove the global state in the application and add new components and have them instantly accessible across the application.***\n\n\u003e[!TIP]\n\u003e***When applying this approach in a real-life application, as with most things, taking the layering approach to an extreme level can have a negative effect. Ask yourself if what you are doing actually helps make the code understandable or simply spreads the application logic across many files and makes the overall structure difficult to see.***\n\n\n## 👨‍🚀 Getting Started\n\nBesides the obvious prerequisite of having Go! on your machine, you must have Air installed for hot reloading when editing code.\n\nSince we use the PostgreSQL database from a Docker container, it is necessary to have the latter also installed and execute this command in the project folder:\n\n```\n$ docker compose up -d\n```\n\nThese other commands will also be useful to manage the database from its container:\n\n```\n$ docker container start shortify-db # start container\n$ docker container stop shortify-db # stop container\n$ docker exec -it shortify-db psql -U admin -W shortify_db # (pass: admin) access the database\n```\n\nDownload the necessary dependencies:\n\n```\n$ go mod tidy\n```\n\nStart the app in development mode:\n\n```\n$ air # Ctrl + C to stop the application\n```\n\nBuild for production:\n\n```\n$ go build -ldflags=\"-s -w\" -o ./bin/main . # ./bin/main to run the application / Ctrl + C to stop the application\n```\n\n\u003e[!TIP]\n\u003e***In order to have autocompletion and syntax highlighting in VS Code for the Teml templating language, you will have to install the [templ-vscode](https://marketplace.visualstudio.com/items?itemName=a-h.templ) extension (for vim/nvim install this [plugin](https://github.com/joerdav/templ.vim)). To generate the Go code corresponding to these templates you will have to download this [executable binary](https://github.com/a-h/templ/releases/tag/v0.2.476) from Github and place it in the PATH of your system. The command:***\n\n```\n$ templ generate --watch\n```\n\n\u003e[!TIP]\n\u003e***This will allow us to monitor changes to the .templ files and compile them as we save them. Review the documentation on Templ [installation](https://templ.guide/quick-start/installation) and [support](https://templ.guide/commands-and-tools/ide-support/) for your IDE.***\n\n---\n\n### Happy coding 😀!!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarifer%2Furl-shortener-echo-templ-htmx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femarifer%2Furl-shortener-echo-templ-htmx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarifer%2Furl-shortener-echo-templ-htmx/lists"}