diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e88843 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.cache +.cecil +_site/* +.idea/* +*.*~ +.code-workspace/* + +# Local Netlify folder +.netlify + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fcbb5be --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +# Contributing to Veilid +Before you get started, please review our [Code of Conduct](./code_of_conduct.md). We're here to make things better and we cannot do that by treating each other without respect. + + +## Code Contributions + +### Tech Overview +veilid.com is a flat-file website hosted on Netlify and generated using [cecil.app](https://cecil.app/). Cecil is powered by PHP and Twig templates with the content in markdown files. + +The site theme uses [Bootstrap](https://getbootstrap.com/) and [Sass](https://sass-lang.com/); [jQuery](https://jquery.com/) is available as more content is added we may need more UI features. + +The [Cecil documentation](https://cecil.app/documentation/) is pretty great but here's a quick start guide: + +### Local Development + +1. Install [PHP 7.4](https://cecil.app/documentation/) or higher +2. [Download and install Cecil](https://cecil.app/download/) +3. Fork and/or clone the website repository at `git@gitlab.com:veilid-tc-hacking/veilid-dot-com.git` +4. In the project directory, run `cecil serve` to run the site locally on port 8000 +5. Open `http://localhost:8000/` in your browser to view it + +As you make changes to the code, Cecil will reload the website for you so you can see your changes as you work. + +- `pages` contains the content for the website in markdown +- files in `static` get served off of `/` in the site URL +- the site theme is in `themes/veilid` + - the Sass files are in `themes/veilid/assets/scss` and get compiled into CSS for you by Cecil — please do not edit the CSS files directly + - `themes/veilid/static` get added to the static content directory + - `themes/veilid/layouts` has all the twig template files + - note that not all twig templates in the theme directory are used on the site + +### Code Contribution Do's & Don'ts: + +Keeping the following in mind gives your contribution the best chance of landing! + +#### Merge Requests + +* **Do** create a [feature branch] to work on instead of working directly on `main`. This helps to: + * Protect the process. + * Ensures users are aware of commits on the branch being considered for merge. + * Allows for a location for more commits to be offered without mingling with other contributor changes. + * Allows contributors to make progress while a MR is still being reviewed. +* **Do** follow the [50/72 rule] for Git commit messages. +* **Do** target your merge request to the **main branch**. +* **Do** specify a descriptive title to make searching for your merge request easier. +* **Do** list [verification steps] so your code is testable. +* **Do** reference associated issues in your merge request description. +* **Don't** leave your merge request description blank. +* **Don't** abandon your merge request. Being responsive helps us land your code faster. +* **Don't** submit unfinished code. + + + +## Contributions Without Writing Code +There are numerous ways you can contribute to the growth and success of the Veilid project without writing code: + + - Submit bugs as well as feature/enhancement requests. Letting us know you found a bug, have an idea for a new feature, or see a way we can enhance existing features is just as important and useful as writing the code related to those things. Send us detailed information about your issue or idea: + - Features/Enhancements: Describe your idea. If you're able to, sketch out a diagram or mock-up. + - Bugs: Please be sure to include the expected behavior, the observed behavior, and steps to reproduce the problem. Please be descriptive about the environment you've installed your node or application into. + - [Help other users with open issues]. Sometimes all an issue needs is a little conversation to clear up a process or misunderstanding. Please keep the [Code of Conduct](./code_of_conduct.md) in mind. + - Help other contributors test recently submitted merge requests. By pulling down a merge request and testing it, you can help validate new code contributions for stability and quality. + - Report a security or privacy vulnerability. Please let us know if you find ways in which Veilid could handle security and/or privacy in a different or better way. Surely let us know if you find broken or otherwise flawed security and/or privacy functions. You can report these directly to security@veilid.org. + - Add or edit documentation. Documentation is a living and evolving library of knowledge. As such, care, feeding, and even pruning is needed from time to time. If you're a non-native english speaker, you can help by replacing any ambiguous idioms, metaphors, or unclear language that might make our documentation hard to understand. + + +#### Bug Fixes +* **Do** include reproduction steps in the form of [verification steps]. +* **Do** link to any corresponding issues in your commit description. + +## Bug Reports + +When reporting Veilid issues: +* **Do** write a detailed description of your bug and use a descriptive title. +* **Do** include reproduction steps, stack traces, and anything that might help us fix your bug. +* **Don't** file duplicate reports. Search open issues for similar bugs before filing a new report. +* **Don't** attempt to report issues on a closed PR. New issues should be openned against the `main` branch. + +Please report vulnerabilities in Veilid directly to security@veilid.org. + +If you're looking for more guidance, talk to other Veilid contributors on the [Veilid Discord]. + +**Thank you** for taking the few moments to read this far! Together we will build something truly remarkable. + + + +This contributor guide is inspired by the contribution guidelines of the [Metasploit Framework](https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md) project found on GitHub. + +[Help other users with open issues]:https://gitlab.com/veilid/veilid-dot-com/-/issues +[50/72 rule]:http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[feature branch]:https://docs.gitlab.com/ee/gitlab-basics/feature_branch_workflow.html +[verification steps]:https://docs.gitlab.com/ee/user/markdown.html#task-lists +[Veilid Discord]:https://discord.gg/DmEGxyA87N diff --git a/README.md b/README.md index e69de29..8c46e20 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,22 @@ +# veilid-dot-com + +Important documents to read + +- [Contributing](./CONTRIBUTING.md) +- [Code of Conduct](./code_of_conduct.md) +- [Cecil Documentation](https://cecil.app/documentation/) + +## Website To-Do + +The following are known issues or to-build items as of 2023-08-15 + +- [ ] Move this site to the main Veilid project in Gitlab +- [ ] Create an off-season location for DefCon pages +- [ ] Use Cecil's multi-language capabilities for translations +- Documentation and FAQs + - [ ] for lay people + - [ ] for technical people + - [ ] for cryptography people + - [ ] for legal entities + + diff --git a/code_of_conduct.md b/code_of_conduct.md new file mode 100644 index 0000000..c039824 --- /dev/null +++ b/code_of_conduct.md @@ -0,0 +1,137 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[security@veilid.org](security@veilid.org). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + +## Revisions +Veilid Foundation, Inc reserves the right to make revisions to this document +to ensure its continued alignment with our ideals. \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..e4742de --- /dev/null +++ b/config.yml @@ -0,0 +1,37 @@ +title: Veilid +baseurl: 'https://veilid.com' +description: Veilid is a project by cDc and friends. +image: img/Veilid-Framework-Cover.png +debug: true +favicon: + enabled: true + image: /favicon.ico +compile: + enabled: true + style: compressed + sourcemap: true +theme: + - veilid +social: + twitter: "veilidnetwork" + fediverse: "@VeilidNetwork@hackers.town" +virtualpages: + - path: contact + redirect: /about-us/contact-us/ + - path: discord + redirect: https://discord.gg/5Qx3B9eedU + - path: code + redirect: https://gitlab.com/veilid/veilid + - path: give + redirect: https://buy.stripe.com/6oE9ACboP5r3ag86oo + - path: launch + redirect: /defcon/ +pagination: + max: 12 +cache: + dir: '.cache' + enabled: false +languages: + - code: en + name: English + locale: en_US \ No newline at end of file diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..ef52470 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,21 @@ +[build] + publish = "_site" + command = "curl -sSOL https://cecil.app/build.sh && bash ./build.sh" + +[build.environment] + PHP_VERSION = "7.4" + +[context.production.environment] + CECIL_ENV = "production" + +[context.deploy-preview.environment] + CECIL_ENV = "preview" + +[[headers]] + for = "/*" + [headers.values] + X-Frame-Options = "SAMEORIGIN" + X-XSS-Protection = "0" + X-Content-Type-Options = "nosniff" + Content-Security-Policy = "default-src 'self'; script-src 'self'" + X-Clacks-Overhead = "GNU Terry Pratchett" \ No newline at end of file diff --git a/pages/about-us/FAQ.md b/pages/about-us/FAQ.md new file mode 100644 index 0000000..f9492e1 --- /dev/null +++ b/pages/about-us/FAQ.md @@ -0,0 +1,39 @@ +--- +title: F.A.Q. +description: Frequently asked questions about Veilid +weight: 6 +layout: subpage +--- + + + +
 
+ + +
+ Have a question? Email press@veilid.org +
+ diff --git a/pages/about-us/community.md b/pages/about-us/community.md new file mode 100644 index 0000000..2407c6b --- /dev/null +++ b/pages/about-us/community.md @@ -0,0 +1,13 @@ +--- +title: Community +description: Join our community of developers. +layout: subpage +weight: 3 +--- + + +We want to build a community people who want a better way to connect and communicate. +We want to bring together folks to help build great applications using the Veilid framework. + +Join Us on Discord + diff --git a/pages/about-us/contact-us.md b/pages/about-us/contact-us.md new file mode 100644 index 0000000..958bca6 --- /dev/null +++ b/pages/about-us/contact-us.md @@ -0,0 +1,18 @@ +--- +title: Contact Us +description: How to contact the Veilid project +layout: subpage +weight: 2 +--- + +

Contact Us

+

For app support, please email support@veilid.com

+ +

Social Media Accounts

+ + diff --git a/pages/about-us/index.md b/pages/about-us/index.md new file mode 100644 index 0000000..6fc2456 --- /dev/null +++ b/pages/about-us/index.md @@ -0,0 +1,78 @@ +--- +title: About Us +description: Meet the Veilid Foundation members leading the project as well as contributors. +menu: + main: + weight: 7 +layout: subpage +weight: 1 +--- + +

+ Veilid Foundation Members +

+ + +
+

Christien Rioux

+

+ Christien Rioux is the primary author and inventor of Veilid's core technology. + A long-time member and figure in the security industry and hacker scene, + Christien is a member of CULT OF THE DEAD COW, + and formerly L0pht Heavy Industries, + the formative hacker think-tank. + He has been a company founder and published numerous security tools and advisories over the years, + and is also proprietor of the hacker-fashion line HACK.XXX. + Christien is a staunch believer that if you want to change the present you need to build the future. +

+
+ +
+

Katelyn Bowden

+

+ Katelyn Bowden is a hacker, activist, and CULT OF THE DEAD COW member, who embraces the human side of hacking and tech. + Katelyn has dedicated her life to changing the world for the positive- between her work fighting Non-consensual pornography, and her dedication to educating users on security, she is dedicated to making the internet a safer place for everyone. Her alignment is chaotic good, with a hard emphasis on the chaos. + She also creates strange furby art and has over 60 dead things on display in her house. +

+
+ +
+

Paul Miller

+

+ Paul Miller is the founder/leader/community organizer of + hackers.town, + Projekt:ONI (Optimistic Nihilists Inc.) organizer and founder, Hacker, Infosec professional, and is a passionate privacy advocate. Paul has worked to show the ways a centralized internet has harmed our culture and the future. He believes you should always be N00bin', and that collectively we can restore the promise of the future the internet once offered us. +

+
+ + + +### Contributors + +Veilid contributors include coders, admins, writers, legal, and more. + + + + +### Special Thanks + +A heart-felt thank you to our families and friends for putting up with supporting us. + + diff --git a/pages/about-us/press.md b/pages/about-us/press.md new file mode 100644 index 0000000..6d0381b --- /dev/null +++ b/pages/about-us/press.md @@ -0,0 +1,27 @@ +--- +title: Press +description: Information for the press and media about Veilid +layout: subpage +weight: 4 +--- + +### Press Kit + +PDF press summary: Veilid Framework Press Kit, 20.6 kB + +### Press Contact +Press and media inquiries should be sent to press@veilid.org + +### In The News + + \ No newline at end of file diff --git a/pages/chat/index.md b/pages/chat/index.md new file mode 100644 index 0000000..364520a --- /dev/null +++ b/pages/chat/index.md @@ -0,0 +1,24 @@ +--- +title: VeilidChat +description: VeilidChat is a proof of concept of the Veilid protocol and framework. +menu: + main: + weight: 5 +weight: 1 +layout: subpage +--- + +VeilidChat is a demo of the Veilid framework and protocol working. + +We built it using the [Flutter](https://flutter.dev/) framework and the Veilid core code. + +If you want to try out this proof of concept, please stay tuned for details on how to gain access. + +### Source Code + +You can get the code for Veilid Chat at https://gitlab.com/veilid/veilidchat + +### Support + +

For app support, please email support@veilid.com

+ diff --git a/pages/chat/privacy-policy.md b/pages/chat/privacy-policy.md new file mode 100644 index 0000000..965cf77 --- /dev/null +++ b/pages/chat/privacy-policy.md @@ -0,0 +1,189 @@ +--- +title: Privacy Policy +description: The privacy policy for VeilidChat +weight: 2 +layout: subpage +--- + +### VeilidChat Privacy Policy + +Last Revised 2023 Aug 3 + +This privacy notice for the Veilid Foundation ("Veilid," "we," "us," or "our"), describes how and why we might collect, store, use, and/or share ("process") your information when you use our services ("Services"), such as when you: + +- Download and use our mobile application (VeilidChat), or any other application of ours that links to this privacy notice in the future. + +Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use VeilidChat. If you still have any questions or concerns, please contact us at [support@veilid.com](mailto:support@veilid.com). + +

Summary of Key Points

+ +- VeilidChat is a messaging application built on a decentralized, distributed, and end-to-end fully encrypted framework. +- VeilidChat is a proof-of-concept application in beta-testing and you must receive an invitation to activate the application. +- VeilidChat will never ask you for contact information, personal information, or financial information. +- When you register and use VeilidChat, any information entered into the app is either stored locally on your device, or encrypted and distributed in a method that is inaccessible and irretrievable by the Veilid Foundation (the creators of the application). +- We do not collect or process any personal information, nor do we have the capability to collect or process any personal information from VeilidChat. +- We do not collect or process sensitive personal information, nor do we have the capability to collect or process any sensitive information from VeilidChat. +- We do not receive or transmit any information to or from third parties. +- The Veilid Framework processes encrypted and distributed information to provide and administer services for VeilidChat. +- We do not share personal information. Because of the encrypted and distributed nature of information entered into the VeilidChat app, we are unable to access your personal information. +- How do we keep your information safe? We have organizational and technical processes and procedures in place to protect your personal information. However, no electronic transmission over the internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. +- VeilidChat will provide you with a recovery pass-phrase to use in the event that your app is deleted or your device is no longer available/functional for you. If you cannot access this pass-phrase, you will have to create a new account. The Veilid Foundation is unable to restore your account through any means. +- How do you exercise your rights? The easiest way to exercise your rights is to delete VeilidChat. The Veilid Foundation is a non-profit organization that does not collect, process, or use any of your information. You may contact us by visiting https://veilid.com/contact, or by emailing [support@veilid.com](mailto:support@veilid.com). We will consider and act upon any request in accordance with applicable data protection laws. + +

Table of Contents

+ +1. [What Information Do We Collect?](#section-1) +1. [How Do We Process Your Information?](#section-2) +1. [What Legal Bases Do We Rely On To Process Your Personal Information?](#section-3) +1. [When And With Whom Do We Share Your Personal Information?](#section-4) +1. [How Long Do We Keep Your Information?](#section-5) +1. [How Do We Keep Your Information Safe?](#section-6) +1. [Do We Collect Information From Minors?](#section-7) +1. [What Are Your Privacy Rights?](#section-8) +1. [Controls For Do-not-track Features](#section-9) +1. [US State-specific Privacy Rights](#section-10) +1. [Do We Make Updates To This Notice?](#section-11) +1. [How Can You Contact Us About This Notice?](#section-12) +1. [How Can You Review, Update, Or Delete The Data We Collect From You?](#section-13) +1. [Cookie And Data Analytics Disclosures](#section-14) + +

1. What information do we collect?

+ +VeilidChat collects no information from you. VeilidChat is designed to not collect your information and to operate in an encrypted, distributed manner, which means we cannot access your information even if we wanted to (which we don’t). Any information you enter into VeilidChat on your device is inaccessible to us. + +The Veilid Foundation only collects personal information that you voluntarily provide to us when you request an invitation to the beta version of the application. This will only be the contact information necessary for us to send you an invitation. This process is managed by the Apple App Store and the Veilid Foundation only retains this information long enough to provide it to the Apple App Store to generate an invitation. + +

2. How do we process your information?

+ +We don’t. VeilidChat does not collect your information, nor are we able to collect it. Administration of, improvements to, and changes to the VeilidChat application will be made without any processing of personal information. The Veilid Foundation will never ask you for personal, sensitive, or financial information. + +If you provide any information to us at [support@veilid.com](mailto:support@veilid.com), though our Discord server, through our website at https://veilid.com/contact, or directly via postal mail to our foundation, we will only process that information to answer your questions or attempt to support your issues, with two major exceptions: + +- Legal Obligations. We may process information sent to us via email, our website, or via postal mail where we believe it is necessary for compliance with our legal obligations, such as to cooperate with a law enforcement body or regulatory agency, exercise or defend our legal rights, or disclose your information as evidence in litigation in which we are involved. +- Vital Interests. We may process information sent to us via email, our website, or via postal mail where we believe it is necessary to protect your vital interests or the vital interests of a third party, such as situations involving potential threats to the safety of any person. + +

3. What legal bases do we rely on to process uour information?

+ +VeilidChat does not process any personal information. Because the Veilid Foundation cannot access information entered into VeilidChat in any way, shape, or form, the Veilid Foundation does not process your information. + +As for information sent to the Veilid Foundation via email, Discord server, postal mail, or through our website, we only process your personal information when we believe it is necessary and we have a valid legal reason (i.e.,legal obligations) to do so under applicable law, to comply with laws, to protect your rights, or to fulfill our legitimate business interests. + +If you are located in the EU or UK, this section applies to you. + +The General Data Protection Regulation (GDPR) and UK GDPR require us to explain the valid legal bases we rely on in order to process your personal information. VeilidChat does not collect or process personal information. For any information that is sent directly to the Veilid Foundation, we may rely on the following legal bases to process your personal information: + +- Consent. The Veilid Foundation may process your information if you have given us specific permission (i.e. consent) to use your personal information for a specific purpose. This is generally limited to contacting us and requesting an invite code to the beta version of the application, however, the Veilid Foundation does not store this information. Apple, through the App Store, will manage the invitation process. Your contact information cannot be linked to your VeilidChat account by the Veilid Foundation. You can withdraw your consent to Apple at any time. +- Legal Obligations. We may process your information where we believe it is necessary for compliance with our legal obligations, such as to cooperate with a law enforcement body or regulatory agency, exercise or defend our legal rights, or disclose your information as evidence in litigation in which we are involved. +- Vital Interests. We may process your information where we believe it is necessary to protect your vital interests or the vital interests of a third party, such as situations involving potential threats to the safety of any person. + +If you are located in Canada, this section applies to you. + +VeilidChat does not collect or process personal information. For any information that is sent directly to the Veilid Foundation, we may rely on the following legal bases to process your personal information: + +We may process your information if you have given us specific permission (i.e., express consent) to use your personal information for a specific purpose, or in situations where your permission can be inferred (i.e., implied consent). This is generally limited to contacting us and requesting an invite code to the beta version of the application. Apple, through the App Store, will manage the invitation process. Your contact information cannot be linked to your VeilidChat account by the Veilid Foundation. You can withdraw your consent to Apple at any time. + +- In some exceptional cases, we may be legally permitted under applicable law to process your information without your consent, including, for example: +- If collection is clearly in the interests of an individual and consent cannot be obtained in a timely way +- For investigations and fraud detection and prevention +- If it is contained in a witness statement and the collection is necessary to assess, process, or settle an insurance claim +- For identifying injured, ill, or deceased persons and communicating with next of kin +- If we have reasonable grounds to believe an individual has been, is, or may be victim of financial abuse +- If it is reasonable to expect collection and use with consent would compromise the availability or the accuracy of the information and the collection is reasonable for purposes related to investigating a breach of an agreement or a contravention of the laws of Canada or a province +- If disclosure is required to comply with a subpoena, warrant, court order, or rules of the court relating to the production of records +- If it was produced by an individual in the course of their employment, business, or profession and the collection is consistent with the purposes for which the information was produced +- If the collection is solely for journalistic, artistic, or literary purposes +- If the information is publicly available and is specified by the regulations + + +

4. When and with whom do we share your personal information?

+ +In no way, shape, or form do we ever share your personal information. We cannot share what we do not retain, or what we cannot access. + +- Business Transfers. In the event of any merger, sale, or acquisition of any portion of the Veilid Foundation, the Veilid Foundation will provide updates on our website or through application updates for the VeilidChat application through the App Store. Because the Velid Foundation does not collect any personal information, we have no other methods to provide this information to you. + +

5. How long do we keep your information?

+ +We keep your information for as long as necessary to fulfill the purposes outlined in this privacy notice unless otherwise required by law. However, in most cases, we are incapable of retaining information because we do not collect it. + +The Veilid Foundation will only keep your personal information for as long as it is necessary for the purposes set out in this privacy notice, unless a longer retention period is required by law. VeilidChat will retain a local copy of your information (accessible only to your device and the people you directly share information with) for as long as you utilize the application. In future iterations of the application, there will be a “delete messages after a certain period of time” functionality, but for the beta testing proof-of-concept, this functionality has not been introduced. + +

6. How do we keep your information safe?

+ +We have implemented appropriate and reasonable technical and organizational security measures designed to protect the security of any personal information we process. However, despite our safeguards and efforts to secure your information, no electronic transmission over the Internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that any unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. + +Although we will do our best to protect your personal information, transmission of personal information to and from Velid Chat is at your own risk. You should only access VeilidChat within a secure environment. If you lose access to your device, the Velid Foundation cannot access or delete information stored there. + + +

7. Do we collect information from minors?

+ +We do not collect information from or market to anyone. If you suspect that someone underage is violating the Apple App Store terms of service by downloading VeilidChat, please contact Apple at Support.Apple.com. + +

8. What are your privacy rights?

+ +In some regions (like the EEA, UK, and Canada), you have certain rights under applicable data protection laws. These may include the right (i) to request access and obtain a copy of your personal information, (ii) to request rectification or erasure; (iii) to restrict the processing of your personal information; and (iv) if applicable, to data portability. In certain circumstances, you may also have the right to object to the processing of your personal information. + +However, due to the unique nature of VeilidChat, the only information available is stored locally on the user’s device and is inaccessible by the Veilid Foundation. VeilidChat does not collect or process any personal information. If a user wishes to exercise their data rights, they may copy any data within the VeilidChat application and export it themselves, or delete the application from their device. The Veilid Foundation has no access to any user’s data. + +We will consider and act upon any request in accordance with applicable data protection laws. + +If you are located in the EEA or UK and you believe we are unlawfully processing your personal information, you also have the right to complain to your Member State data protection authority or UK data protection authority. + +If you are located in Switzerland, you may contact the Federal Data Protection and Information Commissioner. + +##### Account Information + +If you would at any time like to review or change the information in your account or terminate your account, you can: + +- Log in to your account settings and update your user account. +- Delete the application from your device. + +Upon your decision to delete the application from your device, it will no longer be able to be accessed by anyone, including the creators of the application. Any data still in existence will be encrypted, distributed, and inaccessible by any party. + +However, we may retain some information that is sent directly to the Veilid Foundation via email, our website, our Discord server, or via post mail in our files to prevent fraud, troubleshoot problems, assist with any investigations, enforce our legal terms and/or comply with applicable legal requirements. + +If you have questions or comments about your privacy rights, you may email us at [support@veilid.com](mailto:support@veilid.com). + + +

9. Controls for Do-Not-track Features

+ +Most web browsers and some mobile operating systems and mobile applications include a Do-Not-Track ("DNT") feature or setting you can activate to signal your privacy preference not to have data about your online browsing activities monitored and collected. VeilidChat is compliant with this technology because we do not monitor, track, collect, or process any information. + + +

10. US State-Specific Privacy Rights

+ +- California (knows how to party): + - We do not sell, rent, or share information with anyone, including third parties who engage in direct marketing activities. We do not collect or share your information with anyone, for any reason. No marketing, no third party sharing, nothing. + - VeilidChat has no ability to post public information. If you are under 18 years of age, reside in California, and have a registered account with VeilidChat, you can delete the application on your device and that will serve to exercise your rights to deletion. + - Please note that the Veilid Foundation and the VeilidChat application HAVE NOT collected, rented, shared, or sold any personal information from any individual, and especially not within the past 12 months. +- De-identified Data Disclosure (CA, CO, CT, UT, VA and soon to be more) + - We may use de-identified data in certain circumstances. In those circumstances, not only do we never attempt to re-identify that data, but we are completely unable to re-identify any data because of our encryption and distributed data frameworks. +- Profiling Disclosure (Hi Colorado!) + - We do not engage in profiling of consumers in any way, shape, or form. We especially don’t do it in a way that supports automated decisions that might have a legal or significant effect on anyone. + + +

11. Do we make updates to this notice?

+ +We will update this notice as necessary to stay compliant with relevant laws and as it relates to new features or products available. + +The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes on the Veilid Foundation’s website, or by providing an updated policy through the Apple App Store as part of any version updates. Because we do not collect your information, we are unable to directly contact you. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information. + +

12. How can you contact us about this notice?

+ +If you have questions or comments about this notice, you may email us at [support@veilid.com](mailto:support@veilid.com) or contact us by post at: + +
+Veilid Foundation
+PO BOX 1593
+Madison AL
+35758
+
+ + +

13. How can you review, update, or delete the data we collect from you?

+ +The only effective method to review, update, or delete any of your data is locally on the VeilidChat application on your device. The Veilid Foundation is unable to collect or access your information through the VeilidChat application and thus does not have the ability to review, update, or delete information that we do not possess. + + +

14. Cookie and Data Analytics Disclosure

+ +We don’t use cookies. We don’t use data analytics. You can check on our website. diff --git a/pages/contribute/code-of-conduct.md b/pages/contribute/code-of-conduct.md new file mode 100644 index 0000000..101f6d8 --- /dev/null +++ b/pages/contribute/code-of-conduct.md @@ -0,0 +1,143 @@ +--- +title: Code of Conduct +description: Veilid community and developer code of conduct +weight: 2 +layout: subpage +--- + +Our code of conduct on the Contributor Covenant Code of Conduct and will be updated as needed. + +Questions, comments, or concerns about the code of conduct may be sent to +security@veilid.org. + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations + diff --git a/pages/contribute/index.md b/pages/contribute/index.md new file mode 100644 index 0000000..c7709ce --- /dev/null +++ b/pages/contribute/index.md @@ -0,0 +1,49 @@ +--- +title: Contribute +description: Learn about all the ways you can help Veilid +menu: + main: + weight: 6 +weight: 1 +layout: subpage +--- + +### How You Can Help + + + +### Get Started + +Please read our Code of Conduct and then join us on our discord. + +Veilid Discord diff --git a/pages/defcon/index.md b/pages/defcon/index.md new file mode 100644 index 0000000..7ad8af0 --- /dev/null +++ b/pages/defcon/index.md @@ -0,0 +1,27 @@ +--- +title: DefCon +description: Veilid is launching at DefCon 31 in Las Vegas +layout: subpage +menu: + main: + weight: 2 +weight: 1 +--- + +
+
+

We're premiering Veilid at Def Con 31 in Las Vegas!

+

+ The launch talk and + demo lab targeted more at developers and other technical folks.

+

The party is for anyone attending the conference.

+
+
+
+ DefCon 31 Logo +
+
+
+ + + diff --git a/pages/defcon/lab.md b/pages/defcon/lab.md new file mode 100644 index 0000000..3d3806f --- /dev/null +++ b/pages/defcon/lab.md @@ -0,0 +1,24 @@ +--- +title: Demo Lab +description: TC and Veggie demonstrated how to communicate with Veilid +weight: 3 +layout: subpage +--- + +### Veilid + +#### A Demo Lab + +##### Who + +TC Johnson & Deth Veggie + +##### Where & When + +Saturday August 12, 10:00 – 11:55, Committee Boardroom, Forum + +##### What + +Veilid is a new, distributed communication protocol developed by Cult of the Dead Cow's Dildog (of BO2K fame). This p2p, E2EE, distributed protocol is being released at Defcon 31, fully open source, and with an example app called Veilid Chat. These demos will cover setting up an identity, connecting to others, deploying heavy nodes to support the network, and contributing to the project. + +[Official Forum Page](https://forum.defcon.org/node/246329) \ No newline at end of file diff --git a/pages/defcon/party.md b/pages/defcon/party.md new file mode 100644 index 0000000..58accab --- /dev/null +++ b/pages/defcon/party.md @@ -0,0 +1,71 @@ +--- +title: Veilid Launch Party +description: There ain't no party like a cDc party; join us to celebrate the launch of the Veilid framework. +weight: 4 +layout: subpage +--- + +
(Begin transmission)
+ +
+
+ Veilid Launch Party Flyer, Details Listed Below +
+
+ +
+
+

+ Cult of the Dead Cow breaks the internet!! +

+
+
+

And you can too!

+ + + + + + + + + + + + + + + + + + +
Where + Forums 105,136 +
WhenFriday, August 11. 8pm to Midnight.
Dress Code + Recommended (but not required) dress code- y2k 31337 Haxxor threads. + Think Zero Cool and Acid Burn meet Max Headroom and Franken Gibe. + There is no contest, but the Bovine Mother is watching, so make her proud. +
Schedule +
    +
  • 20:00 - 20:45 — Jackalope
  • +
  • 20:45 - 21:30 — DotorNot
  • +
  • 21:30 - 21:15 — cDc/Veilid
  • +
  • 21:15 - 22:45 — Rocky Rivera & DJ Roza
  • +
  • 22:45 - 23:30 — EVA
  • +
  • 23:30 - Close — DJ McGrew
  • +
+
+

DefCon Forum Post

+
+
+ +

The herd hath spoken. ooMen.

+ +
(End transmission)
diff --git a/pages/defcon/talk.md b/pages/defcon/talk.md new file mode 100644 index 0000000..be1ada7 --- /dev/null +++ b/pages/defcon/talk.md @@ -0,0 +1,24 @@ +--- +title: Launch Talk +description: Dildog and Medus4 go over the how's and why's of Veilid in "The Internals of Veilid" +weight: 2 +layout: subpage +--- + +### The Internals of Veilid + +#### A New Decentralized Application Framework + +##### Who +Christien 'DilDog' Rioux and Katelyn 'Medus4' Bowden at DefCon 31 + +[Launch-Slides-Veilid.pdf](/Launch-Slides-Veilid.pdf) + +##### Where & When +Friday, August 11 at 09:00; Track 1 + +##### What + +Attend our presentation of Veilid: an open-source, peer-to-peer, mobile-first networked application framework. Talk covers how it works as a protocol, structures, cryptography, and how to write applications. + +[Official Forum Page](https://forum.defcon.org/node/246124) \ No newline at end of file diff --git a/pages/docs/code-repositories.md b/pages/docs/code-repositories.md new file mode 100644 index 0000000..f69799c --- /dev/null +++ b/pages/docs/code-repositories.md @@ -0,0 +1,35 @@ +--- +title: Code Repositories +description: The code base for the different parts and tools of Veilid +weight: 3 +layout: subpage +--- + +### Veilid Framework + +#### Getting Started + +Please recursively check out the project using this command + +`git clone --recurse-submodules git@gitlab.com:veilid/veilid.git` + +Then read the [development](https://gitlab.com/veilid/veilid/-/blob/main/DEVELOPMENT.md) guide to get started. + +#### About the Code Repo + +The main repository is located at https://gitlab.com/veilid/veilid and includes several components +- `veilid-core` - the main Veilid crate: https://crates.io/crates/veilid-core +- `veilid-tools` - misc functions for veilid and friends: https://crates.io/crates/veilid-tools +- `veilid-wasm` - Veilid bindings for webassembly: https://crates.io/crates/veilid-wasm +- `veilid-flutter` - Veilid bindings for Flutter/Dart. Comes with an example program: https://crates.io/crates/veilid-flutter +- Also `veilid-server` and `veilid-cli` source are also in this repo for building headless nodes + + +### Packages + +If you want to install `veilid-server` and `veilid-cli` from package repositories, +please refer to our [instructions](/docs/package-repositories/). + +### VeilidChat + +The code for VeilidChat will be available at https://gitlab.com/veilid/veilidchat once we're recovered from DefCon. diff --git a/pages/docs/index.md b/pages/docs/index.md new file mode 100644 index 0000000..bc4498a --- /dev/null +++ b/pages/docs/index.md @@ -0,0 +1,19 @@ +--- +title: Documentation +description: Documentation for Veilid framework and protocol +menu: + main: + weight: 4 +weight: 1 +layout: subpage +--- + +The documentation is currently a work in progress. + +Here's what we've got so far: + +- [Rust documentation](https://docs.rs/releases/search?query=veilid) + + +Are you good at writing? We could use your help. + diff --git a/pages/docs/package-repositories.md b/pages/docs/package-repositories.md new file mode 100644 index 0000000..c002fb7 --- /dev/null +++ b/pages/docs/package-repositories.md @@ -0,0 +1,47 @@ +--- +title: Package Repositories +description: Veilid has Rust, Python, Debian, and Fedora packages available. +weight: 4 +layout: subpage +--- + +To run a "headless" Veilid node, you can install `veilid-server` and `veilid-cli` from repositories. + +

Debian Based Systems

+ +
+ + +
+ +

Note: The key's fingerprint is 516C76D1E372C5C96EE54E22AE0E059BC64CD052

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +

Fedora Based Systems

+ +
+ + +
+
+ + +
+ +

PyPi

+

https://pypi.org/project/veilid/

diff --git a/pages/donate.md b/pages/donate.md new file mode 100644 index 0000000..3a770f0 --- /dev/null +++ b/pages/donate.md @@ -0,0 +1,45 @@ +--- +title: Donate +description: Help support Veilid by gifting a tax-deductible donation +menu: + main: + weight: 10 +layout: index +--- + +
+
+

+ Veilid Foundation was formed to develop, distribute, and maintain a privacy focused + communication platform and protocol for the purposes of defending human and civil rights. +

+

+ Supporting us in this mission helps ensure the Veilid framework gets the support and defense + it needs to protect your privacy. +

+

+ You have a very real chance at private, secure, and accessible communication tools. +

+

+ You can escape the data economy and help others do the same. You don't have to be the product. +

+
+
+
+

+ Veilid Foundation Inc is a registered 501c3 non-profit organization; your donations are tax-deductible. +

+
+

You can learn more at Veilid.org

+
+
+ +
+

+ Donations are collected via Stripe; clicking this link will open a new window or tab. +

+

+ Support Veilid Today +

+
+ diff --git a/pages/framework/cryptography.md b/pages/framework/cryptography.md new file mode 100644 index 0000000..90d466c --- /dev/null +++ b/pages/framework/cryptography.md @@ -0,0 +1,167 @@ +--- +title: Cryptography +description: An overview of the cryptography used in Veilid +weight: 3 +layout: subpage +--- + + +Strong, appropriate, cryptography choices are essential to the functioning of Veilid. + +Veilid provides applications guarantees about how data is handled on the wire and at rest. + +Cryptosystems were chosen that work well together and provide a balance of speed and cryptographic hardness. + +### Current Cryptography Systems + + + +### Upgrading Cryptography Systems + +Nothing lasts forever and cryptography is no exception. As computing power improves and cryptographic attacks evolve, weaknesses in cryptosystems are inevitable. + +Veilid has ensured that upgrading to newer cryptosystems is streamlined and minimally invasive to app developers, and handled transparently at the node level. + + + +### Secure Storage + + + +- Device-level secret storage APIs are available for all platforms +- Encrypted table store APIs are exposed to applications to make safe data storage easy +- Device data keys can also be password protected +- Apps never need to write anything to disk unencrypted + +
+
+
+
+

ProtectedStore

+
+
+

Device-level Secret Storage

+
    +
  • MacOS / iOS Keychain
  • +
  • Android Keystore
  • +
  • Windows Protected Storage
  • +
  • Linux Secret Service
  • +
+ New Rust Crate: keyring-manager +
+
+
+
+
+
+

TableStore

+
+
+

Encrypted Key-Value Database

+
    +
  • SQLITE on Native
  • +
  • IndexedDB in Browser
  • +
  • Device Key can be protected from backup dumping attacks
  • +
+ New Rust Crate: keyvaluedb +
+
+
+
+
+
+

RecordStore

+
+
+

Distributed Hash Table Storage

+
    +
  • Encrypted + Authenticated
  • +
  • Subkey support
  • +
  • LRU distributed cache
  • +
  • Per-key multi-writer schemas
  • +
+
+
+
+
+
+
+

BlockStore

+
+
+

Content-addressable Data Distribution +

    +
  • Take What You Give model
  • +
  • Connect and share cloud storage
  • +
  • Bittorrent-like sharding
  • +
+ This feature is "coming soon." +
+
+
+
+ +### On The Wire + +
+

Everything is end-to-end encrypted

+

Data is encrypted at rest and on the wire

+

Your data is protected even if you lose your device

+
+ + diff --git a/pages/framework/index.md b/pages/framework/index.md new file mode 100644 index 0000000..3f84223 --- /dev/null +++ b/pages/framework/index.md @@ -0,0 +1,26 @@ +--- +title: Framework +description: An overview of the Veilid Framework +menu: + main: + weight: 3 +weight: 1 +layout: subpage +sortby: weight +--- + + + + +
+Veilid is an open-source, peer-to-peer, mobile-first, networked application framework. +
+ +The framework is conceptually similar to IPFS and Tor, but faster and designed from the ground-up to provide all +services over a privately routed network. + +The framework enables development of fully-distributed applications without a 'blockchain' or +a 'transactional layer' at their base. + +The framework can be included as part of user-facing applications or run as a 'headless node' +for power users who wish to help build the network. diff --git a/pages/framework/networking.md b/pages/framework/networking.md new file mode 100644 index 0000000..e1e3456 --- /dev/null +++ b/pages/framework/networking.md @@ -0,0 +1,63 @@ +--- +title: Networking +description: An overview of the networking used in Veilid +weight: 2 +layout: subpage +--- + +
+

All devices are welcome and treated fairly.

+

You can use the public Veilid Network or build your own.

+

Nodes help each other like mutual aid for connectivity

+
+ +All Veilid applications running `veilid-core` are 'nodes', and they are all equal in the eyes of the network. No nodes are 'special'. + +Nodes are only limited by the resources they bring and the configuration of the network they are on. + +DNS is only used one time during ‘bootstrap'; it is not required though. + +SSL is optional and only for HTTPS Websockets for Veilid Webapps. + +### Protocols + +Veilid uses UDP, TCP, and Websockets. + +Low level protocols supported by Veilid are kept simple, to minimize complications. Everything uses framed RPC operations up +to 64KB in size. Protocol support is extensible and may add WebRTC and other specialized protocols in the future. + +### Network Topology + +

A topology graph for Veilid networks

+

To zoom in on the details, view the full size image directly.

+ +### Bootstrapping + +Bootstrap nodes not 'special' nodes. Any node can bootstrap a Veilid network. Networks can be 'keyed' to keep nodes off that don't have the key. You can join the ‘big Veilid network' or make your own isolated network. + + diff --git a/pages/framework/private-routing.md b/pages/framework/private-routing.md new file mode 100644 index 0000000..9cf739b --- /dev/null +++ b/pages/framework/private-routing.md @@ -0,0 +1,84 @@ +--- +title: Private Routing +description: An overview of how private routing works in Veilid +weight: 5 +layout: subpage +--- + +### Private and Safety Routes + +
+ a diagram of routes between points a and b +
+ Veilid Routes are a combination of source and destination private routing. + Because no node can trust any other node to pick the whole route, both source and destination must participate. +
+
+ +### Compiled Routes + +
+ a diagram of routes between points a and b, shown with components +
+ Private Routes are published as a ‘private destination’ and Safety Routes are allocated locally and combined + together with a Private Route to form a Compiled Route. +
+
+ +### Secure Envelopes + +
+ a diagram how a message is passed from B to A +
+

+ Each node hop only knows about the next one This is similar to onion routing, but assumes that + the source is fully in control of the Safety Route and the destination is fully in control of + the Private Route. +

+

To zoom in on the details, view the image directly.

+
+
+ + +### Toward The Future + +
+

Private routing is a balance of performance and security

+

Applications can make use of higher node hop counts if they desire

+

Future private routing advancements will be transparent to users

+
+ + + +
+

IP Privacy means your location is safe too

+

Users don’t have to do anything to use it

+

No IP address means no tracking, collection, or correlation

+
diff --git a/pages/framework/rpc.md b/pages/framework/rpc.md new file mode 100644 index 0000000..fb4aac3 --- /dev/null +++ b/pages/framework/rpc.md @@ -0,0 +1,91 @@ +--- +title: RPC Protocol +description: An overview of the RPC protocol used in Veilid +weight: 4 +layout: subpage +--- + +Strong, appropriate, cryptography choices are essential to the functioning of Veilid. + +Veilid provides applications guarantees about how data is handled on the wire and at rest. + +Cryptosystems were chosen that work well together and provide a balance of speed and cryptographic hardness. + +### RPC Summary + + + +### Distributed Hash Table + +Distributed Hash Tables are a way of storing data in records that have keys that are close to nodes in the network. + +#### DHT Is Just ‘Search’ +It may look complicated, but all the DHT algorithms out there are just ‘search’ algorithms. Finding data that is stored on some node somewhere out there. + +#### Improving Search +We built a better DHT by making both search and data locality more relevant. Veilid synchronizes popular data when nodes come and go from the network. + +a tree diagram for the search ability + +Locating a node by its ID. Here the node with the prefix 0011 finds the node with the prefix 1110 by +successively learning of and querying closer and closer nodes. The line segment on top represents the +space of 160-bit IDs, and shows how the lookups coverge to the target node. Below we illustrate RPC messages +made by 1110. The first RPC is to node 101, already known to 1110. Subsequent RPCs are to nodes return by the +previous RPC. + +#### DHT Schema +Veilid DHT is built using GetValue and SetValue RPC operations. Nodes can opt out of DHT storage if they do not want to participate. + +Veilid DHT records have schemas that define subkeys that are individually addressable and can have multiple writers. + +DHT record subkeys have sequence numbers and are eventually consistent across multiple writes and background synchronizations. + +
+
+
+ a diagram showing key-value pairs +
+

Veilid Default DHT Schema - DFLT

+

To zoom in on the details, view the image directly.

+
+
+
+
+
+ a diagram showing key-value pairs, but with more fields +
+

Veild Simple DHT Schema - SMPL

+

To zoom in on the details, view the image directly.

+
+
+
+
+ + + +
+

The DHT gives you full control over your data

+

Our DHT is not based on a blockchain or a coin

+

Popular data becomes more available automatically

+
diff --git a/pages/index.md b/pages/index.md new file mode 100644 index 0000000..c619258 --- /dev/null +++ b/pages/index.md @@ -0,0 +1,73 @@ +--- +title: Take Back Control +description: Veilid is an open-source, distributed application framework. +menu: + main: + weight: 1 +layout: index +--- + + +

+ Veilid is an + open-source, + peer-to-peer, + mobile-first, + networked + application framework. +

+ +

Veilid (pronounced Vay-Lid, from 'Valid and Veiled Identification')

+

+ Veilid allows anyone to build a distributed, private app. Veilid gives users the privacy to opt out of + data collection and online tracking. Veilid is being built with user experience, privacy, and safety as our top priorities. + It is open source and available to everyone to use and build upon. +

+

+ Veilid goes above and beyond existing privacy technologies and has the potential to completely change the way + people use the Internet. Veilid has no profit motive, which puts us in a unique position to promote ideals + without the compromise of capitalism. +

+

+ We built Veilid because when the Internet was young and new, we viewed it as an endless and open realm of possibility. +

+

+ Instead, the Internet we know now has been heavily commercialized, with users and their data being the most + sought-after commodity. The only ways to opt-out of becoming the product for billionaires to exploit are either + too technical for the average user, or to simply not go online. +

+

+ We don't believe that is fair; we still haven't given up our dream for the entire Internet to be free + and accessible without trading privacy to use it. +

+

+ We believe that everyone should be able to forge relationships, learn, create, and build online — without being monetized. +

+

+ With Veilid, the user is in control, in a way that is approachable and friendly, regardless of technical + ability. We want to give the world the Internet we should have had all along. +

+ + + +
+
+ Technical Details +
+
+ VeilidChat +
+
+ Code +
+
+ Discord +
+
+ +
+
+ Donate +
+
+ diff --git a/pages/translations.md b/pages/translations.md new file mode 100644 index 0000000..3c26fd7 --- /dev/null +++ b/pages/translations.md @@ -0,0 +1,30 @@ +--- +title: Translations +description: Help translate documentation and more for the Veilid project +layout: index +exclude: true +--- + + +
+
+

+ We are very early on in this project and currently only have our text in English. +

+

+ We are seeking volunteers to help with this project's translations. +

+

+ Please join us on our server to talk about how we can expand our reach. +

+
+
+

Help Wanted

+

+ Veilid Discord +

+
+
+ + + diff --git a/pages/web-text.md b/pages/web-text.md new file mode 100644 index 0000000..71f7dba --- /dev/null +++ b/pages/web-text.md @@ -0,0 +1,71 @@ +--- +title: Web Text +description: How to customize your browser text appearance; based on the WAI customize design document. +layout: index +exclude: true +--- + +## Change Text Size with Zoom + +

Most web browsers let you increase and decrease the size of text, images, and other web page content with "zoom" features. Some browsers let you choose to zoom only the text size.

+

To change the zoom in most browsers, press the following two keys at the same time:

+ + +Browsers provide specific guidance on different ways to change the page zoom or text-only zoom: + +* [Google Chrome - Change text, image, and video sizes (zoom)](https://support.google.com/chrome/answer/96810) +* [Apple Safari - Zoom in on webpages](https://support.apple.com/guide/safari/zoom-in-on-webpages-ibrw1068/mac) +* [Mozilla Firefox - Font size and zoom](https://support.mozilla.org/en-US/kb/font-size-and-zoom-increase-size-of-web-pages) +* [Opera - Zoom](https://help.opera.com/en/latest/browser-window/#zoom) +* [Internet Explorer - Ease of access options](https://support.microsoft.com/en-us/help/17456/windows-internet-explorer-ease-of-access-options) +* [Microsoft Edge - Ease of Access in Microsoft Edge](https://support.microsoft.com/en-gb/help/4000734/windows-10-microsoft-edge-ease-of-access) +* [Vivaldi - Zooming options in Vivaldi](https://help.vivaldi.com/article/zooming-options-in-vivaldi/) + +## Other Text and Color Changes + +Some browsers provide functionality to set different aspects of font and color in the default view. + +* [Mozilla Firefox - Change the fonts and colors websites use](https://support.mozilla.org/en-US/kb/change-fonts-and-colors-websites-use) +* [Opera - Look and feel > Fonts](https://help.opera.com/en/presto/look-and-feel/#fonts) +* [Microsoft Internet Explorer - Ease of Access Options](https://support.microsoft.com/en-us/help/17456/windows-internet-explorer-ease-of-access-options) + +Other text and color settings are available in Reader View. + +## Reader View + +Most browsers offer a "Reader View" or "Reading View" that shows just the main content; it gets rid of navigation, ads, etc. Some browsers let you set the text font, text size, text color, background color, and line spacing in Reader View. + +* [Apple Safari - Hide ads when reading articles](https://support.apple.com/en-ca/guide/safari/hide-ads-when-reading-articles-sfri32632/mac) +* [Mozilla Firefox - Reader View for clutter-free web pages](https://support.mozilla.org/en-US/kb/firefox-reader-view-clutter-free-web-pages) +* [Microsoft Edge - Change font style and size for Reading view in Microsoft Edge](https://support.microsoft.com/en-us/help/4028023/microsoft-edge-change-font-style-and-size-for-reading-view) +* [Vivaldi - Reader View](https://help.vivaldi.com/article/reader-view/) + +## Advanced Options + +There are many browser extensions and add-ons that provide additional control over how the browser displays text and other content. + +While most browsers no long support user style sheets, extensions provide similar advanced user control. For example, the Stylus extension is available for several major browsers. + +### Note: No Endorsement + +We do not endorse specific web browsers or extensions and does not recommend one over another. +While some common browsers are included in this page, mention of a specific browser does not imply +endorsement or recommendation. + + +### About This Page + +This page is based off the [WAI customize design document](https://github.com/w3c/wai-customize-design/blob/master/index.md). \ No newline at end of file diff --git a/static/.keep b/static/.keep new file mode 100644 index 0000000..e69de29 diff --git a/static/Launch-Slides-Veilid.pdf b/static/Launch-Slides-Veilid.pdf new file mode 100644 index 0000000..3bb4d5c Binary files /dev/null and b/static/Launch-Slides-Veilid.pdf differ diff --git a/static/Veilid-Framework-Press-Kit.pdf b/static/Veilid-Framework-Press-Kit.pdf new file mode 100644 index 0000000..d9368da Binary files /dev/null and b/static/Veilid-Framework-Press-Kit.pdf differ diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..8bf8a31 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/img/Network-Thumbnail.png b/static/img/Network-Thumbnail.png new file mode 100644 index 0000000..48cf553 Binary files /dev/null and b/static/img/Network-Thumbnail.png differ diff --git a/static/img/Network.png b/static/img/Network.png new file mode 100644 index 0000000..7603082 Binary files /dev/null and b/static/img/Network.png differ diff --git a/static/img/Veilid-Framework-Cover.png b/static/img/Veilid-Framework-Cover.png new file mode 100644 index 0000000..8efc985 Binary files /dev/null and b/static/img/Veilid-Framework-Cover.png differ diff --git a/static/img/Veilid-Framework.png b/static/img/Veilid-Framework.png new file mode 100644 index 0000000..5557cee Binary files /dev/null and b/static/img/Veilid-Framework.png differ diff --git a/static/img/Veilid-Framework.svg b/static/img/Veilid-Framework.svg new file mode 100644 index 0000000..f7574c3 --- /dev/null +++ b/static/img/Veilid-Framework.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/static/img/Veilid-Launch-Party.png b/static/img/Veilid-Launch-Party.png new file mode 100644 index 0000000..30ee361 Binary files /dev/null and b/static/img/Veilid-Launch-Party.png differ diff --git a/static/img/Veilid-V.png b/static/img/Veilid-V.png new file mode 100644 index 0000000..64a14b2 Binary files /dev/null and b/static/img/Veilid-V.png differ diff --git a/static/img/Veilid-V.svg b/static/img/Veilid-V.svg new file mode 100644 index 0000000..017d250 --- /dev/null +++ b/static/img/Veilid-V.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/static/img/Veilid.png b/static/img/Veilid.png new file mode 100644 index 0000000..057da34 Binary files /dev/null and b/static/img/Veilid.png differ diff --git a/static/img/Veilid.svg b/static/img/Veilid.svg new file mode 100644 index 0000000..551393e --- /dev/null +++ b/static/img/Veilid.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/static/img/break-the-internet.jpg b/static/img/break-the-internet.jpg new file mode 100644 index 0000000..fabbe8a Binary files /dev/null and b/static/img/break-the-internet.jpg differ diff --git a/static/img/compiled-routes.png b/static/img/compiled-routes.png new file mode 100644 index 0000000..c6a3ea0 Binary files /dev/null and b/static/img/compiled-routes.png differ diff --git a/static/img/defcon31-logo-gradient.png b/static/img/defcon31-logo-gradient.png new file mode 100644 index 0000000..edfc241 Binary files /dev/null and b/static/img/defcon31-logo-gradient.png differ diff --git a/static/img/dht-dflt-framed.png b/static/img/dht-dflt-framed.png new file mode 100644 index 0000000..26537f7 Binary files /dev/null and b/static/img/dht-dflt-framed.png differ diff --git a/static/img/dht-dflt.png b/static/img/dht-dflt.png new file mode 100644 index 0000000..9891d5a Binary files /dev/null and b/static/img/dht-dflt.png differ diff --git a/static/img/dht-diagram.png b/static/img/dht-diagram.png new file mode 100644 index 0000000..706b0ce Binary files /dev/null and b/static/img/dht-diagram.png differ diff --git a/static/img/dht-smpl.png b/static/img/dht-smpl.png new file mode 100644 index 0000000..1f0c316 Binary files /dev/null and b/static/img/dht-smpl.png differ diff --git a/static/img/fonts.svg b/static/img/fonts.svg new file mode 100644 index 0000000..3afc7d2 --- /dev/null +++ b/static/img/fonts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/img/private-and-safety-routes.png b/static/img/private-and-safety-routes.png new file mode 100644 index 0000000..e431ffa Binary files /dev/null and b/static/img/private-and-safety-routes.png differ diff --git a/static/img/secure-envelopes.png b/static/img/secure-envelopes.png new file mode 100644 index 0000000..35105b6 Binary files /dev/null and b/static/img/secure-envelopes.png differ diff --git a/static/img/translate.svg b/static/img/translate.svg new file mode 100644 index 0000000..39a17d2 --- /dev/null +++ b/static/img/translate.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/img/veilid-bg-16-9.png b/static/img/veilid-bg-16-9.png new file mode 100644 index 0000000..ac98d33 Binary files /dev/null and b/static/img/veilid-bg-16-9.png differ diff --git a/static/img/veilid-bg.png b/static/img/veilid-bg.png new file mode 100644 index 0000000..e95bc1c Binary files /dev/null and b/static/img/veilid-bg.png differ diff --git a/static/veilid-launch-party-glitch.mp4 b/static/veilid-launch-party-glitch.mp4 new file mode 100644 index 0000000..ae81f7c Binary files /dev/null and b/static/veilid-launch-party-glitch.mp4 differ diff --git a/themes/veilid/assets/scss/_fonts.css b/themes/veilid/assets/scss/_fonts.css new file mode 100644 index 0000000..dc45caa --- /dev/null +++ b/themes/veilid/assets/scss/_fonts.css @@ -0,0 +1,35 @@ +@font-face { + font-family: 'Atkinson Hyperlegible'; + src: url('/fonts/AtkinsonHyperlegible-Regular.woff2') format('woff2'), + url('/fonts/AtkinsonHyperlegible-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Atkinson Hyperlegible'; + src: url('/fonts/AtkinsonHyperlegible-Bold.woff2') format('woff2'), + url('/fonts/AtkinsonHyperlegible-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Bitter'; + src: url('/fonts/Bitter-Medium.woff2') format('woff2'), + url('/fonts/Bitter-Medium.woff') format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Bitter'; + src: url('/fonts/Bitter-Bold.woff2') format('woff2'), + url('/fonts/Bitter-Bold.woff') format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} diff --git a/themes/veilid/assets/scss/_general.scss b/themes/veilid/assets/scss/_general.scss new file mode 100644 index 0000000..57bbfc1 --- /dev/null +++ b/themes/veilid/assets/scss/_general.scss @@ -0,0 +1,81 @@ + +/* ========================== General Rules ==================================== */ + +body { + font-family: 'Bitter', serif; + overflow-x: hidden; +} + + + +h1, h2, h3, h4, h5, h6 { + font-family: 'Atkinson Hyperlegible', sans-serif; + margin-top: 1.3em; /* EM on purpose: proportional to font size please */ + @extend .mb-1; + color: $primary; +} + +code { + font-size: 1em; +} + +.list-inline-item:after { + content: ', '; +} + +.list-inline-item:last-child:after { + content: ''; +} + +@include media-breakpoint-down(md) { + .no-comma .list-inline-item:after { + content: ''; + } +} + + + +li { + @extend .my-2; +} + +p:last-child { + margin-bottom: 0; +} + +figure { + @extend .p-3; + border: 1px solid $border-color; + figcaption { + @extend .mt-3; + } +} + +.btn { + text-decoration: underline; +} + +.highlighter-1, .highlighter-2, .highlighter-3, .highlighter-4 { + display: inline-block; + padding: 0.15em 0.3em; + margin: 0.15em 0; + @extend .rounded; +} + +.highlighter-1 { + background-color: #dde97d; + color: black; +} +.highlighter-2 { + background-color: #FFE680; + color: black; +} +.highlighter-3 { + background-color: #99DBFF; + color: black; +} +.highlighter-4 { + background-color: #F080D8; + color: black; +} + diff --git a/themes/veilid/assets/scss/_layout.scss b/themes/veilid/assets/scss/_layout.scss new file mode 100644 index 0000000..94dd821 --- /dev/null +++ b/themes/veilid/assets/scss/_layout.scss @@ -0,0 +1,161 @@ + +#site-logo { + max-height: 4rem; + + @extend .my-2; + @extend .me-3; +} + +#site-title { + display: block; + position: absolute; + top: -100vh; +} + + +.navbar-toggler img { + min-height: 2rem; + display: block; +} + +/* +// No media query necessary for xs breakpoint as it's effectively `@media (min-width: 0) { ... }` +@include media-breakpoint-up(sm) { ... } +@include media-breakpoint-up(md) { ... } +@include media-breakpoint-up(lg) { ... } +@include media-breakpoint-up(xl) { ... } +@include media-breakpoint-up(xxl) { ... } +*/ + + +@mixin nav-link-theme { + @extend .nav; + @extend .me-3; + + .nav-link:visited, .nav-link:link, .nav-link:hover, .nav-link:active, .nav-link.active { + text-align: left !important; + padding: 0.25rem 0.5rem; + background: transparent !important; + } + .nav-link:visited, .nav-link:link { + text-decoration: underline; + color: $veilid_purple_medium; + } + .nav-link:hover, .nav-link:active { + text-decoration: none; + color: $veilid_fuchsia !important; + } +} + +.header-nav { + @include nav-link-theme; + display: block; + li { + display: block; + @extend .my-4; + } +} + + +@include media-breakpoint-up(lg) { + .header-nav { + display: flex; + li { + } + } +} + +.subsectionnav { + @include nav-link-theme; + display: block; +} + + +#site-options { + font-family: 'Atkinson Hyperlegible', sans-serif; + color: $black; + background-color: #E3E4F1; + a:link, a:active, a:visited, a:hover { + color: inherit; + img { + height: 1.5em; + } + } + +} +@include media-breakpoint-up(lg) { + #site-options img { + padding-right: 0.25rem; + } +} + +#site-nav { + @extend .mt-2; + @extend .mb-4; +} + + +#site-nav .navbar-brand { + margin-right: 2rem; +} + + +html, body { + height: 100%; +} + +body { + display: flex; + flex-direction: column; + #content { + flex: 2; + margin-top: 0rem; + margin-bottom: 4rem; + } +} + +@media (min-width: 992px) { + .subsectionnav li { + display: block; + width: 100%; + } +} + +#page-footer { + background-color: $black; + color: $white; + padding: 2rem; + p { + margin: 1rem 0; + } + a:link, a:active, a:hover, a:visited { + color: $white; + } +} + + + +@include media-breakpoint-up(md) { + .col-list { columns: 2; } +} +@include media-breakpoint-up(lg) { + .col-list { columns: 3; } +} + + +.front-page-hero { + display: flex; + flex-direction: column; + justify-content: end; + height: 25vh; + @extend .mb-4; + .focus-text { + margin-bottom: 0 !important; + } + .take-back-control { + margin: 0 !important; + h2 { + margin: 0 !important; + } + } +} \ No newline at end of file diff --git a/themes/veilid/assets/scss/_settings.scss b/themes/veilid/assets/scss/_settings.scss new file mode 100644 index 0000000..d816e6b --- /dev/null +++ b/themes/veilid/assets/scss/_settings.scss @@ -0,0 +1,54 @@ + +/* I like how it looks. That's why and that's good enough. */ + +$line-height-base: 1.62; + +$spacer: 1rem; +$spacers: ( + 0: 0, + 1: $spacer * .41, + 2: $spacer * .81, + 3: $spacer, + 4: $spacer * 1.62, + 5: $spacer * 3.24, +); + +/* Bigger hit box please */ +$list-group-item-padding-y: $spacer * .81; + +$veilid_purple: #4f4d9d; +$veilid_purple_pastel: #c7c8e2; +$veilid_purple_border: #8B8BC0; +$veilid_purple_medium: #3D3783; +$veilid_purple_darkest: #2b2068; + +$veilid_magenta: #e100b0; +$veilid_fuchsia: #8e0097; + +$veilid_plum_dark: #441168; + + +$primary: $veilid_purple; +$primary-bg-subtle: $veilid_purple_pastel; +$primary-border-subtle: #a2a5ce; + +$dark: #131c45; +$success: #008219 ; +$warning:#dde97d; +$danger: #cd9c2d; +$info: #001d7f; + +$code-color: $veilid_fuchsia; + +$secondary: #495057; +$navbar-dark-color: rgba(#fff, .75); +$navbar-dark-hover-color: rgba(#fff, 1); +$table-dark-bg: rgba($dark,0.5); +$link-decoration: underline; + +.bgv-purple { background-color: $veilid_purple !important; color: white !important; } +.bgv-fuschia { background-color: $veilid_fuchsia !important; color: white !important; } +.bgv-plum { background-color: $veilid_plum_dark !important; color: white !important; } + +$link-color: $veilid_purple_medium; +$link-hover-color: $veilid_fuchsia; \ No newline at end of file diff --git a/themes/veilid/assets/scss/bootstrap/_accordion.scss b/themes/veilid/assets/scss/bootstrap/_accordion.scss new file mode 100644 index 0000000..75588a5 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_accordion.scss @@ -0,0 +1,158 @@ +// +// Base styles +// + +.accordion { + // scss-docs-start accordion-css-vars + --#{$prefix}accordion-color: #{$accordion-color}; + --#{$prefix}accordion-bg: #{$accordion-bg}; + --#{$prefix}accordion-transition: #{$accordion-transition}; + --#{$prefix}accordion-border-color: #{$accordion-border-color}; + --#{$prefix}accordion-border-width: #{$accordion-border-width}; + --#{$prefix}accordion-border-radius: #{$accordion-border-radius}; + --#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius}; + --#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x}; + --#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y}; + --#{$prefix}accordion-btn-color: #{$accordion-button-color}; + --#{$prefix}accordion-btn-bg: #{$accordion-button-bg}; + --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)}; + --#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width}; + --#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform}; + --#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition}; + --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)}; + --#{$prefix}accordion-btn-focus-border-color: #{$accordion-button-focus-border-color}; + --#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow}; + --#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x}; + --#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y}; + --#{$prefix}accordion-active-color: #{$accordion-button-active-color}; + --#{$prefix}accordion-active-bg: #{$accordion-button-active-bg}; + // scss-docs-end accordion-css-vars +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x); + @include font-size($font-size-base); + color: var(--#{$prefix}accordion-btn-color); + text-align: left; // Reset button style + background-color: var(--#{$prefix}accordion-btn-bg); + border: 0; + @include border-radius(0); + overflow-anchor: none; + @include transition(var(--#{$prefix}accordion-transition)); + + &:not(.collapsed) { + color: var(--#{$prefix}accordion-active-color); + background-color: var(--#{$prefix}accordion-active-bg); + box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color); // stylelint-disable-line function-disallowed-list + + &::after { + background-image: var(--#{$prefix}accordion-btn-active-icon); + transform: var(--#{$prefix}accordion-btn-icon-transform); + } + } + + // Accordion icon + &::after { + flex-shrink: 0; + width: var(--#{$prefix}accordion-btn-icon-width); + height: var(--#{$prefix}accordion-btn-icon-width); + margin-left: auto; + content: ""; + background-image: var(--#{$prefix}accordion-btn-icon); + background-repeat: no-repeat; + background-size: var(--#{$prefix}accordion-btn-icon-width); + @include transition(var(--#{$prefix}accordion-btn-icon-transition)); + } + + &:hover { + z-index: 2; + } + + &:focus { + z-index: 3; + border-color: var(--#{$prefix}accordion-btn-focus-border-color); + outline: 0; + box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow); + } +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + color: var(--#{$prefix}accordion-color); + background-color: var(--#{$prefix}accordion-bg); + border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color); + + &:first-of-type { + @include border-top-radius(var(--#{$prefix}accordion-border-radius)); + + .accordion-button { + @include border-top-radius(var(--#{$prefix}accordion-inner-border-radius)); + } + } + + &:not(:first-of-type) { + border-top: 0; + } + + // Only set a border-radius on the last item if the accordion is collapsed + &:last-of-type { + @include border-bottom-radius(var(--#{$prefix}accordion-border-radius)); + + .accordion-button { + &.collapsed { + @include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius)); + } + } + + .accordion-collapse { + @include border-bottom-radius(var(--#{$prefix}accordion-border-radius)); + } + } +} + +.accordion-body { + padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x); +} + + +// Flush accordion items +// +// Remove borders and border-radius to keep accordion items edge-to-edge. + +.accordion-flush { + .accordion-collapse { + border-width: 0; + } + + .accordion-item { + border-right: 0; + border-left: 0; + @include border-radius(0); + + &:first-child { border-top: 0; } + &:last-child { border-bottom: 0; } + + .accordion-button { + &, + &.collapsed { + @include border-radius(0); + } + } + } +} + +@if $enable-dark-mode { + @include color-mode(dark) { + .accordion-button::after { + --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)}; + --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)}; + } + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_alert.scss b/themes/veilid/assets/scss/bootstrap/_alert.scss new file mode 100644 index 0000000..b8cff9b --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_alert.scss @@ -0,0 +1,68 @@ +// +// Base styles +// + +.alert { + // scss-docs-start alert-css-vars + --#{$prefix}alert-bg: transparent; + --#{$prefix}alert-padding-x: #{$alert-padding-x}; + --#{$prefix}alert-padding-y: #{$alert-padding-y}; + --#{$prefix}alert-margin-bottom: #{$alert-margin-bottom}; + --#{$prefix}alert-color: inherit; + --#{$prefix}alert-border-color: transparent; + --#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}alert-border-color); + --#{$prefix}alert-border-radius: #{$alert-border-radius}; + --#{$prefix}alert-link-color: inherit; + // scss-docs-end alert-css-vars + + position: relative; + padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x); + margin-bottom: var(--#{$prefix}alert-margin-bottom); + color: var(--#{$prefix}alert-color); + background-color: var(--#{$prefix}alert-bg); + border: var(--#{$prefix}alert-border); + @include border-radius(var(--#{$prefix}alert-border-radius)); +} + +// Headings for larger alerts +.alert-heading { + // Specified to prevent conflicts of changing $headings-color + color: inherit; +} + +// Provide class for links that match alerts +.alert-link { + font-weight: $alert-link-font-weight; + color: var(--#{$prefix}alert-link-color); +} + + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissible { + padding-right: $alert-dismissible-padding-r; + + // Adjust close link position + .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: $stretched-link-z-index + 1; + padding: $alert-padding-y * 1.25 $alert-padding-x; + } +} + + +// scss-docs-start alert-modifiers +// Generate contextual modifier classes for colorizing the alert +@each $state in map-keys($theme-colors) { + .alert-#{$state} { + --#{$prefix}alert-color: var(--#{$prefix}#{$state}-text-emphasis); + --#{$prefix}alert-bg: var(--#{$prefix}#{$state}-bg-subtle); + --#{$prefix}alert-border-color: var(--#{$prefix}#{$state}-border-subtle); + --#{$prefix}alert-link-color: var(--#{$prefix}#{$state}-text-emphasis); + } +} +// scss-docs-end alert-modifiers diff --git a/themes/veilid/assets/scss/bootstrap/_badge.scss b/themes/veilid/assets/scss/bootstrap/_badge.scss new file mode 100644 index 0000000..cc3d269 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_badge.scss @@ -0,0 +1,38 @@ +// Base class +// +// Requires one of the contextual, color modifier classes for `color` and +// `background-color`. + +.badge { + // scss-docs-start badge-css-vars + --#{$prefix}badge-padding-x: #{$badge-padding-x}; + --#{$prefix}badge-padding-y: #{$badge-padding-y}; + @include rfs($badge-font-size, --#{$prefix}badge-font-size); + --#{$prefix}badge-font-weight: #{$badge-font-weight}; + --#{$prefix}badge-color: #{$badge-color}; + --#{$prefix}badge-border-radius: #{$badge-border-radius}; + // scss-docs-end badge-css-vars + + display: inline-block; + padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x); + @include font-size(var(--#{$prefix}badge-font-size)); + font-weight: var(--#{$prefix}badge-font-weight); + line-height: 1; + color: var(--#{$prefix}badge-color); + text-align: center; + white-space: nowrap; + vertical-align: baseline; + @include border-radius(var(--#{$prefix}badge-border-radius)); + @include gradient-bg(); + + // Empty badges collapse automatically + &:empty { + display: none; + } +} + +// Quick fix for badges in buttons +.btn .badge { + position: relative; + top: -1px; +} diff --git a/themes/veilid/assets/scss/bootstrap/_breadcrumb.scss b/themes/veilid/assets/scss/bootstrap/_breadcrumb.scss new file mode 100644 index 0000000..b8252ff --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_breadcrumb.scss @@ -0,0 +1,40 @@ +.breadcrumb { + // scss-docs-start breadcrumb-css-vars + --#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x}; + --#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y}; + --#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom}; + @include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size); + --#{$prefix}breadcrumb-bg: #{$breadcrumb-bg}; + --#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius}; + --#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color}; + --#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x}; + --#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color}; + // scss-docs-end breadcrumb-css-vars + + display: flex; + flex-wrap: wrap; + padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x); + margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom); + @include font-size(var(--#{$prefix}breadcrumb-font-size)); + list-style: none; + background-color: var(--#{$prefix}breadcrumb-bg); + @include border-radius(var(--#{$prefix}breadcrumb-border-radius)); +} + +.breadcrumb-item { + // The separator between breadcrumbs (by default, a forward-slash: "/") + + .breadcrumb-item { + padding-left: var(--#{$prefix}breadcrumb-item-padding-x); + + &::before { + float: left; // Suppress inline spacings and underlining of the separator + padding-right: var(--#{$prefix}breadcrumb-item-padding-x); + color: var(--#{$prefix}breadcrumb-divider-color); + content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"}; + } + } + + &.active { + color: var(--#{$prefix}breadcrumb-item-active-color); + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_button-group.scss b/themes/veilid/assets/scss/bootstrap/_button-group.scss new file mode 100644 index 0000000..55ae3f6 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_button-group.scss @@ -0,0 +1,142 @@ +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; // match .btn alignment given font-size hack above + + > .btn { + position: relative; + flex: 1 1 auto; + } + + // Bring the hover, focused, and "active" buttons to the front to overlay + // the borders properly + > .btn-check:checked + .btn, + > .btn-check:focus + .btn, + > .btn:hover, + > .btn:focus, + > .btn:active, + > .btn.active { + z-index: 1; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + + .input-group { + width: auto; + } +} + +.btn-group { + @include border-radius($btn-border-radius); + + // Prevent double borders when buttons are next to each other + > :not(.btn-check:first-child) + .btn, + > .btn-group:not(:first-child) { + margin-left: calc(#{$btn-border-width} * -1); // stylelint-disable-line function-disallowed-list + } + + // Reset rounded corners + > .btn:not(:last-child):not(.dropdown-toggle), + > .btn.dropdown-toggle-split:first-child, + > .btn-group:not(:last-child) > .btn { + @include border-end-radius(0); + } + + // The left radius should be 0 if the button is: + // - the "third or more" child + // - the second child and the previous element isn't `.btn-check` (making it the first child visually) + // - part of a btn-group which isn't the first child + > .btn:nth-child(n + 3), + > :not(.btn-check) + .btn, + > .btn-group:not(:first-child) > .btn { + @include border-start-radius(0); + } +} + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-sm > .btn { @extend .btn-sm; } +.btn-group-lg > .btn { @extend .btn-lg; } + + +// +// Split button dropdowns +// + +.dropdown-toggle-split { + padding-right: $btn-padding-x * .75; + padding-left: $btn-padding-x * .75; + + &::after, + .dropup &::after, + .dropend &::after { + margin-left: 0; + } + + .dropstart &::before { + margin-right: 0; + } +} + +.btn-sm + .dropdown-toggle-split { + padding-right: $btn-padding-x-sm * .75; + padding-left: $btn-padding-x-sm * .75; +} + +.btn-lg + .dropdown-toggle-split { + padding-right: $btn-padding-x-lg * .75; + padding-left: $btn-padding-x-lg * .75; +} + + +// The clickable button for toggling the menu +// Set the same inset shadow as the :active state +.btn-group.show .dropdown-toggle { + @include box-shadow($btn-active-box-shadow); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + @include box-shadow(none); + } +} + + +// +// Vertical button groups +// + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; + + > .btn, + > .btn-group { + width: 100%; + } + + > .btn:not(:first-child), + > .btn-group:not(:first-child) { + margin-top: calc(#{$btn-border-width} * -1); // stylelint-disable-line function-disallowed-list + } + + // Reset rounded corners + > .btn:not(:last-child):not(.dropdown-toggle), + > .btn-group:not(:last-child) > .btn { + @include border-bottom-radius(0); + } + + > .btn ~ .btn, + > .btn-group:not(:first-child) > .btn { + @include border-top-radius(0); + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_buttons.scss b/themes/veilid/assets/scss/bootstrap/_buttons.scss new file mode 100644 index 0000000..cbc0784 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_buttons.scss @@ -0,0 +1,207 @@ +// +// Base styles +// + +.btn { + // scss-docs-start btn-css-vars + --#{$prefix}btn-padding-x: #{$btn-padding-x}; + --#{$prefix}btn-padding-y: #{$btn-padding-y}; + --#{$prefix}btn-font-family: #{$btn-font-family}; + @include rfs($btn-font-size, --#{$prefix}btn-font-size); + --#{$prefix}btn-font-weight: #{$btn-font-weight}; + --#{$prefix}btn-line-height: #{$btn-line-height}; + --#{$prefix}btn-color: #{$btn-color}; + --#{$prefix}btn-bg: transparent; + --#{$prefix}btn-border-width: #{$btn-border-width}; + --#{$prefix}btn-border-color: transparent; + --#{$prefix}btn-border-radius: #{$btn-border-radius}; + --#{$prefix}btn-hover-border-color: transparent; + --#{$prefix}btn-box-shadow: #{$btn-box-shadow}; + --#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity}; + --#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} rgba(var(--#{$prefix}btn-focus-shadow-rgb), .5); + // scss-docs-end btn-css-vars + + display: inline-block; + padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x); + font-family: var(--#{$prefix}btn-font-family); + @include font-size(var(--#{$prefix}btn-font-size)); + font-weight: var(--#{$prefix}btn-font-weight); + line-height: var(--#{$prefix}btn-line-height); + color: var(--#{$prefix}btn-color); + text-align: center; + text-decoration: if($link-decoration == none, null, none); + white-space: $btn-white-space; + vertical-align: middle; + cursor: if($enable-button-pointers, pointer, null); + user-select: none; + border: var(--#{$prefix}btn-border-width) solid var(--#{$prefix}btn-border-color); + @include border-radius(var(--#{$prefix}btn-border-radius)); + @include gradient-bg(var(--#{$prefix}btn-bg)); + @include box-shadow(var(--#{$prefix}btn-box-shadow)); + @include transition($btn-transition); + + &:hover { + color: var(--#{$prefix}btn-hover-color); + text-decoration: if($link-hover-decoration == underline, none, null); + background-color: var(--#{$prefix}btn-hover-bg); + border-color: var(--#{$prefix}btn-hover-border-color); + } + + .btn-check + &:hover { + // override for the checkbox/radio buttons + color: var(--#{$prefix}btn-color); + background-color: var(--#{$prefix}btn-bg); + border-color: var(--#{$prefix}btn-border-color); + } + + &:focus-visible { + color: var(--#{$prefix}btn-hover-color); + @include gradient-bg(var(--#{$prefix}btn-hover-bg)); + border-color: var(--#{$prefix}btn-hover-border-color); + outline: 0; + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + + .btn-check:focus-visible + & { + border-color: var(--#{$prefix}btn-hover-border-color); + outline: 0; + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + + .btn-check:checked + &, + :not(.btn-check) + &:active, + &:first-child:active, + &.active, + &.show { + color: var(--#{$prefix}btn-active-color); + background-color: var(--#{$prefix}btn-active-bg); + // Remove CSS gradients if they're enabled + background-image: if($enable-gradients, none, null); + border-color: var(--#{$prefix}btn-active-border-color); + @include box-shadow(var(--#{$prefix}btn-active-shadow)); + + &:focus-visible { + // Avoid using mixin so we can pass custom focus shadow properly + @if $enable-shadows { + box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow); + } @else { + box-shadow: var(--#{$prefix}btn-focus-box-shadow); + } + } + } + + &:disabled, + &.disabled, + fieldset:disabled & { + color: var(--#{$prefix}btn-disabled-color); + pointer-events: none; + background-color: var(--#{$prefix}btn-disabled-bg); + background-image: if($enable-gradients, none, null); + border-color: var(--#{$prefix}btn-disabled-border-color); + opacity: var(--#{$prefix}btn-disabled-opacity); + @include box-shadow(none); + } +} + + +// +// Alternate buttons +// + +// scss-docs-start btn-variant-loops +@each $color, $value in $theme-colors { + .btn-#{$color} { + @if $color == "light" { + @include button-variant( + $value, + $value, + $hover-background: shade-color($value, $btn-hover-bg-shade-amount), + $hover-border: shade-color($value, $btn-hover-border-shade-amount), + $active-background: shade-color($value, $btn-active-bg-shade-amount), + $active-border: shade-color($value, $btn-active-border-shade-amount) + ); + } @else if $color == "dark" { + @include button-variant( + $value, + $value, + $hover-background: tint-color($value, $btn-hover-bg-tint-amount), + $hover-border: tint-color($value, $btn-hover-border-tint-amount), + $active-background: tint-color($value, $btn-active-bg-tint-amount), + $active-border: tint-color($value, $btn-active-border-tint-amount) + ); + } @else { + @include button-variant($value, $value); + } + } +} + +@each $color, $value in $theme-colors { + .btn-outline-#{$color} { + @include button-outline-variant($value); + } +} +// scss-docs-end btn-variant-loops + + +// +// Link buttons +// + +// Make a button look and behave like a link +.btn-link { + --#{$prefix}btn-font-weight: #{$font-weight-normal}; + --#{$prefix}btn-color: #{$btn-link-color}; + --#{$prefix}btn-bg: transparent; + --#{$prefix}btn-border-color: transparent; + --#{$prefix}btn-hover-color: #{$btn-link-hover-color}; + --#{$prefix}btn-hover-border-color: transparent; + --#{$prefix}btn-active-color: #{$btn-link-hover-color}; + --#{$prefix}btn-active-border-color: transparent; + --#{$prefix}btn-disabled-color: #{$btn-link-disabled-color}; + --#{$prefix}btn-disabled-border-color: transparent; + --#{$prefix}btn-box-shadow: 0 0 0 #000; // Can't use `none` as keyword negates all values when used with multiple shadows + --#{$prefix}btn-focus-shadow-rgb: #{to-rgb(mix(color-contrast($link-color), $link-color, 15%))}; + + text-decoration: $link-decoration; + @if $enable-gradients { + background-image: none; + } + + &:hover, + &:focus-visible { + text-decoration: $link-hover-decoration; + } + + &:focus-visible { + color: var(--#{$prefix}btn-color); + } + + &:hover { + color: var(--#{$prefix}btn-hover-color); + } + + // No need for an active state here +} + + +// +// Button Sizes +// + +.btn-lg { + @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-border-radius-lg); +} + +.btn-sm { + @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm); +} diff --git a/themes/veilid/assets/scss/bootstrap/_card.scss b/themes/veilid/assets/scss/bootstrap/_card.scss new file mode 100644 index 0000000..d3535a9 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_card.scss @@ -0,0 +1,239 @@ +// +// Base styles +// + +.card { + // scss-docs-start card-css-vars + --#{$prefix}card-spacer-y: #{$card-spacer-y}; + --#{$prefix}card-spacer-x: #{$card-spacer-x}; + --#{$prefix}card-title-spacer-y: #{$card-title-spacer-y}; + --#{$prefix}card-title-color: #{$card-title-color}; + --#{$prefix}card-subtitle-color: #{$card-subtitle-color}; + --#{$prefix}card-border-width: #{$card-border-width}; + --#{$prefix}card-border-color: #{$card-border-color}; + --#{$prefix}card-border-radius: #{$card-border-radius}; + --#{$prefix}card-box-shadow: #{$card-box-shadow}; + --#{$prefix}card-inner-border-radius: #{$card-inner-border-radius}; + --#{$prefix}card-cap-padding-y: #{$card-cap-padding-y}; + --#{$prefix}card-cap-padding-x: #{$card-cap-padding-x}; + --#{$prefix}card-cap-bg: #{$card-cap-bg}; + --#{$prefix}card-cap-color: #{$card-cap-color}; + --#{$prefix}card-height: #{$card-height}; + --#{$prefix}card-color: #{$card-color}; + --#{$prefix}card-bg: #{$card-bg}; + --#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding}; + --#{$prefix}card-group-margin: #{$card-group-margin}; + // scss-docs-end card-css-vars + + position: relative; + display: flex; + flex-direction: column; + min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106 + height: var(--#{$prefix}card-height); + color: var(--#{$prefix}body-color); + word-wrap: break-word; + background-color: var(--#{$prefix}card-bg); + background-clip: border-box; + border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + @include border-radius(var(--#{$prefix}card-border-radius)); + @include box-shadow(var(--#{$prefix}card-box-shadow)); + + > hr { + margin-right: 0; + margin-left: 0; + } + + > .list-group { + border-top: inherit; + border-bottom: inherit; + + &:first-child { + border-top-width: 0; + @include border-top-radius(var(--#{$prefix}card-inner-border-radius)); + } + + &:last-child { + border-bottom-width: 0; + @include border-bottom-radius(var(--#{$prefix}card-inner-border-radius)); + } + } + + // Due to specificity of the above selector (`.card > .list-group`), we must + // use a child selector here to prevent double borders. + > .card-header + .list-group, + > .list-group + .card-footer { + border-top: 0; + } +} + +.card-body { + // Enable `flex-grow: 1` for decks and groups so that card blocks take up + // as much space as possible, ensuring footers are aligned to the bottom. + flex: 1 1 auto; + padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x); + color: var(--#{$prefix}card-color); +} + +.card-title { + margin-bottom: var(--#{$prefix}card-title-spacer-y); + color: var(--#{$prefix}card-title-color); +} + +.card-subtitle { + margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y)); // stylelint-disable-line function-disallowed-list + margin-bottom: 0; + color: var(--#{$prefix}card-subtitle-color); +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link { + &:hover { + text-decoration: if($link-hover-decoration == underline, none, null); + } + + + .card-link { + margin-left: var(--#{$prefix}card-spacer-x); + } +} + +// +// Optional textual caps +// + +.card-header { + padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x); + margin-bottom: 0; // Removes the default margin-bottom of + color: var(--#{$prefix}card-cap-color); + background-color: var(--#{$prefix}card-cap-bg); + border-bottom: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + + &:first-child { + @include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0); + } +} + +.card-footer { + padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x); + color: var(--#{$prefix}card-cap-color); + background-color: var(--#{$prefix}card-cap-bg); + border-top: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color); + + &:last-child { + @include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius)); + } +} + + +// +// Header navs +// + +.card-header-tabs { + margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y)); // stylelint-disable-line function-disallowed-list + margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + border-bottom: 0; + + .nav-link.active { + background-color: var(--#{$prefix}card-bg); + border-bottom-color: var(--#{$prefix}card-bg); + } +} + +.card-header-pills { + margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list + margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list +} + +// Card image +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: var(--#{$prefix}card-img-overlay-padding); + @include border-radius(var(--#{$prefix}card-inner-border-radius)); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch +} + +.card-img, +.card-img-top { + @include border-top-radius(var(--#{$prefix}card-inner-border-radius)); +} + +.card-img, +.card-img-bottom { + @include border-bottom-radius(var(--#{$prefix}card-inner-border-radius)); +} + + +// +// Card groups +// + +.card-group { + // The child selector allows nested `.card` within `.card-group` + // to display properly. + > .card { + margin-bottom: var(--#{$prefix}card-group-margin); + } + + @include media-breakpoint-up(sm) { + display: flex; + flex-flow: row wrap; + // The child selector allows nested `.card` within `.card-group` + // to display properly. + > .card { + // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 + flex: 1 0 0%; + margin-bottom: 0; + + + .card { + margin-left: 0; + border-left: 0; + } + + // Handle rounded corners + @if $enable-rounded { + &:not(:last-child) { + @include border-end-radius(0); + + .card-img-top, + .card-header { + // stylelint-disable-next-line property-disallowed-list + border-top-right-radius: 0; + } + .card-img-bottom, + .card-footer { + // stylelint-disable-next-line property-disallowed-list + border-bottom-right-radius: 0; + } + } + + &:not(:first-child) { + @include border-start-radius(0); + + .card-img-top, + .card-header { + // stylelint-disable-next-line property-disallowed-list + border-top-left-radius: 0; + } + .card-img-bottom, + .card-footer { + // stylelint-disable-next-line property-disallowed-list + border-bottom-left-radius: 0; + } + } + } + } + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_carousel.scss b/themes/veilid/assets/scss/bootstrap/_carousel.scss new file mode 100644 index 0000000..0ac8f87 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_carousel.scss @@ -0,0 +1,244 @@ +// Notes on the classes: +// +// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically) +// even when their scroll action started on a carousel, but for compatibility (with Firefox) +// we're preventing all actions instead +// 2. The .carousel-item-start and .carousel-item-end is used to indicate where +// the active slide is heading. +// 3. .active.carousel-item is the current slide. +// 4. .active.carousel-item-start and .active.carousel-item-end is the current +// slide in its in-transition state. Only one of these occurs at a time. +// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end +// is the upcoming slide in transition. + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; + @include clearfix(); +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + backface-visibility: hidden; + @include transition($carousel-transition); +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + + +// +// Alternate transitions +// + +.carousel-fade { + .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; + } + + .carousel-item.active, + .carousel-item-next.carousel-item-start, + .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; + } + + .active.carousel-item-start, + .active.carousel-item-end { + z-index: 0; + opacity: 0; + @include transition(opacity 0s $carousel-transition-duration); + } +} + + +// +// Left/right controls for nav +// + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + // Use flex for alignment (1-3) + display: flex; // 1. allow flex styles + align-items: center; // 2. vertically center contents + justify-content: center; // 3. horizontally center contents + width: $carousel-control-width; + padding: 0; + color: $carousel-control-color; + text-align: center; + background: none; + border: 0; + opacity: $carousel-control-opacity; + @include transition($carousel-control-transition); + + // Hover/focus state + &:hover, + &:focus { + color: $carousel-control-color; + text-decoration: none; + outline: 0; + opacity: $carousel-control-hover-opacity; + } +} +.carousel-control-prev { + left: 0; + background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null); +} +.carousel-control-next { + right: 0; + background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null); +} + +// Icons for within +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: $carousel-control-icon-width; + height: $carousel-control-icon-width; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + +/* rtl:options: { + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] +} */ +.carousel-control-prev-icon { + background-image: escape-svg($carousel-control-prev-icon-bg); +} +.carousel-control-next-icon { + background-image: escape-svg($carousel-control-next-icon-bg); +} + +// Optional indicator pips/controls +// +// Add a container (such as a list) with the following class and add an item (ideally a focusable control, +// like a button) with data-bs-target for each slide your carousel holds. + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + // Use the .carousel-control's width as margin so we don't overlay those + margin-right: $carousel-control-width; + margin-bottom: 1rem; + margin-left: $carousel-control-width; + + [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: $carousel-indicator-width; + height: $carousel-indicator-height; + padding: 0; + margin-right: $carousel-indicator-spacer; + margin-left: $carousel-indicator-spacer; + text-indent: -999px; + cursor: pointer; + background-color: $carousel-indicator-active-bg; + background-clip: padding-box; + border: 0; + // Use transparent borders to increase the hit area by 10px on top and bottom. + border-top: $carousel-indicator-hit-area-height solid transparent; + border-bottom: $carousel-indicator-hit-area-height solid transparent; + opacity: $carousel-indicator-opacity; + @include transition($carousel-indicator-transition); + } + + .active { + opacity: $carousel-indicator-active-opacity; + } +} + + +// Optional captions +// +// + +.carousel-caption { + position: absolute; + right: (100% - $carousel-caption-width) * .5; + bottom: $carousel-caption-spacer; + left: (100% - $carousel-caption-width) * .5; + padding-top: $carousel-caption-padding-y; + padding-bottom: $carousel-caption-padding-y; + color: $carousel-caption-color; + text-align: center; +} + +// Dark mode carousel + +@mixin carousel-dark() { + .carousel-control-prev-icon, + .carousel-control-next-icon { + filter: $carousel-dark-control-icon-filter; + } + + .carousel-indicators [data-bs-target] { + background-color: $carousel-dark-indicator-active-bg; + } + + .carousel-caption { + color: $carousel-dark-caption-color; + } +} + +.carousel-dark { + @include carousel-dark(); +} + +@if $enable-dark-mode { + @include color-mode(dark) { + @if $color-mode-type == "media-query" { + .carousel { + @include carousel-dark(); + } + } @else { + .carousel, + &.carousel { + @include carousel-dark(); + } + } + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_close.scss b/themes/veilid/assets/scss/bootstrap/_close.scss new file mode 100644 index 0000000..4d6e73c --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_close.scss @@ -0,0 +1,63 @@ +// Transparent background and border properties included for button version. +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + +.btn-close { + // scss-docs-start close-css-vars + --#{$prefix}btn-close-color: #{$btn-close-color}; + --#{$prefix}btn-close-bg: #{ escape-svg($btn-close-bg) }; + --#{$prefix}btn-close-opacity: #{$btn-close-opacity}; + --#{$prefix}btn-close-hover-opacity: #{$btn-close-hover-opacity}; + --#{$prefix}btn-close-focus-shadow: #{$btn-close-focus-shadow}; + --#{$prefix}btn-close-focus-opacity: #{$btn-close-focus-opacity}; + --#{$prefix}btn-close-disabled-opacity: #{$btn-close-disabled-opacity}; + --#{$prefix}btn-close-white-filter: #{$btn-close-white-filter}; + // scss-docs-end close-css-vars + + box-sizing: content-box; + width: $btn-close-width; + height: $btn-close-height; + padding: $btn-close-padding-y $btn-close-padding-x; + color: var(--#{$prefix}btn-close-color); + background: transparent var(--#{$prefix}btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements + border: 0; // for button elements + @include border-radius(); + opacity: var(--#{$prefix}btn-close-opacity); + + // Override 's hover style + &:hover { + color: var(--#{$prefix}btn-close-color); + text-decoration: none; + opacity: var(--#{$prefix}btn-close-hover-opacity); + } + + &:focus { + outline: 0; + box-shadow: var(--#{$prefix}btn-close-focus-shadow); + opacity: var(--#{$prefix}btn-close-focus-opacity); + } + + &:disabled, + &.disabled { + pointer-events: none; + user-select: none; + opacity: var(--#{$prefix}btn-close-disabled-opacity); + } +} + +@mixin btn-close-white() { + filter: var(--#{$prefix}btn-close-white-filter); +} + +.btn-close-white { + @include btn-close-white(); +} + +@if $enable-dark-mode { + @include color-mode(dark) { + .btn-close { + @include btn-close-white(); + } + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_containers.scss b/themes/veilid/assets/scss/bootstrap/_containers.scss new file mode 100644 index 0000000..83b3138 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_containers.scss @@ -0,0 +1,41 @@ +// Container widths +// +// Set the container width, and override it for fixed navbars in media queries. + +@if $enable-container-classes { + // Single container class with breakpoint max-widths + .container, + // 100% wide container at all breakpoints + .container-fluid { + @include make-container(); + } + + // Responsive containers that are 100% wide until a breakpoint + @each $breakpoint, $container-max-width in $container-max-widths { + .container-#{$breakpoint} { + @extend .container-fluid; + } + + @include media-breakpoint-up($breakpoint, $grid-breakpoints) { + %responsive-container-#{$breakpoint} { + max-width: $container-max-width; + } + + // Extend each breakpoint which is smaller or equal to the current breakpoint + $extend-breakpoint: true; + + @each $name, $width in $grid-breakpoints { + @if ($extend-breakpoint) { + .container#{breakpoint-infix($name, $grid-breakpoints)} { + @extend %responsive-container-#{$breakpoint}; + } + + // Once the current breakpoint is reached, stop extending + @if ($breakpoint == $name) { + $extend-breakpoint: false; + } + } + } + } + } +} diff --git a/themes/veilid/assets/scss/bootstrap/_dropdown.scss b/themes/veilid/assets/scss/bootstrap/_dropdown.scss new file mode 100644 index 0000000..587ebb4 --- /dev/null +++ b/themes/veilid/assets/scss/bootstrap/_dropdown.scss @@ -0,0 +1,250 @@ +// The dropdown wrapper (`
`) +.dropup, +.dropend, +.dropdown, +.dropstart, +.dropup-center, +.dropdown-center { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; + + // Generate the caret automatically + @include caret(); +} + +// The dropdown menu +.dropdown-menu { + // scss-docs-start dropdown-css-vars + --#{$prefix}dropdown-zindex: #{$zindex-dropdown}; + --#{$prefix}dropdown-min-width: #{$dropdown-min-width}; + --#{$prefix}dropdown-padding-x: #{$dropdown-padding-x}; + --#{$prefix}dropdown-padding-y: #{$dropdown-padding-y}; + --#{$prefix}dropdown-spacer: #{$dropdown-spacer}; + @include rfs($dropdown-font-size, --#{$prefix}dropdown-font-size); + --#{$prefix}dropdown-color: #{$dropdown-color}; + --#{$prefix}dropdown-bg: #{$dropdown-bg}; + --#{$prefix}dropdown-border-color: #{$dropdown-border-color}; + --#{$prefix}dropdown-border-radius: #{$dropdown-border-radius}; + --#{$prefix}dropdown-border-width: #{$dropdown-border-width}; + --#{$prefix}dropdown-inner-border-radius: #{$dropdown-inner-border-radius}; + --#{$prefix}dropdown-divider-bg: #{$dropdown-divider-bg}; + --#{$prefix}dropdown-divider-margin-y: #{$dropdown-divider-margin-y}; + --#{$prefix}dropdown-box-shadow: #{$dropdown-box-shadow}; + --#{$prefix}dropdown-link-color: #{$dropdown-link-color}; + --#{$prefix}dropdown-link-hover-color: #{$dropdown-link-hover-color}; + --#{$prefix}dropdown-link-hover-bg: #{$dropdown-link-hover-bg}; + --#{$prefix}dropdown-link-active-color: #{$dropdown-link-active-color}; + --#{$prefix}dropdown-link-active-bg: #{$dropdown-link-active-bg}; + --#{$prefix}dropdown-link-disabled-color: #{$dropdown-link-disabled-color}; + --#{$prefix}dropdown-item-padding-x: #{$dropdown-item-padding-x}; + --#{$prefix}dropdown-item-padding-y: #{$dropdown-item-padding-y}; + --#{$prefix}dropdown-header-color: #{$dropdown-header-color}; + --#{$prefix}dropdown-header-padding-x: #{$dropdown-header-padding-x}; + --#{$prefix}dropdown-header-padding-y: #{$dropdown-header-padding-y}; + // scss-docs-end dropdown-css-vars + + position: absolute; + z-index: var(--#{$prefix}dropdown-zindex); + display: none; // none by default, but block on "open" of the menu + min-width: var(--#{$prefix}dropdown-min-width); + padding: var(--#{$prefix}dropdown-padding-y) var(--#{$prefix}dropdown-padding-x); + margin: 0; // Override default margin of ul + @include font-size(var(--#{$prefix}dropdown-font-size)); + color: var(--#{$prefix}dropdown-color); + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + list-style: none; + background-color: var(--#{$prefix}dropdown-bg); + background-clip: padding-box; + border: var(--#{$prefix}dropdown-border-width) solid var(--#{$prefix}dropdown-border-color); + @include border-radius(var(--#{$prefix}dropdown-border-radius)); + @include box-shadow(var(--#{$prefix}dropdown-box-shadow)); + + &[data-bs-popper] { + top: 100%; + left: 0; + margin-top: var(--#{$prefix}dropdown-spacer); + } + + @if $dropdown-padding-y == 0 { + > .dropdown-item:first-child, + > li:first-child .dropdown-item { + @include border-top-radius(var(--#{$prefix}dropdown-inner-border-radius)); + } + > .dropdown-item:last-child, + > li:last-child .dropdown-item { + @include border-bottom-radius(var(--#{$prefix}dropdown-inner-border-radius)); + } + + } +} + +// scss-docs-start responsive-breakpoints +// We deliberately hardcode the `bs-` prefix because we check +// this custom property in JS to determine Popper's positioning + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .dropdown-menu#{$infix}-start { + --bs-position: start; + + &[data-bs-popper] { + right: auto; + left: 0; + } + } + + .dropdown-menu#{$infix}-end { + --bs-position: end; + + &[data-bs-popper] { + right: 0; + left: auto; + } + } + } +} +// scss-docs-end responsive-breakpoints + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// Just add .dropup after the standard .dropdown class and you're set. +.dropup { + .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(up); + } +} + +.dropend { + .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(end); + &::after { + vertical-align: 0; + } + } +} + +.dropstart { + .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: var(--#{$prefix}dropdown-spacer); + } + + .dropdown-toggle { + @include caret(start); + &::before { + vertical-align: 0; + } + } +} + + +// Dividers (basically an `
`) within the dropdown +.dropdown-divider { + height: 0; + margin: var(--#{$prefix}dropdown-divider-margin-y) 0; + overflow: hidden; + border-top: 1px solid var(--#{$prefix}dropdown-divider-bg); + opacity: 1; // Revisit in v6 to de-dupe styles that conflict with
element +} + +// Links, buttons, and more within the dropdown menu +// +// `
+ +
+ diff --git a/themes/veilid/layouts/partials/jsonld.js.twig b/themes/veilid/layouts/partials/jsonld.js.twig new file mode 100644 index 0000000..636174a --- /dev/null +++ b/themes/veilid/layouts/partials/jsonld.js.twig @@ -0,0 +1,100 @@ +{% if page.metatags.jsonld|default(site.metatags.jsonld|default(false)) %} + +{%- endif %} \ No newline at end of file diff --git a/themes/veilid/layouts/partials/languages.html.twig b/themes/veilid/layouts/partials/languages.html.twig new file mode 100644 index 0000000..b75ecac --- /dev/null +++ b/themes/veilid/layouts/partials/languages.html.twig @@ -0,0 +1,8 @@ +{#- Language switcher -#} +{%- if page.translations|default({})|length >= 1 -%} + {%- for p in page.translations -%} + {%- if p.language is defined -%} +{{ site.language.name(p.language) }}{% if not loop.last %}, {% endif %} + {%- endif -%} + {%- endfor -%} +{%- endif -%} \ No newline at end of file diff --git a/themes/veilid/layouts/partials/metatags.html.twig b/themes/veilid/layouts/partials/metatags.html.twig new file mode 100644 index 0000000..d3118a6 --- /dev/null +++ b/themes/veilid/layouts/partials/metatags.html.twig @@ -0,0 +1,120 @@ +{# title #} +{% if title is not defined or title is empty %} + {%- set title_divider = page.metatags.title.divider|default(site.metatags.title.divider|default(' · ')) %} + {%- set title_only = page.metatags.title.only|default(site.metatags.title.only|default(false)) %} + {%- set title_pagination_shownumber = page.metatags.title.pagination.shownumber|default(site.metatags.title.pagination.shownumber ?? true) %} + {%- set title_pagination_label = page.metatags.title.pagination.label|default(site.metatags.title.pagination.label|default('Page %s')) %} + {%- set title = page.title|e ~ title_divider ~ site.title|e %} + {%- if title_only %} + {%- set title = page.title|e %} + {%- endif %} + {%- if page.type == 'homepage' %} + {%- set title = site.title|e ~ title_divider ~ site.baseline|default('')|e %} + {%- if title_only or site.baseline|default('') is empty %} + {%- set title = site.title|e %} + {%- endif %} + {%- endif %} + {%- if page.paginator.current|default(0) > 1 %} + {%- if title_pagination_shownumber %} + {%- set title = page.title|e ~ title_divider ~ title_pagination_label|format(page.paginator.current) ~ title_divider ~ site.title|e %} + {%- if title_only %} + {%- set title = page.title|e ~ title_divider ~ title_pagination_label|format(page.paginator.current) %} + {%- endif %} + {%- endif %} + {%- endif %} +{% endif %} +{# description #} +{% set description = page.description|default(site.description)|e %} +{# keywords / tags #} +{% set keywords = page.tags|default([])|merge(site.keywords|default([]))|e %} +{# author #} +{% set author = page.author|default(site.author|default(''))|e %} +{% if author is not empty %} + {%- if author is not iterable %} + {%- set author = {'name': author} %} + {%- endif %} + {%- if author.firstname is defined and author.lastname is defined %} + {%- set author = author|merge({'name': author.firstname|e ~ ' ' ~ author.lastname|e}) %} + {%- endif %} +{% endif %} +{# robots #} +{% set robots = page.metatags.robots|default(site.metatags.robots|default('index,follow')) %} +{% if page.paginator.current|default(0) > 1 %} + {%- set robots = 'noindex,follow' %} +{% endif %} +{# favicon #} +{% if site.metatags.favicon.enabled ?? true %} + {%- set favicon_defaults = { + 'icon': [32, 57, 76, 96, 128, 192, 228], + 'shortcut icon': [196], + 'apple-touch-icon': [120, 152, 180], + } -%} +{% endif %} +{# image #} +{% if image is not defined or image is empty %} + {%- set image = page.image|default(site.image|default()) %} +{% endif %} +{# open graph #} +{% set opengraph = { + 'locale': site.language.locale, + 'site_name': site.title, + 'type': 'website', + 'title': block('title'), + 'description': block('description'), + 'url': url(page, {canonical: true}), +} %} +{% if image %} + {%- if image is not asset %} + {%- set image_asset = asset(image) %} + {%- else %} + {%- set image_asset = image %} + {%- endif %} + {%- set opengraph = opengraph|merge({'image': image_asset|resize(1200)}) %} +{% endif %} +{% if page.section == site.metatags.articles|default('blog') %} + {%- set opengraph = opengraph|merge({'type': 'article'}) %} +{% endif %} +{% if page.opengraph is defined or site.opengraph is defined %} + {%- set opengraph = opengraph|merge(page.opengraph|default(site.opengraph)) %} +{% endif %} + + + {#- template #} + {% block title %}{{ title }}{% endblock %} + +{%- if keywords ~%} + +{%- endif ~%} +{%- if author ~%} + +{%- endif ~%} + +{#- template: favicon ~#} +{%- if site.metatags.favicon.enabled ?? true and asset(site.metatags.favicon.image|default('favicon.png'), {'ignore_missing': true}) is not empty ~%} + {%- for favicon_variant, favicon_sizes in site.metatags.favicon.sizes|default(favicon_defaults) -%} + {%- for size in favicon_sizes ~%} + {%- set favicon_asset = asset(site.metatags.favicon.image|default('favicon.png'), {'ignore_missing': true}) -%} + {%- if not favicon_asset.missing ~%} + + {%- endif -%} + {%- endfor -%} + {%- endfor -%} +{%- endif ~%} +{#- template: alternates ~#} +{%- include 'partials/alternates.html.twig' with {'title': title, 'page': page} only ~%} +{#- template: alternates languages ~#} +{%- include 'partials/alternates-languages.html.twig' with {'page': page} only ~%} +{#- template: Open Graph ~#} + + + + + + +{%- if opengraph.image is defined ~%} + + + + + +{%- endif -%} \ No newline at end of file diff --git a/themes/veilid/layouts/partials/navigation.html.twig b/themes/veilid/layouts/partials/navigation.html.twig new file mode 100644 index 0000000..4ee78cf --- /dev/null +++ b/themes/veilid/layouts/partials/navigation.html.twig @@ -0,0 +1,9 @@ + {%- if menu|length > 1 ~%} + + {%- endif ~%} \ No newline at end of file diff --git a/themes/veilid/layouts/partials/new.css.twig b/themes/veilid/layouts/partials/new.css.twig new file mode 100644 index 0000000..f6c6303 --- /dev/null +++ b/themes/veilid/layouts/partials/new.css.twig @@ -0,0 +1,452 @@ + /* source: https://github.com/xz/new.css/blob/80e7107b491b1062193331ae93ff3670c6a2398d/new.css */ + :root { + --nc-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --nc-font-mono: Consolas, monaco, 'Ubuntu Mono', 'Liberation Mono', 'Courier New', Courier, monospace; + + /* Light theme */ + --nc-tx-1: #000000; + --nc-tx-2: #1A1A1A; + --nc-bg-1: #FFFFFF; + --nc-bg-2: #F6F8FA; + --nc-bg-3: #E5E7EB; + --nc-lk-1: #0070F3; + --nc-lk-2: #0366D6; + --nc-lk-tx: #FFFFFF; + --nc-ac-1: #79FFE1; + --nc-ac-tx: #0C4047; + + /* Dark theme */ + --nc-d-tx-1: #ffffff; + --nc-d-tx-2: #eeeeee; + --nc-d-bg-1: #000000; + --nc-d-bg-2: #111111; + --nc-d-bg-3: #222222; + --nc-d-lk-1: #3291FF; + --nc-d-lk-2: #0070F3; + --nc-d-lk-tx: #FFFFFF; + --nc-d-ac-1: #7928CA; + --nc-d-ac-tx: #FFFFFF; + } + + @media (prefers-color-scheme: dark) { + :root { + --nc-tx-1: var(--nc-d-tx-1); + --nc-tx-2: var(--nc-d-tx-2); + --nc-bg-1: var(--nc-d-bg-1); + --nc-bg-2: var(--nc-d-bg-2); + --nc-bg-3: var(--nc-d-bg-3); + --nc-lk-1: var(--nc-d-lk-1); + --nc-lk-2: var(--nc-d-lk-2); + --nc-lk-tx: var(--nc--dlk-tx); + --nc-ac-1: var(--nc-d-ac-1); + --nc-ac-tx: var(--nc--dac-tx); + } + } + + * { + /* Reset margins and padding */ + margin: 0; + padding: 0; + } + + address, + area, + article, + aside, + audio, + blockquote, + datalist, + details, + dl, + fieldset, + figure, + form, + input, + iframe, + img, + meter, + nav, + ol, + optgroup, + option, + output, + p, + pre, + progress, + ruby, + section, + table, + textarea, + ul, + video { + /* Margins for most elements */ + margin-bottom: 1rem; + } + + html,input,select,button { + /* Set body font family and some finicky elements */ + font-family: var(--nc-font-sans); + } + + body { + /* Center body in page */ + margin: 0 auto; + max-width: 750px; + padding: 2rem; + border-radius: 6px; + overflow-x: hidden; + word-break: break-word; + overflow-wrap: break-word; + background: var(--nc-bg-1); + + /* Main body text */ + color: var(--nc-tx-2); + font-size: 1.03rem; + line-height: 1.5; + } + + ::selection { + /* Set background color for selected text */ + background: var(--nc-ac-1); + color: var(--nc-ac-tx); + } + + h1,h2,h3,h4,h5,h6 { + line-height: 1; + color: var(--nc-tx-1); + padding-top: .875rem; + } + + h1, + h2, + h3 { + color: var(--nc-tx-1); + padding-bottom: 2px; + margin-bottom: 8px; + border-bottom: 1px solid var(--nc-bg-2); + } + + h4, + h5, + h6 { + margin-bottom: .3rem; + } + + h1 { + font-size: 2.25rem; + } + + h2 { + font-size: 1.85rem; + } + + h3 { + font-size: 1.55rem; + } + + h4 { + font-size: 1.25rem; + } + + h5 { + font-size: 1rem; + } + + h6 { + font-size: .875rem; + } + + a { + color: var(--nc-lk-1); + } + + a:hover { + color: var(--nc-lk-2); + } + + abbr:hover { + /* Set the '?' cursor while hovering an abbreviation */ + cursor: help; + } + + blockquote { + padding: 1.5rem; + background: var(--nc-bg-2); + border-left: 5px solid var(--nc-bg-3); + } + + abbr { + cursor: help; + } + + blockquote *:last-child { + padding-bottom: 0; + margin-bottom: 0; + } + + header { + background: var(--nc-bg-2); + border-bottom: 1px solid var(--nc-bg-3); + padding: 2rem 1.5rem; + + /* This sets the right and left margins to cancel out the body's margins. It's width is still the same, but the background stretches across the page's width. */ + + margin: -2rem calc(50% - 50vw) 2rem; + + /* Shorthand for: + + margin-top: -2rem; + margin-bottom: 2rem; + + margin-left: calc(50% - 50vw); + margin-right: calc(50% - 50vw); */ + + padding-left: calc(50vw - 50%); + padding-right: calc(50vw - 50%); + } + + header h1, + header h2, + header h3 { + padding-bottom: 0; + border-bottom: 0; + } + + header > *:first-child { + margin-top: 0; + padding-top: 0; + } + + header > *:last-child { + margin-bottom: 0; + } + + a button, + button, + input[type="submit"], + input[type="reset"], + input[type="button"] { + font-size: 1rem; + display: inline-block; + padding: 6px 12px; + text-align: center; + text-decoration: none; + white-space: nowrap; + background: var(--nc-lk-1); + color: var(--nc-lk-tx); + border: 0; + border-radius: 4px; + box-sizing: border-box; + cursor: pointer; + color: var(--nc-lk-tx); + } + + a button[disabled], + button[disabled], + input[type="submit"][disabled], + input[type="reset"][disabled], + input[type="button"][disabled] { + cursor: default; + opacity: .5; + + /* Set the [X] cursor while hovering a disabled link */ + cursor: not-allowed; + } + + .button:focus, + .button:enabled:hover, + button:focus, + button:enabled:hover, + input[type="submit"]:focus, + input[type="submit"]:enabled:hover, + input[type="reset"]:focus, + input[type="reset"]:enabled:hover, + input[type="button"]:focus, + input[type="button"]:enabled:hover { + background: var(--nc-lk-2); + } + + a img { + margin-bottom: 0px; + } + + code, + pre, + kbd, + samp { + /* Set the font family for monospaced elements */ + font-family: var(--nc-font-mono); + } + + code, + samp, + kbd, + pre { + /* The main preformatted style. This is changed slightly across different cases. */ + background: var(--nc-bg-2); + border: 1px solid var(--nc-bg-3); + border-radius: 4px; + padding: 3px 6px; + /* ↓ font-size is relative to containing element, so it scales for titles*/ + font-size: 0.9em; + } + + kbd { + /* Makes the kbd element look like a keyboard key */ + border-bottom: 3px solid var(--nc-bg-3); + } + + pre { + padding: 1rem 1.4rem; + max-width: 100%; + overflow: auto; + } + + pre code { + /* When is in a
, reset it's formatting to blend in */
+        background: inherit;
+        font-size: inherit;
+        color: inherit;
+        border: 0;
+        padding: 0;
+        margin: 0;
+      }
+
+      code pre {
+        /* When 
 is in a , reset it's formatting to blend in */
+        display: inline;
+        background: inherit;
+        font-size: inherit;
+        color: inherit;
+        border: 0;
+        padding: 0;
+        margin: 0;
+      }
+
+      details {
+        /* Make the 
look more "clickable" */ + padding: .6rem 1rem; + background: var(--nc-bg-2); + border: 1px solid var(--nc-bg-3); + border-radius: 4px; + } + + summary { + /* Makes the look more like a "clickable" link with the pointer cursor */ + cursor: pointer; + font-weight: bold; + } + + details[open] { + /* Adjust the
padding while open */ + padding-bottom: .75rem; + } + + details[open] summary { + /* Adjust the
padding while open */ + margin-bottom: 6px; + } + + details[open]>*:last-child { + /* Resets the bottom margin of the last element in the
while
is opened. This prevents double margins/paddings. */ + margin-bottom: 0; + } + + dt { + font-weight: bold; + } + + dd::before { + /* Add an arrow to data table definitions */ + content: '→ '; + } + + hr { + /* Reset the border of the
separator, then set a better line */ + border: 0; + border-bottom: 1px solid var(--nc-bg-3); + margin: 1rem auto; + } + + fieldset { + margin-top: 1rem; + padding: 2rem; + border: 1px solid var(--nc-bg-3); + border-radius: 4px; + } + + legend { + padding: auto .5rem; + } + + table { + /* border-collapse sets the table's elements to share borders, rather than floating as separate "boxes". */ + border-collapse: collapse; + width: 100% + } + + td, + th { + border: 1px solid var(--nc-bg-3); + text-align: left; + padding: .5rem; + } + + th { + background: var(--nc-bg-2); + } + + tr:nth-child(even) { + /* Set every other cell slightly darker. Improves readability. */ + background: var(--nc-bg-2); + } + + table caption { + font-weight: bold; + margin-bottom: .5rem; + } + + textarea { + /* Don't let the ",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Me(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return R(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return R(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0 + + \ No newline at end of file