Initial Commit

This commit is contained in:
Snazzah 2021-12-31 12:49:24 -06:00
commit 91c23c40c6
No known key found for this signature in database
GPG key ID: 5E71D54F3D86282E
53 changed files with 15543 additions and 0 deletions

16
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,16 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
commit-message:
prefix: chore
include: scope
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
commit-message:
prefix: ci

29
.github/workflows/gh-pages.yml vendored Normal file
View file

@ -0,0 +1,29 @@
name: Deploy
on:
push:
branches: [ master ]
workflow_dispatch:
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 16.x
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Build
run: yarn docs:build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/.vuepress/dist

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/node_modules
/docs/.vuepress/dist
/.vscode/settings.json
*.log
.idea

10
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
"recommendations": [
"syler.sass-indented",
"alan.stylus",
"gruntfuggly.todo-tree",
"octref.vetur",
"gamunu.vscode-yarn",
"editorconfig.editorconfig"
]
}

15
LICENSE Normal file
View file

@ -0,0 +1,15 @@
The MIT License (MIT)
Copyright (c) 2015-2022 LBRY Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OF OTHER DEALINGS IN THE SOFTWARE.

16
README.md Normal file
View file

@ -0,0 +1,16 @@
# lbry.org
The new website for the LBRY Foundation using Vuepress
## Contributing
Learn more about [VuePress](https://vuepress.vuejs.org/) when contributing. New pages should be in the format of `/page/README.md`.
## Development
Install [Node.JS](https://nodejs.org/) v16 or higher (use [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md)) and clone this repository.
```sh
npm i -g yarn
yarn install
yarn docs:dev # serves at localhost:8080
```
## License
This project is MIT licensed. For the full license, see [LICENSE](LICENSE).

13
TODO.md Normal file
View file

@ -0,0 +1,13 @@
# TODO
- [ ] Finish home page
- [x] Privacy Policy
- [ ] Branding page
- [ ] Swarm page
- [ ] Chat page (?)
- [ ] Roadmap page
- [ ] Verified page
- [ ] Governance page
- [ ] Projects page
- [x] 404 page
- [ ] Fix grammatical/format errors in the Privacy Policy

View file

@ -0,0 +1,16 @@
<template>
<Icon :icon="icon" />
</template>
<script>
import { Icon, addCollection } from '@iconify/vue2'
import faSolidIcons from '@iconify/json/json/fa-solid.json';
addCollection(faSolidIcons);
import faBrandsIcons from '@iconify/json/json/fa-brands.json';
addCollection(faBrandsIcons);
export default {
name: 'IconifyIcon',
props: ['icon'],
components: { Icon }
};
</script>

View file

@ -0,0 +1,27 @@
<template>
<img :src="src" :data-original="original" class="md-img" />
</template>
<style lang="stylus">
.md-img
margin .5em 10%
width 80%
border-radius 10px
filter drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.25))
transition border-radius .2s ease, filter .2s ease
// Zoomed in
&[style*="z-index"]
filter drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.25))
border-radius 5px
@media (max-width: $MQMobile)
.md-img
width 100%
margin .5em 0
</style>
<script>
export default {
name: 'markdownimage',
props: ['src', 'original'],
};
</script>

View file

@ -0,0 +1,55 @@
<template>
<div class="person">
<img
v-if="!!avatar" no-zoom
draggable="false"
:alt="`${name}'s Avatar`"
:src="avatar"
:class="imageClass ? `image-title ${imageClass}` : 'image-title'">
<div class="person-content">
<h4 :class="avatar || subtitle ? 'title' : 'title minimal'">{{ name }}</h4>
<p v-if="!!subtitle" class="subtitle">{{ subtitle }}</p>
<div class="buttons"><slot/></div>
</div>
</div>
</template>
<style lang="stylus">
.person
border-radius .5em
background-color var(--secondaryBG)
padding .5em 1em
margin .5em
display flex
.title
font-size 24px
&.minimal
font-size 16px
font-weight normal
.title, .subtitle
margin 0
img
height 5em
& + .person-content
margin-left 1em
&.large
height 10em
&.rounded
border-radius 50%
.person-content
display flex
flex-direction column
flex auto
justify-content center
.subtitle
color var(--tertiaryText)
.buttons a
line-height 2
</style>
<script>
export default {
name: 'person',
props: ['avatar', 'name', 'subtitle', 'imageClass'],
};
</script>

155
docs/.vuepress/config.js Normal file
View file

@ -0,0 +1,155 @@
const sidebar = require('./sidebar.js');
const metaTitle = 'LBRY Foundation',
metaDesc = 'LBRY is a secure, open, and community-run digital marketplace.',
metaURL = 'https://lbry.org',
metaLogo = '/logo.png',
metaColor = '#27E4EB';
const config = {
title: metaTitle,
description: metaDesc,
main: 'layouts/Layout.vue',
head: [
// Manifest
['link', { rel: 'icon', href: metaLogo }],
['link', { rel: 'manifest', href: '/manifest.json' }],
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }],
// Icons
['link', { rel: 'mask-icon', href: '/logo/safari-pinned-tab.svg', color: metaColor }],
['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/logo/apple-touch-icon.png' }],
['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
['link', { rel: 'icon', sizes: '16x16', href: '/logo/favicon-16x16.png' }],
['link', { rel: 'icon', sizes: '32x32', href: '/logo/favicon-32x32.png' }],
['link', { rel: 'icon', sizes: '192x192', href: '/logo/android-chrome-192x192.png' }],
['link', { rel: 'icon', sizes: '512x512', href: '/logo/android-chrome-512x512.png' }],
// Theme Color
['meta', { name: 'theme-color', content: metaColor }],
['meta', { name: 'msapplication-TileColor', content: metaColor }],
// Twitter
['meta', { name: 'twitter:card', content: 'summary' }],
['meta', { name: 'twitter:url', content: metaURL }],
['meta', { name: 'twitter:title', content: metaTitle }],
['meta', { name: 'twitter:description', content: metaDesc }],
['meta', { name: 'twitter:image', content: metaLogo }],
// OpenGraph
['meta', { name: 'og:type', content: 'website' }],
['meta', { name: 'og:url', content: metaURL }],
['meta', { name: 'og:title', content: metaTitle }],
['meta', { name: 'og:description', content: metaDesc }],
['meta', { name: 'og:locale', content: 'en_US' }],
['meta', { name: 'og:image', content: metaLogo }],
['meta', {
name: 'og:keywords',
content: [
'lbry'
].join(',')
}]
],
plugins: [
[
'zooming',
{
selector: '.md-img,img[zoomable]',
options: {
bgColor: 'black',
bgOpacity: 0.5,
scaleBase: 0.8
}
}
],
'@vuepress/pwa',
'@vuepress/last-updated',
[
'sitemap',
{
hostname: 'https://lbry.org'
}
],
[
require('./plugins/redirect.js'),
[
// TODO update redirects
{ url: 'https://github.com/LBRYFoundation',
aliases: ['/github/'] }
]
],
require('./plugins/richmeta.js')
],
themeConfig: {
search: false,
nav: [
// TODO update?
{ text: 'Swarm', link: '/swarm/' },
{ text: 'Chat', link: '/chat/' },
{ text: 'Roadmap', link: '/roadmap/' },
{ text: 'Verified', link: '/verified/' },
{ text: 'Governance', link: '/governance/' },
{ text: 'Projects', link: '/projects/' }
],
sidebar,
nextLinks: true,
prevlinks: true,
docsRepo: 'LBRYFoundation/lbry.org',
docsDir: 'docs',
editLinks: true,
editLinkText: 'Improve this page on GitHub!',
logo: '/logo-horizontal.svg',
smoothScroll: true,
footer: {
logo: '/logo-vertical.svg',
columns: [
{
title: 'More',
rows: [{
text: 'Privacy Policy',
link: '/privacy/'
},
{
text: 'Branding',
link: '/branding/'
},
{
text: 'GitHub Repo',
link: 'https://github.com/LBRYFoundation/lbry.org'
}]
},
{
title: 'Other Sites',
rows: [{
text: 'LBRY.com',
link: 'https://lbry.com/'
},
{
text: 'LBRY.tech',
link: 'https://lbry.tech/'
},
{
text: 'LBRY.fund',
link: 'https://lbry.fund/'
},
{
text: 'LBRY.tv',
link: 'https://lbry.tv/'
}]
}
],
finePrints: [
'© 2021 LBRY Foundation Inc',
'With love for community'
]
}
}
}
for (const group of Object.values(config.themeConfig.sidebar)) {
for (const section of group) {
if (section.collapsable) continue;
section.collapsable = false;
}
}
module.exports = config;

View file

@ -0,0 +1,71 @@
const fs = require('fs-extra');
const path = require('path');
function getTemplate (path) {
const result = '<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<meta charset="utf-8">' +
'<title>Redirecting...</title>' +
'<link rel="canonical" href="' + path + '">' +
'<meta http-equiv="refresh" content="0; url=' + path + '">' +
'</head>' +
'</html>';
return result;
}
function getAliases (options, ctx) {
let aliasArray = [];
ctx.pages.filter(({ frontmatter }) => {
return frontmatter.alias || frontmatter.aliases
}).forEach(page => {
let aliases = page.frontmatter.alias || page.frontmatter.aliases;
if (!Array.isArray(aliases)) aliases = [aliases];
if (!aliases.length) return;
aliasArray.push({ url: page.path, aliases });
});
if (options && Array.isArray(options))
aliasArray = aliasArray.concat(options);
return aliasArray;
}
// function getAbsLink (options, ctx, link) {
// const alias = getAliases(options, ctx).find(link => link.aliases.includes(link));
// return alias ? alias.url : link;
// }
module.exports = (options, ctx) => ({
name: 'redirect-pages',
extendPageData($page) {
Object.assign($page.frontmatter, { _aliases: getAliases(options, ctx) });
},
beforeDevServer(app) {
getAliases(options, ctx).forEach(({ url, aliases }) =>
aliases.forEach(alias =>
app.get(alias, (_, res) => res.redirect(url)))
);
},
generated() {
const { outDir } = ctx;
getAliases(options, ctx).forEach(({ url, aliases }) => {
aliases.forEach(alias => {
let filePaths = [alias];
if (/^\/.+\/$/.test(alias))
filePaths = [
alias.slice(1).replace(/\/$/, '') + '.html',
alias.slice(1).replace(/\/$/, '') + '/index.html'
];
filePaths.forEach(async file => {
const aliasPagePath = path.resolve(outDir, file)
await fs.outputFile(aliasPagePath, getTemplate(url))
});
});
});
}
})

View file

@ -0,0 +1,6 @@
const path = require('path')
module.exports = {
name: 'rich-meta',
clientRootMixin: path.resolve(__dirname, 'richmeta.mixin.js')
}

View file

@ -0,0 +1,106 @@
export default {
created () {
if (this.$ssrContext) {
const scriptTypes = this.getScriptTypes()
this.$ssrContext.pageMeta = renderScriptTypes(scriptTypes)
}
},
mounted () {
this.currentScriptTypes = {}
this.updateScriptTypes()
},
methods: {
updateScriptTypes (scriptTypes) {
if (!scriptTypes) scriptTypes = this.getScriptTypes();
Object.keys(scriptTypes).forEach(t => {
if (!hasScriptType(t)) addScriptType(t, ...scriptTypes[t]);
else setScriptType(t, scriptTypes[t]);
});
if (this.currentScriptTypes)
Object.keys(this.currentScriptTypes).forEach(t => {
if (hasScriptType(t) && !scriptTypes[t]) removeScriptType(t);
});
this.currentScriptTypes = scriptTypes;
},
getScriptTypes () {
const scriptTypes = this.$page.frontmatter.scriptTypes || {};
if (scriptTypes.faq) {
scriptTypes.faq[1] = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: scriptTypes.faq[1].map(([q, a]) => ({
'@type': 'Question',
name: q,
acceptedAnswer: {
'@type': 'Answer',
text: a
}
}))
}
}
if (scriptTypes.org) {
scriptTypes.org[1] = {
'@context': 'https://schema.org',
'@type': 'Organization',
url: scriptTypes.org[1][0],
logo: scriptTypes.org[1][1],
name: scriptTypes.org[1][2]
}
}
return scriptTypes;
}
},
watch: {
$page () {
this.updateScriptTypes()
}
},
beforeDestroy () {
updateScriptTypes({})
}
}
function hasScriptType (type) {
return !!document.querySelector(`script[data-id='${type}']`);
}
function removeScriptType (type) {
document.head.removeChild(document.querySelector(`script[data-id='${type}']`))
}
function addScriptType (type, props = {}, content = '') {
const script = document.createElement('script');
script.setAttribute('data-id', type);
Object.keys(props).forEach(p => script.setAttribute(p, props[p]));
script.innerHTML = typeof content === 'object' ? JSON.stringify(content) : content;
document.head.appendChild(script);
}
function setScriptType (type, content) {
document.querySelector(`script[type='${type}']`).innerHTML = content;
}
function renderScriptTypes (scriptTypes) {
if (!scriptTypes || !Object.keys(scriptTypes).length) return '';
return Object.keys(scriptTypes).map(t => {
const props = scriptTypes[t][0] || {}
let content = ''
if (typeof scriptTypes[t][1] === 'string') content = scriptTypes[t][1];
if (typeof scriptTypes[t][1] === 'object') content = JSON.stringify(scriptTypes[t][1]);
let res = `<script data-id="${t}"`
Object.keys(props).forEach(key => {
res += ` ${key}="${props[key]}"`
})
return `${res}>${content}</script>`
}).join('\n ')
}

View file

@ -0,0 +1 @@
lbry.org

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/logo/mstile-150x150.png"/>
<TileColor>#27e4eb</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 595.28 514.73"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{mask:url(#mask);}.cls-3{fill:#52c5d2;}</style><linearGradient id="linear-gradient" x1="295.62" y1="334.7" x2="295.62" y2="44.07" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="0.12" stop-color="#e9e9e9"/><stop offset="0.36" stop-color="#afafaf"/><stop offset="0.71" stop-color="#545454"/><stop offset="1" stop-color="#010101"/></linearGradient><mask id="mask" x="-38.72" y="-29.4" width="668.69" height="553.16" maskUnits="userSpaceOnUse"><rect class="cls-1" x="-38.72" y="-29.4" width="668.69" height="553.16"/></mask></defs><title>lbry</title><g id="Layer_2" data-name="Layer 2"><g class="cls-2"><path class="cls-3" d="M585.81,324.31,294.2,478.2,13.61,326.67,0,356,294.3,514.73l301-160.45Zm-24.81-41L392.24,193.66V99.15H356.09v192.5L392.24,272V234.6L484,283.34,294.57,384,105.18,283.34l86.36-45.89v36.11L227.69,292V108.49H191.54v88L28.14,283.34,294.57,424.93ZM227.69,44.2H191.54V86.79h36.15Zm83.6,272.13V173.57H275.15V316.71l18.09,9.39Zm0-316.59H275.15v140h36.14Zm80.95,32.64H356.09V75h36.15Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 595.28 595.28"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{mask:url(#mask);}.cls-3{fill:#52c5d2;}</style><linearGradient id="linear-gradient" x1="295.62" y1="374.98" x2="295.62" y2="84.35" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="0.12" stop-color="#e9e9e9"/><stop offset="0.36" stop-color="#afafaf"/><stop offset="0.71" stop-color="#545454"/><stop offset="1" stop-color="#010101"/></linearGradient><mask id="mask" x="-38.72" y="10.87" width="668.69" height="553.16" maskUnits="userSpaceOnUse"><rect class="cls-1" x="-38.72" y="10.87" width="668.69" height="553.16"/></mask></defs><title>lbry-square</title><g id="Layer_2" data-name="Layer 2"><g class="cls-2"><path class="cls-3" d="M585.81,364.58,294.2,518.47,13.61,366.94,0,396.31,294.3,555l301-160.45Zm-24.81-41L392.24,233.94V139.43H356.09v192.5l36.15-19.71V274.87L484,323.62,294.57,424.27,105.18,323.62l86.36-45.9v36.11l36.15,18.42V148.76H191.54v88L28.14,323.62,294.57,465.2ZM227.69,84.47H191.54v42.59h36.15Zm83.6,272.13V213.85H275.15V357l18.09,9.4Zm0-316.58H275.15V180h36.14Zm80.95,32.64H356.09v42.59h36.15Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -0,0 +1,22 @@
{
"name": "LBRY Foundation",
"short_name": "LBRY Foundation",
"description": "LBRY is a secure, open, and community-run digital marketplace.",
"icons": [
{
"src": "/logo/android-chrome-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/logo/android-chrome-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "/?source=pwa",
"background_color": "#072a46",
"display": "minimal-ui",
"scope": "/",
"theme_color": "#27e4eb"
}

12
docs/.vuepress/sidebar.js Normal file
View file

@ -0,0 +1,12 @@
module.exports = {
// '/other/': [
// {
// title: 'Additional Information',
// children: [
// '/other/',
// '/',
// ['https://github.com/LBRYFoundation', 'Outside link']
// ],
// },
// ]
};

4072
docs/.vuepress/styles/animate.styl vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,250 @@
@import './animate'
@import '~@fontsource/roboto/300.css'
@import '~@fontsource/roboto/400.css'
@import '~@fontsource/roboto/500.css'
@import '~@fontsource/roboto/700.css'
@import '~@fontsource/roboto/400-italic.css'
@import '~@fontsource/roboto/500-italic.css'
table
overflow visible
.animate__animated
animation-fill-mode both
html
background-color var(--primaryBG)
body
font-family Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell, 'Fira Sans' , 'Droid Sans' , 'Helvetica Neue', sans-serif;
#app
background-color var(--primaryBG)
color var(--text)
h2
border-color var(--tertiaryBG)
h1, h2, h3, h4, h5, h6
color var(--headerText)
.sidebar
background-color var(--secondaryBG)
border none
.nav-links
background-color var(--secondaryBG)
border-color var(--tertiaryBG)
&::-webkit-scrollbar-track
background-color var(--tertiaryBG)
border-radius 10px
border 3px solid var(--secondaryBG)
&::-webkit-scrollbar-thumb
background-color var(--primaryBG)
border-radius 10px
border 3px solid var(--secondaryBG)
a.sidebar-link:not(.active):not(:hover)
color var(--secondaryText)
.page-nav .inner
border-top 1px solid var(--tertiaryBG)
.page-edit .edit-link a, .page-edit .last-updated .prefix
color var(--secondaryText)
*::-webkit-scrollbar
width 15px
*::-webkit-scrollbar-track
background-color var(--secondaryBG)
border-radius 10px
border 3px solid var(--primaryBG)
*::-webkit-scrollbar-thumb
background-color var(--tertiaryBG)
border-radius 10px
border 3px solid var(--primaryBG)
.theme-default-content
code
color var(--secondaryText)
background-color var(--secondaryBG)
table
tr
border-top 1px solid var(--tertiaryBG)
&:nth-child(2n)
background-color var(--secondaryBG)
th, td
border 1px solid var(--tertiaryBG)
padding .6em 1em
[class^='language-']
background-color var(--text)
.custom-block
color var(--text)
border-radius 10px
overflow hidden
.custom-block-title
font-size 18px
font-weight 500
&.tip, &.details, &.warning, &.danger
color var(--text)
background-color alpha(#000, 0.2)
&.tip, &.details
border-color var(--accent)
.custom-block-title
color var(--headerText)
&.warning
border-color var(--warning)
.custom-block-title
color var(--warning)
a
color var(--accent)
&.danger
border-color var(--error)
.custom-block-title
color var(--error)
a
color var(--accent)
.sidebar-link
&.active
border none
.sidebar-heading.open
color var(--headerText) !important
// Lightbox
.lightbox__default-loader {
position:absolute;
top:50%;
left:50%;
-webkit-transform:translate(-50%,-50%);
transform:translate(-50%,-50%);
z-index:-1
}
.lightbox__default-loader__element {
-webkit-animation:LightboxDefaultLoaderAnimation 1s linear infinite;
animation:LightboxDefaultLoaderAnimation 1s linear infinite;
border:3px solid #292929;
border-top:3px solid #fff;
border-radius:50%;
height:75px;
width:75px
}
@-webkit-keyframes LightboxDefaultLoaderAnimation{
to {
border-top-color:#fff;
-webkit-transform:rotate(1turn);
transform:rotate(1turn)
}
}
@keyframes LightboxDefaultLoaderAnimation{
to{
border-top-color:#fff;
-webkit-transform:rotate(1turn);
transform:rotate(1turn)
}
}
.lightbox {
position:fixed;
top: $navbarHeight;
left:0;
background:rgba(0,0,0,.8);
display:-webkit-box;
display:-ms-flexbox;
display:flex;
-webkit-box-pack:center;
-ms-flex-pack:center;
justify-content:center;
-webkit-box-align:center;
-ms-flex-align:center;
align-items:center;
z-index:1
}
.lightbox__thumbnail {
width:100%;
height:100%
}
.lightbox {
width: 100%;
height: calc(100% - 3.6rem)
}
.lightbox__thumbnail img {
width:100%
}
.lightbox__close {
position:fixed;
right:0;
top: $navbarHeight;
padding:1rem;
font-size:1.5rem;
cursor:pointer;
color:#fff;
width:4rem;
height:4rem
}
.lightbox__arrow--invisible {
visibility:hidden
}
.lightbox__element {
width:100%;
height:-webkit-fit-content;
height:-moz-fit-content;
height:fit-content
}
.lightbox__arrow,.lightbox__element {
display:-webkit-box;
display:-ms-flexbox;
display:flex
}
.lightbox__arrow {
padding:0 2rem;
cursor:pointer;
-webkit-box-pack:center;
-ms-flex-pack:center;
justify-content:center;
-webkit-box-align:center;
-ms-flex-align:center;
align-items:center
}
.lightbox__arrow svg {
fill:#fff;
pointer-events:none
}
.lightbox__image {
-webkit-box-flex:1;
-ms-flex:1;
flex:1
}
.lightbox__image img{
width:100%;
height:auto!important
}
@media screen and (max-width:720px) {
.lightbox__arrow{
padding:0 1rem
}
}
@media screen and (max-width:500px) {
.lightbox__element{
position:relative
}
.lightbox__arrow{
position:absolute;
padding:0 2rem;
height:100%
}
.lightbox__arrow--right{
right:0;
background:-webkit-gradient(linear,left top,right top,from(transparent),to(rgba(0,0,0,.3)));
background:linear-gradient(90deg,transparent,rgba(0,0,0,.3))
}
.lightbox__arrow--left{
left:0;
background:-webkit-gradient(linear,right top,left top,from(transparent),to(rgba(0,0,0,.3)));
background:linear-gradient(270deg,transparent,rgba(0,0,0,.3))
}
}

View file

@ -0,0 +1,40 @@
// layout
$navbarHeight = 4rem
$sidebarWidth = 20rem
$contentWidth = 740px
$homePageWidth = 1440px
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 2.5rem
// responsive breakpoints
$MQNarrow = 959px
$MQMobile = 719px
$MQMobileNarrow = 419px
// LBRY
$accentColor = #27E4EB
$counter-accent = #fff
$warning = #F1C40F
$error = #E74C3C
$bg1 = #072A46
$bg2 = #051D31
$bg3 = #041523
$header-text = #FAFAFA
$text = #DDDDDD
:root {
--accent: $accentColor
--accentLight10: lighten($accentColor, 10%)
--accentDark10: darken($accentColor, 10%)
--counterAccent: $counter-accent
--tip: $accent
--warning: $warning
--error: $error
--primaryBG: $bg1
--secondaryBG: $bg2
--tertiaryBG: $bg3
--headerText: $header-text
--text: $text
}

View file

@ -0,0 +1,101 @@
<template>
<div class="footer">
<div class="footer-main">
<img v-if="config.logo" :src="config.logo" draggable="false" />
<div class="columns" v-if="config.columns && config.columns.length">
<div class="column" :key="i" v-for="(column, i) in config.columns">
<span class="col-title">{{ column.title }}</span>
<div class="links" v-if="column.rows">
<NavLink :key="j" v-for="(cell, j) in column.rows" :item="cell" />
</div>
</div>
</div>
</div>
<div class="fine-print" v-if="config.finePrints">
<span>{{ config.finePrints[0] }}</span> <i>{{ config.finePrints[1] }}</i>
</div>
</div>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
export default {
name: 'Footer',
components: { NavLink },
computed: {
data () {
return this.$page.frontmatter
},
config () {
return this.$site.themeConfig.footer || {}
},
}
}
</script>
<style lang="stylus">
.footer
background-color var(--tertiaryBG)
background-repeat no-repeat
background-size contain
background-position right
padding 1rem
width calc(100% - 2rem)
margin-top 5rem
.footer-main
display flex
flex-direction row
justify-content space-between
max-width $contentWidth
margin 0 auto
img
flex none
height 100px
.columns
display flex
gap 40px
.column-opener
max-width 200px
.column
display flex
flex-direction column
.col-title
font-weight 500
margin-bottom 5px
color var(--headerText)
.links
display flex
align-self center
flex-direction column
align-self flex-start
a
font-weight 400
color var(--text)
& svg
display none
&:hover
text-decoration underline
.fine-print
color var(--text)
font-size 10px
max-width $contentWidth
margin 0 auto
margin-top 30px
display flex
gap 10px
@media (max-width: $MQMobile)
.footer
background-image none
.columns
flex-wrap wrap
gap 20px
.column-opener
max-width none
margin-bottom 2rem
.column
align-self flex-start
.links
justify-content center
.fine-print
margin-top 2rem
</style>

View file

@ -0,0 +1,153 @@
<template>
<main class="home" role="main">
<header class="landing">
<div class="hero">
<img :src="data.heroImage" draggable="false" />
<div class="hero-text">
<h1>{{ data.heroText || $title || 'Hello' }}</h1>
<p class="description">{{ data.tagline || $description || 'Welcome to your VuePress site' }}</p>
</div>
</div>
<p class="action-buttons" v-if="data.actionButtons && data.actionButtons.length">
<a
class="action-button"
v-for="abtn in data.actionButtons"
target="_blank"
rel="noopener"
:key="abtn.text"
:href="abtn.link"
>
<IconifyIcon v-if="abtn.icon" :icon="abtn.icon" />
<span>{{ abtn.text }}</span>
</a>
</p>
</header>
<Content class="content" />
</main>
</template>
<script>
import { Icon, addCollection } from '@iconify/vue2'
import faSolidIcons from '@iconify/json/json/fa-solid.json';
addCollection(faSolidIcons);
import faBrandsIcons from '@iconify/json/json/fa-brands.json';
addCollection(faBrandsIcons);
export default {
name: 'Home',
components: { IconifyIcon: Icon },
computed: {
data () {
return this.$page.frontmatter
}
}
}
</script>
<style lang="stylus">
.home
padding $navbarHeight 0
margin 0 auto
display flex
flex-direction column
position relative
.landing
display flex
flex-direction column
justify-content space-between
margin 2.5rem 0
.hero
display flex
flex-direction column
text-align center
align-self center
justify-content center
align-items center
gap 20px
max-width $contentWidth - 100px
width calc(100% - 40px)
img
width 200px
flex none
.hero-text
display flex
flex-direction column
text-align center
align-self center
justify-content center
align-items center
gap 10px
h1
font-size 48px
margin 0
.description
width 100%
font-size 26px
line-height 1.3
color var(--text)
margin 0
.action-buttons
display flex
justify-content space-evenly
align-self center
flex-wrap wrap
gap 20px
.action-button
display inline-flex
align-items center
gap 10px
padding 15px 20px
font-size 20px
font-weight 500
flex-direction row
color var(--counterAccent)
background-color var(--tertiaryBG)
border-radius 8px
line-height 1
&:hover
background-color var(--secondaryBG)
text-decoration none
.content
background-color var(--secondaryBG)
border-radius 15px
box-shadow 0px 0px 4px rgba(0, 0, 0, 0.25)
padding 20px
margin 0 auto
max-width $contentWidth
width calc(100% - 80px)
& > :first-child
margin-top 0
& > :last-child
margin-bottom 0
hr
margin 0
// @media (max-width: $MQNarrow)
@media (max-width: $MQMobile)
.home
padding-bottom 0
.landing
.hero
img
width 150px
.hero-text
h1
font-size 24px
.description
font-size 20px
.action-buttons
gap 10px
.action-button
gap 10px
padding 10px 15px
font-size 18px
.content
border-radius 0
box-shadow none
width calc(100% - 40px)
& + .footer
margin-top 0
</style>

View file

@ -0,0 +1,85 @@
<template>
<RouterLink
v-if="isInternal"
class="nav-link"
role="button"
:class="item.class || ''"
:to="link"
:exact="exact"
@focusout.native="focusoutAction"
>
{{ item.text }}
</RouterLink>
<a
v-else
:href="link"
class="nav-link external"
role="button"
:class="item.class || ''"
:target="target"
:rel="rel"
@focusout="focusoutAction"
>
{{ item.text }}
<OutboundLink v-if="isBlankTarget" />
</a>
</template>
<script>
import { isExternal, isMailto, isTel, ensureExt } from '@parent-theme/util'
export default {
name: 'NavLink',
props: {
item: {
required: true
}
},
computed: {
absLink () {
const alias = this.$page.frontmatter._aliases ? this.$page.frontmatter._aliases.find(link => link.aliases.includes(this.item.link)) : null;
return alias ? alias.url : this.item.link;
},
link () {
return ensureExt(this.absLink)
},
exact () {
if (this.$site.locales) {
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
}
return this.link === '/'
},
isNonHttpURI () {
return isMailto(this.link) || isTel(this.link)
},
isBlankTarget () {
return this.target === '_blank'
},
isInternal () {
return !isExternal(this.link) && !this.isBlankTarget
},
target () {
if (this.isNonHttpURI) {
return null
}
if (this.item.target) {
return this.item.target
}
return isExternal(this.link) ? '_blank' : ''
},
rel () {
if (this.isNonHttpURI) {
return null
}
if (this.item.rel) {
return this.item.rel
}
return this.isBlankTarget ? 'noopener noreferrer' : ''
}
},
methods: {
focusoutAction () {
this.$emit('focusout')
}
}
}
</script>

View file

@ -0,0 +1,149 @@
<template>
<header class="navbar" role="navigation">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" role="button" />
<RouterLink
:to="$localePath"
class="home-link"
>
<img
v-if="$site.themeConfig.logo"
class="logo"
:src="$site.themeConfig.logo"
:alt="$siteTitle"
>
<span
v-if="$siteTitle"
ref="siteName"
class="site-name"
>{{ $siteTitle }}</span>
</RouterLink>
<div
class="links"
:style="linksWrapMaxWidth ? {
'max-width': linksWrapMaxWidth + 'px'
} : {}"
>
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
role="search"
:options="algolia"
/>
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
<NavLinks class="can-hide" />
</div>
</header>
</template>
<script>
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@parent-theme/components/SidebarButton.vue'
import NavLinks from '@parent-theme/components/NavLinks.vue'
export default {
name: 'Navbar',
components: {
SidebarButton,
NavLinks,
SearchBox,
AlgoliaSearchBox
},
data () {
return {
linksWrapMaxWidth: null
}
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
},
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
},
mounted () {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null
} else {
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
}
}
handleLinksWrapWidth()
// deepscan-disable-next-line VUE_MISSING_CLEANUP_IN_LIFECYCLE
window.addEventListener('resize', handleLinksWrapWidth, false)
}
}
function css (el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property]
}
</script>
<style lang="stylus">
.navbar, .sidebar .nav-links
.nav-link
color var(--headerText)
font-weight 300
&.router-link-active
font-weight 500
& svg
display none
&:hover, &.router-link-active
color var(--accent)
.navbar
padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbarHeight - 1.4rem
background-color var(--tertiaryBG)
border none
a, span, img
display inline-block
.logo
height $navbarHeight - 1.4rem
min-width $navbarHeight - 1.4rem
margin-right 0.8rem
vertical-align top
.site-name
font-size 1.3rem
font-weight 600
color var(--headerText)
position relative
display none
.links
padding-left 1.5rem
box-sizing border-box
white-space nowrap
font-size 0.9rem
position absolute
right $navbar-horizontal-padding
top $navbar-vertical-padding
display flex
.search-box
flex: 0 0 auto
vertical-align top
@media (max-width: $MQMobile)
.navbar
padding-left 4rem
.can-hide
display none
.links
padding-left 1.5rem
.site-name
width calc(100vw - 11.4rem)
overflow hidden
white-space nowrap
text-overflow ellipsis
@media (min-width: $MQMobile)
.nav-links a
&:hover, &.router-link-active
color var(--accent)
.nav-item > a:not(.external)
&:hover, &.router-link-active
border none
</style>

View file

@ -0,0 +1,3 @@
module.exports = {
extend: '@vuepress/theme-default'
}

View file

@ -0,0 +1,101 @@
<template>
<div class="error-page">
<img src="/logo-fit.svg">
<div class="content">
<h1>Oh no!</h1>
<p class="description">The page you have requested could not be found.</p>
<div class="action-buttons">
<RouterLink
class="action-button"
target="_blank"
rel="noopener"
:to="'/'"
>
<IconifyIcon icon="fa-solid:arrow-circle-left" />
<span>Go Back Home</span>
</RouterLink>
</div>
</div>
</div>
</template>
<style lang="stylus">
.error-page
padding 2rem 2.5rem
display flex
flex-direction column
justify-content center
align-items center
text-align center
gap 40px
width auto
height calc(100vh - 4rem)
& > img
filter grayscale()
width 200px
flex none
.content
display flex
flex-direction column
justify-content center
align-items center
gap 10px
h1
font-size 48px
margin 0
.description
width 100%
font-size 26px
line-height 1.3
color var(--text)
margin 0
.action-buttons
display flex
justify-content space-evenly
align-self center
flex-wrap wrap
gap 20px
.action-button
display inline-flex
align-items center
gap 10px
padding 15px 20px
font-size 20px
font-weight 500
flex-direction row
color var(--counterAccent)
background-color var(--tertiaryBG)
border-radius 8px
line-height 1
&:hover
background-color var(--secondaryBG)
text-decoration none
@media (max-width: $MQNarrow)
.error-page
padding 2rem
@media (max-width: $MQMobile)
.error-page
gap 20px
& > img
width 150px
h1
font-size 24px
.description
font-size 20px
.action-buttons .action-button
gap 10px
padding 10px 15px
font-size 18px
</style>
<script>
import { Icon, addCollection } from '@iconify/vue2'
import faSolidIcons from '@iconify/json/json/fa-solid.json';
addCollection(faSolidIcons);
export default {
components: { IconifyIcon: Icon }
}
</script>

View file

@ -0,0 +1,144 @@
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"
/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"
/>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar"
>
<template #top>
<slot name="sidebar-top" />
</template>
<template #bottom>
<slot name="sidebar-bottom" />
</template>
</Sidebar>
<Home v-if="$page.frontmatter.home" />
<Page
v-else
:sidebar-items="sidebarItems"
>
<template #top>
<slot name="page-top" />
</template>
<template #bottom>
<slot name="page-bottom" />
</template>
</Page>
<Footer v-if="$page.frontmatter.footer && $site.themeConfig.footer" />
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Navbar from '@theme/components/Navbar.vue'
import Page from '@parent-theme/components/Page.vue'
import Sidebar from '@parent-theme/components/Sidebar.vue'
import Footer from '@theme/components/Footer.vue'
import { resolveSidebarItems } from '@parent-theme/util'
export default {
name: 'Layout',
components: {
Home,
Page,
Sidebar,
Navbar,
Footer
},
data () {
return {
isSidebarOpen: false
}
},
computed: {
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
if (
frontmatter.navbar === false
|| themeConfig.navbar === false) {
return false
}
return (
this.$title
|| themeConfig.logo
|| themeConfig.repo
|| themeConfig.nav
|| this.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
const { frontmatter } = this.$page
return (
!frontmatter.home
&& frontmatter.sidebar !== false
&& this.sidebarItems.length
)
},
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
pageClasses () {
const userPageClass = this.$page.frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
},
methods: {
toggleSidebar (to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
this.$emit('toggle-sidebar', this.isSidebarOpen)
},
// side swipe
onTouchStart (e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
}
},
onTouchEnd (e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x
const dy = e.changedTouches[0].clientY - this.touchStart.y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true)
} else {
this.toggleSidebar(false)
}
}
}
}
}
</script>

27
docs/README.md Normal file
View file

@ -0,0 +1,27 @@
---
home: true
heroImage: /logo-fit.svg
heroText: Welcome to LBRY.
tagline: LBRY is a secure, open, and community-run digital marketplace.
actionButtons:
- text: Download LBRY
icon: fa-solid:arrow-alt-circle-down
link: https://lbry.com/get
- text: Join Discord
icon: fa-brands:discord
link: https://chat.lbry.com/
footer: true
sitemap:
changefreq: hourly
priority: 0.8
scriptTypes:
org:
- type: application/ld+json
-
- https://lbry.org
- https://lbry.org/logo.png
- LBRY Foundation
---
<!-- TODO update with actual content -->
Example text.

37
docs/governance/README.md Normal file
View file

@ -0,0 +1,37 @@
# Governance
The LBRY Foundation is a US-based non-profit corporation governed by a board of directors.
<!-- TODO probably add more about the governance here -->
## Board of Directors
<!-- TODO update images with real people -->
<Person
avatar="/logo.png"
imageClass="rounded"
name="Julie Sigwart"
subtitle="Founding board member of LBRY Foundation, Inc."/>
<Person
avatar="/logo.png"
imageClass="rounded"
name="Jon Ringo"
subtitle="First community elected board member of LBRY Foundation, Inc."/>
<Person
avatar="/logo.png"
imageClass="rounded"
name="Leo Rodrigues"
subtitle="Second community elected board member of LBRY Foundation, Inc."/>
<Person
avatar="/logo.png"
imageClass="rounded"
name="Ralph Streb"
subtitle="Second community elected board member of LBRY Foundation, Inc."/> <!-- TODO typo? -->
## Board Elections
The first board election was the December 2019 Board Election, won by Jon Ringo.
The second board election was the December 2020 Board Election, won by Ralph Streb and Leo Rodrigues.
The board is expected to be add several more members through 2021.
<!-- TODO more info? -->
## Future Structure
The Foundation is expected to integrate network organization principles through 2020.
The intent is to decentralize decision making and management powers throughout the LBRY network and community as they develop.
<!-- TODO more info? -->

167
docs/privacy/README.md Normal file
View file

@ -0,0 +1,167 @@
# Privacy Policy
This privacy policy has been compiled to better serve those who are concerned with how their 'Personally Identifiable Information' (PII) is being used online. PII, as described in US privacy law and information security, is information that can be used on its own or with other information to identify, contact, or locate a single person, or to identify an individual in context. Please read our privacy policy carefully to get a clear understanding of how we collect, use, protect or otherwise handle your Personally Identifiable Information in accordance with our website.
## What personal information do we collect from the people that visit our blog, website or app?
When ordering or registering on our site, as appropriate, you may be asked to enter your name, email address, mailing address, phone number, credit card information or other details to help you with your experience.
## When do we collect information?
We collect information from you when you register on our site, place an order, subscribe to a newsletter, respond to a survey, fill out a form, open a support ticket or enter information on our site, or provide us with feedback on our products or services.
## How do we use your information?
We may use the information we collect from you when you register, make a purchase, sign up for our newsletter, respond to a survey or marketing communication, surf the website, or use certain other site features in the following ways:
* To personalize your experience and to allow us to deliver the type of content and product offerings in which you are most interested.
* To improve our website in order to better serve you.
* To allow us to better service you in responding to your customer service requests.
* To administer a contest, promotion, survey or other site feature.
* To quickly process your transactions.
* To send periodic emails regarding your order or other products and services.
* To follow up with them after correspondence (live chat, email or phone inquiries)
## How do we protect your information?
* Our website is scanned on a regular basis for security holes and known vulnerabilities in order to make your visit to our site as safe as possible.
* We use regular Malware Scanning.
* Your personal information is contained behind secured networks and is only accessible by a limited number of persons who have special access rights to such systems, and are required to keep the information confidential. In addition, all sensitive/credit information you supply is encrypted via Secure Socket Layer (SSL) technology.
* We implement a variety of security measures when a user places an order enters, submits, or accesses their information to maintain the safety of your personal information.
* All transactions are processed through a gateway provider and are not stored or processed on our servers.
## Do we use "cookies"?
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow) that enables the site's or service provider's systems to recognize your browser and capture and remember certain information. For instance, we use cookies to help us remember and process the items in your shopping cart. They are also used to help us understand your preferences based on previous or current site activity, which enables us to provide you with improved services. We also use cookies to help us compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future.
We use cookies to:
* Help remember and process the items in the shopping cart.
* Compile aggregate data about site traffic and site interactions in order to offer better site experiences and tools in the future. We may also use trusted third-party services that * track this information on our behalf.
* You can choose to have your computer warn you each time a cookie is being sent, or you can choose to turn off all cookies. You do this through your browser settings. Since browser is a little different, look at your browser's Help Menu to learn the correct way to modify your cookies.
### If users disable cookies in their browser:
If you turn cookies off it will turn off some of the features of the site.
## Third-party disclosure
We do not sell, trade, or otherwise transfer to outside parties your Personally Identifiable Information unless we provide users with advance notice. This does not include website hosting partners and other parties who assist us in operating our website, conducting our business, or serving our users, so long as those parties agree to keep this information confidential. We may also release information when it's release is appropriate to comply with the law, enforce our site policies, or protect ours or others' rights, property or safety.
However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
## Third-party links
Occasionally, at our discretion, we may include or offer third-party products or services on our website. These third-party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
### Google
Google's advertising requirements can be summed up by Google's Advertising Principles. They are put in place to provide a positive experience for users. https://support.google.com/adwordspolicy/answer/1316548?hl=en
We use Google AdSense Advertising on our website.
Google, as a third-party vendor, uses cookies to serve ads on our site. Google's use of the DART cookie enables it to serve ads to our users based on previous visits to our site and other sites on the Internet. Users may opt-out of the use of the DART cookie by visiting the Google Ad and Content Network privacy policy.
We have implemented the following:
* Remarketing with Google AdSense
* Google Display Network Impression Reporting
* Demographics and Interests Reporting
* We, along with third-party vendors such as Google use first-party cookies (such as the Google Analytics cookies) and third-party cookies (such as the DoubleClick cookie) or other third-party identifiers together to compile data regarding user interactions with ad impressions and other ad service functions as they relate to our website.
## Opting out:
Users can set preferences for how Google advertises to you using the Google Ad Settings page. Alternatively, you can opt out by visiting the Network Advertising Initiative Opt Out page or by using the Google Analytics Opt Out Browser add on.
## Google Forms
We use Google Forms for manual input of data by users. Data input into Google Forms are subject to Google's Privacy policy listed [here](https://www.google.com/intl/en/policies/privacy/).
## California Online Privacy Protection Act
CalOPPA is the first state law in the nation to require commercial websites and online services to post a privacy policy. The law's reach stretches well beyond California to require any person or company in the United States (and conceivably the world) that operates websites collecting Personally Identifiable Information from California consumers to post a conspicuous privacy policy on its website stating exactly the information being collected and those individuals or companies with whom it is being shared. - See more at: http://consumercal.org/california-online-privacy-protection-act-caloppa/#sthash.0FdRbT51.dpuf
According to CalOPPA, we agree to the following:
* Users can visit our site anonymously.
* Once this privacy policy is created, we will add a link to it on our home page or as a minimum, on the first significant page after entering our website.
* Our Privacy Policy link includes the word 'Privacy' and can easily be found on the page specified above.
### You will be notified of any Privacy Policy changes:
Here, on our Privacy Policy Page.
## You can change your personal information:
* By emailing us
* By logging in to your account
* By chatting with us or by sending us a support ticket
## How does our site handle Do Not Track signals?
We honor Do Not Track signals and Do Not Track, plant cookies, or use advertising when a Do Not Track (DNT) browser mechanism is in place.
## Does our site allow third-party behavioral tracking?
It's also important to note that we do not allow third-party behavioral tracking
## COPPA (Children Online Privacy Protection Act)
When it comes to the collection of personal information from children under the age of 13 years old, the Children's Online Privacy Protection Act (COPPA) puts parents in control. The Federal Trade Commission, United States' consumer protection agency, enforces the COPPA Rule, which spells out what operators of websites and online services must do to protect children's privacy and safety online.
We do not specifically market to children under the age of 13 years old.
Do we let third-parties, including ad networks or plug-ins collect PII from children under 13?
## Fair Information Practices
The Fair Information Practices Principles form the backbone of privacy law in the United States and the concepts they include have played a significant role in the development of data protection laws around the globe. Understanding the Fair Information Practice Principles and how they should be implemented is critical to comply with the various privacy laws that protect personal information.
In order to be in line with Fair Information Practices we will take the following responsive action, should a data breach occur:
### We will notify you via email:
Within 7 business days
### We will notify the users via in-site notification:
Within 7 business days
We also agree to the Individual Redress Principle which requires that individuals have the right to legally pursue enforceable rights against data collectors and processors who fail to adhere to the law. This principle requires not only that individuals have enforceable rights against data users, but also that individuals have recourse to courts or government agencies to investigate and/or prosecute non-compliance by data processors.
## CAN SPAM Act
The CAN-SPAM Act is a law that sets the rules for commercial email, establishes requirements for commercial messages, gives recipients the right to have emails stopped from being sent to them, and spells out tough penalties for violations.
### We collect your email address in order to:
Send information, respond to inquiries, and/or other requests or questions
Process orders and to send information and updates pertaining to orders.
Send you additional information related to your product and/or service
Market to our mailing list or continue to send emails to our clients after the original transaction has occurred.
To be in accordance with CANSPAM, we agree to the following:
Not use false or misleading subjects or email addresses.
Identify the message as an advertisement in some reasonable way.
Include the physical address of our business or site headquarters.
Monitor third-party email marketing services for compliance, if one is used.
Honor opt-out/unsubscribe requests quickly.
Allow users to unsubscribe by using the link at the bottom of each email.
If at any time you would like to unsubscribe from receiving future emails, you can email us at: [board@lbry.org](mailto:board@lbry.org)
Follow the instructions at the bottom of each email.
and we will promptly remove you from ALL correspondence.
## Contacting Us
If there are any questions regarding this privacy policy, you may contact us using the information below.
> LBRY Foundation Inc.
> 1072 CASITAS PASS RD #122
> CARPINTERIA CA 93013
> United States
> [board@lbry.com](mailto:board@lbry.com)

17
package.json Normal file
View file

@ -0,0 +1,17 @@
{
"license": "MIT",
"devDependencies": {
"@fontsource/roboto": "^4.5.1",
"@iconify/json": "^1.1.449",
"@iconify/vue2": "^1.1.1",
"@vuepress/plugin-pwa": "^1.5.0",
"fs-extra": "^9.0.1",
"vuepress": "^1.5.0",
"vuepress-plugin-sitemap": "^2.3.1",
"vuepress-plugin-zooming": "^1.1.7"
},
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
}

8141
yarn.lock Normal file

File diff suppressed because it is too large Load diff