{"id":17034902,"url":"https://github.com/rantav/go-archetype","last_synced_at":"2026-03-14T22:03:35.234Z","repository":{"id":42372000,"uuid":"200004339","full_name":"rantav/go-archetype","owner":"rantav","description":"Project archetyping and templating in Golang","archived":false,"fork":false,"pushed_at":"2024-05-09T20:26:24.000Z","size":127,"stargazers_count":47,"open_issues_count":3,"forks_count":17,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T07:11:22.822Z","etag":null,"topics":["archetypes","blueprint","golang","project","skeleton","template"],"latest_commit_sha":null,"homepage":"https://go-archetype.dev/","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/rantav.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":"2019-08-01T07:53:50.000Z","updated_at":"2025-03-12T05:30:08.000Z","dependencies_parsed_at":"2023-02-19T04:50:27.123Z","dependency_job_id":"769a0755-5b29-4ed1-b97f-82e9ce0118c5","html_url":"https://github.com/rantav/go-archetype","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rantav%2Fgo-archetype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rantav%2Fgo-archetype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rantav%2Fgo-archetype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rantav%2Fgo-archetype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rantav","download_url":"https://codeload.github.com/rantav/go-archetype/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248566566,"owners_count":21125686,"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":["archetypes","blueprint","golang","project","skeleton","template"],"created_at":"2024-10-14T08:44:55.704Z","updated_at":"2026-03-14T22:03:30.197Z","avatar_url":"https://github.com/rantav.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[//]: # ({% raw %})\n\n# go-archetype\n\n[![Actions Status](https://github.com/rantav/go-archetype/workflows/Go/badge.svg)](https://github.com/rantav/go-archetype/actions)\n\n*Dead simple project blueprints for the rest of us.*\n\n*go-archetype* is a tool for creating project blueprints (aka archetypes) in your native language.\n\nIf you or your company create new projects and you want all these projects to preserve a similar structure or simply create a good starting point for other develoeprs, use go-archetype to define project archtypes (templates).\n\n## Concept\n\nTypically two roles are involved:\n\n* The **archetype creator** (typically a senior developer/architect)\n* The **developer** creating a new project\n\n### The archetype creator\n\nAs the archetype creator you create a template (aka blueprint) project. This project is fully functional, valid code written in your native language, be it Golang, JavaScript, Java, Python etc. (go-archetype is written in golang but can be used to generate tempaltes in any language)\nThen you define a set of transformations. E.g. ask the user for the project name and replace here, here and here.\n\nWhat you don't need to do is: Create a bluprint in a meta-language. Other templating tools, such as the python cookiecutter require you to write your blueprint (template) project in a meta-language, e.g. cookiecutter's language. With go-archetype you don't have to do that; your write your tempalte in your native language and then define a simple set of transformations for generating templates.\n\n### Developer using the archetype\n\nAs a developer creating a new project based on the archetype, you run `go-archetype` with a few parameters, you answer a few questions (defined by the template creator such as what is your new project's name, these questions are defined by the archetype creator) and your new code is generated.\n\n### Summary\n\nHere are the steps:\n\n1. Architect creates an actual working project. This project is used as a blueprint or an archetype. It's a barebones project, no templating involved.\n1. Architect defines a set of transformations in transformations.yml. These transformations are used for simple search-and-replace in the blueprint. (and there are more compicated types, see below)\n1. Developer runs go-archetype to create a new project based on the blueprint.\n\n### Example project\nExample project using go-archetype: https://github.com/rantav/go-template\n\n\n## Usage\n\n    go-archetype transform --transformations=transformations.yml --source=. --destination=/path/to/your/new/project\n\n## The transformations.yml file\n\nThe transformations file contains two main sections:\n\n* **inputs**\n* and **transformations**\n\nThe *inputs* section defines user inputs, see description below.\nThe *transformations* section defines the list of ordered transformations as explained below.\n\nSee the file transformations.yml in this very project as an example.\n\n## Requesting for user input\n\nIt is common to request user inputs in order to apply a set of transformations. For example you might want to request for the project name, description, whether to include this or that functionality.\n\nThere are following types of input: `text`, `yesno` and `select`. \n- `text` provides simple, single-line text inputs. \n- `yesno` originates a boolean [y/N] question.\n- `select` allows to select from a list of predefined options.\n\nExample:\n\n```yml\ninputs:\n  - id: ProjectName\n    text: What is the project name?\n    type: text\n  - id: IncludeReadme\n    text: Would you like to include the readme file?\n    type: yesno\n  - id: ProjectType\n    text: Select project type\n    type: select\n    options:\n      - simple\n      - advanced    \n```\n\nThe `id` must be unique and is later also used for performing the transformations (see below).\n\nA user may provide the required inputs interactively when promped to when running go-archetype.\n\nLikewise, The user may also provide the input as CLI arguments, which is useful for automation. (see example below)\n\nInteractive question example: (what the user sees while running go-archetype)\n\n    ? Would you like to include the readme file? (y/N)\n\nAnd when providing the input as CLI args:\n\n```sh\ngo-archetype transform --transformations=transformations.yml \\\n    --source=. \\\n    --destination=.tmp/go/my-go-project \\\n    -- \\\n    --ProjectName my-go-project \\\n    --IncludeReadme yes \\\n    --ProjectType simple \n```\n\nIn this example there are following inputs: `ProjectName`, `IncludeReadme` and `ProjectType`.\n\nTo seperate program args from user input we use `--`. After the `--` the list of user inputs is provided.\n\n## Templating user input\n\nAfter accepting user input you might want to transform and tempalte it.\n\nWe use go templates as a templatting languate. For the full overview of the templating language see [text/template](https://golang.org/pkg/text/template/)\nFollowing is a list of several examples to get you started.\n\n* User inputs are wrapped in `{{` and `}}`\n* User inputs are prepended with `.`, so for example `{{.ProjectName}}` would yield the user's provided project name.\n* You may combine user input with constats, for example `{{.ProjectName}} - {{.ProjectDescription}}`, which concatenates the project's name with a hyphen and then it's description.\n\nPipelines and functions are a useful concept. For example you might request the project's name and then display this project name  in uppercase in the readme file and lowercase in source files. To that end we provide a host of **template pipelines**.\n\n    {{ .ProjectName | upper }} # ProjectName is provided by the user and we transform it to all uppercase. with the upper pipeline\n    {{ wrap 80 .Description }} # Wordwrap the project description by 80 characters\n\nWe include out the the box the [sprig](http://masterminds.github.io/sprig/strings.html) library, which includes many differnet string manipulation functions, to list a few: `trim`, `trimAll`, `trimSuffix`, `trimPrefix`, `upper`, `lower`, `title`, `wrap`, `plural`, `snakecase`, `camelcase`, `kebabcase` etc.\n\n## Transformers\n\nThere are two types of transformers: the **include** and **replace** transformers.\n\n### The *include* transformer\n\nThe include transformer allows inclusion or exclusion of whole files as well as parts of files in the generated project. A simple example: you ask then user whether to include a README file and based on the answer you include or exlude this entire file.\n\n#### Including or exluding whole files\n\nAll files that pass the global ignore filter are included by default. Unless one or more of the *include* rules with an empty `region_marker` applies to them, in which case the files are included only if the condition evaluates to true.\n\nCondition is a go template condition as can be used in an `{{if}}` expression. As such a simple boolean is expressed as simply `.var` where `var` is typically a user input.\n\nFor example with the following user input:\n\n```yml\ninputs:\n  - id: IncludeReadme\n    text: Would you like to include the readme file?\n    type: yesno\n```\n\nIt is possbible to define the following include transformer:\n\n```yml\ntransformations:\n  - name: include the readme file\n    type: include\n    region_marker: # When there's no marker, the entire file(s) is included\n    condition: .IncludeReadme\n    files: [\"README.md\"]\n```\n\nNote that when there's no `region_marker` that simply means that the entire file is included/excluded based on the user's input.\n\nMore sophisticated expresions could also be utilized, such as boolean algebra, using `and .x .y`, `or .x .y` etc (`x` and `y` are user inputs). For a complete reference, see [go templates](https://golang.org/pkg/text/template/).\n\n#### Don't forget the dot `.`\n\nKeep in mind that go templates require a dot (`.`) to prepend a value. So when utilizing user input, for example such as `IncludeReadme` be sure to prepend the dot, e.g. `.IncludeReadme` whenever used in conditions or replacements.\n\nOne caveat to that is that for simplicity go-archetype allows dot-less conditions when they are very simple, e.g. only `variable`, such as `IncludeReadme`. So the following conditions are actually equivalent:\n\n```\ncondition: .IncludeReadme\n```\n\nand\n\n```\ncondition: IncludeReadme # No dot here\n```\n\nThis is done in order to simplify the simple single-operand conditions. However, with more complex conditions be sure to prepend the dot.\nFor example the following condition is valid where x and y are user inputs:\n\n```\ncondition: and .x .y\n```\n\nBut the following is not valid:\n\n```\ncondition: and x y # Not valid. x and y need to be prepended by a dot .\n```\n\n#### Including or exluding parts of files\n\nSometimes it's useful to conditionally include or exlude parts of files and not the entire files. To do this we utilize special region markers.\n\nExample:\n\n```go\nimport (\n\t\"net\"\n\t\"net/http\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t// BEGIN __INCLUDE_GRPC__\n\tchannelz \"github.com/rantav/go-grpc-channelz\"\n\tchannelzservice \"google.golang.org/grpc/channelz/service\"\n\t// END __INCLUDE_GRPC__\n)\n```\n\nThe includes `channelz` and `channelzservice` are only required in cases where the user selected to add gRPC functionality to the project.\n\nThe corresponding transformations.yml file sections are:\n\n```yml\ninputs:\n  - id: include_grpc\n    text: Should gRPC functionality be included?\n    type: yesno\n\ntransformations:\n  - name: \"include grpc - parts of files\"\n    type: include\n    region_marker: __INCLUDE_GRPC__\n    condition: .include_grpc\n    files: [\"Makefile\", \"**/*.go\", \"deployments/*\"] # optional, just as an example\n```\n\nTo summarize, in cases where you'd like to include or exlude just parts of files (and not the entire file), you use special *region markers* inside the source code file. These region markers are simply comments in Go or in Java, PHP etc.\n\n### The *replace* transformer\n\nThis transformer performs a search and replace functionality. For example, you might ask the user for the project name and then replace the generic template project name with the user's provided name\n\nExample:\n\n```yml\ninputs:\n  - id: name\n    text: What is the project name? (e.g. my-awesome-go-project)\n    type: text\n\ntransformations:\n  - name: project name\n    type: replace # The type of the transformer is **replace**\n    pattern: go-template # The text pattern to search and replace\n    replacement: \"{{ .name }}\" # The text to replace. You may use go tempalates and perform arbitrary replacements.\n    files: [\"*.go\", \"**/*.go\", \"**/*.sh\", \".gitignore\", \"README.md\"]\n```\n\n### The *rename* transformer\n\nThis transformer renames files. For example, you might want to rename all the files with the pattern `\u003cgo-template\u003e` with the user's provided project name.\n\nExample:\n\nLet's imagine, you have a project template with the following structure:\n\n```\ngo-template\n├── cmd\n│  └── go-template\n│     ├── go-template.go\n│     └── main.go\n├── Dockerfile\n└── README.md\n```\n\nAnd the following `transformations.yml` file:\n\n```yml\ninputs:\n  - id: name\n    text: What is the project name? (e.g. my-awesome-go-project)\n    type: text\n\ntransformations:\n  - name: rename files to the project name\n    type: rename # The type of the transformer is **rename**\n    pattern: go-template # The text pattern to search and replace\n    replacement: \"{{ .name }}\" # The text to replace. You may use go tempalates and perform arbitrary replacements.\n    files: [\"**\"]\n```\n\nThen, after transformations you will get a new project with the renamed files like these:\n\n```\nmy-awesome-go-project\n├── cmd\n│  └── my-awesome-go-project\n│     ├── my-awesome-go-project.go\n│     └── main.go\n├── Dockerfile\n└── README.md\n```\n\n### Recepies\n\nA list of useful recepies.\n\n#### Always ignore\n\nTo always exclude some parts of the output regardless of user input, do as follows:\n\n```yml\ntransformers:\n  - name: do not include template code in the final output\n    type: include\n    region_marker: __DO_NOT_INCLUDE__\n    condition: false\n    files: [\"**\"]\n```\n\nAnd then in your source file(s):\n\n```\n# BEGIN __DO_NOT_INCLUDE__\n... Code that should neven be included in the final output, such as\n... templating specific scripts, makefiles etc\n# END __DO_NOT_INCLUDE__\n```\n\n#### Conditional replace\n\nSometimes you need to conditionally replace a pattern. The condition may depend on user input. For example you may ask the user whether they'd like to includ gRPC functionality in the project or not and based on that render a different makefile.\n\nSince the underlying rendering engine uses [go templates](https://golang.org/pkg/text/template/) it is possible to utilize the following condition:\n\n```\n{{ if .include_grpc }}build: build-grpc{{ else }}build:{{end}}\n```\n\nThis condition will render `build:` if `.include_grpc` is false and `build: build-grpc` if `.include_grpc` is true. `include_grpc` is a user input in this case.\n\nThe complete example would look as follows then:\n\n```yml\ninputs:\n  - id: include_grpc\n    text: Should gRPC functionality be included?\n    type: yesno\ntransformations:\n  - name: build with grpc or not\n    type: replace\n    pattern: \"build: build-grpc\"\n    replacement: \"{{ if .include_grpc }}build: build-grpc{{ else }}build:{{end}}\"\n    files: [\"Makefile\"]\n```\n\n#### Change to CamelCase\n\nIf you have a string that you'd like to change to CamelCase, for example `my-project`, first convert to snake_case and then to CamelCase. This is unfortunately a limitation of sprig.\n\nExample:\n\n```\nreplacement: \"{{ .name | snakecase | camelcase }}\"\n```\n\nChanging to camelCase where the first letter is lowercased is even more ticky, but here goes:\n\n```\nreplacement: \"{{ .name | snakecase | camelcase | swapcase | title | swapcase }}\"\n```\n\nYeah it works...\n\n#### Inclusion By Selection\nSelect allows to select one of the options and include section depends on selected choice.\n\n```yml\n  - name: simple\n    type: include\n    region_marker: __ProjectType_SIMPLE__\n    condition: \"eq .ProjectType \\\"simple\\\"\"\n    files: [\"main.go\"]\n  - name: medium\n    type: include\n    region_marker: __ProjectType_MEDIUM__\n    condition: \"eq .ProjectType \\\"medium\\\"\"\n    files: [\"main.go\"]\n  - name: advanced\n    type: include\n    region_marker: __ProjectType_ADVANCED__\n    condition: \"eq .ProjectType \\\"advanced\\\"\"\n    files: [\"main.go\"]\n```\n\n## Order of execution\n\nTransformatinos are executed by the order they appear inside the transformations.yml file. The output of the first transformation is then piped into the input of the second transformation and so forth.\nThat means that the order is important such that if you're pattern needs to match certain text, you need to make sure that no previous transformation had changed this text. That's why it's wise to start with the more specific replacements and then move on to the more generic replacements.\n\nExample:\n\n```yml\ntransformations:\n  - name: project long description\n    type: replace\n    pattern: Use go-archetype to transform project archetypes into existing live projects\n    replacement: \"{{ wrap 80 .ProjectDescription }}\"\n    files: [\"cmd/root.go\"]\n  - name: project name\n    type: replace\n    pattern: go-archetype\n    replacement: \"{{ .ProjectName }}\"\n    files: [\"*.go\", \"**/*.go\"]\n```\n\n`project long description` should be placed before `project name`. If it weren't so then after applying ProjetName replacement on all occurences of the string `\"go-archetype\"` then the sentence `\"Use go-archetype to transform project archetypes into existing live projects\"` would have become `\"Use my-project-name to transform project archetypes into existing live projects\"` and then the replacement would not have been matched.\n\n## Before and After\n\nThe `before` and `after` hooks allow you to run arbitrary shell command just before running all transformations or just after then.\n\nThey are provided with useful context that can be used in the actual command, which includes:\n\n* `source` (Used as `{{ .source }}`)\n* `destination` (Used as `{{ .destination }}`)\n* As well as all user inputs\n\nExample:\n\n```yaml\nafter:\n  operations:\n    - sh:\n      # You can define commands with the basic syntax.\n      # If so, each command will be separated by the \u003cnewline\u003e symbol. Each line will be executed\n      # separately.\n      - cd {{.destination}} \u0026\u0026 echo $PWD\n      # Either, you can use the extended syntax.\n      # cmd defines command line to be executed.\n      - cmd: echo Done archetyping from {{ .source }} to {{ .destination }} of project {{ .ProjectName }}\n        # if multiline is set to false, then it runs exactly as basic syntax command\n        multiline: false\n      # Or, you can set multiline to true. Then, the command will be executed as-is.\n      # To make this happen, use YAML multiline operator \"|\".\n      # See also: https://yaml-multiline.info/\n      - cmd: |\n          if [ 1 == 1 ]; then\n            echo \"OK!\"\n          fi\n        multiline: true\n```\n\n## Operations and debugging\n\nThe view detailed logs, run with `LOG_LEVEL=debug`\n\n[//]: # ({% endraw %})\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frantav%2Fgo-archetype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frantav%2Fgo-archetype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frantav%2Fgo-archetype/lists"}