{"id":13707161,"url":"https://github.com/piranha/gostatic","last_synced_at":"2025-04-04T13:13:57.380Z","repository":{"id":3983689,"uuid":"5079470","full_name":"piranha/gostatic","owner":"piranha","description":"Fast static site generator","archived":false,"fork":false,"pushed_at":"2023-03-02T05:31:58.000Z","size":399,"stargazers_count":451,"open_issues_count":16,"forks_count":41,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-03-28T12:04:46.368Z","etag":null,"topics":["blog-engine","go","markdown","static-site-generator"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piranha.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2012-07-17T08:55:39.000Z","updated_at":"2025-03-22T22:56:45.000Z","dependencies_parsed_at":"2023-07-06T05:57:04.012Z","dependency_job_id":null,"html_url":"https://github.com/piranha/gostatic","commit_stats":{"total_commits":329,"total_committers":26,"mean_commits":"12.653846153846153","dds":"0.18541033434650456","last_synced_commit":"bf366bcf14fd047b10868473af46822d3f14aca5"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piranha%2Fgostatic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piranha%2Fgostatic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piranha%2Fgostatic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piranha%2Fgostatic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piranha","download_url":"https://codeload.github.com/piranha/gostatic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247179879,"owners_count":20897112,"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":["blog-engine","go","markdown","static-site-generator"],"created_at":"2024-08-02T22:01:23.150Z","updated_at":"2025-04-04T13:13:57.350Z","avatar_url":"https://github.com/piranha.png","language":"Go","funding_links":[],"categories":["Go","By Language"],"sub_categories":["Go"],"readme":"# gostatic\n\nGostatic is a static site generator. It tracks file changes during compilation,\nwhich is why it works reasonably [fast](#speed). Also it provides framework for\n[configuration](#configuration) akin to Make, which makes it easy to understand\nand to write custom configurations.\n\nFeatures include:\n\n - No run-time dependencies, just a single binary - [download](https://github.com/piranha/gostatic/releases/) it and run\n - Dependency tracking and re-rendering only changed pages\n - Markdown support - [Commonmark](https://commonmark.org/) via [goldmark](https://github.com/yuin/goldmark/)\n - Simple [config syntax](#configuration)\n - Flexible [filter system](#processors)\n - Support for pagination\n - Plays well with external commands and scripts\n - HTTP server and watcher (instant rendering on changes)\n - Suitable for automation (ability to query state with `gostatic --dump`)\n\nAnd all in all, it works nicely for me, so it may work for you!\n\n## Installation\n\nJust download a binary from [releases page](https://github.com/piranha/gostatic/releases).\n\nIf you need to automate downloading latest release, I use this script (change\n`64-linux` to the type you need):\n\n```\nURL=$(curl -s https://api.github.com/repos/piranha/gostatic/releases | awk '/download_url.*64-linux/ { print $2; exit }')\ncurl -Lso gostatic $(URL)\nchmod +x gostatic\n```\n\nWhen downloading in Macos, your file will be quarantined and to use it you'll\nhave to assure Macos you know what you're doing:\n\n```\nxattr -r -d com.apple.quarantine gostatic\n```\n\nObviously, `go get https://github.com/piranha/gostatic` also works, if you want\nto compile from source.\n\n\n## Quick Start\n\nRun `gostatic -i my-site` to generate basic site in directory `my-site`. It will\nhave a basic `config` file, which you should edit to put relevant variables at\nthe top - it also contains description of how files in your `src` directory are\ntreated.\n\n`src` directory obviously contains sources of your site (name of this directory\ncan be changed in `config`). You can follow general idea of this directory to\ncreate new blog posts or new pages. All files, which are not mentioned in\n`config`, are just copied over. Run `gostatic -fv config` to see how your `src`\nis processed.\n\n`site.tmpl` is a file that defines templates your are able to use for your\npages. You can see those templates mentioned in `config`.\n\nAnd, finally, there is a `Makefile`, just for convenience. Run `make` to build\nyour site once or `make w` to run watcher and server, to see your site changes\nin real time.\n\nAlso, you could look at [my site](https://github.com/piranha/solovyov.net) for\nan example of advanced usage.\n\nGood luck! And remember, your contributions either to gostatic or to\ndocumentation (even if it's just this `README.md`) are always very welcome!\n\n## Documentation index:\n\n- [Approach](#approach)\n- [Speed](#speed)\n- [External Resources](#external-resources)\n- [Configuration](#configuration)\n  - [Constants](#constants)\n- [Page Config](#page-config)\n- [Processors](#processors)\n- [Template API Reference](#template-api-reference)\n  - [Global Functions](#global-functions)\n  - [Page interface](#page-interface)\n  - [Page list interface](#page-list-interface)\n  - [Site interface](#site-interface)\n- [Extensibility](#extensibility)\n\nAlso, see [wiki](https://github.com/piranha/gostatic/wiki) - and feel free to\nadd more information there!\n\n## Approach\n\nEach given file is processed through a pipeline of filters, which modify the\nfile state and then rendered on disk. Single input file corresponds to a single\noutput file, but filters can generate virtual input files (like tag files).\n\nFile is rendering in those cases:\n\n- output file does not exists\n- file source is newer than it's output\n- one of those is the case for one of file's dependencies\n\nAll files are sorted by date. This date is taken in their [config](#page-config)\nor, in case if date in config is absent or dates there are equal, by file\nmodification time.\n\n## Speed\n\n| Box                       | Pages |  Full |  Noop |      Single post |\n|:--------------------------|------:|------:|------:|-----------------:|\n| Macbook Air '15 (i7)      |   630 | 450ms | 100ms | 160ms (93 pages) |\n| Macbook Air '15 (i7)      |   250 | 180ms |   n/a |              n/a |\n| Macbook Air '20 (M1)      |   486 | 185ms |  39ms | 140ms (97 pages) |\n| Hetzner CX21 (2 vCPU/4GB) |   486 | 502ms |  89ms | 414ms (97 pages) |\n\nThis are results of forced full site rebuild, then checking there are no\nmodification, and then re-rendering a single changed page (along with pages\nwhich depend on this page).\n\nAlso note that if you're using various external post-processors (like uglifyjs\nor sassc) they tend to slow down things a bit (for my specific use case both\nuglifyjs and sassc add another `0.25s` when files they process change).\n\nTo reproduce numbers, [download hyperfine][], [download gostatic][], clone\n[solovyov.net][], comment out `:google-closure-compiler` in `config` and then run:\n\n- `hyperfine 'gostatic -f config'`\n- `hyperfine 'gostatic config'`\n- `hyperfine 'touch src/blog/2017/fuji-raw.md \u0026\u0026 gostatic config'`\n\n[download hyperfine]: https://github.com/sharkdp/hyperfine/releases\n[download gostatic]: https://github.com/piranha/gostatic/releases\n[solovyov.net]: https://github.com/piranha/solovyov.net\n\n## External resources\n\n - Jack Pearkes made a [Heroku buildpack][] for gostatic.\n\n[Heroku buildpack]: https://github.com/pearkes/heroku-buildpack-gostatic\n\n## Configuration\n\nConfig syntax is Makefile-inspired with some simplifications, look at the\nexample:\n\n```Makefile\nTEMPLATES = site.tmpl templates-folder\nSOURCE = src\nOUTPUT = site\n\n# this is a comment\n*.md:\n    config\n    ext .html\n    directorify\n    tags tags/*.tag\n    markdown\n    template page # yeah, this is a comment as well\n\nindex.md: blog/*.md\n    config\n    ext .html\n    inner-template\n    markdown\n    template page\n\n*.tag: blog/*.md\n    ext .html\n    directorify\n    template tag\n    markdown\n    template page\n```\n\nHere we have constants declaration (first three lines), a comment and then three\nrules. One for any markdown file, one specifically for index.md and one for\ngenerated tags.\n\nSpecific rules override generic matching rules, but logic is not exactly very\nsmart, and there is no real precedence defined, so if you have several matches\nfor a single file you could end up with any of them. Note that there is some\norder: exact path match, exact name match, glob path match, glob name\nmatch. NOTE: this may change in future.\n\nRules consist of path/match, list of dependencies (also paths and matches, the\nones listed after colon) and commands.\n\nEach command consists of a name of processor and (possibly) some\narguments. Arguments are separated by spaces.\n\nNote: if a file has no rules whatsoever, it will be copied to exactly same\nlocation at destination as it was in source without being read into memory. So\nheavy images etc shouldn't be a problem.\n\n### Constants\n\nThere are three configuration constants:\n\n- `SOURCE` - sources to read (relative to location of config)\n- `OUTPUT` - directory for output (relative to location of config)\n- `TEMPLATES` - list of files and/or directories (containing `*.tmpl` files),\nwhich will be parsed as Go templates. Each file can contain more than one\ntemplate (see [docs](https://golang.org/pkg/text/template/#hdr-Nested_template_definitions)\non that).\n\nYou can also use arbitrary names for constants to\n[access later](#site-interface) from templates - just use any other name\n(`AUTHOR` could be one).\n\nAll constants can also be accessed from the config itself, using\n`$(CONSTANT_NAME)` syntax, just like in `Makefile`.\n\n## Page Config\n\nPage config is only processed if you specify `config` processor for a page. It's\nformat is `name: value`, for example:\n\n```\ntitle: This is a page\ntags: test\ndate: 2013-01-05\n```\n\nParsed properties:\n\n- `title` - page title.\n- `tags` - list of tags, separated by `,`.\n- `date` - page date, could be used for blog. Accepts formats from bigger to\n  smaller (from `\"2006-01-02 15:04:05 -07\"` to `\"2006-01-02\"`)\n- `hide` - false if not specified or is one of `f`, `false`, `False`,\n  `FALSE`. True in other cases. Hides page from children and tag lists when true.\n\nYou can also define any other property you like, it's value will be treated as a\nstring and it's key is capitalized and put on the `.Other`\n[page property](#page-interface).\n\n## Processors\n\nYou can always check list of available processors with `gostatic --processors`.\n\n- `config` - reads config from content. Config should be in format \"name: value\"\n  and separated by four dashes on empty line (`----`) from content.\n\n- `ignore` - ignore file.\n\n- `rename \u003cnew-name\u003e` - rename a file to `new-name`. Note this does not change\n  path to a file (you can use `..`, though, but be careful about platform\n  differences). If `new-name` contains `*`, then it'll be replaced with content\n  of `*` from path match. For example, with `blog/*.md: rename ../blog-*.html`\n  this will rename `blog/one.html` to `blog-one.html`.\n\n- `ext \u003c.ext\u003e` - change file extension to a given one (which should be prefixed\n  with a dot).\n\n- `datefilename` - rename a file from `whatever/2021-02-08-name.html` to\n  `whatever/name.html` and set the `page.Date` to `2021-02-08`.\n\n- `directorify` - rename a file from `whatever/name.html` to\n  `whatever/name/index.html`.\n\n- `markdown` - process content as Markdown.  \n  `markdown` without any arguments will not do any code-block highlighting.  \n  `markdown chroma=monokai` will use the [Chroma][chroma] highlighter to highlight code blocks, using the Monokai style, with inline CSS styles. (No .css file needed).  \n  You can see the styles at the [Chroma style previewer][chromaStyles1].  \n  The official list of styles is in the [Chroma repo here][chromaStyles2].\n\n[chroma]: https://github.com/alecthomas/chroma\n[chromaStyles1]: https://xyproto.github.io/splash/docs/\n[chromaStyles2]: https://github.com/alecthomas/chroma/tree/master/styles\n\n- `inner-template` - process content as Go template.\n\n- `template \u003cname\u003e` - pass page to a template named `\u003cname\u003e`.\n\n- `tags \u003cpath-pattern\u003e` - create a virtual page for all tags of a current\n  page. This tag page has path formed by replacing `*` in `\u003cpath-pattern\u003e` with\n  a tag name and has a tag as its `.Title` (use `{{ range .Site.Pages.WithTag\n  .Title }}...{{end}}` to get a list of tagged pages.\n\n- `relativize` - change all urls archored at `/` to be relative (i.e. add\n  appropriate amount of `../`) so that generated content can be deployed in a\n  subfolder of a site.\n\n- `external \u003ccommand\u003e \u003cargs...\u003e` - call external command with content of a page\n  as stdin and using stdout as a new content of a page. Has a shortcut:\n  `:\u003ccommand\u003e \u003cargs...\u003e` (`:` is replaced with `external `).\n\n- `paginate \u003cn\u003e \u003cpath-pattern\u003e` - create a virtual page for each `n` of pages\n  (grouped by `path-pattern`, so you can paginate few groups of pages as a\n  single one). `path-pattern` has `*` replaced by an index of this virtual page\n  (1-based), and you can get a list of pages with `{{ range paginator\n  .}}...{{end}}` (see [paginator](#global-functions) function). Using `paginate`\n  with the same `path-pattern` on different types of pages will group them in\n  same paginated list (*request*: please open an\n  [issue](https://github.com/piranha/gostatic/issues/new) if you have an idea\n  how to phrase this better).\n\n- `jekyllify` - creating pages in jekyll style, for example, the page\n  `2018-02-02-name.md` will be converted to `/2018/02/02/name.md`.\n\n- `yaml` - read the configuration for the page using yaml format (like jekyll).\n\n## Template API Reference\n\nTemplating is provided using\n[Go templates](https://golang.org/pkg/text/template/). See link for documentation\non syntax.\n\nEach template is executed in context of a [page](#page-interface). This means it\nhas certain properties and methods it can output or call to generate content,\ni.e. `{{ .Content }}` will output page content in place.\n\n### Global functions\n\nGo template system provides some convenient\n[functions](https://golang.org/pkg/text/template/#hdr-Functions), and gostatic\nexpands on that a bit:\n\n- `absurl \u003cbase\u003e \u003curl\u003e` - given an url and a base will join them to something\n  sane: leave the `\u003curl\u003e` in place if it's absolute, or resolve it within\n  `\u003cbase\u003e` if it's not.\n\n- `changed \u003cname\u003e \u003cvalue\u003e` - checks if `\u003cvalue\u003e` has changed since previous call\n  with the same name. Storage used for checking is global over the whole run of\n  gostatic, so choose unique names for different places.\n\n- `cut \u003cbegin\u003e \u003cend\u003e \u003cvalue\u003e` - cut partial content from `\u003cvalue\u003e`, delimited\n  by regular expressions `\u003cbegin\u003e` and `\u003cend\u003e`.\n\n- `hash \u003cvalue\u003e` - return 32-bit hash of a given value.\n\n- `version \u003cpage\u003e \u003cpath\u003e` - return relative URL to a page with resulting path\n  `\u003cpath\u003e` with `?v=\u003c32-bit hash\u003e` appended (use to override cache settings for\n  static files).\n\n- `truncate \u003clength\u003e \u003cvalue\u003e` - truncate string to given length (if it's\n  longer).\n\n- `strip_html \u003cvalue\u003e` - remove all HTML tags from string.\n\n- `strip_newlines \u003cvalue\u003e` - remove all line breaks and newlines from string.\n\n- `trim \u003cvalue\u003e` - trim all whitespace ([strings.TrimSpace](https://golang.org/pkg/strings/#TrimSpace)).\n\n- `replace \u003cold\u003e \u003cnew\u003e \u003cvalue\u003e` - replace all occurrences of `old` with `new` in\n  `value`.\n\n- `replacen \u003cold\u003e \u003cnew\u003e \u003cn\u003e \u003cvalue\u003e` - same as above, but only `n` times.\n\n- `replacere \u003cpattern\u003e \u003creplacement\u003e \u003cvalue\u003e` - replace text in `value`\n  according to [regexp](https://golang.org/pkg/regexp/syntax/) `pattern` and\n  `replacement`.\n\n- `split \u003cseparator\u003e \u003cvalue\u003e` - split string by separator, generating an array\n  (you can use `range` with result of this function).\n\n- `contains \u003cneedle\u003e \u003cvalue\u003e` - check if a string `value` contains `needle`.\n\n- `starts \u003cneedle\u003e \u003cvalue\u003e` - check if a string `value` starts with `needle`.\n\n- `ends \u003cneedle\u003e \u003cvalue\u003e` - check if a string `value` ends with `needle`.\n\n- `matches \u003cpattern\u003e \u003cvalue\u003e` - check if a\n  [regexp](https://golang.org/pkg/regexp/syntax/) `pattern` matches string `value`.\n\n- `refind \u003cpattern\u003e \u003cvalue\u003e` - apply regexp `pattern` to a string `value` and\n  return first submatch (the thing in parentheses), if any, or a whole matched\n  string.\n\n- `markdown \u003cvalue\u003e` - convert a string (`value`) from Markdown to HTML.\n\n- `paginator \u003cpage\u003e` - get a [paginator](#paginator-interface) object for\n  current page (only works on pages created by `paginate` processor).\n\n- `exec \u003ccmd\u003e [\u003carg1\u003e \u003carg2\u003e ....]` - exec a command with (optional) arguments.\n\n- `exectext \u003ccmd\u003e [\u003carg1\u003e \u003carg2\u003e ....] \u003ctext\u003e` - exec a command with (optional)\n  arguments and last argument (presumably some text) bound to command's\n  stdin. If you need to do something hard, use it like `{{ exectext \"sh\" \"-c\"\n  \"pipe | line\" .Content }}`.\n\n- `excerpt \u003ctext\u003e \u003cmaxWordCount\u003e` - Gets an excerpt from the given text, to a\n  maximum of `maxWordCount` words. When the text is shortened, it will produce\n  an `[...]` string, denoting there's more. For example, `The quick brown fox`\n  with `maxWordCount` of 2 will result in `The quick [...]`.\n\n- `even \u003cn\u003e` - tests if `n` is divisible by 2.\n\n- `odd \u003cn\u003e` - tests if `n` is not divisible by 2.\n\n- `count \u003ctext\u003e` - returns a number of words in text.\n\n- `reading_time \u003ctext\u003e` - returns reading time based on [average reading speed\n  being 200](https://help.medium.com/hc/en-us/articles/214991667-Read-time).\n\n- `some \u003cx\u003e \u003cx\u003e \u003cx\u003e....` - returns first non-nil value as a string\n\n- `dir \u003cpath\u003e` - returns all but the last element of a path (same as [filepath.Dir](https://golang.org/pkg/path/filepath/#Dir))\n\n- `base \u003cpath\u003e` - returns the last element of a path (same as [filepath.Base](https://golang.org/pkg/path/filepath/#Base))\n\n- `abcsort \u003cpages\u003e` - returns the pages sorted in alphabetical order of their .Name\n\n### Page interface\n\n- `.Site` - global [site object](#site-interface).\n- `.Rule` - rule object, matched by page.\n- `.Pattern` - pattern, which matched this page.\n- `.Deps` - list of pages, which are dependencies for this page.\n- `.Next` - next page in a list of all site pages (use specific PageSlice's\n  `.Next` method if you need more precise matching).\n- `.Prev` - previous page in a list of all site pages (use specific PageSlice's\n  `.Prev` method if you need more precise matching).\n\n----\n\n- `.Source` - relative path to page source.\n- `.FullPath` - full path to page source.\n- `.Path` - relative path to page destination.\n- `.OutputPath` - full path to page destination.\n- `.ModTime` - page last modification time.\n\n----\n\n- `.Title` - page title.\n- `.Tags` - list of page tags.\n- `.Date` - page date, as defined in [page config](#page-config).\n- `.Hide` - boolean if page is going to be absent from `{{ .Children }}` or `{{\n  .WithTag }}` lists.\n- `.Other` - map of all other properties (capitalized) from\n  [page config](#page-config), like `{{ .Other.Author }}`.\n\n----\n\n- `.Raw` - page content after preprocessors (i.e. after `config` has stripped it\n  part), that was originally read from the disk.\n- `.Content` - page content.\n- `.Url` - page url (i.e. `.Path`, but with `index.html` stripped from the end).\n- `.Name` - page name (i.e. last part of `.Url`).\n- `.UrlTo \u003cother-page\u003e` - relative url from current to some other page.\n- `.Rel \u003curl\u003e` - relative url to given absolute (anchored at `/`) url.\n- `.Is \u003curl\u003e` - checks if page is at passed url (or path) - use it for marking\n  active elements in menu, for example.\n- `.UrlMatches \u003cpattern\u003e` - checks if page url matches regular expression\n  `\u003cpattern\u003e`.\n- `.Has \u003cfield\u003e \u003cvalue\u003e` - backend for `.Where` and `.WhereNot`, checks if field equals to value, or:\n   - `\"Url\"` - calls `UrlMatches`\n   - `\"Tag\"` - checks tag is present in `.Tags`\n   - `\"Source\"` - [matches](https://golang.org/pkg/path/#Match) source path for `value`.\n\n### Paginator interface\n\n- `.Number` - number of paginator page, first is 1\n- `.PathPattern` - whatever was passed as `path-pattern` to `paginate`\n  (processor)[#processors]\n- `.Page` - paginator's own [page](#page-interface)\n- `.Pages` - [list of pages](#page-list-interface)\n- `.Prev` - previous paginator object (if current is first, then `nil`)\n- `.Next` - next paginator object (if current is last, then `nil`)\n\n### Page list interface\n\n- `.Get \u003cn\u003e` - [page](#page-interface) number `\u003cn\u003e`.\n- `.First` - first page.\n- `.Last` - last page.\n- `.Len` - length of page list.\n- `.Prev \u003cpage\u003e` - return page with earlier date than given. Returns nil if no\n  earlier pages exist or page is not in page list.\n- `.Next \u003cpage\u003e` - return page with later date than given. Returns nil if no\n  later pages exist or page is not in page list.\n- `.Slice \u003cfrom\u003e \u003cto\u003e` - return pages from `from` to `to` (i.e. from 0 to 10).\n\n----\n\n- `.Children \u003cprefix\u003e` - list of pages, nested under `\u003cprefix\u003e`.\n- `.WithTag \u003ctag-name\u003e` - list of pages, tagged with `\u003ctag-name\u003e`.\n- `.Reverse` - list of pages, sorted in reverse order.\n\n----\n\n- `.BySource \u003cpath\u003e` - finds a page with source path `\u003cpath\u003e`.\n- `.ByPath \u003cpath\u003e` - finds a page with resulting path `\u003cpath\u003e`.\n- `.GlobSource \u003cpattern\u003e` - list of pages, [matching](https://golang.org/pkg/path/#Match) source path `\u003cpattern\u003e`.\n- `.Where \u003cfield\u003e \u003cvalue\u003e` - list of pages, which return `true` for `.Has \u003cfield\u003e \u003cvalue\u003e`\n- `.WhereNot \u003cfield\u003e \u003cvalue\u003e` - list of pages, which return `false` for `.Has \u003cfield\u003e \u003cvalue\u003e`\n\n### Site interface\n\n- `.Pages` - [list of all pages](#page-list-interface).\n- `.Source` - path to site source.\n- `.Output` - path to site destination.\n- `.Templates` - list of template files used for the site.\n- `.Other` - any other properties (capitalized) defined in site config.\n\n## Extensibility\n\nObviously, the easiest way to extend gostatic's functionality is to use\n`external` [processor](#processors). It makes you able to process files in the\nway you want, but is more or less limited to that. There is no API right now to\ncreate pages on the fly (like `tags` processor does) using this method, for\nexample.\n\nBut `gostatic` itself is a\n[library](https://github.com/piranha/gostatic/tree/master/lib), and you can\nwrite your own static site generator using this library. See\n[gostatic.go](https://github.com/piranha/gostatic/blob/master/gostatic.go) for\nan example of one.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiranha%2Fgostatic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiranha%2Fgostatic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiranha%2Fgostatic/lists"}