🎉 Initial setup

🎉 Initial setup

Setup deployment
This commit is contained in:
Dennis Reimann
2020-10-03 21:49:25 +02:00
commit 0202e858e6
55 changed files with 11718 additions and 0 deletions

20
.editorconfig Normal file
View File

@@ -0,0 +1,20 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

42
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: build
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14]
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install
run: npm ci
- name: Build
run: npm run prod
- name: Predeploy
if: success() && github.ref == 'refs/heads/master'
run: |
# https://github.blog/2009-12-29-bypassing-jekyll-on-github-pages/
touch dist/.nojekyll
# https://help.github.com/en/articles/managing-a-custom-domain-for-your-github-pages-site
echo einundzwanzig.space > dist/CNAME
- name: Deploy
if: success() && github.ref == 'refs/heads/master'
uses: maxheld83/ghpages@v0.2.1
env:
BUILD_DIR: dist/
GH_PAT: ${{ secrets.GH_PAT }}

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
/dist
/log
/node_modules
/rev-manifest.json
/site-data.json

5
.prettierrc.json Normal file
View File

@@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"arrowParens": "avoid"
}

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# Einundzwanzig Podcast Website
Die offizielle [Einundzwanzig](https://einundzwanzig.space) website.
![Build](https://github.com/Einundzwanzig-Podcast/einundzwanzig.space/workflows/build/badge.svg)
## Content
The content can be edited via the JSON files in the [content directory](./content).
## Local build
[Node.js](https://nodejs.org/en/) is a prerequisite, the dependencies are managed via npm.
Once you have cloned this repo, you can setup the packages:
```bash
npm install
```
Create a build and rebuild on file change:
```bash
npm start
```
This will bring up the dev server on [localhost:3000](http://localhost:3000).

6
browser-sync.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
open: false,
notify: false,
ghostMode: false,
server: ['./static', './dist'],
}

8
content/meta.json Normal file
View File

@@ -0,0 +1,8 @@
{
"title": "Einundzwanzig",
"description": "Toximalistisches Infotainment für bullishe Bitcoiner.",
"keywords": "Bitcoin,Podcast,Lightning Network",
"themeColor": "#FFFFFF",
"cardImage": "img/card.png",
"twitter": "_einundzwanzig_"
}

37
content/team.json Normal file
View File

@@ -0,0 +1,37 @@
[
{
"name": "Markus",
"twitter": "MarkusTurm",
"github": "MarkusTurm",
"text": "Bester Mann.",
"image": "/img/team/markus.jpg"
},
{
"name": "Gigi",
"twitter": "dergigi",
"github": "dergigi",
"text": "Der Gigi.",
"image": "/img/team/gigi.jpg"
},
{
"name": "Fab",
"twitter": "fabthefoxx",
"url": "http://fabthefox.com",
"text": "The Fox 🦊",
"image": "/img/team/fab.jpg"
},
{
"name": "Dennis",
"twitter": "dennisreimann",
"github": "dennisreimann",
"url": "https://d11n.net",
"text": "d11n",
"image": "/img/team/dennis.png"
},
{
"name": "Daniel",
"twitter": "danielwingen",
"text": "Value Of Bitcoin.",
"image": "/img/team/daniel.jpg"
}
]

14
markdown.js Normal file
View File

@@ -0,0 +1,14 @@
// configure markdown-it
const transformer = require('jstransformer')
const { _tr: mdTransformer } = transformer(require('jstransformer-markdown-it'))
const config = {
typographer: true,
}
// monkey-patch render function to pass custom options
const { render: renderMd } = mdTransformer
mdTransformer.render = str => renderMd(str, config)
module.exports = mdTransformer.render

10648
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

54
package.json Normal file
View File

@@ -0,0 +1,54 @@
{
"private": true,
"version": "0.1.0",
"name": "einundzwanzig.space",
"description": "Einundzwanzig Podcast Website",
"repository": "git@github.com:Einundzwanzig-Podcast/einundzwanzig.space.git",
"license": "UNLICENSED",
"engines": {
"node": ">=14.0.0"
},
"scripts": {
"clean": "rm -rf rev-manifest.json site-data.json dist/* && mkdir -p dist",
"start": "npm-run-all clean -p start:*",
"start:pages": "onchange -i -k 'site-data.json' 'pug.config.js' 'markdown.js' 'src/**/*.pug' 'src/**/*.svg' 'tasks/generate_pages.js' -- npm run build:pages",
"start:styles": "onchange -i -k 'src/**/*.css' -- npm run build:styles",
"start:data": "onchange -i -k 'content/**/*' -- npm run build:data",
"start:serve": "browser-sync start --config browser-sync.config.js --watch",
"build": "npm-run-all clean -p build:*",
"build:static": "cp -r static/* dist",
"build:data": "node tasks/generate_site_data.js",
"build:pages": "node tasks/generate_pages.js",
"build:styles": "postcss src/css/main.css --output dist/css/main.css",
"optimize": "npm-run-all -p optimize:* -s rev",
"optimize:styles": "csso dist/css/main.css --output dist/css/main.css",
"rev": "node-file-rev --root=dist/ dist/css/* dist/js/* dist/img/*.jpg dist/img/*.png dist/img/*.svg",
"prod": "npm-run-all build optimize -s build:pages",
"images": "node tasks/optimize_images.js"
},
"devDependencies": {
"autoprefixer": "10.0.1",
"browser-sync": "2.26.12",
"csso-cli": "3.0.0",
"jstransformer-markdown-it": "2.1.0",
"markdown-it": "11.0.1",
"node-file-rev": "1.1.2",
"npm-run-all": "4.1.5",
"onchange": "7.0.2",
"postcss": "8.1.1",
"postcss-calc": "7.0.5",
"postcss-cli": "8.0.0",
"postcss-custom-media": "7.0.8",
"postcss-import": "12.0.1",
"postcss-media-variables": "2.0.1",
"postcss-nesting": "7.0.1",
"pug-cli": "1.0.0-alpha6"
},
"optionalDependencies": {
"compress-images": "1.9.5",
"gifsicle": "5.1.0",
"mozjpeg": "7.0.0",
"pngquant-bin": "6.0.0",
"svgo": "1.3.2"
}
}

13
postcss.config.js Normal file
View File

@@ -0,0 +1,13 @@
const mediaVariables = require('postcss-media-variables')
module.exports = {
plugins: [
require('autoprefixer'),
require('postcss-import'),
require('postcss-nesting'),
mediaVariables,
require('postcss-custom-media'),
require('postcss-calc'),
mediaVariables,
],
}

24
pug.config.js Normal file
View File

@@ -0,0 +1,24 @@
// initialize markdown rendering
const renderMarkdown = require('./markdown')
const slugify = str => str.toLowerCase().replace(/\W/, '-')
const random = max => Math.floor(Math.random() * Math.floor(max))
const linkTarget = url => url.startsWith('http') ? '_blank' : null
const assetPath = path => {
let revs
try { revs = require('./rev-manifest.json') } catch (error) { }
return `${(revs && revs[path]) || path}`
}
const assetUrl = (path, protocol = 'https') => {
return `${protocol}://einundzwanzig.space/${assetPath(path)}`
}
module.exports = {
basedir: './src/includes',
random,
slugify,
assetUrl,
assetPath,
linkTarget,
renderMarkdown,
}

114
src/css/base/elements.css Normal file
View File

@@ -0,0 +1,114 @@
*,
*::before,
*::after {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
vertical-align: baseline;
@media (prefers-reduced-motion: reduce) {
animation: none !important;
transition: none !important;
}
}
html {
height: 100%;
line-height: 1.5;
font-family: var(--font-family-base);
font-size: var(--font-size-base);
scroll-behavior: smooth;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
display: flex;
flex-direction: column;
height: 100%;
color: var(--color-body-text);
background-color: var(--color-body-bg);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-family-head);
line-height: 1.05;
& a {
color: currentColor;
text-decoration: none !important;
}
}
h1 {
font-size: var(--font-size-xxxl);
}
h2 {
font-size: var(--font-size-xxl);
}
h3 {
font-size: var(--font-size-xl);
}
h4, h5, h6 {
font-size: var(--font-size-m);
}
a {
outline: 0;
color: inherit;
text-decoration: underline;
transition-property: background, color;
transition-duration: var(--transition-duration-fast);
&:hover {
@media not all and (hover: none) {
color: var(--color-accent);
text-decoration: underline;
}
}
& svg {
transition-property: background, color;
transition-duration: var(--transition-duration-fast);
}
}
p {
margin-bottom: var(--space-l);
}
ul {
margin-left: var(--space-m);
margin-bottom: var(--space-l);
}
p,
ul {
& + h2 {
margin-top: var(--space-xl);
}
& + h3,
& + h4,
& + h5,
& + h6 {
margin-top: var(--space-l);
}
}
img:-moz-loading {
visibility: hidden;
}
[aria-hidden="true"] {
display: none;
}

4
src/css/base/fonts.css Normal file
View File

@@ -0,0 +1,4 @@
@font-face {
font-family: 'The Bold Font';
src: url('../fonts/theboldfont.woff2') format('woff2');
}

4
src/css/base/footer.css Normal file
View File

@@ -0,0 +1,4 @@
.footer {
text-align: center;
font-size: var(--font-size-xs);
}

119
src/css/base/header.css Normal file
View File

@@ -0,0 +1,119 @@
.header {
/* position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 10; */
color: var(--color-body-text);
background-color: var(--color-body-bg);
@media (--up_to_L) {
padding-top: var(--space-l);
padding-bottom: var(--space-l);
}
@media (--L_and_up) {
padding-top: var(--space-xl);
padding-bottom: var(--space-xl);
}
@nest body.topbar & {
box-shadow: 0px 5px 5px rgba(0, 0, 0, 0.1);
}
@nest body.topbar.topbar--appear & {
opacity: 1;
transition-property: opacity;
transition-duration: var(--transition-duration-fast);
}
& .wrap {
@media (--L_and_up) {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
}
}
& .brand {
display: inline-block;
margin-right: var(--space-xl);
}
& .logo {
display: block;
@media (--up_to_M) {
height: 27px;
width: 300px;
}
@media (--M_to_L) {
height: 45px;
width: 500px;
}
@media (--L_and_up) {
height: 63px;
width: 700px;
}
}
& .nav {
position: relative;
top: 3px;
left: -1px;
display: flex;
flex: 1;
@media (--up_to_L) {
margin-top: var(--space-m);
}
@media (--L_and_up) {
margin-top: var(--space-l);
}
& a {
text-decoration: none;
&.navItem {
text-transform: uppercase;
letter-spacing: -0.04em;
font-weight: var(--font-weight-bold);
margin-right: var(--space-l);
line-height: 1;
@media (--up_to_L) {
font-size: var(--font-size-l);
}
@media (--L_and_up) {
font-size: var(--font-size-xl);
}
}
}
& .social {
display: flex;
align-items: center;
@media (--L_and_up) {
margin-left: auto;
}
& a,
& svg {
display: inline-block;
@media (--up_to_L) {
height: calc(var(--font-size-l) - 0.2rem);
width: calc(var(--font-size-l) - 0.2rem);
}
@media (--L_and_up) {
height: calc(var(--font-size-xl) - 0.2rem);
width: calc(var(--font-size-xl) - 0.2rem);
}
}
& a + a {
margin-left: var(--space-l);
}
}
}
}

24
src/css/base/layout.css Normal file
View File

@@ -0,0 +1,24 @@
.wrap {
max-width: 1440px;
margin-left: auto;
margin-right: auto;
@media (--up_to_M) {
padding-left: var(--space-l);
padding-right: var(--space-l);
}
@media (--M_to_L) {
padding-left: var(--space-xl);
padding-right: var(--space-xl);
}
@media (--L_and_up) {
padding-left: var(--space-xxl);
padding-right: var(--space-xxl);
}
}
.main {
flex: 1;
padding-top: var(--space-xl);
padding-bottom: var(--space-xl);
}

View File

@@ -0,0 +1,61 @@
@custom-media --up_to_M screen and (max-width: 599px);
@custom-media --up_to_L screen and (max-width: 839px);
@custom-media --M_to_L screen and (min-width: 600px) and (max-width: 839px);
@custom-media --M_and_up screen and (min-width: 600px);
@custom-media --L_and_up screen and (min-width: 840px);
:root {
--color-neutral-0: #fff;
--color-neutral-10: #ddd;
--color-neutral-90: #222;
--color-body-text: var(--color-neutral-90);
--color-body-bg: var(--color-neutral-0);
--color-accent: #f7931a;
--color-derweg: #00B4CF;
--color-interview: #151515;
--space-xs: .125rem;
--space-s: .25rem;
--space-m: .5rem;
--space-l: 1rem;
--space-xl: 2rem;
--space-xxl: 4rem;
--transition-duration-fast: 0.25s;
--transition-duration-medium: 0.75s;
--transition-duration-slow: 1.5s;
--border-radius: 16px;
--opacity-text: 0.7;
--font-family-base: sans-serif;
--font-family-head: 'The Bold Font', var(--font-family-base);
--font-weight-light: 300;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--font-size-base: 18px;
--font-size-xs: .7rem;
--font-size-s: .85rem;
--font-size-m: 1rem;
--font-size-l: 1.25rem;
--font-size-xl: 1.5rem;
--font-size-xxl: 2.5rem;
--font-size-xxxl: 4rem;
}
:root[data-theme="dark"] {
--color-body-text: var(--color-neutral-0);
--color-body-bg: var(--color-neutral-90);
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-body-text: var(--color-neutral-0);
--color-body-bg: var(--color-neutral-90);
}
}

11
src/css/main.css Normal file
View File

@@ -0,0 +1,11 @@
/* Base */
@import 'base/variables.css';
@import 'base/fonts.css';
@import 'base/elements.css';
@import 'base/layout.css';
@import 'base/header.css';
@import 'base/footer.css';
/* Sections */
@import 'sections/podcast.css';
@import 'sections/team.css';

View File

@@ -0,0 +1,104 @@
#updates {
position: relative;
padding-top: 120px;
@media (--M_and_up) {
padding-bottom: 180px;
}
& h3 {
@media (--up_to_M) {
font-size: 36px;
margin-bottom: var(--space-l);
}
@media (--M_and_up) {
font-size: 48px;
margin-bottom: var(--space-xl);
}
}
& .update + .update {
margin-top: var(--space-xxl);
}
&:after {
display: inline-block;
content: '';
position: absolute;
left: -65px;
bottom: -80px;
z-index: -1;
background-image: url(../img/bg/updates.svg);
background-repeat: no-repeat;
background-position: 0 100%;
background-size: contain;
max-width: 55%;
width: 369px;
height: 344px;
@media (--up_to_M) {
display: none;
}
}
}
.update {
display: block;
text-decoration: none !important;
@media (--M_and_up) {
display: flex;
align-items: center;
max-width: 53em;
transition-property: background, border, transform;
transition-duration: var(--transition-duration-fast);
}
& .image {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--color-neutral-90);
box-shadow: 0px 100px 80px rgba(12, 11, 24, 0.15), 0px 41.7776px 33.4221px rgba(12, 11, 24, 0.107828), 0px 22.3363px 17.869px rgba(12, 11, 24, 0.0894161), 0px 12.5216px 10.0172px rgba(12, 11, 24, 0.075), 0px 6.6501px 5.32008px rgba(12, 11, 24, 0.0605839), 0px 2.76726px 2.21381px rgba(12, 11, 24, 0.0421718);
border: 3px solid var(--color-neutral-90);
border-radius: var(--space-l);
& img {
max-width: 80%;
max-height: 80%;
}
@media (--up_to_M) {
width: 100%;
height: 195px;
margin-bottom: 25px;
}
@media (--M_and_up) {
flex: 1 0 42.5%;
height: 275px;
margin-right: 25px;
}
}
& h4 {
margin-bottom: 15px;
@media (--up_to_M) {
font-size: var(--font-size-xl);
}
}
& p {
opacity: var(--opacity-text);
color: var(--color-body-text) !important;
}
&:hover {
& .image {
@media not all and (hover: none) {
border-color: var(--color-accent);
background-image: linear-gradient(45deg, #1A136E 29.26%, #0D0AB7 92.45%);
}
}
}
}

68
src/css/sections/team.css Normal file
View File

@@ -0,0 +1,68 @@
#team {
& .members {
display: grid;
grid-gap: var(--space-xxl);
margin: 0;
list-style: none;
@media (--up_to_M) {
grid-template-columns: 1fr;
}
@media (--M_to_L) {
grid-template-columns: 1fr 1fr;
}
@media (--L_and_up) {
grid-template-columns: 1fr 1fr 1fr;
}
}
& .member {
margin: 0;
& img {
display: block;
border-radius: 50%;
@media (--up_to_L) {
height: 87px;
width: 87px;
}
@media (--L_and_up) {
height: 112px;
width: 112px;
}
}
& h4 {
margin-top: var(--space-m);
font-size: 21px;
}
& a {
font-size: var(--font-size-xs);
text-decoration: none;
text-transform: uppercase;
}
& p {
margin: var(--space-s) 0 var(--space-l);
font-size: var(--font-size-s);
opacity: var(--opacity-text);
max-width: 30em;
overflow-wrap: anywhere;
}
& .links {
& a,
& svg {
display: inline-block;
height: 28px;
width: 28px;
}
& a + a {
margin-left: var(--space-m);
}
}
}
}

67
src/includes/template.pug Normal file
View File

@@ -0,0 +1,67 @@
block vars
- const pageTitle = title ? `${title} · ${site.title}` : site.meta.title
- const pageDescription = description || site.meta.description
- const pageKeywords = keywords || site.meta.keywords
- const pageCard = cardImage || site.meta.cardImage
- const themeColor = '#FFFFFF'
mixin sprite(id)
svg(role="img" title=id)&attributes(attributes)
use(xlink:href=`${assetPath("/img/sprite.svg")}#${id}`)
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(http-equiv="X-UA-Compatible" content="ie=edge")
meta(name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover")
meta(name="keywords" content=pageKeywords)
meta(name="description" content=pageDescription)
meta(property="og:locale" content="de_DE")
meta(property="og:site_name" content=site.title)
meta(property="og:title" content=pageTitle)
meta(property="og:description" content=pageDescription)
meta(property="og:type" content="website")
meta(property="og:image" content=assetUrl(pageCard, "http"))
meta(property="og:image:secure_url" content=assetUrl(pageCard))
meta(property="og:image:width" content=1402)
meta(property="og:image:height" content=1402)
meta(property="twitter:card" content="summary")
meta(property="twitter:title" content=pageTitle)
meta(property="twitter:description" content=pageDescription)
meta(property="twitter:image" content=assetUrl(pageCard))
meta(name="msapplication-TileColor" content=themeColor)
meta(name="theme-color" content=themeColor)
link(rel="preload" as="font" crossorigin href=assetPath("/fonts/theboldfont.woff2"))
link(rel="apple-touch-icon" href=assetPath("/img/einundzwanzig-square.svg"))
link(rel="icon" href=assetPath("/img/einundzwanzig-square.svg"))
link(rel="manifest" href="/site.webmanifest")
link(rel="mask-icon" href=assetPath("/img/favicon/safari-pinned-tab.svg") color=themeColor)
link(rel="stylesheet" href=assetPath("/css/main.css"))
title= pageTitle
body
header.header#header
.wrap
a(href="/").brand
+sprite("logo-horizontal").logo
nav.nav
a.navItem(href="/podcast" sclass=(navCurrent === 'podcast' && 'current')) Podcast
a.navItem(href="/team" class=(navCurrent === 'team' && 'current')) Team
.social
a.twitter(href="https://twitter.com/_einundzwanzig_" target="_blank" title="Twitter")
+sprite("twitter")
a.telegram(href="https://t.me/einundzwanzigpodcast" target="_blank" title="Telegram")
+sprite("telegram")
#header-anchor
main.main
.wrap
block main
footer#footer.footer
.wrap
p Craig Wright is a fraud.
script(src=assetPath("/js/main.js"))

9
src/index.pug Normal file
View File

@@ -0,0 +1,9 @@
extends /template.pug
block main
section
:markdown-it(html linkify typographer)
# Start
Content
- [Shoutouts](https://tallyco.in/s/zfxqtu/)

13
src/podcast.pug Normal file
View File

@@ -0,0 +1,13 @@
extends /template.pug
block main
section
:markdown-it(html linkify typographer)
# Podcast
Content
- [Spotify](https://open.spotify.com/show/10408JFbE1n8MexfrBv33r)
- [Apple Podcasts](https://podcasts.apple.com/de/podcast/einundzwanzig-der-bitcoin-podcast/id1488229907)
- [Overcast](https://overcast.fm/itunes1488229907/einundzwanzig-der-bitcoin-podcast)
- [Anchor](https://anchor.fm/einundzwanzig)
- [RSS](https://anchor.fm/s/d8d3c38/podcast/rss)

21
src/team.pug Normal file
View File

@@ -0,0 +1,21 @@
extends /template.pug
block main
section#team
h1 Team
ul.members
each m in team
li.member
img(src=(assetPath(m.image)) alt=m.name loading="lazy")
h4=m.name
p(style=(m.name.startsWith('Arik') ? 'word-break:break-all;' : null))=m.text
.links
if m.twitter
a(href=(m.twitter.startsWith('https://') ? m.twitter : `https://twitter.com/${m.twitter}`) target="_blank" title=`${m.name} on Twitter`)
+sprite("twitter")
if m.github
a(href=(m.github.startsWith('https://') ? m.github : `https://github.com/${m.github}`) target="_blank" title=`${m.name} on GitHub`)
+sprite("github")
if m.url
a(href=m.url target="_blank")
+sprite("url")

11
static/browserconfig.xml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/img/favicon/mstile-150x150.png"/>
<square310x310logo src="/img/favicon/mstile-310x310.png"/>
<wide310x150logo src="/img/favicon/mstile-310x150.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

BIN
static/img/card.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M622 5983 l3 -748 483 -3 482 -2 0 175 0 175 -310 0 -310 0 0 120 0
120 250 0 250 0 0 170 0 170 -250 0 -250 0 0 115 0 115 310 0 310 0 0 170 0
170 -485 0 -485 0 2 -747z"/>
<path d="M1770 5980 l0 -750 173 2 172 3 3 748 2 747 -175 0 -175 0 0 -750z"/>
<path d="M2320 5980 l0 -750 175 0 175 0 2 433 3 434 244 -434 245 -433 188 0
188 0 0 750 0 750 -175 0 -175 0 -2 -432 -3 -432 -241 430 -242 429 -191 3
-191 2 0 -750z"/>
<path d="M3360 4346 l0 -756 169 0 c201 0 296 12 401 49 114 40 184 85 281
181 72 71 93 100 132 180 26 52 53 121 61 152 89 353 -92 726 -428 878 -119
54 -165 62 -398 67 l-218 5 0 -756z m486 364 c37 -18 81 -51 113 -85 231 -244
109 -618 -222 -680 l-37 -7 0 407 0 408 43 -7 c23 -4 69 -20 103 -36z"/>
<path d="M650 4583 c0 -412 3 -518 15 -563 66 -247 290 -422 544 -424 108 -1
175 16 273 66 147 76 265 229 297 386 7 34 11 230 11 547 l0 495 -175 0 -174
0 -3 -504 -3 -504 -30 -44 c-60 -86 -187 -122 -281 -79 -53 24 -109 91 -123
146 -7 29 -11 204 -11 514 l0 471 -170 0 -170 0 0 -507z"/>
<path d="M2000 4340 l0 -750 170 0 170 0 0 437 c0 240 3 433 7 429 5 -4 116
-200 249 -434 l241 -427 186 -3 187 -2 0 750 0 750 -170 0 -170 0 0 -431 c0
-245 -4 -428 -9 -425 -5 3 -116 197 -247 431 l-239 425 -187 0 -188 0 0 -750z"/>
<path d="M660 3290 l0 -170 271 0 c254 0 271 -1 265 -17 -4 -10 -144 -271
-311 -580 -168 -310 -305 -565 -305 -568 0 -3 270 -5 600 -5 l600 0 0 175 0
175 -309 2 -310 3 309 570 c170 314 310 573 310 578 0 4 -252 7 -560 7 l-560
0 0 -170z"/>
<path d="M1832 3448 c3 -7 116 -347 252 -756 l248 -742 171 2 172 3 85 367
c46 202 87 365 89 362 3 -3 49 -168 102 -367 l95 -362 171 -3 171 -2 11 32
c27 85 431 1462 431 1469 0 5 -81 9 -179 9 -162 0 -180 -2 -185 -17 -3 -10
-55 -189 -117 -398 -61 -209 -114 -385 -118 -392 -3 -7 -55 172 -115 398
l-109 409 -171 0 -171 0 -94 -410 c-52 -226 -97 -407 -101 -403 -4 4 -68 189
-141 411 l-134 402 -183 0 c-143 0 -183 -3 -180 -12z"/>
<path d="M4285 3438 c-28 -78 -505 -1475 -505 -1481 0 -4 82 -6 182 -5 l182 3
31 88 30 87 239 -2 239 -3 30 -87 29 -88 179 0 c114 0 179 4 179 10 0 9 -302
945 -436 1353 l-46 137 -164 0 c-123 0 -166 -3 -169 -12z m226 -780 l55 -173
-114 -3 c-63 -1 -117 0 -120 2 -5 6 111 346 119 346 3 0 30 -78 60 -172z"/>
<path d="M5210 2700 l0 -750 173 2 172 3 5 427 5 427 241 -427 241 -427 186
-3 187 -2 0 750 0 750 -170 0 -170 0 0 -431 c0 -236 -4 -428 -8 -425 -5 3
-116 197 -248 431 l-239 425 -187 0 -188 0 0 -750z"/>
<path d="M660 1650 l0 -170 271 0 c254 0 271 -1 265 -17 -4 -10 -144 -271
-311 -580 -168 -310 -305 -565 -305 -568 0 -3 270 -5 600 -5 l600 0 0 175 0
175 -310 2 -309 3 309 570 c170 314 310 573 310 578 0 4 -252 7 -560 7 l-560
0 0 -170z"/>
<path d="M3100 1809 c-170 -17 -325 -92 -451 -218 -89 -89 -139 -170 -182
-296 -29 -83 -31 -100 -32 -225 0 -234 57 -376 217 -538 82 -82 180 -143 298
-183 89 -31 103 -33 230 -33 90 1 152 6 188 16 49 14 52 14 52 -3 0 -18 11
-19 175 -19 l175 0 0 420 0 420 -325 0 -325 0 0 -170 0 -170 151 0 150 0 -3
-42 c-3 -42 -5 -44 -63 -73 -56 -28 -68 -30 -170 -30 -103 0 -114 2 -175 31
-169 81 -263 267 -225 445 61 293 399 422 644 246 l48 -35 122 122 123 123
-44 37 c-155 133 -364 197 -578 175z"/>
<path d="M1992 1063 l3 -748 173 -3 172 -2 0 750 0 750 -175 0 -175 0 2 -747z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

9
static/img/sprite.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

BIN
static/img/team/daniel.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
static/img/team/dennis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
static/img/team/fab.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
static/img/team/gigi.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
static/img/team/markus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

35
static/js/main.js Normal file
View File

@@ -0,0 +1,35 @@
document.addEventListener("DOMContentLoaded", () => {
const $body = document.body
const $headerAnchor = document.getElementById('header-anchor')
// Topbar
const topbarClass = 'topbar'
const topbarAppearClass = 'topbar--appear'
const addTopbar = () => {
$body.classList.add(topbarClass)
window.setTimeout(() => {
$body.classList.add(topbarAppearClass)
}, 25)
}
const removeTopbar = () => {
$body.classList.remove(topbarClass)
$body.classList.remove(topbarAppearClass)
}
if (
"IntersectionObserver" in window &&
"IntersectionObserverEntry" in window &&
"intersectionRatio" in window.IntersectionObserverEntry.prototype
) {
const headerObserver = new IntersectionObserver(entries => {
const { boundingClientRect: { y, height } } = entries[0]
if (Math.abs(y) > height) {
addTopbar()
} else {
removeTopbar()
}
})
headerObserver.observe($headerAnchor)
}
})

19
static/site.webmanifest Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "Einundzwanzig",
"short_name": "Einundzwanzig",
"icons": [
{
"src": "/img/favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/img/favicon/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

13
tasks/fetch_feed.js Normal file
View File

@@ -0,0 +1,13 @@
const { writeFileSync } = require('fs')
const { join, resolve } = require('path')
const Parser = require('rss-parser')
const dir = resolve(__dirname, '..')
const dst = join(dir, 'feed.json')
;(async () => {
const parser = new Parser()
const feed = await parser.parseURL('https://anchor.fm/s/d8d3c38/podcast/rss')
writeFileSync(dst, JSON.stringify(feed, null, 2))
})()

22
tasks/generate_pages.js Normal file
View File

@@ -0,0 +1,22 @@
const pug = require('pug')
const { mkdirSync, writeFileSync } = require('fs')
const { dirname, resolve } = require('path')
const config = require('../pug.config')
const site = require('../site-data')
const feed = require('../feed.json')
const team = require('../content/team.json')
const renderPage = (name, out, data = {}) => {
const file = resolve(__dirname, '..', `src/${name}.pug`)
const options = Object.assign({}, config, { site }, data)
const rendered = pug.renderFile(file, options)
const dst = resolve(__dirname, '..', 'dist', `${out}.html`)
const dir = dirname(dst)
mkdirSync(dir, { recursive: true })
writeFileSync(dst, rendered)
}
renderPage('index', 'index', { navCurrent: 'index' })
renderPage('team', 'team/index', { navCurrent: 'team', team })
renderPage('podcast', 'podcast/index', { navCurrent: 'podcast', feed })

View File

@@ -0,0 +1,12 @@
const { writeFileSync } = require('fs')
const { join, resolve } = require('path')
const meta = require('../content/meta.json')
const dir = resolve(__dirname, '..')
const dst = join(dir, 'site-data.json')
const date = (new Date()).toJSON().split('T')[0]
const data = { date, meta }
writeFileSync(dst, JSON.stringify(data, null, 2))

14
tasks/optimize_images.js Normal file
View File

@@ -0,0 +1,14 @@
const compress_images = require('compress-images')
const input = 'compress/*.{jpg,png,svg,gif}'
const output = 'compress/out/'
compress_images(input, output, { compress_force: true, statistic: true, autoupdate: false }, false,
{ jpg: { engine: "mozjpeg", command: ["-quality", "60"] } },
{ png: { engine: "pngquant", command: ["--quality=20-50", "-o"] } },
{ svg: { engine: "svgo", command: "--multipass" } },
{ gif: { engine: "gifsicle", command: ["--colors", "64", "--use-col=web"] } },
(error, completed, statistic) => {
if (error) console.error(error)
if (statistic) console.log(statistic)
}
)