{"id":26952422,"url":"https://github.com/nonk123/sanity","last_synced_at":"2026-05-24T21:02:04.468Z","repository":{"id":285614456,"uuid":"958740408","full_name":"nonk123/sanity","owner":"nonk123","description":"The only sane static site generator in existence","archived":false,"fork":false,"pushed_at":"2026-05-24T17:30:24.000Z","size":447,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-24T19:24:00.735Z","etag":null,"topics":["jinja2","lua","rust","sane","sanity","sass","scss","static-site-generator"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nonk123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":null,"dco":null,"cla":null}},"created_at":"2025-04-01T17:26:00.000Z","updated_at":"2026-05-24T17:30:28.000Z","dependencies_parsed_at":"2025-12-30T14:03:41.573Z","dependency_job_id":null,"html_url":"https://github.com/nonk123/sanity","commit_stats":null,"previous_names":["nonk123/sanity"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/nonk123/sanity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonk123%2Fsanity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonk123%2Fsanity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonk123%2Fsanity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonk123%2Fsanity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nonk123","download_url":"https://codeload.github.com/nonk123/sanity/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonk123%2Fsanity/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33450402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-24T19:21:36.376Z","status":"ssl_error","status_checked_at":"2026-05-24T19:21:10.562Z","response_time":57,"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":["jinja2","lua","rust","sane","sanity","sass","scss","static-site-generator"],"created_at":"2025-04-03T00:29:13.084Z","updated_at":"2026-05-24T21:02:04.447Z","avatar_url":"https://github.com/nonk123.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sanity\n\n\u003e [!TIP]\n\u003e You can now install the [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=nonk123.vscode-sanity-liveserver) for a more pleasant experience! See other supported IDEs in [the integrations section](#integrations)!\n\nThe only sane static site generator in existence. Refer to the [examples directory](sanity/examples) for a quickstart.\n\nHere's what it does for you:\n\n- Process [SCSS](https://sass-lang.com/documentation/syntax) to CSS using [grass](https://github.com/connorskees/grass).\n- Render [Jinja2](https://jinja.palletsprojects.com/en/stable/templates) templates with [minijinja](https://github.com/mitsuhiko/minijinja).\n- Run [Lua scripts](#basic-scripting) with [mlua](https://github.com/mlua-rs/mlua), using [LuaJIT](https://luajit.org/) for the backend. Useful for rendering a template with different sets of inputs.\n- Minify HTML/JS/CSS resulting in the build process.\n- Leave other files alone and copy them as-is.\n\nDirectories are walked recursively depth-first, with files processed and directories read in an alphanumeric order. Files are processed as soon as they are encountered, with the exception being Jinja2 templates, the rendering of which happens in a separate step that runs _after_ everything else has been processed.\n\nFiles prefixed with `_` are excluded from SCSS/Jinja2/Lua processing and aren't copied to the resulting site. This is useful for:\n\n- Base templates that are meant to be inherited rather than rendered on their own.\n- Templates rendered programmatically, such as blog articles, product pages, project descriptions.\n- Reused template partials residing as separate files.\n- SCSS `@use` modules.\n- Lua `require()` imports.\n\nHere are some of the sites powered by `sanity`:\n\n- [nonk.dev](https://nonk.dev) ([repo](https://github.com/nonk123/nonk.dev))\n- [schwung.us](https://schwung.us) ([repo](https://github.com/Schwungus/schwung.us))\n- [cantsleep.cc](https://cantsleep.cc) ([repo](https://github.com/LocalInsomniac/LocalInsomniac.github.io))\n\n## Integrations\n\nYou can use `sanity` without ever touching the command-line by installing one of our IDE extensions:\n\n- [for Visual Studio Code](https://github.com/nonk123/vscode-sanity).\n- [for GNU/Emacs](https://github.com/nonk123/sanity-emacs).\n\n## Basic Usage\n\n\u003e [!NOTE]\n\u003e Make sure to add the `dist` folder to your `.gitignore`. It doesn't (usually) make sense to version auto-generated files.\n\nPlace your Jinja2 templates, SCSS sheets, and [Lua scripts](#basic-scripting) inside the `www` folder. Run sanity from [the command line](#command-line-usage) or through [one of the integration packages](#integrations). You should get a fully processed site inside the `dist` folder right next to `www`.\n\nYou can either upload the contents of `dist` to a free website-hosting such as [Neocities](https://neocities.org) or [GitHub Pages](https://pages.github.com), or you can serve them locally using the built-in `sanity` live-server before pushing the site to production. The details of the latter scenario depend on the integration you're using. If you're unsure, just use [VSCode](https://code.visualstudio.com) and [our integration](https://github.com/nonk123/vscode-sanity): this combo runs the live-server automatically once you open your project folder.\n\n## Command-Line Usage\n\nDownload a binary from [available releases](https://github.com/nonk123/sanity/releases#latest). Run without arguments for a one-off build. Run with `server` to serve your site using the built-in development server; it rebuilds the site whenever the contents of `www` change. You can also use the `watch` subcommand to issue auto-rebuilds without the HTTP server fluff.\n\nDiscover more options by running `sanity` with `--help`.\n\n## Basic Scripting\n\nThere isn't much to scripting sanity besides the custom `render` function. It lets you send a template to the render queue programmatically rather than forcing you to use one whole file per page. Take a look at this static blog example:\n\n```lua\nlocal blog = {\n    [\"nice-day\"] = {\n        date = \"today\",\n        contents = \"I had a nice day today.\"\n    }\n};\n\nfor id, post in pairs(blog) do\n    render(\"_article.html\", \"blog/\" .. id .. \".html\", {\n        id = id,\n        date = post.date,\n        contents = post.contents,\n    });\nend\n```\n\n`render` accepts:\n\n- A template name (path relative to `www`, without the `.j2` extension) to add to the _render queue_.\n- Output file path relative to `dist`.\n- A dictionary to supply to the renderer.\n\nFields `id`, `date`, and `contents` from the example above can be referenced from within the template by using the mustache syntax: `{{ id }}`, `{{ date }}`, `{{ contents }}`.\n\n\u003e [!NOTE]\n\u003e I repeat: the `render` function doesn't render immediately; it _queues_ rendering. Lua scripts are processed _before_ the rendering happens.\n\n## Advanced Scripting\n\n### JSON Parsing\n\nYou can read JSON files inside `www` by using the `json` function:\n\n```lua\nlocal blog = json(\"blog/db.json\");\n-- the rest is the same as the example above...\n```\n\n### Reading Text Files\n\n`read` can be used to store a text file's contents in a string:\n\n```lua\nlocal id = \"nice-day\";\nlocal contents = read(\"blog/\" .. id .. \".md\");\n-- simile\n```\n\n### Adding Global Variables\n\n`inject` can be used to add/modify globals available inside _all_ templates:\n\n```lua\ninject(\"last_updated\", os.date(\"%Y-%m-%d\"));\n```\n\n## Misc. usage\n\n### Schema Validation\n\nLet's say you're loading a list of blog articles to render from a really long JSON file, and you want all articles to have a short description field. To ensure each article has such a `description` field by spitting out an error otherwise, you can use the `required` filter in your templates:\n\n```html\n{% for article in articles %}\n\u003cp\u003e{{ article.description | required(\"All articles need a description\") }}\u003c/p\u003e\n{% endfor }\n```\n\nThis won't help with figuring out which article is missing a description, but at least you'll be sure all of them have it once you find the culprit.\n\n### Exclude Analytics from Dev Builds\n\nYou can check for the `__prod` boolean in your templates to exclude analytics \u0026 trackers from dev builds:\n\n```html\n{% if __prod %}\n\u003cscript src=\"https://example.org/tracker.js\"\u003e\u003c/script\u003e\n{% endif }\n```\n\n### LuaLS Definitions\n\nUse the `lua-lib` subcommand to add a LuaLS definitions file to your project folder. This should hide the 999 warnings about undefined functions you've been getting. Make sure to point your IDE to this file, e.g. in VSCode `settings.json`:\n\n```json\n{\n    \"Lua.workspace.library\": [\"_sanity.lua\"]\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonk123%2Fsanity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnonk123%2Fsanity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonk123%2Fsanity/lists"}