@networkpro/web 1.5.0 β†’ 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,116 +1,208 @@
1
- <!-- =========================================================================
2
- README.md
1
+ # 🌐 Network Pro β€” Web Presence
3
2
 
4
- SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
- This file is part of Network Pro.
6
- ========================================================================== -->
3
+ > **Locking Down Networks, Unlocking Confidenceβ„’**
4
+ > _Security, Networking, Privacy β€” Network Proβ„’_
7
5
 
8
- <!--
9
- Copyright Β© 2025 Network Pro Strategies (Network Pro)
6
+ &nbsp;
10
7
 
11
- ---
8
+ ## πŸš€ Project Overview
9
+
10
+ This is the official web presence for **[Network Pro Strategies](https://netwk.pro/about)**, a privacy-forward consultancy specializing in network engineering, information security, and public advocacy focused on cybersecurity and digital privacy.
11
+
12
+ Built with [SvelteKit](https://kit.svelte.dev/) and deployed via [Netlify](https://www.netlify.com/).
13
+ Blog and documentation subsites built with [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) and deployed via [GitHub Pages](https://pages.github.com/).
14
+ All infrastructure and data flows are designed with **maximum transparency, self-hosting, and user privacy** in mind.
15
+
16
+ ### πŸ“ Repository Structure
12
17
 
13
- I. Creative Commons Attribution 4.0 International
18
+ ```bash
19
+ .
20
+ β”œβ”€β”€ src/
21
+ β”‚ β”œβ”€β”€ lib/ # Reusable components, styles, utilities
22
+ β”‚ β”œβ”€β”€ routes/ # SvelteKit routes (+page.svelte, +page.server.js)
23
+ β”‚ β”œβ”€β”€ hooks.client.ts # Client-only lifecycle hooks (e.g., SW control)
24
+ β”‚ └── app.html # SvelteKit entry HTML with CSP/meta/bootstrap
25
+ β”œβ”€β”€ tests/ # Vitest test suites
26
+ β”œβ”€β”€ public/ # Static assets served at root
27
+ β”œβ”€β”€ netlify.toml # Netlify configuration
28
+ β”œβ”€β”€ .github/ # CI workflows and automation
29
+ └── ...
30
+ ```
14
31
 
15
- Network Pro (the "Licensed Material") is licensed under Creative Commons Attribution 4.0 International ("CC BY 4.0"). To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/.
32
+ &nbsp;
33
+
34
+ ## πŸ›  Getting Started
35
+
36
+ ### πŸ“¦ Environment Setup
16
37
 
17
- Per the terms of the License, you are free to distribute, remix, adapt, and build upon the Licensed Material for any purpose, even commercially. You must give appropriate credit, provide a link to the License, and indicate if changes were made.
38
+ ```bash
39
+ git clone https://github.com/netwk-pro/netwk-pro.github.io.git
40
+ cd netwk-pro.github.io
41
+ cp .env.template .env
42
+ npm install
43
+ ```
18
44
 
19
- The Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable.
45
+ Edit .env to configure your environment mode:
20
46
 
21
- Permissions beyond the scope of this Licenseβ€”or instead of those permitted by this Licenseβ€”may be available as further defined within this document.
47
+ ```env
48
+ ENV_MODE=dev # Options: dev, test, ci, preview, prod
49
+ ```
22
50
 
23
- SPDX Reference: https://spdx.org/licenses/CC-BY-4.0.html
24
- Canonical URL: https://creativecommons.org/licenses/by/4.0/
51
+ > ENV*MODE is used for tooling and workflows β€” not by SvelteKit itself.
52
+ > Use VITE*-prefixed env variables for runtime values.
53
+
54
+ &nbsp;
55
+
56
+ ### πŸ“ Node.js Version Management
57
+
58
+ This repo uses .nvmrc and .node-version for version consistency with tools like:
59
+
60
+ - nvm
61
+ - asdf
62
+ - Volta
63
+ - GitHub Actions
64
+
65
+ ```bash
66
+ node -v # Should match "engines" in package.json
67
+ npm -v
68
+ ```
69
+
70
+ &nbsp;
25
71
 
26
72
  ---
27
73
 
28
- II. GNU General Public License
74
+ &nbsp;
29
75
 
30
- Network Pro is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License ("GNU GPL") as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
76
+ ## πŸ“œ Available Scripts
31
77
 
32
- This material is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33
- FITNESS FOR A PARTICULAR PURPOSE.
78
+ The following CLI commands are available via `npm run <script>` or `pnpm run <script>`.
34
79
 
35
- See the GNU General Public License for more details.
80
+ ### πŸ”„ Development
36
81
 
37
- SPDX Reference: https://spdx.org/licenses/GPL-3.0-or-later.html
38
- Canonical URL: https://www.gnu.org/licenses/gpl-3.0.html
82
+ | Script | Description |
83
+ | --------------- | ---------------------------------- |
84
+ | `dev` | Start development server with Vite |
85
+ | `preview` | Preview production build locally |
86
+ | `build` | Build the project with Vite |
87
+ | `build:netlify` | Build using Netlify CLI |
88
+ | `css:bundle` | Bundle and minify CSS |
39
89
 
40
90
  ---
41
91
 
42
- Author: Scott Lopez
43
- Email: <contact@neteng.pro>
44
- Web: <https://bio.neteng.pro>
45
- -->
92
+ ### βœ… Pre-check / Sync
46
93
 
47
- <section id="top">
94
+ | Script | Description |
95
+ | ------------- | ------------------------------------------------------------ |
96
+ | `prepare` | Run SvelteKit sync |
97
+ | `check` | Run SvelteKit sync and type check with `svelte-check` |
98
+ | `check:watch` | Watch mode for type checks |
99
+ | `check:node` | Validate Node & NPM versions match package.json `engines` |
100
+ | `checkout` | Full local validation: check versions, test, lint, typecheck |
101
+ | `verify` | Alias for `checkout` |
48
102
 
49
- <sup>[SPDX-License-Identifier](https://spdx.dev/learn/handling-license-info/): `CC-BY-4.0 OR GPL-3.0-or-later`</sup>
103
+ ---
50
104
 
51
- # Network Pro Strategies
105
+ ### 🧹 Cleanup & Maintenance
52
106
 
53
- </section>
107
+ | Script | Description |
108
+ | --------- | ----------------------------------------------- |
109
+ | `delete` | Remove build artifacts and `node_modules` |
110
+ | `clean` | Fully reset environment and reinstall |
111
+ | `upgrade` | Update all dependencies via `npm-check-updates` |
54
112
 
55
- [![Netlify Status](https://api.netlify.com/api/v1/badges/93910633-3fdb-4bb3-a9bf-5d91ccfeebf9/deploy-status)](https://app.netlify.com/projects/networkpro-web/deploys) [![NPM Version](https://img.shields.io/npm/v/%40networkpro%2Fweb?registry_uri=https%3A%2F%2Fregistry.npmjs.com&style=flat&logo=npm&logoSize=auto&color=%23CB3837)](https://www.npmjs.com/package/@networkpro/web) [![Build and Publish to Registries](https://github.com/netwk-pro/netwk-pro.github.io/actions/workflows/build-and-publish.yml/badge.svg)](https://github.com/netwk-pro/netwk-pro.github.io/actions/workflows/build-and-publish.yml)
56
- [![Code Style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat)](https://github.com/prettier/prettier) [![stylelint](https://img.shields.io/badge/stylelint-%23747474?style=flat&logo=stylelint&logoSize=auto&labelColor=%23263238)](https://stylelint.io/)
57
- [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/netwk-pro/netwk-pro.github.io/blob/master/CODE_OF_CONDUCT.md)
113
+ ---
58
114
 
59
- ## Security That Respects You
115
+ ### πŸ§ͺ Testing
60
116
 
61
- At **Network Pro Strategies (Network Pro&trade;)**, we deliver network security, cybersecurity, and digital privacy consulting with clarity, credibility, and care. We believe that real security doesn’t have to come at the cost of user autonomy, and that privacy-minded solutions can be both practical and powerful.
117
+ | Script | Description |
118
+ | --------------- | -------------------------------------------- |
119
+ | `test` | Alias for `test:all` |
120
+ | `test:all` | Run both client and server test suites |
121
+ | `test:client` | Run client tests with Vitest |
122
+ | `test:server` | Run server-side tests with Vitest |
123
+ | `test:watch` | Watch mode for client tests |
124
+ | `test:coverage` | Collect coverage from both client and server |
62
125
 
63
- Our approach is built on a simple principle: **the best security is the one that fits.** That means we don’t push ideologiesβ€”we apply what works. We advocate for and implement **free and open source solutions** where they offer competitive functionality, control, and visibility. When proprietary platforms are better suited, we deploy them responsibly and securelyβ€”ensuring every recommendation is grounded in **technical merit**, **scalability**, and **client goals**.
126
+ ---
64
127
 
65
- ### **What We Do**
128
+ ### 🧼 Linting & Formatting
66
129
 
67
- As a remote-first consultancy, we support clients across industries and geographies with a focus on:
130
+ | Script | Description |
131
+ | ------------ | --------------------------------------- |
132
+ | `lint` | Run ESLint on JS, MJS, and Svelte files |
133
+ | `lint:fix` | Auto-fix ESLint issues |
134
+ | `lint:jsdoc` | Check JSDoc annotations |
135
+ | `lint:css` | Run Stylelint on CSS and Svelte styles |
136
+ | `lint:md` | Lint Markdown content |
137
+ | `lint:all` | Run all linters and formatting checks |
138
+ | `format` | Run Prettier formatting check |
139
+ | `format:fix` | Auto-format code using Prettier |
68
140
 
69
- - **Network Hardening & Perimeter Defense**
70
- - **Firewall Architecture & Policy Optimization**
71
- - **Cloud Security & Zero Trust Implementation**
72
- - **Secure Infrastructure Design & Implementation**
73
- - **Risk Reduction & Security Posture Assessment**
141
+ ---
74
142
 
75
- Our consulting engagements range from tactical one-off solutions to strategic, long-term partnerships. Whether it’s helping a business segment its internal network, lock down its cloud footprint, or plan scalable defensesβ€”we deliver clear value, with zero fluff.
143
+ ### πŸ’‘ Lighthouse / Performance
76
144
 
77
- We also believe education is a core pillar of real-world security. That’s why we invest in raising awarenessβ€”across both technical and general audiencesβ€”on best practices in digital privacy, secure design, and threat mitigation.
145
+ | Script | Description |
146
+ | ------------------ | ----------------------------------------------- |
147
+ | `lhci` | Alias for Lighthouse CI |
148
+ | `lighthouse` | Run local Lighthouse test and launch viewer |
149
+ | `lighthouse:local` | Build site, preview, and run Lighthouse locally |
150
+ | `lhci:run` | Run Lighthouse CI autorun |
78
151
 
79
- **Network Pro&trade; exists to bring strong, thoughtful security to organizations that value integrityβ€”without sacrificing agility or trust.** We don’t just secure infrastructure. We secure confidence.
152
+ ---
80
153
 
81
- &nbsp;
154
+ ### πŸ“‹ Audits / Validation
82
155
 
83
- πŸ”Ή [Let’s connect](https://netwk.pro/contact) to discuss how we can help secure and strengthen your business today.
156
+ | Script | Description |
157
+ | --------------- | -------------------------------------------- |
158
+ | `audit:scripts` | Check for untested utility scripts |
159
+ | `head:flatten` | Flatten headers for Netlify |
160
+ | `head:validate` | Validate headers file against project config |
84
161
 
85
162
  ---
86
163
 
87
- You can find our PGP keys and a vCard containing our contact information for your convenience below.
164
+ ### πŸ”„ Lifecycle Hooks
88
165
 
89
- | <img decoding="sync" loading="eager" src="https://netwk.pro/img/qr/pgp-support.png" width="125px" height="125px" alt="PGP Key - support@neteng.pro"> | **[support@neteng.pro](https://keys.openpgp.org/search?q=support%40neteng.pro)**<br />**PGP Key (ed25519)**<br />&nbsp;<br /><a href="https://raw.githubusercontent.com/netwk-pro/netwk-pro.github.io/refs/heads/master/assets/bin/support@neteng.pro.aexpk" download type="application/pgp-keys">**aexpk**</a>&nbsp; **&#47;** &nbsp;<a href="https://raw.githubusercontent.com/netwk-pro/netwk-pro.github.io/refs/heads/master/assets/bin/support@neteng.pro.asc" download type="application/pgp-keys">**asc**</a><br />&nbsp;<br />6590b992e2e3eff12738<br />7bce2af093e9dec61ba0 |
90
- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
91
- | **[contact@s.neteng.pro](https://keys.openpgp.org/search?q=contact%40s.neteng.pro)**<br />**PGP Key (ed25519)**<br />&nbsp;<br /><a href="https://raw.githubusercontent.com/netwk-pro/netwk-pro.github.io/refs/heads/master/assets/bin/contact@s.neteng.pro.aexpk" download type="application/pgp-keys">**aexpk**</a>&nbsp; **&#47;** &nbsp;<a href="https://raw.githubusercontent.com/netwk-pro/netwk-pro.github.io/refs/heads/master/assets/bin/contact@s.neteng.pro.asc" download type="application/pgp-keys">**asc**</a><br />&nbsp;<br />**df118baa6c2d9dcdebdc**<br />**2ddcf99373499495f957** | <img decoding="async" loading="lazy" src="https://netwk.pro/img/qr/pgp-contact.png" width="125px" height="125px" alt="PGP Key - contact@s.neteng.pro"> |
92
- | <img decoding="async" loading="lazy" src="https://netwk.pro/img/qr/vcard.png" width="125px" height="125px" alt="vCard"> | **vCard**<br />&nbsp;<br /><a href="https://raw.githubusercontent.com/netwk-pro/netwk-pro.github.io/refs/heads/master/assets/bin/contact.vcf" download type="text/vcard">**vcf**</a> |
166
+ | Script | Description |
167
+ | ------------- | ----------------------------------- |
168
+ | `postinstall` | Ensures version check after install |
93
169
 
94
- <sub>[Back to top](#top)</sub>
170
+ &nbsp;
95
171
 
96
172
  ---
97
173
 
98
- <div style="font-size: 12px; font-weight: bold; text-align: center;">
174
+ &nbsp;
99
175
 
100
- [Home](https://netwk.pro) &nbsp; | &nbsp; [Terms of Use](https://netwk.pro/terms-of-use)
101
- [Privacy Policy](https://netwk.pro/privacy-policy) &nbsp; | &nbsp; [Legal](https://netwk.pro/license)
176
+ ## 🧾 License
102
177
 
103
- </div>
178
+ This project is licensed under:
179
+
180
+ - [Creative Commons BY 4.0](https://netwk.pro/license#cc-by)
181
+
182
+ - Or optionally, [GNU GPL v3 or later](https://netwk.pro/license#gnu-gpl)
183
+
184
+ Source code, branding, and visual assets are subject to reuse and distribution terms specified on our [Legal, Copyright, and Licensing page](https://netwk.pro/license).
185
+
186
+ &nbsp;
187
+
188
+ ## πŸ™‹β€β™‚οΈ Questions?
189
+
190
+ Reach out via [netwk.pro/contact](https://netwk.pro/contact), open an issue on this repo, or email us directly at `contact (at) s.neteng.pro`.
104
191
 
105
192
  &nbsp;
106
193
 
107
- <span style="font-size: 12px; text-align: center;">
194
+ _Designed for professionals. Hardened for privacy. Built with intent._
195
+ β€” **Network Pro Strategies**
196
+
197
+ ---
198
+
199
+ <div style="font-size: 12px; text-align: center;">
108
200
 
109
201
  Copyright &copy; 2025
110
- **[Network Pro Strategies](https://netwk.pro/)** (Network Pro&trade;)
202
+ **[Network Pro Strategies](https://netwk.pro) (Network Pro&trade;)**
111
203
 
112
204
  Network Pro&trade;, the shield logo, and the "Locking Down Networks&trade;" slogan are [trademarks](https://netwk.pro/license#trademark) of Network Pro Strategies.
113
205
 
114
- Licensed under **[CC BY 4.0](https://netwk.pro/license#cc-by)** and the **[GNU GPL](https://netwk.pro/license#gnu-gpl)**, as published by the [Free Software Foundation](https://fsf.org), either version 3 of the License, or (at your option) any later version.
206
+ Licensed under **[CC BY 4.0](https://netwk.pro/license#cc-by)** and the **[GNU GPL](https://netwk.pro/license#gnu-gpl)**, as published by the [Free Software Foundation](https://www.fsf.org), either version 3 of the License, or (at your option) any later version.
115
207
 
116
- </span>
208
+ </div>
package/package.json CHANGED
@@ -2,17 +2,18 @@
2
2
  "name": "@networkpro/web",
3
3
  "private": false,
4
4
  "sideEffects": false,
5
- "version": "1.5.0",
5
+ "version": "1.5.1",
6
6
  "description": "Locking Down Networks, Unlocking Confidence | Security, Networking, Privacy β€” Network Pro Strategies",
7
7
  "keywords": [
8
- "security",
9
- "networking",
10
- "privacy",
11
- "cybersecurity",
12
8
  "advisory",
13
9
  "consulting",
14
- "android",
15
- "linux"
10
+ "cybersecurity",
11
+ "networking",
12
+ "privacy",
13
+ "pwa",
14
+ "security",
15
+ "svelte",
16
+ "sveltekit"
16
17
  ],
17
18
  "homepage": "https://netwk.pro",
18
19
  "bugs": {
@@ -84,7 +85,7 @@
84
85
  "postinstall": "npm run check:node"
85
86
  },
86
87
  "dependencies": {
87
- "svelte": "5.31.1"
88
+ "svelte": "5.32.1"
88
89
  },
89
90
  "devDependencies": {
90
91
  "@eslint/compat": "^1.2.9",
@@ -102,7 +103,7 @@
102
103
  "eslint": "^9.27.0",
103
104
  "eslint-config-prettier": "^10.1.5",
104
105
  "eslint-plugin-jsdoc": "^50.6.17",
105
- "eslint-plugin-svelte": "^3.8.2",
106
+ "eslint-plugin-svelte": "^3.9.0",
106
107
  "globals": "^16.1.0",
107
108
  "jsdom": "^26.1.0",
108
109
  "lightningcss": "^1.30.1",
@@ -16,8 +16,8 @@ This file is part of Network Pro.
16
16
 
17
17
  import fs from "fs";
18
18
 
19
- const HEADERS_PATH = "./static/_headers"; // update if needed
20
- const OUTPUT_PATH = "./static/_headers.flattened";
19
+ const HEADERS_PATH = "./.headers_new"; // update if needed
20
+ const OUTPUT_PATH = "./_headers.flattened";
21
21
 
22
22
  const lines = fs.readFileSync(HEADERS_PATH, "utf-8").split("\n");
23
23
  const output = [];
@@ -17,7 +17,7 @@ This file is part of Network Pro.
17
17
  // validate-headers.js
18
18
  import fs from "fs";
19
19
 
20
- const file = "./static/_headers";
20
+ const file = "./_headers";
21
21
  const lines = fs.readFileSync(file, "utf-8").split("\n");
22
22
 
23
23
  let currentPath = null;
package/src/app.html CHANGED
@@ -16,7 +16,7 @@
16
16
  content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
17
17
  <meta name="author" content="Network Pro Strategies" />
18
18
 
19
- <!-- Optional CSP for Dev -->
19
+ <!-- CSP for Dev -->
20
20
  <meta
21
21
  http-equiv="Content-Security-Policy"
22
22
  content="default-src 'self'; script-src 'self' 'unsafe-inline' https://snap.licdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://px.ads.linkedin.com; connect-src 'self' https://px.ads.linkedin.com;" />
@@ -0,0 +1,62 @@
1
+ <!-- ==========================================================================
2
+ src/lib/components/RedirectPage.svelte
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== -->
7
+
8
+ <script>
9
+ import { onMount } from "svelte";
10
+
11
+ export let to;
12
+ export let delay = 3;
13
+
14
+ onMount(() => {
15
+ if (!to) {
16
+ console.warn("β›” No redirect target provided");
17
+ return;
18
+ }
19
+
20
+ console.log("βœ… Starting redirect to:", to);
21
+
22
+ setTimeout(() => {
23
+ window.location.href = to;
24
+ }, delay * 1000);
25
+ });
26
+ </script>
27
+
28
+ <svelte:head>
29
+ <title>Redirecting…</title>
30
+ <meta name="robots" content="noindex, nofollow" />
31
+ </svelte:head>
32
+
33
+ <div class="container">
34
+ <h1>Redirecting…</h1>
35
+ <p>You'll be taken to the destination in just a moment.</p>
36
+ <div class="loading-spinner" aria-hidden="true"></div>
37
+ <p>If nothing happens, <a href={to}>click here</a>.</p>
38
+ </div>
39
+
40
+ <style>
41
+ .loading-spinner {
42
+ width: 48px;
43
+ height: 48px;
44
+ margin: 2rem auto;
45
+ border: 4px solid #ddd;
46
+ animation: spin 1s linear infinite;
47
+ border-radius: 50%;
48
+ border-top: 4px solid #ffc627;
49
+ }
50
+
51
+ @keyframes spin {
52
+ to {
53
+ transform: rotate(360deg);
54
+ }
55
+ }
56
+
57
+ .container {
58
+ text-align: center;
59
+ font-family: system-ui, sans-serif;
60
+ margin-top: 5rem;
61
+ }
62
+ </style>
package/src/lib/meta.js CHANGED
@@ -50,15 +50,7 @@ const meta = {
50
50
  description:
51
51
  "FOSS Spotlight | Security, Networking, Privacy β€” Network Proβ„’",
52
52
  },
53
- "/contact": {
54
- title: "Contact Form β€” Network Proβ„’",
55
- description: "Contact Form | Security, Networking, Privacy β€” Network Proβ„’",
56
- },
57
- "/privacy-rights": {
58
- title: "Privacy Rights Request Form β€” Network Proβ„’",
59
- description:
60
- "Privacy Rights Request Form | Security, Networking, Privacy β€” Network Proβ„’",
61
- },
53
+ // Excludes redirect-only routes like /contact, /consultation, /privacy-rights
62
54
  };
63
55
 
64
56
  /** @type {MetaData} */
@@ -58,7 +58,7 @@ This file is part of Network Pro.
58
58
  */
59
59
  const constants = {
60
60
  company: "Network Pro Strategies",
61
- effectiveDate: "May 8, 2025",
61
+ effectiveDate: "May 21, 2025",
62
62
  classSmall: "small-text",
63
63
  rel: "noopener noreferrer",
64
64
  hrefTop: "#top",
@@ -141,9 +141,10 @@ This file is part of Network Pro.
141
141
  These Terms of Use apply to all platforms associated with the Company,
142
142
  including but not limited to:
143
143
  <strong>
144
- GitHub, our main website (hosted via GitHub Pages), communications on
145
- Discord and/or Slack, Stack Overflow Teams, Nextcloud, and our social
146
- media presence (e.g., Facebook, Instagram, X, and similar platforms).
144
+ GitHub, our main website (hosted via Netlify and GitHub Pages), Stack
145
+ Overflow Teams, Nextcloud, communications on Discord and/or Slack, and
146
+ our social media presence (e.g., Facebook, Instagram, X, and similar
147
+ platforms).
147
148
  </strong>
148
149
  </p>
149
150
  {:else if link.id === "acceptable-use"}
@@ -0,0 +1,17 @@
1
+ /* ==========================================================================
2
+ src/lib/types/metadata.js
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== */
7
+
8
+ /**
9
+ * @typedef {object} MetaData
10
+ * @property {string} title - Page title
11
+ * @property {string} description - Meta description for SEO/social
12
+ * @property {string} [image] - Optional OG image URL
13
+ * @property {string} [url] - Canonical URL
14
+ */
15
+
16
+ // Export types only for JSDoc
17
+ export /** @typedef {import('./metadata.js').MetaData} MetaData */ {};
@@ -0,0 +1,19 @@
1
+ /* ==========================================================================
2
+ src/lib/utils/utm.js
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== */
7
+
8
+ /**
9
+ * Append UTM parameter from window.location to a given URL.
10
+ * Returns `null` if not in a browser context.
11
+ * @param {string} url - The base URL to append to
12
+ * @returns {string | null}
13
+ */
14
+ export function appendUTM(url) {
15
+ if (typeof window === "undefined") return null;
16
+
17
+ const utm = new URLSearchParams(window.location.search).get("utm_source");
18
+ return utm ? `${url}?utm_source=${encodeURIComponent(utm)}` : url;
19
+ }
@@ -0,0 +1,34 @@
1
+ <!-- ==========================================================================
2
+ src/routes/consultation/+page.svelte
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== -->
7
+
8
+ <script>
9
+ import RedirectPage from "$lib/components/RedirectPage.svelte";
10
+ import { appendUTM } from "$lib/utils/utm.js";
11
+ import { onMount } from "svelte";
12
+ import { browser } from "$app/environment";
13
+
14
+ /** @type {string | null} */
15
+ let target = null;
16
+
17
+ /** @type {boolean} */
18
+ let show = false;
19
+
20
+ onMount(() => {
21
+ if (!browser) return;
22
+
23
+ target = appendUTM(
24
+ "https://cloud.neteng.pro/index.php/apps/appointments/pub/8clCqQrt3AtGbNrr/form",
25
+ );
26
+ show = true;
27
+ });
28
+ </script>
29
+
30
+ {#if show && target}
31
+ <RedirectPage to={target} />
32
+ {:else}
33
+ <p style="text-align: center; margin-top: 4rem;">Preparing to redirect…</p>
34
+ {/if}
@@ -0,0 +1,34 @@
1
+ <!-- ==========================================================================
2
+ src/routes/contact/+page.svelte
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== -->
7
+
8
+ <script>
9
+ import RedirectPage from "$lib/components/RedirectPage.svelte";
10
+ import { appendUTM } from "$lib/utils/utm.js";
11
+ import { onMount } from "svelte";
12
+ import { browser } from "$app/environment";
13
+
14
+ /** @type {string | null} */
15
+ let target = null;
16
+
17
+ /** @type {boolean} */
18
+ let show = false;
19
+
20
+ onMount(() => {
21
+ if (!browser) return;
22
+
23
+ target = appendUTM(
24
+ "https://cloud.neteng.pro/index.php/apps/forms/s/nyWEq9fdE7kWAjqMtMySLqJc",
25
+ );
26
+ show = true;
27
+ });
28
+ </script>
29
+
30
+ {#if show && target}
31
+ <RedirectPage to={target} />
32
+ {:else}
33
+ <p style="text-align: center; margin-top: 4rem;">Preparing to redirect…</p>
34
+ {/if}
@@ -0,0 +1,34 @@
1
+ <!-- ==========================================================================
2
+ src/routes/privacy-rights/+page.svelte
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== -->
7
+
8
+ <script>
9
+ import RedirectPage from "$lib/components/RedirectPage.svelte";
10
+ import { appendUTM } from "$lib/utils/utm.js";
11
+ import { onMount } from "svelte";
12
+ import { browser } from "$app/environment";
13
+
14
+ /** @type {string | null} */
15
+ let target = null;
16
+
17
+ /** @type {boolean} */
18
+ let show = false;
19
+
20
+ onMount(() => {
21
+ if (!browser) return;
22
+
23
+ target = appendUTM(
24
+ "https://cloud.neteng.pro/index.php/apps/forms/s/6HpZKZCaLwb6TXYL99nLQM8t",
25
+ );
26
+ show = true;
27
+ });
28
+ </script>
29
+
30
+ {#if show && target}
31
+ <RedirectPage to={target} />
32
+ {:else}
33
+ <p style="text-align: center; margin-top: 4rem;">Preparing to redirect…</p>
34
+ {/if}
@@ -0,0 +1,48 @@
1
+ /* ==========================================================================
2
+ tests/unit/utm.test.js
3
+
4
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
+ This file is part of Network Pro.
6
+ ========================================================================== */
7
+
8
+ import { appendUTM } from "$lib/utils/utm.js";
9
+ import { afterEach, describe, expect, it } from "vitest";
10
+
11
+ describe("appendUTM", () => {
12
+ const originalWindow = globalThis.window;
13
+
14
+ afterEach(() => {
15
+ globalThis.window = originalWindow;
16
+ });
17
+
18
+ it("should return null when not in a browser environment", () => {
19
+ // @ts-expect-error – simulating SSR
20
+ delete globalThis.window;
21
+
22
+ const url = "https://example.com";
23
+ const result = appendUTM(url);
24
+ expect(result).toBe(null);
25
+ });
26
+
27
+ it("should return URL with utm_source appended", () => {
28
+ globalThis.window = {
29
+ // @ts-expect-error – mock minimal window for test
30
+ location: { search: "?utm_source=linkedin" },
31
+ };
32
+
33
+ const url = "https://example.com";
34
+ const result = appendUTM(url);
35
+ expect(result).toBe("https://example.com?utm_source=linkedin");
36
+ });
37
+
38
+ it("should return original URL if no utm_source is present", () => {
39
+ globalThis.window = {
40
+ // @ts-expect-error – mock minimal window for test
41
+ location: { search: "" },
42
+ };
43
+
44
+ const url = "https://example.com";
45
+ const result = appendUTM(url);
46
+ expect(result).toBe("https://example.com");
47
+ });
48
+ });
@@ -1,24 +0,0 @@
1
- /* ==========================================================================
2
- src/routes/contact/+page.server.js
3
-
4
- SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
- This file is part of Network Pro.
6
- ========================================================================== */
7
-
8
- import { redirect } from "@sveltejs/kit";
9
-
10
- export const prerender = false;
11
-
12
- /** @type {import('./$types').PageServerLoad} */
13
- export function load({ url }) {
14
- const utmSource = url.searchParams.get("utm_source");
15
-
16
- // Set target to your actual contact page path
17
- const target =
18
- "https://cloud.neteng.pro/index.php/apps/forms/s/nyWEq9fdE7kWAjqMtMySLqJc";
19
-
20
- // Preserve the tracking parameter
21
- const redirectTo = utmSource ? `${target}?utm_source=${utmSource}` : target;
22
-
23
- throw redirect(302, redirectTo);
24
- }
@@ -1,24 +0,0 @@
1
- /* ==========================================================================
2
- src/routes/privacy-rights/+page.server.js
3
-
4
- SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
- This file is part of Network Pro.
6
- ========================================================================== */
7
-
8
- import { redirect } from "@sveltejs/kit";
9
-
10
- export const prerender = false;
11
-
12
- /** @type {import('./$types').PageServerLoad} */
13
- export function load({ url }) {
14
- const utmSource = url.searchParams.get("utm_source");
15
-
16
- // Set target to your actual privacy rights form path
17
- const target =
18
- "https://cloud.neteng.pro/index.php/apps/forms/s/6HpZKZCaLwb6TXYL99nLQM8t";
19
-
20
- // Preserve the tracking parameter
21
- const redirectTo = utmSource ? `${target}?utm_source=${utmSource}` : target;
22
-
23
- throw redirect(302, redirectTo);
24
- }