diff --git a/web/package.json b/web/package.json
index a93605d..224c1f6 100644
--- a/web/package.json
+++ b/web/package.json
@@ -17,6 +17,7 @@
},
"devDependencies": {
"@builder.io/qwik-city": "^1.1.4",
+ "@types/js-yaml": "^4.0.9",
"@types/node": "^20.11.16",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
diff --git a/web/public/manifest.json b/web/public/manifest.json
index c18e75f..b9c60dc 100644
--- a/web/public/manifest.json
+++ b/web/public/manifest.json
@@ -1,9 +1,9 @@
{
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
- "name": "qwik-project-name",
- "short_name": "Welcome to Qwik",
+ "name": "digital-defense",
+ "short_name": "Digital Defense",
"start_url": ".",
"display": "standalone",
- "background_color": "#fff",
- "description": "A Qwik project app."
+ "background_color": "#5616c6",
+ "description": "The ultimate personal security checklist"
}
diff --git a/web/src/routes/_404.tsx b/web/src/routes/_404.tsx
new file mode 100644
index 0000000..caed421
--- /dev/null
+++ b/web/src/routes/_404.tsx
@@ -0,0 +1,12 @@
+// src/routes/_404.tsx
+import { component$ } from '@builder.io/qwik';
+
+export default component$(() => {
+ return (
+
+ );
+});
diff --git a/web/src/routes/about/index.tsx b/web/src/routes/about/index.tsx
index 1c98238..d905070 100644
--- a/web/src/routes/about/index.tsx
+++ b/web/src/routes/about/index.tsx
@@ -212,11 +212,11 @@ export default component$(() => {
});
export const head: DocumentHead = {
- title: "Welcome to Qwik",
+ title: "About | Digital Defense",
meta: [
{
name: "description",
- content: "Qwik site description",
+ content: "This project aims to give you practical guidance on how to improve your digital security, and protect your privacy online",
},
],
};
diff --git a/web/src/routes/checklist/[title]/index.tsx b/web/src/routes/checklist/[title]/index.tsx
index 9eb9da5..125ce88 100644
--- a/web/src/routes/checklist/[title]/index.tsx
+++ b/web/src/routes/checklist/[title]/index.tsx
@@ -4,17 +4,20 @@ import { marked } from 'marked';
import Icon from '~/components/core/icon';
import { ChecklistContext } from '~/store/checklist-context';
+import { useChecklist } from '~/store/local-checklist-store';
import type { Section } from "~/types/PSC";
import Table from '~/components/psc/checklist-table';
export default component$(() => {
const checklists = useContext(ChecklistContext);
+ const localChecklist = useChecklist();
const loc = useLocation();
const slug = loc.params.title;
- const section: Section | undefined = checklists.value.find((item: Section) => item.slug === slug);
+ const section: Section | undefined = (localChecklist.checklist.checklist || checklists.value)
+ .find((item: Section) => item.slug === slug);
const parseMarkdown = (text: string | undefined): string => {
return marked.parse(text || '', { async: false }) as string || '';
diff --git a/web/src/routes/checklist/index.tsx b/web/src/routes/checklist/index.tsx
index 89941de..dc3e561 100644
--- a/web/src/routes/checklist/index.tsx
+++ b/web/src/routes/checklist/index.tsx
@@ -2,17 +2,19 @@ import { component$, useContext } from "@builder.io/qwik";
import { ChecklistContext } from '~/store/checklist-context';
import { useLocalStorage } from "~/hooks/useLocalStorage";
+import { useChecklist } from '~/store/local-checklist-store';
import type { Section } from "~/types/PSC";
export default component$(() => {
const checklists = useContext(ChecklistContext);
+ const localChecklist = useChecklist();
const [completed, setCompleted] = useLocalStorage('PSC_PROGRESS', {});
return (
- {checklists.value.map((section: Section, index: number) => (
+ {(localChecklist.checklist.checklist || checklists.value).map((section: Section, index: number) => (
diff --git a/web/src/routes/index.tsx b/web/src/routes/index.tsx
index 7cf4083..bf02565 100644
--- a/web/src/routes/index.tsx
+++ b/web/src/routes/index.tsx
@@ -7,14 +7,18 @@ import Progress from "~/components/psc/progress";
import { ChecklistContext } from '~/store/checklist-context';
+import { useChecklist } from '~/store/local-checklist-store';
+
export default component$(() => {
const checklists = useContext(ChecklistContext);
-
+
+ const localChecklist = useChecklist();
+
return (
<>
-
+
>
);
});
diff --git a/web/src/routes/layout.tsx b/web/src/routes/layout.tsx
index a62c907..180d311 100644
--- a/web/src/routes/layout.tsx
+++ b/web/src/routes/layout.tsx
@@ -1,18 +1,16 @@
import { component$, useContextProvider, Slot } from "@builder.io/qwik";
import { routeLoader$, type RequestHandler } from "@builder.io/qwik-city";
-
-import Navbar from "../components/furniture/nav";
-import Footer from "../components/furniture/footer";
-
-import { ChecklistContext } from "../store/checklist-context";
-
-import { type Sections } from "~/types/PSC";
import jsyaml from "js-yaml";
+import Navbar from "~/components/furniture/nav";
+import Footer from "~/components/furniture/footer";
+import { ChecklistContext } from "~/store/checklist-context";
+import type { Sections } from "~/types/PSC";
export const useChecklists = routeLoader$(async () => {
- const url = import.meta.env.DEV ? `http://localhost:5173/personal-security-checklist.yml` : '/personal-security-checklist.yml';
- return await fetch(url)
+ const remoteUrl = 'https://gist.githubusercontent.com/Lissy93/0c26e4255b6fabc2c027ac72a4428aeb/raw/4ccdbc71e0fffdef53472cf98acbe40b0acf982b/personal-security-checklist.yml';
+ // TODO: Update this URL to point to the Git repository
+ return fetch(remoteUrl)
.then((res) => res.text())
.then((res) => jsyaml.load(res) as Sections)
.catch(() => []);
@@ -26,13 +24,11 @@ export const onGet: RequestHandler = async ({ cacheControl }) => {
};
export default component$(() => {
-
const checklists = useChecklists();
- useContextProvider(ChecklistContext, checklists)
+ useContextProvider(ChecklistContext, checklists);
return (
<>
- {/*
*/}
diff --git a/web/src/store/local-checklist-store.ts b/web/src/store/local-checklist-store.ts
new file mode 100644
index 0000000..0aa8fd1
--- /dev/null
+++ b/web/src/store/local-checklist-store.ts
@@ -0,0 +1,29 @@
+
+import { $, useStore, useOnWindow } from '@builder.io/qwik';
+import jsyaml from 'js-yaml';
+import type { Sections } from '~/types/PSC';
+
+export const useChecklist = () => {
+ const state = useStore<{ checklist: Sections | null }>({ checklist: null });
+
+ const fetchChecklist = $(async () => {
+ const localUrl = '/personal-security-checklist.yml';
+ return fetch(localUrl)
+ .then((res) => res.text())
+ .then((yamlText) => {
+ return jsyaml.load(yamlText);
+ });
+ });
+
+ useOnWindow('load', $(() => {
+ fetchChecklist().then((checklist) => {
+ state.checklist = checklist as Sections;
+ });
+ }));
+
+ const setChecklist = $((newChecklist: Sections) => {
+ state.checklist = newChecklist;
+ });
+
+ return { checklist: state, setChecklist };
+};
diff --git a/web/yarn.lock b/web/yarn.lock
index 24150c0..2bfda65 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -656,6 +656,11 @@
dependencies:
"@types/unist" "^2"
+"@types/js-yaml@^4.0.9":
+ version "4.0.9"
+ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2"
+ integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==
+
"@types/json-schema@^7.0.12":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"