Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# GitHub Issue Forms chooser config.
# Issue Forms (the *.yml files in this folder) let non-technical users propose
# content without opening a pull request. The PR templates under
# .github/PULL_REQUEST_TEMPLATE/ remain the path for contributors who can edit
# files directly.
blank_issues_enabled: true
contact_links:
- name: Contribute via Pull Request (for coders)
url: https://github.com/natobytes/Volts/tree/main/.github/PULL_REQUEST_TEMPLATE
about: Comfortable with Git? Open a PR using the per-category templates and run `npm run validate` first.
- name: Authoring & schema docs
url: https://github.com/natobytes/Volts/blob/main/SCHEMA.md
about: Read the content spec (required fields, file types, size limits) before submitting.
96 changes: 96 additions & 0 deletions .github/ISSUE_TEMPLATE/submit-content.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Submit content (no coding required)
description: Propose a light show, lock sound, boombox track, wrap, or horn sound — no Git or pull request needed.
title: "[content] "
labels:
- content-submission
body:
- type: markdown
attributes:
value: |
Thanks for contributing to **Volts**! This form lets you propose content
without editing files or opening a pull request. A maintainer will review
your submission and add it to the catalog.

Please make sure you have the right to share the content (it must be
free-to-use / properly licensed). See the
[content schema](https://github.com/natobytes/Volts/blob/main/SCHEMA.md)
for the size limits and file types per category.
- type: dropdown
id: category
attributes:
label: Category
description: Which kind of content is this?
options:
- Light Show (.fseq + matching audio)
- Lock Sound (.wav, max 1 MB)
- Boombox Track (.mp3 / .wav / .flac)
- Wrap (.png, 512–1024 px, max 1 MB)
- Horn Sound (.mp3 / .wav)
validations:
required: true
- type: input
id: title
attributes:
label: Title
description: The display name for this item.
placeholder: e.g. Thunderstruck Rock Show
validations:
required: true
- type: input
id: author
attributes:
label: Author / credit
description: Who created this? A name, handle, or community to credit.
placeholder: e.g. Community (XLightShows)
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: A short description of the content (theme, song, vehicle fit, effects…).
placeholder: A high-energy rock-themed synchronized light show with dramatic flashes.
validations:
required: true
- type: input
id: tags
attributes:
label: Tags
description: >
Comma-separated tags. Must come from the
[allowed tag list](https://github.com/natobytes/Volts/blob/main/content/tags.yaml) —
a maintainer can add a new tag if needed.
placeholder: rock, synchronized
validations:
required: false
- type: textarea
id: files
attributes:
label: Files (link or upload)
description: >
Share the actual content files. You can **drag-and-drop or paste files
directly into this box** to upload them to the issue, or paste a link to
where they're hosted (Google Drive, Dropbox, GitHub gist, etc.). Include
all assets (e.g. both the `.fseq` and the matching `.mp3` for a light show).
placeholder: |
Link: https://drive.google.com/...
or drag files here to attach them.
validations:
required: true
- type: input
id: license
attributes:
label: License / source
description: Where did this come from, and is it free to redistribute?
placeholder: e.g. Original work — free to use, or "Sourced from XLightShows (free-to-use license)"
validations:
required: false
- type: checkboxes
id: confirmations
attributes:
label: Confirmations
options:
- label: I have the right to share this content and it is free to redistribute.
required: true
- label: I have read the per-category file type and size limits in SCHEMA.md.
required: false
7 changes: 7 additions & 0 deletions .github/workflows/build-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ jobs:
cache: npm

- run: npm ci

# Surface high/critical dependency vulnerabilities on every PR.
# Non-blocking (|| true) so a fresh advisory can't wall off content PRs,
# but the report stays visible in the job log for maintainers to triage.
- name: Audit npm dependencies (high+)
run: npm audit --audit-level=high || true

- run: npm run build

- uses: ruby/setup-ruby@v1
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ gem "webrick", "~> 1.8"

group :jekyll_plugins do
gem "jekyll-seo-tag", "~> 2.8"
gem "jekyll-sitemap", "~> 1.4"
end
15 changes: 14 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
title: Volts
description: "Vehicle orchestration: Lights, Tunes & Skins — Community-curated light shows, lock sounds, boombox tracks, wraps, and horn sounds for Tesla vehicles."
baseurl: "/Volts"
url: ""
url: "https://natobytes.com"

# Social / SEO metadata. `url` (host) + `baseurl` (/Volts) give absolute URLs
# for jekyll-seo-tag, jekyll-sitemap, and the OpenGraph/Twitter-card meta in
# _layouts/default.html. Note: the app still resolves catalog downloadUrls
# against the host only — baseurl is unchanged.
author: NatoBytes
twitter:
card: summary_large_image
social:
name: Volts
links:
- https://github.com/natobytes/Volts

markdown: kramdown

plugins:
- jekyll-seo-tag
- jekyll-sitemap

exclude:
- node_modules
Expand Down
35 changes: 35 additions & 0 deletions _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.title }} | {{ site.title }}</title>
{% seo %}

{%- comment -%}
Explicit OpenGraph / Twitter-card metadata. jekyll-seo-tag above already
emits a baseline set; these reinforce title/description/url/site_name and
add an image when one is available, guarding for missing front matter.
{%- endcomment -%}
{%- if page.title -%}
{%- assign og_title = page.title | append: " | " | append: site.title -%}
{%- else -%}
{%- assign og_title = site.title -%}
{%- endif -%}
{%- assign og_desc = page.description | default: site.description -%}
{%- assign og_url = page.url | absolute_url -%}
{%- comment -%} Per-item images: wraps carry a thumbnail; otherwise fall back to a site default if present. {%- endcomment -%}
{%- comment -%} absolute_url already prepends baseurl, so paths start at /content/. {%- endcomment -%}
{%- assign og_image = "" -%}
{%- if page.thumbnail and page.collection -%}
{%- capture og_image -%}/content/{{ page.collection }}/{{ page.slug }}/{{ page.thumbnail }}{%- endcapture -%}
{%- assign og_image = og_image | absolute_url -%}
{%- elsif site.og_image -%}
{%- assign og_image = site.og_image | absolute_url -%}
{%- endif -%}

<meta property="og:type" content="{% if page.collection %}article{% else %}website{% endif %}">
<meta property="og:site_name" content="{{ site.title }}">
<meta property="og:title" content="{{ og_title | escape }}">
{% if og_desc %}<meta property="og:description" content="{{ og_desc | escape }}">{% endif %}
<meta property="og:url" content="{{ og_url }}">
{% if og_image != "" %}<meta property="og:image" content="{{ og_image }}">{% endif %}

<meta name="twitter:card" content="{% if og_image != '' %}summary_large_image{% else %}summary{% endif %}">
<meta name="twitter:title" content="{{ og_title | escape }}">
{% if og_desc %}<meta name="twitter:description" content="{{ og_desc | escape }}">{% endif %}
{% if og_image != "" %}<meta name="twitter:image" content="{{ og_image }}">{% endif %}

<script>
(function() {
var stored = localStorage.getItem('theme');
Expand Down
42 changes: 42 additions & 0 deletions _layouts/item.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,48 @@
{% endif %}
{% endfor %}

{%- comment -%}
schema.org structured data for this item. Audio-bearing categories are
modelled as MediaObject; everything else (e.g. wraps) as CreativeWork.
All optional fields are guarded and run through `jsonify` so quotes and
newlines are safely escaped. `url`/`absolute_url` produce absolute links.
{%- endcomment -%}
{%- assign audio_categories = "locksounds,hornsounds,boombox,lightshows" | split: "," -%}
{%- if audio_categories contains col_name -%}
{%- assign schema_type = "MediaObject" -%}
{%- else -%}
{%- assign schema_type = "CreativeWork" -%}
{%- endif -%}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": {{ schema_type | jsonify }},
"name": {{ page.title | default: page.slug | jsonify }},
"url": {{ page.url | absolute_url | jsonify }},
"genre": {{ category_label | jsonify }}
{%- if page.author %},
"author": { "@type": "Person", "name": {{ page.author | jsonify }} }
{%- endif -%}
{%- if page.description %},
"description": {{ page.description | jsonify }}
{%- endif -%}
{%- if page.tags and page.tags.size > 0 %},
"keywords": {{ page.tags | join: ", " | jsonify }}
{%- endif -%}
{%- if page.thumbnail %},
{%- comment -%} absolute_url already prepends baseurl, so the path starts at /content/. {%- endcomment -%}
{%- capture jsonld_thumb -%}/content/{{ col_name }}/{{ page.slug }}/{{ page.thumbnail }}{%- endcapture %}
"image": {{ jsonld_thumb | absolute_url | jsonify }}
{%- endif -%}
{%- if page.audio %},
{%- capture jsonld_audio -%}/content/{{ col_name }}/{{ page.slug }}/{{ page.audio }}{%- endcapture %}
"contentUrl": {{ jsonld_audio | absolute_url | jsonify }}
{%- endif -%}
,
"isPartOf": { "@type": "WebSite", "name": {{ site.title | jsonify }}, "url": {{ site.url | append: site.baseurl | jsonify }} }
}
</script>

<div class="breadcrumb">
<a href="{{ site.baseurl }}/">Home</a> &rsaquo;
<a href="{{ site.baseurl }}/{{ col_name }}/">{{ category_label }}</a> &rsaquo;
Expand Down