{"id":20103804,"url":"https://github.com/ancientlore/whisper","last_synced_at":"2026-05-13T19:33:40.563Z","repository":{"id":44540487,"uuid":"225275240","full_name":"ancientlore/whisper","owner":"ancientlore","description":"Media-oriented web serving experiment","archived":false,"fork":false,"pushed_at":"2026-04-08T00:43:24.000Z","size":16254,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-08T02:27:49.043Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ancientlore.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-12-02T03:14:56.000Z","updated_at":"2026-04-08T00:43:11.000Z","dependencies_parsed_at":"2023-11-29T17:27:46.772Z","dependency_job_id":"61feb8c2-4b94-4127-8946-7fb9a01195af","html_url":"https://github.com/ancientlore/whisper","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/ancientlore/whisper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ancientlore%2Fwhisper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ancientlore%2Fwhisper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ancientlore%2Fwhisper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ancientlore%2Fwhisper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ancientlore","download_url":"https://codeload.github.com/ancientlore/whisper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ancientlore%2Fwhisper/sbom","scorecard":{"id":191548,"data":{"date":"2025-08-11","repo":{"name":"github.com/ancientlore/whisper","commit":"b19d0a9b8e309934b145f0e6c2998e8cb075a83a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.9,"checks":[{"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":"Code-Review","score":0,"reason":"Found 0/29 approved changesets -- score normalized to 0","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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/codeql-analysis.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":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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":"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":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/ancientlore/whisper/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/ancientlore/whisper/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/ancientlore/whisper/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/ancientlore/whisper/codeql-analysis.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:4","Warn: containerImage not pinned by hash: Dockerfile:11","Warn: containerImage not pinned by hash: Dockerfile-test:5","Warn: containerImage not pinned by hash: Dockerfile-test:14","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 containerImage dependencies pinned","Info:   1 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":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"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":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 2 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"}},{"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"}}]},"last_synced_at":"2025-08-16T20:48:22.603Z","repository_id":44540487,"created_at":"2025-08-16T20:48:22.604Z","updated_at":"2025-08-16T20:48:22.604Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32997714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"ssl_error","status_checked_at":"2026-05-13T13:14:51.610Z","response_time":115,"last_error":"SSL_read: 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":[],"created_at":"2024-11-13T17:38:34.361Z","updated_at":"2026-05-13T19:33:35.554Z","avatar_url":"https://github.com/ancientlore.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# whisper\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/ancientlore/whisper.svg)](https://pkg.go.dev/github.com/ancientlore/whisper)\n\nA web server mainly oriented at media serving for small websites.\n\n![whisper](example/static/dog.png)\n\n## Conventions\n\nIn general, _whisper_ serves static content from the location it's found - making it easy to structure your site how you want. There is special handling for certain content like Markdown files.\n\nSee the [example](example) folder for a sample site layout. In general, _whisper_ uses conventions instead of configuration files. Conventions used by this server include:\n\n* The `template` folder holds HTML templates, using Go's `html/template` package. These templates are used for rendering content but never served directly.\n* A `sitemap.txt` can be created as a template. See the [example](example) for details.\n* The default page for a folder is a Markdown file called `index.md`.\n* An optional `whisper.cfg` file holds settings should you want to preserve them.\n* Files `404.md` and `500.md` can be provided for custom errors.\n\n## Markdown\n\nWeb pages are generally written in Markdown and use HTML templates to render into the site. The default template to use is called `default`; you must have a `default` template and an `image` template.  Templates are stored in the `template` folder.\n\n\u003e NOTE: If no `template` folder is found, then default templates are loaded named `default` and `image`. You probably don't want these because they are extremely basic, but it's okay for just messing around and viewing Markdown locally.\n\nMarkdown may contain *front matter* which is in TOML format. The front matter is delimited by `+++` at the start and end. For example:\n\n    +++\n    # This is my front matter\n    title = \"My glorious page\"\n    +++\n    # This is my Heading\n    This is my [Markdown](https://en.wikipedia.org/wiki/Markdown).\n\nFront matter may include:\n\nName         | Type             | Description\n-------------|------------------|------------------------------------------\ntitle        | string           | Title of page\ndate         | time             | Publish date\ntags         | array of strings | Tags for the articles (not used yet)\ntemplate     | string           | Override the template to render this file\nredirect     | duration         | Provide redirect info (not automated)\noriginalfile | string           | Name of the base Markdown or image file\n\nFront matter is used for sorting and constructing lists of articles.\n\n## Templates\n\n_whisper_ uses standard Go templates from the `html/template` package. Templates are passed the following data:\n\n    // FrontMatter holds data scraped from a Markdown page.\n    type FrontMatter struct {\n        Title        string    `toml:\"title\"`        // Title of this page\n        Date         time.Time `toml:\"date\"`         // Date the article appears\n        Template     string    `toml:\"template\"`     // The name of the template to use\n        Tags         []string  `toml:\"tags\"`         // Tags to assign to this article\n        Redirect     string    `toml:\"redirect\"`     // Issue a redirect to another location\n        OriginalFile string    `toml:\"originalfile\"` // The original file (markdown or image)\n    }\n\n    // PageInfo has information about the current page.\n    type PageInfo struct {\n        Path     string // path from URL\n        Filename string // end portion (file) from URL\n    }\n\n    // data is what is passed to markdown templates.\n    type data struct {\n        FrontMatter FrontMatter   // front matter from Markdown file or defaults\n        Page        PageInfo      // information aboout current page\n        Content     template.HTML // rendered Markdown\n    }\n\n`Page` is information about the current page, and `FrontMatter` is the front-matter from the current Markdown file. `Content` contains the HTML version of the Markdown file.\n\nFunctions are added to the template for your convenience.\n\nFunction                            | Description\n------------------------------------|------------\n`dir(path string) []File`           | Return the contents of the given folder, excluding special files and subfolders.\n`sortbyname([]File) []File`         | Sort by name (reverse)\n`sortbytime([]File) []File`         | Sort by time (reverse)\n`match(string, ...string) bool`     | Match string against file patterns\n`filter([]File, ...string) []File`  | Filter list against file patterns\n`join(parts ...string) string`      | The same as path.Join\n`ext(path string) string`           | The same as path.Ext\n`prev([]File, string) *File`        | Find the previous file based on Filename\n`next([]File, string) *File`        | Find the next file based on Filename\n`reverse([]File) []File`            | Reverse the list\n`trimsuffix(string, string) string` | The same as strings.TrimSuffix\n`trimprefix(string, string) string` | The same as strings.TrimPrefix\n`trimspace(string) string `         | The same as strings.TrimSpace\n`markdown(string) template.HTML`    | Render Markdown file into HTML\n`frontmatter(string) *FrontMatter`  | Read front matter from file\n`now() time.Time`                   | Current time\n\n`File` is defined as:\n\n    // File holds data about a page endpoint.\n    type File struct {\n        FrontMatter FrontMatter\n        Filename    string\n    }\n\nIf `File` is not a Markdown file, then `FrontMatter.Title` is set to the file name and `FrontMatter.Date` is set to the modification time. The array is sorted by reverse date (most recent items first).\n\nNote that `FrontMatter.OriginalFile` is very useful because, for image templates, it will hold the name of the image file. You probably want to use it in the template.\n\n### Image Templates\n\nFolders named `photos`, `images`, `pictures`, `cartoons`, `toons`, `sketches`, `artwork`, or `drawings` use a special handler that can serve images using an HTML template called `image`.\n\n## Non-Goals\n\n* It's not a goal to make templates reusable. I expect templates need editing for new sites.\n* It's not a goal to automate creation of the menu.\n* It's not a goal to be a fully-featured server. I run [Caddy](https://caddyserver.com/) in front of it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fancientlore%2Fwhisper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fancientlore%2Fwhisper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fancientlore%2Fwhisper/lists"}