{"id":14988590,"url":"https://github.com/adnaan/gomodest-template","last_synced_at":"2025-07-27T12:43:03.552Z","repository":{"id":46769239,"uuid":"336619090","full_name":"adnaan/gomodest-template","owner":"adnaan","description":"A template to build dynamic web apps quickly using Go, html/template and javascript","archived":false,"fork":false,"pushed_at":"2021-10-22T03:31:31.000Z","size":1100,"stargazers_count":94,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-04T05:29:43.262Z","etag":null,"topics":["bulma","go","html","stimulusjs","sveltejs"],"latest_commit_sha":null,"homepage":"https://gomodest-template.fly.dev","language":"HTML","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/adnaan.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}},"created_at":"2021-02-06T19:29:02.000Z","updated_at":"2024-06-10T01:42:00.000Z","dependencies_parsed_at":"2022-09-23T03:52:37.253Z","dependency_job_id":null,"html_url":"https://github.com/adnaan/gomodest-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnaan%2Fgomodest-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnaan%2Fgomodest-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnaan%2Fgomodest-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adnaan%2Fgomodest-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adnaan","download_url":"https://codeload.github.com/adnaan/gomodest-template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248498146,"owners_count":21114049,"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","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":["bulma","go","html","stimulusjs","sveltejs"],"created_at":"2024-09-24T14:17:00.015Z","updated_at":"2025-04-12T00:22:10.869Z","avatar_url":"https://github.com/adnaan.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gomodest-template\n\nA [modest](https://modestjs.works) template to build dynamic web apps in Go, HTML and [sprinkles and spots](https://modestjs.works/book/part-2/same-ui-three-modest-ways/) of javascript.\n\n## Why ?\n\n- Build dynamic websites using the tools you already know(Go, HTML, CSS, Vanilla Javascript) for the most part.\n- Use [bulma components](https://bulma.io/documentation/components/) to speed up prototyping a responsive and good-looking UI.\n- Use [turbo \u0026 stimulusjs](https://hotwire.dev/) for most of the interactivity.\n- For really complex interactivity use [Svelte](https://svelte.dev/) for a single div in a few spots.\n- Lightweight and productive. Fast development cycle.\n- Easy to start, easy to maintain.\n\nFor a more complete implementation using this technique please see [gomodest-starter](https://github.com/adnaan/gomodest-starter).\n\n## Usage\n- [Use as a github template](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template#creating-a-repository-from-a-template)\n- `git clone https://github.com/\u003cuser\u003e/\u003cmytemplate\u003e` and `cd /path/to/your/gomodest-template`\n- `make watch` (starts hot-reload for go, html and javascript changes)\n- open [localhost:3000](http://localhost:3000).\n\nor \n\n```bash\nbrew install gh\ngh repo create myapp --template adnaan/gomodest-template\ncd myapp\nmake install # or (make install-x64)\n# replace gomodest-template with your app name\ngo get github.com/piranha/goreplace\n$(go env GOPATH)/bin/goreplace gomodest-template -r myapp\ngit add . \u0026\u0026 git commit -m \"replace gomodest-template\"\nmake watch # or make watch-x64\n```\n\n\n![gomodest tempalte home](screenshots/gomodest-template-index.png?raw=true \"\")\n\n## TOC\n\n* [Folder Structure](#folder-structure)\n* [Views using html templates](#views-using-html-templates)\n  + [Step 1: Add a layout partial](#step-1--add-a-layout-partial)\n  + [Step 2: Add a layout](#step-2--add-a-layout)\n  + [Step 4: Add a view partial](#step-4--add-a-view-partial)\n  + [Step 5: Add a view](#step-5--add-a-view)\n  + [Step 6: Render view](#step-6--render-view)\n* [Interactivity using Javascript](#interactivity-using-javascript)\n  + [Stimulus Controllers](#stimulus-controllers)\n    - [Step 1: Add a controller](#step-1--add-a-controller)\n    - [Step 2: Add data attributes to the target div](#step-2--add-data-attributes-to-the-target-div)\n  + [Svelte Components](#svelte-components)\n    - [Step 1: Add data attributes to the target div.](#step-1--add-data-attributes-to-the-target-div)\n    - [Step 2: Create and export svelte component](#step-2--create-and-export-svelte-component)\n    - [Step 3: Hydrate initial props from the server](#step-3--hydrate-initial-props-from-the-server)\n* [Styling and Images](#styling-and-images)\n* [Samples](#samples)\n* [Dependencies](#dependencies)\n\n\u003csmall\u003e\u003ci\u003e\u003ca href='http://ecotrust-canada.github.io/markdown-toc/'\u003eTable of contents generated with markdown-toc\u003c/a\u003e\u003c/i\u003e\u003c/small\u003e\n\n## Folder Structure\n\n- templates/\n    \n    - layouts/\n    - partials/\n    - list of view files\n  \n- assets/\n  \n  - images/\n  - src/\n  \n    - components/\n    - controllers/\n    - index.js\n    - styles.scss\n\n\n\n- `templates` is the root directory where all html/templates assets are found.\n- `layouts` contains the layout files. Layout is a container for `partials` and `view files`\n- `partials` contains the partial files. Partial is a reusable html template which can be used in one of two ways:\n\n    - Included in a `layout` file: `{{include \"partials/header\"}}`\n    - Included in a `view` file: `{{template \"main\" .}}`. When used in a view file, a partial must be enclosed in a `define` tag:\n      \n        ```html\n            {{define \"main\"}}\n              Hello {{.hello}}\n            {{end}}\n        ```\n- `view` files are put in the root of the `templates` directory. They are contained within a `layout` must be enclosed in a `define content` tag:\n\n    ```html\n        {{define \"content\"}}\n            App's {{.dashboard}}\n        {{end}}\n    ```\n    `View` is rendered within a `layout`: \n    \n    ```go\n        indexLayout, err := rl.New(\n\t\trl.Layout(\"index\"),\n\t\trl.DisableCache(true),\n\t\trl.DefaultHandler(func(w http.ResponseWriter, r *http.Request) (rl.M, error) {\n\t\t\treturn rl.M{\n\t\t\t\t\"app_name\": \"gomdest-template\",\n\t\t\t}, nil\n\t\t}))\n       \n        ...\n        \n        r.Get(\"/\", indexLayout.Handle(\"home\",\n\t\tfunc(w http.ResponseWriter, r *http.Request) (rl.M, error) {\n\t\t\treturn rl.M{\n\t\t\t\t\"hello\": \"world\",\n\t\t\t}, nil\n\t\t}))\n    ```\n  \n    Here the `view`: `home` is rendered within the `index` layout.\n\nPlease see the `templates` directory.\n\n- `assets` directory contains the public asset pipeline for the project.\n\n  - `styles.scss` is a custom `scss` file for [bulma][https://bulma.io] as [documented here](https://bulma.io/documentation/customize/with-webpack/).\n  - `index.js`  is the entrypoint for loading `stimulusjs` controllers sourced from this [example](https://github.com/hotwired/stimulus-starter.\n  - `controllers` contains [stimulusjs controllers](https://stimulus.hotwire.dev/reference/controllers).\n  - `components` contains single file svelte components.\n\n\n\n## Views using html templates\n\nThere are three kinds of `html/template` files in this project.\n\n- `layout`: defines the base structure of a web page.\n- `partial`: reusable snippets of html. It can be of two types: `layout partials` \u0026 `view partials`.\n- `view`: the main container for the web page logic contained within a `layout`. It must be enclosed in a `define content` template definition. It can use view partials.\n\n### Step 1: Add a layout partial\n\nCreate `header.html` file in `templates/partials`.\n\n```html\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"description\" content=\"A modest way to build golang web apps\"\u003e\n\u003cmeta name=\"viewport\"content=\"width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0\"\u003e\n\u003cmeta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"\u003e\n...\n```\n\n### Step 2: Add a layout\n\nCreate `index.html` file in `templates/layouts` and use the above partial.\n\n```html\n\u003c!DOCTYPE html\u003e\n\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003ctitle\u003e{{.app_name}}\u003c/title\u003e\n    {{include \"partials/header\"}}\n\u003c/head\u003e\n\u003cbody ...\u003e\n...\n\u003c/body\u003e\n\u003c/html\u003e\n\n```\n\n### Step 4: Add a view partial\n\nCreate `main.html` in `templates/partials`\n\n```html\n{{define \"main\"}}\n    \u003cmain\u003e\n        \u003cdiv class=\"columns is-centered is-vcentered is-mobile py-5\"\u003e\n            \u003cdiv class=\"column is-narrow\" style=\"width: 70%\"\u003e\n                \u003ch1 class=\"has-text-centered title\"\u003eHello {{.hello}}\u003c/h1\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/main\u003e\n{{end}}\n```\n\nThis is a different from the `layout partial` since it's closed in a `define` tag.\n\n### Step 5: Add a view\n\nCreate `home.html` in `templates` and use the above partial.\n\n```html\n{{define \"content\"}}\n\u003cdiv class=\"columns is-mobile is-centered\"\u003e\n    \u003cdiv class=\"column is-half-desktop\"\u003e\n        {{template \"main\" .}}\n    \u003c/div\u003e\n\u003c/div\u003e\n{{end}}\n```\nNotice that a `view` is always enclosed in `define content` template definition.\n\n### Step 6: Render view\n\nTo render the view with data we use a wrapper over the `html/template` package.\n\n```go\nr.Get(\"/\", indexLayout.Handle(\"home\",\n    func(w http.ResponseWriter, r *http.Request) (rl.M, error) {\n        return rl.M{\n            \"hello\": \"world\",\n    }, nil\n}))\n```\n\nTo learn more about `html/template`, please look into this amazing [cheatsheet](https://curtisvermeeren.github.io/2017/09/14/Golang-Templates-Cheatsheet).\n\n\nReference:\n\n- `templates/layout/index.html`\n- `templates/partials/header.html`\n- `templates/partials/main.html`\n- `templates/home.html`\n- `main.go`\n\n## Interactivity using Javascript\n\nFor client-side interactivity we use a bit of javascript.\n\n### Stimulus Controllers\n\nA stimulus controller is a snippet of javascript which handles a single aspect of interactivity. To add a new svelte component:\n\n#### Step 1: Add a controller\n\nCreate a file with suffix: `_controller.js` \n\n`util_controller.js`\n```js\nimport { Controller } from \"stimulus\"\n\nexport default class extends Controller {\n  ...\n\n    connect(){\n\n    }\n\n    goto(e){\n        if (e.currentTarget.dataset.goto){\n            window.location = e.currentTarget.dataset.goto;\n        }\n    }\n\n    goback(e){\n       window.history.back();\n    }\n\n   ...\n}\n\n\n```\n\nSee complete implementation in `assets/src/controller/util_controller.js`. To understand how stimulus works, please see the [handbook](https://stimulus.hotwire.dev/handbook/introduction).\n\n#### Step 2: Add data attributes to the target div\n\n```html\n\u003cbody data-controller=\"util svelte\"\n      data-action=\"keydown@window-\u003eutil#keyDown \"\n      data-util-active-class=\"is-active\"\u003e\n  \n    ...\n  \u003cbutton class=\"button\"\n    data-action=\"click-\u003eutil#goto\"\n    data-goto=\"/\"\u003eHome\n  \u003c/button\u003e\n\u003c/body\u003e\n```\n\nHere we are attaching two controllers to the `body` itself since they are used often. Later we can add action and data attributes to use them.\n\nReference:\n- `templates/layout/index.html`\n- `templates/404.html`\n- `assets/src/controllers/util_controller.js`\n\n### Svelte Components\n\nA svelte component is loaded into the targeted div by a stimulujs controller: `controllers/svelte_controller.js`. This is hooked by declaring data attributes on the div which is to be contain the svelte component:\n\n- `data-svelte-target`: Value is **required** to be `component`. It's used for identifying the divs as targets for the `svelte_controller`.\n- `data-component-name`: The name of the component as exported in `src/components/index.js`\n\n  ```js\n    import app from \"./App.svelte\"\n    // export other components here.\n    export default {\n        app: app,\n    }\n  ```\n  \n- `data-component-props`: A string map object which is passed as initial props to the svelte component.\n\nTo add a new svelte component:\n\n#### Step 1: Add data attributes to the target div.\n```html\n{{define \"content\"}}\n\u003cdiv class=\"columns is-mobile is-centered\"\u003e\n \u003cdiv class=\"column is-half-desktop\"\u003e\n  \u003cdiv\n          data-svelte-target=\"component\"\n          data-component-name=\"app\"\n          data-component-props=\"{{.Data}}\"\u003e\n  \u003c/div\u003e\n \u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n{{end}}\n```\n\n#### Step 2: Create and export svelte component\n\n- Create a new svelte component in `src/components` and export it in `src/components/index.js`\n\n```js\nimport app from \"./App.svelte\"\n\n// export other components here.\nexport default {\n    app: app,\n}\n```\n\nThe `controllers/svelte_controller.js` controller loads the svelte component in to the div with the required data attributes shown in step 1.\n\n\n#### Step 3: Hydrate initial props from the server\n\nIt's possible to hydrate initial props from the server and pass onto the component. This is done by templating a string data object into the `data-component-props` attribute.\n\n```go\nr.Get(\"/app\", indexLayout.Handle(\"app\",\n    func(w http.ResponseWriter, r *http.Request) (rl.M, error) {\n      appData := struct {\n      Title string `json:\"title\"`\n      }{\n      Title: \"Hello from server for the svelte component\",\n      }\n    \n      d, err := json.Marshal(\u0026appData)\n      if err != nil {\n      return nil, fmt.Errorf(\"%v: %w\", err, fmt.Errorf(\"encoding failed\"))\n      }\n    \n      return rl.M{\n      \"Data\": string(d), // notice struct data is converted into a string\n      }, nil\n}))\n```\n\nReference:\n- `templates/app.html`\n- `src/controllers/svelte_controller.js`\n- `src/components/*`\n- `main.go`\n\n## Styling and Images\n\n[Bulma](https://bulma.io/) is included by default. Bulma is a productive css framework with prebuilt components and helper utilities.\n\n- `assets/src/styles.scss`: to override default bulma variables. `webpack` bundles and copies css assets to `public/assets/css.\n- `assets/images`: put image assets here. it will be auto-copied to `public/assets/images` by `webpack`. \n\n## Samples\n\nGo to [localhost:3000/samples](http://localhost:3000/samples/) to a list of sample views. Copy-paste at will from the `templates/samples` directory.\n\n## Dependencies\n\n- Backend:\n  - [Go](https://golang.org/)\n  - [renderlayout: a wrapper over foolin/goview](https://github.com/adnaan/renderlayout)\n  - [chi](https://github.com/go-chi/chi)\n- Frontend:\n  - [html/template](https://golang.org/pkg/html/template/)\n  - [masterminds/sprig](http://masterminds.github.io/sprig/)\n  - [StimulusJS(sprinkles)](https://stimulus.hotwire.dev/)\n  - [SvelteJS(spots)](https://svelte.dev/)\n  - [Bulma CSS](https://bulma.io/)\n  - [Webpack](https://webpack.js.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnaan%2Fgomodest-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadnaan%2Fgomodest-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnaan%2Fgomodest-template/lists"}