Qubasa-main (#17)
All checks were successful
check / test (push) Successful in 5s
deploy / test (push) Successful in 4s

Added The Vision paragraph and added a new logo, improved theme switching. Minor changes in Overview paragraph
This commit is contained in:
Luis Hebendanz 2023-09-04 13:53:20 +00:00
parent d570d91e3c
commit 278509165d
18 changed files with 401 additions and 29 deletions

View File

@ -127,6 +127,6 @@ url = "/privacy-policy/"
weight = 10
[[extra.footer.nav]]
name = "Overview"
url = "/docs/overview"
name = "The Vision"
url = "/docs/thevision"
weight = 20

View File

@ -3,8 +3,8 @@ title = "Build your own"
# The homepage contents
[extra]
lead = '<img src="/logo.png" width="100px" height="100px" alt="cLAN logo"></img> <br><b>cLAN</b> envisions a new model for a decentralized network, designed to provide families, smaller groups, and small businesses a platform thats private, secure, and user-friendly. '
url = "/docs/getting-started/introduction/"
lead = '<img src="/logo/clan-dark.png" class="clogo" width="100px" height="100px" alt="cLAN logo"></img> <br><b>cLAN</b> envisions a new model for a decentralized network, designed to provide families, smaller groups, and small businesses a platform thats private, secure, and user-friendly. '
url = "/docs/thevision/"
url_button = "Learn more"
repo_version = "cLAN v0.0.0-alpha"
repo_license = "Open-source MIT License."
@ -14,7 +14,7 @@ repo_url = "https://git.clan.lol/clan/"
[[extra.menu.main]]
name = "Docs"
section = "docs"
url = "/docs/overview"
url = "/docs/thevision"
weight = 10
[[extra.menu.main]]
@ -23,6 +23,8 @@ section = "blog"
url = "/blog/"
weight = 20
[[extra.list]]
title = "Easy to use"
content = 'cLAN provides a user-friendly interface that allows you to establish your own private network, complete with services.'

View File

@ -1,8 +1,8 @@
+++
title = "Hello World"
title = "The Beginning"
description = "Introducing cLAN, a new model for a decentralized network, designed to provide families, smaller groups, and small businesses a platform thats private, secure, and user-friendly."
date = 2021-05-01T09:19:42+00:00
updated = 2021-05-01T09:19:42+00:00
date = 2023-05-01T09:19:42+00:00
updated = 2023-05-01T09:19:42+00:00
draft = false
template = "blog/page.html"
@ -10,6 +10,6 @@ template = "blog/page.html"
authors = ["Mic92"]
[extra]
lead = "A blog post introducing the project."
lead = "Introducing cLAN,"
+++
Some more text
a new model for a decentralized network, designed to provide families, smaller groups, and small businesses a platform that's self hosted while pertaining the commodities of a cloud infrastructure.

View File

@ -1,5 +1,5 @@
+++
title = "Overview"
title = "Technial Overview"
description = "Overview of cLAN's architecture, components and security"
date = 2021-05-01T18:10:00+00:00
updated = 2021-07-13T18:10:00+00:00
@ -15,11 +15,10 @@ top = false
+++
# cLAN
### cLAN
cLAN envisions a new model for a decentralized network, designed to provide families, smaller groups, and small businesses a platform that's private, secure, and user-friendly. The system transcends the conventional reliance on centralized services, allowing for direct, end-to-end encrypted communication among users. Rooted in open-source software, cLAN ensures no vendor lock-in, and introduces robust features including remote management, backup functionality, user-friendly app store, and fleet management for small businesses.
## Architecture Overview
### Decentralized Network Model
@ -151,8 +150,8 @@ This modules would be build by the VM controller into a system with the followin
inputs.myNetworkFlake.nixosModules.default
./local-overrides.nix
];
}
}
};
};
}
```
@ -192,9 +191,9 @@ configs.json
}
```
A crude example of how this interface would look like
<img width="100%" src="flake_controller_new.png" alt="VM Manager New Network">
<!-- A crude example of how this interface would look like
<img width="100%" src="flake_controller_new.png" alt="VM Manager New Network">
-->
### VM Manager
@ -259,7 +258,6 @@ Our safeguards will include virtual machine isolation to mitigate the damage an
To address this, we only offer a limited set of options in our high-level modules, which either restrict or issue warnings for configurations deemed to be unsafe.
For instance, services are exposed exclusively to the internal network and not to the wider internet, thereby offering an extra layer of security.
TODO: Threats that are out-of-scope
### Trusted compute base

View File

@ -0,0 +1,42 @@
+++
title = "The Vision"
description = "The General Vision of this Project"
date = 2021-05-01T19:30:00+00:00
updated = 2021-05-01T19:30:00+00:00
draft = false
weight = 30
sort_by = "weight"
paginator.next = "docs/overview/index.md"
template = "docs/page.html"
+++
In this context, our vision defines how we envision the behavior of the final product and how users will interact with it. cLAN aims to offer a compelling alternative to the ever-increasing centralization of the internet.
### Decentralized Networking
Instead of relying on a centralized cloud accessible via the clearnet, our objective is to establish an encrypted network of interconnected computers, essentially creating a decentralized darknet, which we affectionately call a cLAN.
### Seamless Onboarding
Our vision includes providing users with a seamless experience when they join one or multiple cLANs through invitation links. Clicking the link will trigger a popup that seeks confirmation to connect to the network.
### Effortless VM Integration
During the joining process, the user's computer (referred to as the client hereafter) will download a file containing information about a virtual machine (VM). The client will then automatically set up the VM, and once complete, this VM will become part of the cLAN.
Users can also choose to seamlessly integrate the cLAN configuration into their base system, effectively allowing the cLAN admin(s) to remotely manage their system.
### Dashboard for Services
Once connected, users will have access to a dashboard displaying all the services offered within this specific cLAN. Within this dashboard, users can effortlessly add applications or decide to host services for fellow cLAN members, such as a Nextcloud instance or backup endpoints.
### Decentralization and Redundancy
The core idea is to ensure service decentralization without a single point of failure. If one service fails, another machine within the cLAN network can spin up a replacement service. VMs are designed to be lightweight, minimizing resource consumption.
### Administrative Control
Within a cLAN, administrators define the configuration file and have control over who becomes part of the network.
Go to [Technical Overview](@/docs/overview/index.md) to see more indepth details of our work.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/logo/clan-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
static/logo/clan-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

264
templates/macros/head.html Normal file
View File

@ -0,0 +1,264 @@
{% macro resource() %}
<link rel="preload" as="font" href="{{ get_url(path="fonts/vendor/jost/jost-v4-latin-regular.woff2") | safe }}" type="font/woff2" crossorigin>
<link rel="preload" as="font" href="{{ get_url(path="fonts/vendor/jost/jost-v4-latin-700.woff2") | safe }}" type="font/woff2" crossorigin>
{% endmacro %}
{% macro stylesheet() %}
<link rel="stylesheet" href="{{ get_url(path="main.css") | safe }}">
{% endmacro %}
{% macro favicons() %}
<meta name="theme-color" content="{{ config.extra.theme_color | default(value="#fff") }}">
<link class="favicon" rel="apple-touch-icon" sizes="180x180" href="{{ get_url(path="dark-favicon/128x128.png") | safe }}">
<link class="favicon" rel="icon" type="image/png" sizes="32x32" href="{{ get_url(path="dark-favicon/32x32.png") | safe }}">
<link class="favicon" rel="icon" type="image/png" sizes="16x16" href="{{ get_url(path="dark-favicon/16x16.png") | safe }}">
{% if not config.extra.is_netlify %}
<link rel="manifest" href="{{ get_url(path="site.webmanifest") | safe }}" crossorigin>
{% endif %}
{% endmacro %}
{# type: website or article, generally setting article for blog articles #}
{# page_images: using for the blog single template page #}
{# page_section: the blog single template page have to pass the parameter #}
{# is_404: using for the 404.html template #}
{% macro seo(
title="",
title_addition="",
description="",
type="website",
is_home=false,
is_404=false,
is_page=false,
page_images="",
page_section="",
created_time="2021-05-01T08:08:00+08:00",
updated_time="2021-05-01T08:08:08+08:00"
)
%}
{% if is_404 %}
<meta name="robots" content="noindex, follow">
{% else %}
<meta name="robots" content="index, follow">
<meta name="googlebot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
<meta name="bingbot" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
{% endif %}
{% if current_url %}
{% set page_url = current_url %}
{% else %}
{% set page_url = get_url(path="404.html") %}
{% endif %}
{% if current_path %}
{% set page_path = current_path %}
{% else %}
{% set page_path = "/404.html" %}
{% endif %}
<title>{{ title ~ title_addition }}</title>
<meta name="description" content="{{ description }}">
<link rel="canonical" href="{{ page_url | safe }}">
{% if config.extra.open.enable %}
<meta name="twitter:card" content="summary_large_image">
{% if page.extra.images %}
{% for image in page.extra.images %}
<meta property="twitter:image" content="{{ get_url(path=image) | safe }}">
{% endfor %}
{% elif section.extra.images %}
{% for image in section.extra.images %}
<meta property="twitter:image" content="{{ get_url(path=image) | safe }}">
{% endfor %}
{% elif config.extra.open.image %}
<meta name="twitter:image" content="{{ config.base_url | safe }}/{{ config.extra.open.image }}">
{% endif %}
<meta name="twitter:title" content="{{ title }}">
<meta name="twitter:description" content="{{ description }}">
<meta name="twitter:site" content="@{{ config.extra.open.twitter_site }}">
<meta name="twitter:creator" content="@{{ config.extra.open.twitter_creator }}">
<meta property="og:title" content="{{ title }}">
<meta property="og:description" content="{{ description }}">
<meta property="og:type" content="{{ type }}">
<meta property="og:url" content="{{ page_url | safe }}">
{% if page.extra.images %}
{% for image in page.extra.images %}
<meta property="og:image" content="{{ get_url(path=image) | safe }}">
{% endfor %}
{% elif section.extra.images %}
{% for image in section.extra.images %}
<meta property="og:image" content="{{ get_url(path=image) | safe }}">
{% endfor %}
{% elif config.extra.open.image %}
<meta property="og:image" content="{{ config.base_url | safe }}/{{ config.extra.open.image }}">
{% endif %}
<meta property="og:updated_time" content="{{ updated_time }}">
<meta property="og:site_name" content="{{ title }}">
{% if config.extra.open.audio %}
<meta property="og:audio" content="{{ config.extra.open.audio }}">
{% endif %}
{% if config.extra.open.locale %}
<meta property="og:locale" content="{{ config.extra.open.locale }}">
{% endif %}
{% if config.extra.open.videos %}
{% for video in config.extra.open.videos %}
<meta property="og:video" content="{{ get_url(path=video) }}">
{% endfor %}
{% endif %}
<meta property="article:publisher" content="https://www.facebook.com/{{ config.extra.open.facebook_publisher }}">
<meta property="article:author" content="https://www.facebook.com/{{ config.extra.open.facebook_author }}">
<meta property="og:locale" content="{{ config.extra.open.og_locale }}">
{% endif %}
{% if is_home and config.extra.schema %}
{% if config.extra.schema.type == "Organization" %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"url": "{{ page_path | safe }}",
"name": "{{ title }}",
"logo": "{{ page_path | safe }}{{ config.extra.schema.logo }}",
"sameAs": [
{% if config.extra.schema.twitter %}"{{ config.extra.schema.twitter | safe }}",{% endif %}
{% if config.extra.schema.linked_in %}"{{ config.extra.schema.linked_in | safe }}",{% endif %}
{% if config.extra.schema.github %}"{{ config.extra.schema.github | safe }}"{% endif %}
]
}
</script>
{% endif %}
{% if config.extra.schema.type == "Person" %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"url": "{{ page_path | safe }}",
"name": "{{ title }}",
"sameAs": [
{% if config.extra.schema.twitter %}"{{ config.extra.schema.twitter | safe }}",{% endif %}
{% if config.extra.schema.linked_in %}"{{ config.extra.schema.linked_in | safe }}",{% endif %}
{% if config.extra.schema.github %}"{{ config.extra.schema.github | safe }}"{% endif %}
]
}
</script>
{% endif %}
{% if config.extra.schema.site_links_search_box %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"url": "{{ page_path | safe }}",
"potentialAction": {
"@type": "SearchAction",
"target": "{{ page_path | safe }}?q={search_term_string}",
"query-input": "required name=search_term_string"
}
}
</script>
{% endif %}
{% endif %}
{% if is_page and config.extra.schema.section %}
{% if config.extra.schema.section == page_section %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{{ page_path | safe }}"
},
"headline": "{{ title }}",
"image": {{ page_images }},
"datePublished": "{{ created_time }}",
"dateModified": "{{ updated_time }}",
"author": {
"@type": "{{ config.extra.schema.type }}",
"name": "{{ title }}"
},
"publisher": {
"@type": "{{ config.extra.schema.type }}",
"name": "{{ title }}",
{% if config.extra.schema.type == "Organization" %}
"logo": {
"@type": "ImageObject",
"url": "{{ get_url(path=config.extra.schema.logo) | replace(from=config.base_url, to="") | safe }}"
}
{% endif %}
},
"description": "{{ description }}"
}
</script>
{% endif %}
{% endif %}
{% set url_prefix = get_url(path="/") | split(pat="://") | first %}
{% set url_main = get_url(path="/") | split(pat="://") | last %}
{% set url_item = url_prefix ~ "://" ~ url_main ~ "/" %}
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "BreadcrumbList",
{% if page_path == "/" %}
{
"@type": "ListItem",
"position": 1 ,
"name": "Home",
"item": "{{ url_item | safe }}"
},
{% else %}
{% set paths = page_path | trim_start_matches(pat="/") | trim_end_matches(pat="/") | split(pat="/") %}
{% for val in paths %}
{% set name_array = val | split(pat="-") %}
{% set_global str = "" %}
{% for val in name_array %}
{% set cap_val = val | capitalize %}
{% set_global str = str ~ cap_val ~ " " %}
{% endfor %}
{% set name = str | trim_end_matches(pat=" ") | title %}
{% if not index %}
{
"@type": "ListItem",
"position": 1 ,
"name": "Home",
"item": "{{ url_item | safe }}"
},
{% set_global index = 2 %}
{% set_global url_item = url_item ~ val ~ "/" %}
{
"@type": "ListItem",
"position": {{ index }} ,
"name": "{{ name }}",
"item": "{{ url_item | safe }}"
},
{% else %}
{% set_global index = index + 1 %}
{% set_global url_item = url_item ~ val ~ "/" %}
{
"@type": "ListItem",
"position": {{ index }} ,
"name": "{{ name }}",
"item": "{{ url_item | safe }}"
},
{% endif %}
{% endfor %}
{% endif %}
}
</script>
{% if config.extra.ganalytics %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{config.extra.ganalytics}}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{config.extra.ganalytics}}');
</script>
{% endif %}
{% endmacro %}

View File

@ -1,14 +1,80 @@
// Set darkmode
document.getElementById('mode').addEventListener('click', () => {
document.body.classList.toggle('dark');
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
let isDarkTheme = document.body.classList.contains('dark');
setColorTheme(!isDarkTheme ? "dark" : "light");
});
// enforce local storage setting but also fallback to user-agent preferences
if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
document.body.classList.add('dark');
let preferDarkTheme = prefersDarkMode();
let theme = localStorage.getItem('theme');
if (theme !== null) {
setColorTheme(theme);
} else {
setColorTheme(preferDarkTheme ? "dark" : "light");
}
// Get the media query list object for the prefers-color-scheme media feature
const colorSchemeQueryList = window.matchMedia("(prefers-color-scheme: dark)");
// Add an event listener for the change event
colorSchemeQueryList.addEventListener("change", handleColorSchemeChange);
function setColorTheme(theme) {
if (theme === "dark") {
document.body.classList.add('dark');
switchClanLogo("white");
localStorage.setItem('theme', 'dark');
} else {
document.body.classList.remove('dark');
switchClanLogo("dark");
localStorage.setItem('theme', 'light');
}
}
// A function that returns true if the user prefers dark mode, false otherwise
function prefersDarkMode() {
// Check if the browser supports the prefers-color-scheme media query
if (window.matchMedia) {
// Get the current value of the media query
let colorScheme = window.matchMedia("(prefers-color-scheme: dark)");
// Return true if the media query matches, false otherwise
return colorScheme.matches;
} else {
// If the browser does not support the media query, return false by default
return false;
}
}
function switchClanLogo(theme) {
let favs = document.getElementsByClassName("favicon");
for (item of favs) {
if (theme === "white")
{
item.href = item.href.replace("dark-favicon", "white-favicon")
} else {
item.href = item.href.replace("white-favicon", "dark-favicon")
}
}
let clogos = document.getElementsByClassName("clogo");
for (item of clogos) {
if (theme === "white")
{
item.src = item.src.replace("dark", "white")
} else {
item.src = item.src.replace("white", "dark")
}
}
}
// A function that executes some logic based on the color scheme preference
function handleColorSchemeChange(e) {
if (e.matches) {
// The user prefers dark mode
setColorTheme("dark");
} else {
// The user prefers light mode
setColorTheme("light");
}
}