{"id":13393883,"url":"https://github.com/asticode/go-astilectron","last_synced_at":"2026-01-14T18:33:39.240Z","repository":{"id":37664968,"uuid":"89053951","full_name":"asticode/go-astilectron","owner":"asticode","description":"Build cross platform GUI apps with GO and HTML/JS/CSS (powered by Electron)","archived":true,"fork":false,"pushed_at":"2024-02-16T13:49:55.000Z","size":682,"stargazers_count":4895,"open_issues_count":54,"forks_count":342,"subscribers_count":132,"default_branch":"master","last_synced_at":"2025-03-12T18:41:16.948Z","etag":null,"topics":["cross-platform","desktop-app","electron","go","golang","gui"],"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/asticode.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":"2017-04-22T07:59:15.000Z","updated_at":"2025-03-11T22:07:09.000Z","dependencies_parsed_at":"2024-06-18T11:18:01.769Z","dependency_job_id":null,"html_url":"https://github.com/asticode/go-astilectron","commit_stats":{"total_commits":213,"total_committers":41,"mean_commits":5.195121951219512,"dds":0.2676056338028169,"last_synced_commit":"26d5ce8e32757b60d8e2937303673f7a8a913c75"},"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"purl":"pkg:github/asticode/go-astilectron","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asticode%2Fgo-astilectron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asticode%2Fgo-astilectron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asticode%2Fgo-astilectron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asticode%2Fgo-astilectron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asticode","download_url":"https://codeload.github.com/asticode/go-astilectron/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asticode%2Fgo-astilectron/sbom","scorecard":{"id":213384,"data":{"date":"2025-08-11","repo":{"name":"github.com/asticode/go-astilectron","commit":"927a6da863781826ad63db7a27703b68214fcf74"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Code-Review","score":6,"reason":"Found 20/30 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/asticode/go-astilectron/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/asticode/go-astilectron/test.yml/master?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/test.yml:32","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T01:10:02.610Z","repository_id":37664968,"created_at":"2025-08-17T01:10:02.610Z","updated_at":"2025-08-17T01:10:02.610Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28430845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:38:47.836Z","status":"ssl_error","status_checked_at":"2026-01-14T16:34:59.695Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["cross-platform","desktop-app","electron","go","golang","gui"],"created_at":"2024-07-30T17:01:01.820Z","updated_at":"2026-01-14T18:33:39.197Z","avatar_url":"https://github.com/asticode.png","language":"Go","readme":"[![GoReportCard](http://goreportcard.com/badge/github.com/asticode/go-astilectron)](http://goreportcard.com/report/github.com/asticode/go-astilectron)\n[![GoDoc](https://godoc.org/github.com/asticode/go-astilectron?status.svg)](https://godoc.org/github.com/asticode/go-astilectron)\n[![Test](https://github.com/asticode/go-astilectron/actions/workflows/test.yml/badge.svg)](https://github.com/asticode/go-astilectron/actions/workflows/test.yml)\n[![Coveralls](https://coveralls.io/repos/github/asticode/go-astilectron/badge.svg?branch=master)](https://coveralls.io/github/asticode/go-astilectron)\n\nThanks to `go-astilectron` build cross platform GUI apps with GO and HTML/JS/CSS. It is the official GO bindings of [astilectron](https://github.com/asticode/astilectron) and is powered by [Electron](https://github.com/electron/electron).\n\n# Warning\n\nThis project is not maintained anymore.\n\n# Demo\n\nTo see a minimal Astilectron app, checkout out the [demo](https://github.com/asticode/go-astilectron-demo).\n\nIt uses the [bootstrap](https://github.com/asticode/go-astilectron-bootstrap) and the [bundler](https://github.com/asticode/go-astilectron-bundler).\n\nIf you're looking for a minimalistic example, run `go run example/main.go -v`.\n\n# Real-life examples\n\nHere's a list of awesome projects using `go-astilectron` (if you're using `go-astilectron` and want your project to be listed here please submit a PR):\n\n- [go-astivid](https://github.com/asticode/go-astivid) Video tools written in GO\n- [GroupMatcher](https://github.com/veecue/GroupMatcher) Program to allocate persons to groups while trying to fulfill all the given wishes as good as possible\n- [Stellite GUI Miner](https://github.com/stellitecoin/GUI-miner) An easy to use GUI cryptocurrency miner for Stellite\n\n# Bootstrap\n\nFor convenience purposes, a [bootstrap](https://github.com/asticode/go-astilectron-bootstrap) has been implemented.\n\nThe bootstrap allows you to quickly create a one-window application.\n\nThere's no obligation to use it, but it's strongly recommended.\n\nIf you decide to use it, read thoroughly the documentation as you'll have to structure your project in a specific way.\n\n# Bundler\n\nStill for convenience purposes, a [bundler](https://github.com/asticode/go-astilectron-bundler) has been implemented.\n\nThe bundler allows you to bundle your app for every os/arch combinations and get a nice set of files to send your users.\n\n# Quick start\n\nWARNING: the code below doesn't handle errors for readibility purposes. However you SHOULD!\n\n## Import `go-astilectron`\n\nTo import `go-astilectron` run:\n\n    $ go get -u github.com/asticode/go-astilectron\n\n## Start `go-astilectron`\n\n```go\n// Initialize astilectron\nvar a, _ = astilectron.New(log.New(os.Stderr, \"\", 0), astilectron.Options{\n    AppName: \"\u003cyour app name\u003e\",\n    AppIconDefaultPath: \"\u003cyour .png icon\u003e\", // If path is relative, it must be relative to the data directory\n    AppIconDarwinPath:  \"\u003cyour .icns icon\u003e\", // Same here\n    BaseDirectoryPath: \"\u003cwhere you want the provisioner to install the dependencies\u003e\",\n    VersionAstilectron: \"\u003cversion of Astilectron to utilize such as `0.33.0`\u003e\",\n    VersionElectron: \"\u003cversion of Electron to utilize such as `4.0.1` | `6.1.2`\u003e\",\n})\ndefer a.Close()\n\n// Start astilectron\na.Start()\n\n// Blocking pattern\na.Wait()\n```\n\nFor everything to work properly we need to fetch 2 dependencies : [astilectron](https://github.com/asticode/astilectron) and [Electron](https://github.com/electron/electron). `.Start()` takes care of it by downloading the sources and setting them up properly.\n\nIn case you want to embed the sources in the binary to keep a unique binary you can use the **NewDisembedderProvisioner** function to get the proper **Provisioner** and attach it to `go-astilectron` with `.SetProvisioner(p Provisioner)`. Or you can use the [bootstrap](https://github.com/asticode/go-astilectron-bootstrap) and the [bundler](https://github.com/asticode/go-astilectron-bundler). Check out the [demo](https://github.com/asticode/go-astilectron-demo) to see how to use them.\n\nBeware when trying to add your own app icon as you'll need 2 icons : one compatible with MacOSX (.icns) and one compatible with the rest (.png for instance).\n\nIf no BaseDirectoryPath is provided, it defaults to the executable's directory path.\n\nThe majority of methods are asynchronous which means that when executing them `go-astilectron` will block until it receives a specific Electron event or until the overall context is cancelled. This is the case of `.Start()` which will block until it receives the `app.event.ready` `astilectron` event or until the overall context is cancelled.\n\n### HTML paths\nNB! All paths in HTML (and Javascript) must be relative, otherwise the files will not be found.\nTo make this happen in React for example, just set the homepage property of your package.json to \"./\".\n\n``` { \"homepage\": \"./\" }```\n\n## Create a window\n\n```go\n// Create a new window\nvar w, _ = a.NewWindow(\"http://127.0.0.1:4000\", \u0026astilectron.WindowOptions{\n    Center: astikit.BoolPtr(true),\n    Height: astikit.IntPtr(600),\n    Width:  astikit.IntPtr(600),\n})\nw.Create()\n```\n    \nWhen creating a window you need to indicate a URL as well as options such as position, size, etc.\n\nThis is pretty straightforward except the `astilectron.Ptr*` methods so let me explain: GO doesn't do optional fields when json encoding unless you use pointers whereas Electron does handle optional fields. Therefore I added helper methods to convert int, bool and string into pointers and used pointers in structs sent to Electron.\n\n## Open the dev tools\n\nWhen developing in JS, it's very convenient to debug your code using the browser window's dev tools:\n\n````go\n// Open dev tools\nw.OpenDevTools()\n\n// Close dev tools\nw.CloseDevTools()\n````\n\n## Add listeners\n\n```go\n// Add a listener on Astilectron\na.On(astilectron.EventNameAppCrash, func(e astilectron.Event) (deleteListener bool) {\n    log.Println(\"App has crashed\")\n    return\n})\n\n// Add a listener on the window\nw.On(astilectron.EventNameWindowEventResize, func(e astilectron.Event) (deleteListener bool) {\n    log.Println(\"Window resized\")\n    return\n})\n```\n    \nNothing much to say here either except that you can add listeners to Astilectron as well.\n\n## Play with the window\n\n```go\n// Play with the window\nw.Resize(200, 200)\ntime.Sleep(time.Second)\nw.Maximize()\n```\n    \nCheck out the [Window doc](https://godoc.org/github.com/asticode/go-astilectron#Window) for a list of all exported methods\n\n## Send messages from GO to Javascript\n\n### Javascript\n\n```javascript\n// This will wait for the astilectron namespace to be ready\ndocument.addEventListener('astilectron-ready', function() {\n    // This will listen to messages sent by GO\n    astilectron.onMessage(function(message) {\n        // Process message\n        if (message === \"hello\") {\n            return \"world\";\n        }\n    });\n})\n```\n\n### GO\n\n```go\n// This will send a message and execute a callback\n// Callbacks are optional\nw.SendMessage(\"hello\", func(m *astilectron.EventMessage) {\n        // Unmarshal\n        var s string\n        m.Unmarshal(\u0026s)\n\n        // Process message\n        log.Printf(\"received %s\\n\", s)\n})\n```\n\nThis will print `received world` in the GO output\n\n## Send messages from Javascript to GO\n\n### GO\n\n```go\n// This will listen to messages sent by Javascript\nw.OnMessage(func(m *astilectron.EventMessage) interface{} {\n        // Unmarshal\n        var s string\n        m.Unmarshal(\u0026s)\n\n        // Process message\n        if s == \"hello\" {\n                return \"world\"\n        }\n        return nil\n})\n```\n\n### Javascript\n\n```javascript\n// This will wait for the astilectron namespace to be ready\ndocument.addEventListener('astilectron-ready', function() {\n    // This will send a message to GO\n    astilectron.sendMessage(\"hello\", function(message) {\n        console.log(\"received \" + message)\n    });\n})\n```\n\nThis will print \"received world\" in the Javascript output\n\n## Play with the window's session\n\n```go\n// Clear window's HTTP cache\nw.Session.ClearCache()\n```\n\n## Handle several screens/displays\n\n```go\n// If several displays, move the window to the second display\nvar displays = a.Displays()\nif len(displays) \u003e 1 {\n    time.Sleep(time.Second)\n    w.MoveInDisplay(displays[1], 50, 50)\n}\n```\n\n## Menus\n\n```go\n// Init a new app menu\n// You can do the same thing with a window\nvar m = a.NewMenu([]*astilectron.MenuItemOptions{\n    {\n        Label: astikit.StrPtr(\"Separator\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Normal 1\")},\n            {\n                Label: astikit.StrPtr(\"Normal 2\"),\n                OnClick: func(e astilectron.Event) (deleteListener bool) {\n                    log.Println(\"Normal 2 item has been clicked\")\n                    return\n                },\n            },\n            {Type: astilectron.MenuItemTypeSeparator},\n            {Label: astikit.StrPtr(\"Normal 3\")},\n        },\n    },\n    {\n        Label: astikit.StrPtr(\"Checkbox\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Checked: astikit.BoolPtr(true), Label: astikit.StrPtr(\"Checkbox 1\"), Type: astilectron.MenuItemTypeCheckbox},\n            {Label: astikit.StrPtr(\"Checkbox 2\"), Type: astilectron.MenuItemTypeCheckbox},\n            {Label: astikit.StrPtr(\"Checkbox 3\"), Type: astilectron.MenuItemTypeCheckbox},\n        },\n    },\n    {\n        Label: astikit.StrPtr(\"Radio\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Checked: astikit.BoolPtr(true), Label: astikit.StrPtr(\"Radio 1\"), Type: astilectron.MenuItemTypeRadio},\n            {Label: astikit.StrPtr(\"Radio 2\"), Type: astilectron.MenuItemTypeRadio},\n            {Label: astikit.StrPtr(\"Radio 3\"), Type: astilectron.MenuItemTypeRadio},\n        },\n    },\n    {\n        Label: astikit.StrPtr(\"Roles\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Minimize\"), Role: astilectron.MenuItemRoleMinimize},\n            {Label: astikit.StrPtr(\"Close\"), Role: astilectron.MenuItemRoleClose},\n        },\n    },\n})\n\n// Retrieve a menu item\n// This will retrieve the \"Checkbox 1\" item\nmi, _ := m.Item(1, 0)\n\n// Add listener manually\n// An OnClick listener has already been added in the options directly for another menu item\nmi.On(astilectron.EventNameMenuItemEventClicked, func(e astilectron.Event) bool {\n    log.Printf(\"Menu item has been clicked. 'Checked' status is now %t\\n\", *e.MenuItemOptions.Checked)\n    return false\n})\n\n// Create the menu\nm.Create()\n\n// Manipulate a menu item\nmi.SetChecked(true)\n\n// Init a new menu item\nvar ni = m.NewItem(\u0026astilectron.MenuItemOptions{\n    Label: astikit.StrPtr(\"Inserted\"),\n    SubMenu: []*astilectron.MenuItemOptions{\n        {Label: astikit.StrPtr(\"Inserted 1\")},\n        {Label: astikit.StrPtr(\"Inserted 2\")},\n    },\n})\n\n// Insert the menu item at position \"1\"\nm.Insert(1, ni)\n\n// Fetch a sub menu\ns, _ := m.SubMenu(0)\n\n// Init a new menu item\nni = s.NewItem(\u0026astilectron.MenuItemOptions{\n    Label: astikit.StrPtr(\"Appended\"),\n    SubMenu: []*astilectron.MenuItemOptions{\n        {Label: astikit.StrPtr(\"Appended 1\")},\n        {Label: astikit.StrPtr(\"Appended 2\")},\n    },\n})\n\n// Append menu item dynamically\ns.Append(ni)\n\n// Pop up sub menu as a context menu\ns.Popup(\u0026astilectron.MenuPopupOptions{PositionOptions: astilectron.PositionOptions{X: astikit.IntPtr(50), Y: astikit.IntPtr(50)}})\n\n// Close popup\ns.ClosePopup()\n\n// Destroy the menu\nm.Destroy()\n```\n\nA few things to know:\n\n* when assigning a role to a menu item, `go-astilectron` won't be able to capture its click event\n* on MacOS there's no such thing as a window menu, only app menus therefore my advice is to stick to one global app menu instead of creating separate window menus\n* on MacOS MenuItem without SubMenu is not displayed\n\n## Tray\n\n```go\n// New tray\nvar t = a.NewTray(\u0026astilectron.TrayOptions{\n    Image:   astikit.StrPtr(\"/path/to/image.png\"),\n    Tooltip: astikit.StrPtr(\"Tray's tooltip\"),\n})\n\n// Create tray\nt.Create()\n\n// New tray menu\nvar m = t.NewMenu([]*astilectron.MenuItemOptions{\n    {\n        Label: astikit.StrPtr(\"Root 1\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Item 1\")},\n            {Label: astikit.StrPtr(\"Item 2\")},\n            {Type: astilectron.MenuItemTypeSeparator},\n            {Label: astikit.StrPtr(\"Item 3\")},\n        },\n    },\n    {\n        Label: astikit.StrPtr(\"Root 2\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Item 1\")},\n            {Label: astikit.StrPtr(\"Item 2\")},\n        },\n    },\n})\n\n// Create the menu\nm.Create()\n\n// Change tray's image\ntime.Sleep(time.Second)\nt.SetImage(\"/path/to/image-2.png\")\n```\n\n## Notifications\n\n```go\n// Create the notification\nvar n = a.NewNotification(\u0026astilectron.NotificationOptions{\n\tBody: \"My Body\",\n\tHasReply: astikit.BoolPtr(true), // Only MacOSX\n\tIcon: \"/path/to/icon\",\n\tReplyPlaceholder: \"type your reply here\", // Only MacOSX\n\tTitle: \"My title\",\n})\n\n// Add listeners\nn.On(astilectron.EventNameNotificationEventClicked, func(e astilectron.Event) (deleteListener bool) {\n\tlog.Println(\"the notification has been clicked!\")\n\treturn\n})\n// Only for MacOSX\nn.On(astilectron.EventNameNotificationEventReplied, func(e astilectron.Event) (deleteListener bool) {\n\tlog.Printf(\"the user has replied to the notification: %s\\n\", e.Reply)\n\treturn\n})\n\n// Create notification\nn.Create()\n\n// Show notification\nn.Show()\n```\n\n## Dock (MacOSX only)\n\n```go\n// Get the dock\nvar d = a.Dock()\n\n// Hide and show the dock\nd.Hide()\nd.Show()\n\n// Make the Dock bounce\nid, _ := d.Bounce(astilectron.DockBounceTypeCritical)\n\n// Cancel the bounce\nd.CancelBounce(id)\n\n// Update badge and icon\nd.SetBadge(\"test\")\nd.SetIcon(\"/path/to/icon\")\n\n// New dock menu\nvar m = d.NewMenu([]*astilectron.MenuItemOptions{\n    {\n        Label: astikit.StrPtr(\"Root 1\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Item 1\")},\n            {Label: astikit.StrPtr(\"Item 2\")},\n            {Type: astilectron.MenuItemTypeSeparator},\n            {Label: astikit.StrPtr(\"Item 3\")},\n        },\n    },\n        {\n        Label: astikit.StrPtr(\"Root 2\"),\n        SubMenu: []*astilectron.MenuItemOptions{\n            {Label: astikit.StrPtr(\"Item 1\")},\n            {Label: astikit.StrPtr(\"Item 2\")},\n        },\n    },\n})\n\n// Create the menu\nm.Create()\n```\n\n## Global Shortcuts\n\nRegistering a global shortcut.\n\n```go\n// Register a new global shortcut\nisRegistered, _ := a.GlobalShortcuts().Register(\"CmdOrCtrl+x\", func() {\n    fmt.Println(\"CmdOrCtrl+x is pressed\")\n})\nfmt.Println(\"CmdOrCtrl+x is registered:\", isRegistered)  // true\n\n// Check if a global shortcut is registered\nisRegistered, _ = a.GlobalShortcuts().IsRegistered(\"Shift+Y\") // false\n\n// Unregister a global shortcut\na.GlobalShortcuts().Unregister(\"CmdOrCtrl+x\")\n\n// Unregister all global shortcuts\na.GlobalShortcuts().UnregisterAll()\n```\n\n## Dialogs\n\nAdd the following line at the top of your javascript file :\n\n```javascript\nconst { dialog } = require('electron').remote\n```\n\nUse the available [methods](https://github.com/electron/electron/blob/v7.1.10/docs/api/dialog.md).\n\n## Basic auth\n\n```go\n// Listen to login events\nw.OnLogin(func(i astilectron.Event) (username, password string, err error) {\n\t// Process the request and auth info\n\tif i.Request.Method == \"GET\" \u0026\u0026 i.AuthInfo.Scheme == \"http://\" {\n\t\tusername = \"username\"\n\t\tpassword = \"password\"\n\t}\n    return\n})\n```\n\n# Features and roadmap\n\n- [x] custom branding (custom app name, app icon, etc.)\n- [x] window basic methods (create, show, close, resize, minimize, maximize, ...)\n- [x] window basic events (close, blur, focus, unresponsive, crashed, ...)\n- [x] remote messaging (messages between GO and Javascript)\n- [x] single binary distribution\n- [x] multi screens/displays\n- [x] menu methods and events (create, insert, append, popup, clicked, ...)\n- [x] bootstrap\n- [x] dialogs (open or save file, alerts, ...)\n- [x] tray\n- [x] bundler\n- [x] session\n- [x] accelerators (shortcuts)\n- [x] dock\n- [x] notifications\n- [ ] loader\n- [ ] file methods (drag \u0026 drop, ...)\n- [ ] clipboard methods\n- [ ] power monitor events (suspend, resume, ...)\n- [ ] desktop capturer (audio and video)\n- [ ] window advanced options (add missing ones)\n- [ ] window advanced methods (add missing ones)\n- [ ] window advanced events (add missing ones)\n- [ ] child windows\n\n# Cheers to\n\n[go-thrust](https://github.com/miketheprogrammer/go-thrust) which is awesome but unfortunately not maintained anymore. It inspired this project.\n","funding_links":[],"categories":["Go","开源类库","GUI","Open source library","\u003ca name=\"Go\"\u003e\u003c/a\u003eGo","\u003cspan id=\"gui\"\u003eGUI\u003c/span\u003e","Best practices","Repositories","Relational Databases"],"sub_categories":["桌面开发","Advanced Console UIs","检索及分析资料库","Desktop Development","Search and Analytic Databases","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","SQL 查询语句构建库"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasticode%2Fgo-astilectron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasticode%2Fgo-astilectron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasticode%2Fgo-astilectron/lists"}