Skip to content

Commit c56047d

Browse files
authored
Merge pull request #537 from jamstack/zl/jamstacktv
Adds JamstackTV section.
2 parents 720f0c1 + 5bc6d8a commit c56047d

File tree

12 files changed

+318
-11
lines changed

12 files changed

+318
-11
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ dist
1818
.cache
1919

2020
# Environment variables
21-
.env
21+
.env

algolia.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require('dotenv').config();
2+
3+
module.exports = {
4+
appId: 'VGOL4P01VV',
5+
indexName: 'jamstack',
6+
// It’s okay to have this in the repo, it’s used in the clientside JS
7+
searchOnlyApiKey: "a457b566acbf454a61eaaae2e4fee0bf",
8+
};

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,27 @@
2323
},
2424
"dependencies": {
2525
"@11ty/eleventy": "^0.11.1",
26-
"@11ty/eleventy-cache-assets": "^2.0.4",
26+
"@11ty/eleventy-cache-assets": "^2.1.0",
2727
"@zachleat/filter-container": "^1.0.3",
28-
"autoprefixer": "^10.2.3",
28+
"autoprefixer": "^10.2.5",
2929
"cssnano": "^4.1.10",
3030
"dotenv": "^8.2.0",
3131
"fast-glob": "^3.2.5",
3232
"gray-matter": "^4.0.2",
33-
"i18n-iso-countries": "^6.4.0",
33+
"i18n-iso-countries": "^6.5.0",
3434
"js-yaml": "^3.14.0",
35-
"lodash": "^4.17.20",
36-
"luxon": "^1.25.0",
35+
"lodash": "^4.17.21",
36+
"luxon": "^1.26.0",
3737
"markdown-it": "^12.0.4",
38-
"netlify-plugin-minify-html": "^0.3.0",
38+
"netlify-plugin-minify-html": "^0.3.1",
3939
"node-fetch": "^2.6.1",
4040
"npm-run-all": "^4.1.5",
4141
"placename": "^1.1.2",
42-
"postcss": "^8.2.4",
42+
"postcss": "^8.2.8",
4343
"postcss-cli": "^8.3.1",
4444
"postcss-import": "^13.0.0",
4545
"spdx-correct": "^3.1.1",
46-
"tailwindcss": "^2.0.2"
46+
"tailwindcss": "^2.0.3"
4747
},
4848
"devDependencies": {
4949
"live-server": "^1.2.1"

src/css/tailwind.css

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
}
1818
}
1919
h2 {
20-
@apply text-white text-3xl font-bold leading-none mb-8;
20+
@apply text-white text-3xl font-bold leading-none mb-8;
2121
}
2222
@screen md {
2323
h2 {
@@ -152,21 +152,29 @@ footer p a:focus {
152152
}
153153

154154
@supports (outline: none) {
155+
.group:hover .group-hover\:card-shadow-blue-seafoam,
156+
.group:focus .group-hover\:card-shadow-blue-seafoam,
155157
.hover\:card-shadow-blue-seafoam:hover,
156158
.hover\:card-shadow-blue-seafoam:focus {
157159
outline: none;
158160
box-shadow: 0px 3px 20px rgba(1, 159, 220, 0.6);
159161
}
162+
.group:hover .group-hover\:card-shadow-seafoam,
163+
.group:focus .group-hover\:card-shadow-seafoam,
160164
.hover\:card-shadow-seafoam:hover,
161165
.hover\:card-shadow-seafoam:focus {
162166
outline: none;
163167
box-shadow: 0px 3px 20px rgba(135, 249, 237, 0.7);
164168
}
169+
.group:hover .group-hover\:card-shadow-sunrise,
170+
.group:focus .group-hover\:card-shadow-sunrise,
165171
.hover\:card-shadow-sunrise:hover,
166172
.hover\:card-shadow-sunrise:focus {
167173
outline: none;
168174
box-shadow: 0px 3px 20px rgba(246, 62, 103, 0.6);
169175
}
176+
.group:hover .group-hover\:card-shadow-gold,
177+
.group:focus .group-hover\:card-shadow-gold,
170178
.hover\:card-shadow-gold:hover,
171179
.hover\:card-shadow-gold:focus {
172180
outline: none;
@@ -330,6 +338,143 @@ details[open] .summary-swap-open {
330338
.filter-country--hide {
331339
display: none !important;
332340
}
341+
342+
/* Jamstack TV */
343+
.ais-SearchBox-input {
344+
@apply bg-blue-900;
345+
@apply text-white;
346+
@apply font-bold;
347+
@apply p-3;
348+
@apply pl-14;
349+
@apply mx-auto;
350+
@apply border;
351+
border-color: #5A5F75;
352+
@apply rounded-full;
353+
@apply block;
354+
@apply w-full;
355+
background-image: url(/img/svg/icon-search.svg);
356+
background-repeat: no-repeat;
357+
background-position: 1em 50%;
358+
position: relative;
359+
}
360+
.ais-SearchBox-input:before {
361+
content: "";
362+
position: absolute;
363+
left: 0;
364+
top: 0;
365+
bottom: 0;
366+
width: 3em;
367+
background-color: #2b3350;
368+
}
369+
@supports (box-shadow: none) {
370+
.ais-SearchBox-input:focus {
371+
outline: none;
372+
box-shadow: 0 0 1px 4px #E7017A;
373+
}
374+
}
375+
376+
.jamstacktv-link {
377+
display: flex;
378+
flex-wrap: wrap;
379+
}
380+
.jamstacktv-card {
381+
flex-basis: 18.75em; /* 300px /16 */
382+
}
383+
.jamstacktv-item {
384+
flex-basis: 18.75em; /* 300px /16 */
385+
flex-grow: 3;
386+
}
387+
.jamstacktv-card,
388+
.jamstacktv-img {
389+
border-radius: 1em 0 1em 1em;
390+
}
391+
.jamstacktv-img {
392+
width: 100%;
393+
}
394+
.jamstacktv-duration {
395+
@apply inline-block;
396+
@apply px-1;
397+
@apply bg-black;
398+
@apply text-sm;
399+
@apply font-bold;
400+
position: absolute;
401+
right: .4em;
402+
top: .4em;
403+
}
404+
.jamstacktv-time {
405+
display: inline-block;
406+
margin-right: 0.25em; /* 4px /16 */
407+
}
408+
.jamstacktv-time > b {
409+
display: inline-block;
410+
width: 0;
411+
height: 0;
412+
border-top: 5px solid transparent;
413+
border-bottom: 5px solid transparent;
414+
border-left: 7px solid currentColor;
415+
}
416+
.jamstacktv-time > b + b {
417+
margin-right: 3px;
418+
}
419+
.jamstacktv-item {
420+
@apply p-4;
421+
display: flex;
422+
flex-direction: column;
423+
justify-content: center;
424+
}
425+
.jamstacktv-item mark {
426+
@apply bg-pink-900;
427+
@apply text-white;
428+
}
429+
.jamstacktv-meta {
430+
@apply leading-normal;
431+
}
432+
.jamstacktv-category:after {
433+
content: ": ";
434+
}
435+
.jamstacktv-no-skip .jamstacktv-category:after {
436+
content: "";
437+
}
438+
.jamstacktv-no-skip .jamstacktv-category {
439+
display: block;
440+
}
441+
.jamstacktv-caption {
442+
@apply text-xl;
443+
@apply font-normal;
444+
}
445+
.jamstacktv-caption-quote {
446+
@apply italic;
447+
}
448+
.jamstacktv-caption-quote:before {
449+
content: "“"
450+
}
451+
.jamstacktv-caption-quote:after {
452+
content: "”"
453+
}
454+
.jamstacktv-no-skip .jamstacktv-title {
455+
@apply text-2xl;
456+
@apply font-bold;
457+
}
458+
.jamstacktv-no-skip .jamstacktv-caption {
459+
display: none;
460+
}
461+
.js .jamstacktv-js {
462+
display: none;
463+
}
464+
.jamstacktv-scrubber {
465+
position: absolute;
466+
bottom: 0;
467+
width: 100%;
468+
display: flex;
469+
align-items: flex-end;
470+
height: 1em;
471+
border-radius: 0 0 1em 1em;
472+
overflow: hidden;
473+
}
474+
.jamstacktv-scrubber > div {
475+
height: 4px;
476+
background-color: red;
477+
}
333478
/* purgecss end ignore */
334479

335480
@tailwind utilities;

src/site/_data/algolia.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const algoliaConfig = require("../../../algolia.config.js");
2+
3+
// don’t hardcode anything here, make the config variables opt-in
4+
module.exports = {
5+
appId: algoliaConfig.appId,
6+
indexName: algoliaConfig.indexName,
7+
searchOnlyApiKey: algoliaConfig.searchOnlyApiKey,
8+
};

src/site/_data/github.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async function githubRequest(user, repo) {
3030
issues: "",
3131
};
3232

33-
if(process.env.ELEVENTY_ENV == 'dev') {
33+
if(process.env.ELEVENTY_ENV == 'dev' || !process.env.GITHUB_READ_TOKEN) {
3434
return errorData;
3535
}
3636

src/site/_includes/header.njk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
{ "url": "/best-practices/", "text": "Jamstack best practices" },
88
{ "url": "/glossary/", "text": "Glossary" }
99
]},
10+
{ "url": "/tv/" , "text": "Jamstack TV" },
1011
{ "url": "/generators/" , "text": "Site Generators" },
1112
{ "url": "/headless-cms/" , "text": "Headless CMS" },
1213
{ "url": "/community/" , "text": "Community" }

src/site/_includes/layouts/base.njk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ ogimage: "/img/og/default-og-image.png"
1515
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicons/apple-touch-icon.png">
1616
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicons/favicon-32x32.png">
1717
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicons/favicon-16x16.png">
18+
{%- for url in preconnect %}
19+
<link rel="preconnect" href="{{ url }}">
20+
{%- endfor %}
1821
<meta property="og:title" content="{{ title }} | Jamstack">
1922
<meta property="og:site_name" content="Jamstack.org">
2023
<meta property="og:url" content="https://jamstack.org{{ page.url }}">
@@ -28,6 +31,7 @@ ogimage: "/img/og/default-og-image.png"
2831
<meta property="twitter:image" content="{{ netlify.deployUrl }}{{ ogimage }}">
2932
<meta name="google-site-verification" content="i5IheizQ6X_M4jNqb_b7vbJrT34i_gvEg8Gxkq9IY_w" />
3033
<meta name="google-site-verification" content="WDIQ_1X8K7XIpPJ5G1Z8KnOqdSeYetPQB4EgoTLfIsc" />
34+
<script type="module">document.documentElement.classList.add("js");</script>
3135
</head>
3236
<body class="bg-blue-900 text-blue-100 leading-relaxed antialiased">
3337
<svg width="0" height="0" aria-hidden="true" style="position: absolute;">
@@ -96,5 +100,8 @@ ogimage: "/img/og/default-og-image.png"
96100
<script type="module" src="/js/filter-container.js"></script>
97101
<script type="module" src="/js/sort-container.js"></script>
98102
<script type="module" src="/js/lazyiframe.js"></script>
103+
{%- for path in javascriptIncludes %}
104+
{% include path %}
105+
{%- endfor %}
99106
</body>
100107
</html>

src/site/_includes/search-js.njk

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script type="module" src="https://cdn.jsdelivr.net/npm/algoliasearch@4.5.1/dist/algoliasearch-lite.umd.js" integrity="sha256-EXPXz4W6pQgfYY3yTpnDa3OH8/EPn16ciVsPQ/ypsjk=" crossorigin="anonymous"></script>
2+
<script type="module" src="https://cdn.jsdelivr.net/npm/instantsearch.js@4.8.3/dist/instantsearch.production.min.js" integrity="sha256-LAGhRRdtVoD6RLo2qDQsU2mp+XVSciKRC8XPOBWmofM=" crossorigin="anonymous"></script>
3+
<script type="module">
4+
const searchClient = algoliasearch('{{ algolia.appId }}', '{{ algolia.searchOnlyApiKey }}');
5+
6+
const search = instantsearch({
7+
indexName: '{{ algolia.indexName }}',
8+
searchClient,
9+
});
10+
11+
{% raw %}
12+
function pad(num) {
13+
return num < 10 ? `0${num}` : num;
14+
}
15+
16+
function getDurationString(duration) {
17+
let secondsInOne = {
18+
hour: 60*60,
19+
minute: 60
20+
};
21+
22+
let hours = Math.floor(duration / secondsInOne.hour);
23+
let minutes = Math.floor((duration % secondsInOne.hour) / secondsInOne.minute);
24+
let seconds = Math.floor(duration % secondsInOne.minute);
25+
26+
return `${hours ? `${hours}:`: ""}${hours ? pad(minutes) : minutes}:${pad(seconds)}`;
27+
}
28+
29+
search.addWidgets([
30+
instantsearch.widgets.searchBox({
31+
container: '#searchbox',
32+
//placeholder: 'Search Video Content',
33+
showReset: false,
34+
showSubmit: false,
35+
}),
36+
37+
instantsearch.widgets.sortBy({
38+
container: '#sort-by',
39+
items: [
40+
{ label: 'Newest', value: 'jamstack' },
41+
{ label: 'Popular', value: 'popular' },
42+
],
43+
cssClasses: {
44+
//root: 'MyCustomSortBy',
45+
select: [
46+
'text-black py-1 px-2 rounded-default border border-white bg-white',
47+
],
48+
},
49+
}),
50+
51+
instantsearch.widgets.hits({
52+
snippetEllipsisText: '',
53+
container: '#hits',
54+
cssClasses: {
55+
root: "bg-blue-900 text-blue-100",
56+
//item: "bg-blue-900 text-blue-100",
57+
},
58+
transformItems(items) {
59+
return items.map(item => {
60+
let start = item.caption.start;
61+
62+
let obj = {
63+
...item,
64+
url: `https://www.youtube.com/watch?v=${item.video.id}}&t=${start}s`,
65+
displayDuration: getDurationString(item.video.duration),
66+
};
67+
68+
if(start > 10) { // only show for deep links > 10 seconds
69+
obj.displayStartInline = `<span class="jamstacktv-time"><b></b><b></b>${getDurationString(start)} of</span>`;
70+
let scrubberWidth = Math.floor( 100 * item.caption.start / item.video.duration );
71+
obj.scrubberHtml = `<div class="jamstacktv-scrubber"><div style="width: ${scrubberWidth}%"></div></div>`;
72+
//obj._highlightResult.caption.content = `…${obj._highlightResult.caption.content}`;
73+
} else {
74+
obj.wrapperClass = "jamstacktv-no-skip";
75+
}
76+
return obj;
77+
});
78+
},
79+
templates: {
80+
item: `
81+
<a href="{{ url }}" class="mb-4 group jamstacktv-link">
82+
<div class="relative jamstacktv-card">
83+
<img src="{{ video.thumbnails.medium }}" alt="{{ video.title }}" class="jamstacktv-img card-shadow bg-gradient-card-sunrise group-hover:card-shadow-sunrise" width="480" height="360">
84+
<span class="jamstacktv-duration">{{{ displayStartInline }}}{{ displayDuration }}</span>
85+
{{{ scrubberHtml }}}
86+
</div>
87+
<div class="jamstacktv-item {{ wrapperClass }}">
88+
<div class="jamstacktv-meta mb-1">
89+
<span class="jamstacktv-category">{{#helpers.highlight}}{ "attribute": "playlist.title" }{{/helpers.highlight}}</span>
90+
<span class="jamstacktv-title">{{#helpers.highlight}}{ "attribute": "video.title" }{{/helpers.highlight}}</span>
91+
</div>
92+
<strong class="jamstacktv-caption"><span class="jamstacktv-caption-quote">{{#helpers.highlight}}{ "attribute": "caption.content" }{{/helpers.highlight}}</span></strong>
93+
</div>
94+
</div>
95+
`,
96+
},
97+
})
98+
]);
99+
100+
search.start();
101+
{% endraw %}
102+
</script>

src/site/img/svg/icon-search.svg

Lines changed: 5 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)