{"id":17526480,"url":"https://github.com/kodehat/portkey","last_synced_at":"2026-04-05T15:00:49.556Z","repository":{"id":223513039,"uuid":"760535852","full_name":"kodehat/portkey","owner":"kodehat","description":"A simple web portal that can act as startup page and shows a collection of links/urls. Also supports adding custom pages. Everything with one config file.","archived":false,"fork":false,"pushed_at":"2026-04-05T13:01:38.000Z","size":7185,"stargazers_count":101,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-05T13:08:32.982Z","etag":null,"topics":["dashboard","golang","portal","webapplication"],"latest_commit_sha":null,"homepage":"https://demo.portkey.page","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kodehat.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-02-20T15:46:31.000Z","updated_at":"2026-04-05T13:01:44.000Z","dependencies_parsed_at":"2026-04-05T15:00:34.004Z","dependency_job_id":null,"html_url":"https://github.com/kodehat/portkey","commit_stats":null,"previous_names":["kodehat/portkey"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/kodehat/portkey","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodehat%2Fportkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodehat%2Fportkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodehat%2Fportkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodehat%2Fportkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kodehat","download_url":"https://codeload.github.com/kodehat/portkey/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodehat%2Fportkey/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31439442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T13:13:19.330Z","status":"ssl_error","status_checked_at":"2026-04-05T13:13:17.778Z","response_time":75,"last_error":"SSL_read: 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":["dashboard","golang","portal","webapplication"],"created_at":"2024-10-20T15:01:49.006Z","updated_at":"2026-04-05T15:00:49.539Z","avatar_url":"https://github.com/kodehat.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"docs/images/logo.png\" alt=\"portkey logo\"\u003e\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eportkey\u003c/h1\u003e\n\u003cdiv align=\"center\"\u003e\n  ⚡🚀🔗\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cstrong\u003eRepository of the portkey application\u003c/strong\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  A simple web portal that can act as startup page and shows a collection of links/urls. It also supports adding small custom pages.\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003c!-- Sonar quality gate --\u003e\n  \u003ca href=\"https://sonarcloud.io/project/overview?id=kodehat_portkey\"\u003e\n    \u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=kodehat_portkey\u0026metric=alert_status\"\n      alt=\"Sonar quality gate\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- GitHub stars --\u003e\n  \u003ca href=\"https://github.com/kodehat/portkey\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/kodehat/portkey\"\n      alt=\"GitHub stars\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- Go version --\u003e\n  \u003cimg src=\"https://img.shields.io/github/go-mod/go-version/kodehat/portkey\"\n      alt=\"Go version\" /\u003e\n  \u003c!-- Docker image size --\u003e\n  \u003ca href=\"https://hub.docker.com/r/codehat/portkey\"\u003e\n    \u003cimg src=\"https://img.shields.io/docker/image-size/codehat/portkey\"\n      alt=\"Docker image size\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003e\n    \u003ca href=\"https://www.portkey.page\"\u003e\n      Website (GitHub)\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"https://github.com/kodehat/portkey/blob/main/.github/CONTRIBUTING.md\"\u003e\n      Contributing\n    \u003c/a\u003e\n  \u003c/h3\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003csub\u003eAs magical as in Harry Potter. Built with ☕️ by\n  \u003ca href=\"https://www.codehat.de\"\u003eCodeHat\u003c/a\u003e and\n  \u003ca href=\"https://github.com/kodehat/portkey/graphs/contributors\"\u003e\n    contributors\n  \u003c/a\u003e\u003c/sub\u003e\n\u003c/div\u003e\n\n## Table of Contents\n\n- [Features](#features)\n- [Screenshots](#screenshots)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [Metrics](#metrics)\n- [Docker](#docker)\n- [Development](#development)\n- [See Also](#see-also)\n- [License](#license)\n\n## Features\n\n- 🔗 Shows a collection of links acting as startup page or similar.\n- 🔎 Includes a search box with configurable keyword support and fuzzy matching.\n- 📂 Portals can be organised into named groups/sections on the home page.\n- 📄 Can be configured easily by modifying only one file.\n- 🗒️ Also supports adding smaller custom pages.\n- 🌓 Dark and light mode available.\n- 🪰 Very lightweight application with Docker images available.\n\n## Screenshots\n\n\u003cp\u003eYou can also find a demo \u003ca href=\"https://demo.portkey.page\"\u003ehere\u003c/a\u003e\u003c/p\u003e\n\n\u003cdetails\u003e\n\n  \u003csummary\u003eClick to view screenshots\u003c/summary\u003e\n\n  #### Link collection\n\n  ![LinkCollection](docs/images/screenshot_full.png \"Link collection\")\n  \n  #### Search for a link\n\n  ![SearchForLink](docs/images/screenshot_search.png \"Search for a link\")\n\n  #### Custom page\n  \n  ![CustomPage](docs/images/screenshot_custom_page.png \"Custom page\")\n\n\u003c/details\u003e\n\n## Installation\n\nDownload the `portkey` file for your OS. Probably to a location that is in your `PATH`, so you can use it right away. \n\n## Usage\n\n1. Create a `config.yml` or use the [example configuration](https://github.com/kodehat/portkey/blob/main/config.yml) from this repository and configure it as you want.\n\u003e You can find a detailed explanation of all configuration options [here](#configuration).\n2. Start the application with `portkey --config-path=\u003cdir_to_config_yml\u003e`. Providing the path to the configuration file is optional if it's in the working directory.\n3. Open your browser at the defined host and port. Default is \u003chttp://localhost:3000\u003e\n\n## Configuration\n\n`portkey` is configured with a single configuration file called `config.yml`. You can pass its location using the `--config-path` argument.\n\nYou can also overwrite configuration values from file by using environment variables in uppercase and prefixed with `PORTKEY_`. For instance, the configuration key `host` can be passed as environment variable `PORTKEY_HOST`.\n\nThe `config.yml` contains the following configuration options:\n\n### Server\n\n```yaml\n# Can be changed to reduce or increase logs. Values could be \"ERROR\", \"WARN\", \"INFO\" (default) or \"DEBUG\".\nlogLevel: INFO\n# If enabled logs are in JSON format.\nlogJson: false\n# Set the host where the application should bind to.\nhost: localhost\n# Set the port where the application should bind to.\nport: 3000\n# Set the context path (aka base-url) portkey is hosted under. Must not be specified unless you're using a reverse proxy and are hosting portkey under a directory. If that's the case then you can set this value to e.g. /portkey or whatever the directory is called. Note that the forward slash (/) in the beginning is required!\ncontextPath: \"\"\n# Enables the HTTP server that serves metrics that can be scraped by e.g. Prometheus.\nenableMetrics: false\n# Set the host where the metrics server should bind to.\nmetricsHost: localhost\n# Set the port where the metrics server should bind to.\nmetricsPort: 3030\n```\n\n### Styling\n\n```yaml\n# Title of the application shown in the browser tab and on the front page.\ntitle: \"portkey\"\n# Allows to hide the title.\nhideTitle: false\n# If set, a subtitle is shown below the title.\nsubtitle: \"Where do you want to go?\"\n# Allows adding additional scripts/stylesheets etc. to the HTML header. Can be useful for analytics or smaller style modifications.\nheaderAddition: |-\n  \u003cscript async src=\"https://analytics.example.com\"\u003e\u003c/script\u003e\n# Footer (HTML support) that is shown on every page.\n# Remember that Tailwind CSS classes used here do only work if already used somewhere else in the application because the bundler couldn't look here!\nfooter: |-\n  \u003cp\u003eThis is a footer!\u003c/p\u003e\n# Defines whether portkey's application icon should be shown at the top left of the front page.\nshowTopIcon: true\n# If true keywords of portals are shown as tooltip on hover.\nshowKeywordsAsTooltips: false\n# If true all links are sorted alphabetically when shown on the front page. Otherwise they are shown in the order they are defined.\nsortAlphabetically: false\n# If true search query is also compared to portals and keywords using Levenshtein string metric.\nsearchWithStringSimilarity: false\n# Minimum required similarity for results when 'searchWithStringSimilarity' is 'true'. Must be between '0.0' (0%) and '1.0' (100%).\nminimumStringSimilarity: 0.5\n# If true, search bar is hidden. Can be useful with a low amount of portals making the search unnecessary.\nhideSearchBar: false\n```\n\n### Portals (Links)\n\n```yaml\n# Defines a list of portals (links) that have additional attributes defining their appearance.\nportals:\n  # Name of the link\n- title: example\n  # (Optional) An emoji shown in front of the title.\n  emoji: 🔗\n  # Link where the portal will lead to (can be relative for custom pages or absolute otherwise)\n  link: https://example.com/\n  # Additional keywords used by the search feature.\n  keywords:\n  - url\n  - example\n  # (Optional) Group name for organising portals into sections on the home page.\n  # Portals sharing the same group value are rendered together under a labelled heading.\n  # Portals without a group are shown ungrouped at the bottom. Groups appear in the\n  # order the first portal of each group is defined.\n  group: My Group\n```\n\n\u003e **Tip:** When a search query is active, portals are shown as a flat list regardless of their group. Groups are only visible on the default (empty-query) home view.\n\n### Custom pages\n\n```yaml\n# Defines a list of custom pages that are made available at the defined paths.\n# Important: These are not automatically added to the list of portals and have to be added manually!\n# This may be changed in the future.\npages:\n  # Heading for the custom page. Shown in browser tab and as heading on the page.\n- heading: Custom\n  # If true, shows the (optionally configured) subtitle also on this page.\n  showSubtitle: true\n  # Path where the custom page will be available.\n  path: /custom\n  # Content of the custom page and it supports using HTML.\n  # The same CSS rules apply as for the footer!\n  content: |-\n    This is a \u003cem\u003ecustom page\u003c/em\u003e\u003cbr\u003e\n    It also supports using \u003cstrong\u003eHTML\u003c/strong\u003e!\n```\n\n## Metrics\n\nMetrics can be enabled with the `enableMetrics` configuration key and are served on a dedicated HTTP server. By default they are served on `http://localhost:3030/metrics`. Use this address to configure your tool of choice (e.g. [Prometheus](https://prometheus.io/)) to scrape the exported metrics.\n\nBesides the default metrics provided by the [Prometheus instrumentation library for Go applications ](https://github.com/prometheus/client_golang), the following additional metrics are provided:\n\n```plain\n# HELP portkey_page_handler_requests_total Total number of HTTP requests by page.\n# TYPE portkey_page_handler_requests_total counter\nportkey_page_handler_requests_total{path=\"\u003cpage_path\u003e\"} 0\n\n# HELP portkey_portal_handler_requests_total Total number of HTTP requests by portal.\n# TYPE portkey_portal_handler_requests_total counter\nportkey_portal_handler_requests_total{portal=\"\u003cportal_title\u003e\"} 0\n\n# HELP portkey_search_requests_no_results_total Total number of HTTP requests for search with no results.\n# TYPE portkey_search_requests_no_results_total counter\nportkey_search_requests_no_results_total 0\n\n# HELP portkey_search_requests_with_results_total Total number of HTTP requests for search with at least one result.\n# TYPE portkey_search_requests_with_results_total counter\nportkey_search_requests_with_results_total 0\n\n# HELP portkey_version_info Version information about portkey.\n# TYPE portkey_version_info gauge\nportkey_version_info{buildTime=\"2024.10.09_17:29:19\",commitHash=\"4fd1a0f\",goVersion=\"1.23.1\",version=\"dev\"} 1\n```\n\n## Docker\n\nThere are also Docker images available at Docker hub that you can use. You can start a container with the following command:\n\n```sh\n# Assumes that there is a config.yml in the current directory.\n# It is probably better to use a specific version than 'latest'.\ndocker run --rm -it -v $(PWD)/config.yml:/opt/config.yml -p 3000:3000 codehat/portkey:latest\n```\n\n## Development\n\n### Application Code\n\n**portkey** is a *Go* application. You can install its dependencies with `go mod download`.\n\n### Frontend\n\nThe frontend dependencies (e.g. TailwindCSS, AlpineJS) can be installed with `npm install --include dev`.\n\nThey can be watched with `npm run watch` and built with `npm run build`.\n\n### Templates\n\nA library called [templ](https://templ.guide) is used for the templates. To generate the `.go` files from the templates, it has to be installed. `templ` is installed using go tools and can be invoked with:\n\n```sh\ngo tool templ\n```\n\nAfterwards you can generate the compiled templates with `templ generate`.\n\n### Live Reload\n\nLive reloading is possible by installing [air](https://github.com/cosmtrek/air) and calling `air`.\n`air` is installed using go tools and can be invoked with:\n\n```sh\ngo tool air\n```\n\n## See Also\n\nThe whole application is heavily inspired by a theme for the static site generator Hugo. You can find the theme at [victoriadrake/hugo-theme-sam](https://github.com/victoriadrake/hugo-theme-sam). I wanted something more dynamic while also trying out Go and improving in the language.\n\n## License\n\n[AGPL-3.0](https://www.tldrlegal.com/license/gnu-affero-general-public-license-v3-agpl-3-0)","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodehat%2Fportkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkodehat%2Fportkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodehat%2Fportkey/lists"}