This commit is contained in:
4
custom.d.ts
vendored
Normal file
4
custom.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module "*.md" {
|
||||||
|
const value: string;
|
||||||
|
export default value;
|
||||||
|
}
|
@ -19,6 +19,7 @@
|
|||||||
"@xterm/addon-webgl": "^0.18.0",
|
"@xterm/addon-webgl": "^0.18.0",
|
||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
"marked": "^15.0.7",
|
||||||
"qr-code-styling": "^1.8.4",
|
"qr-code-styling": "^1.8.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
39
src/components/markdown.css
Normal file
39
src/components/markdown.css
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
.markdown a {
|
||||||
|
@apply underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown blockquote {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 12px;
|
||||||
|
@apply border-l-neutral-800 border-2 text-neutral-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown hr {
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
margin: 20px;
|
||||||
|
@apply bg-neutral-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown img:not(.custom-emoji),
|
||||||
|
.markdown video,
|
||||||
|
.markdown iframe,
|
||||||
|
.markdown audio {
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown iframe,
|
||||||
|
.markdown video {
|
||||||
|
width: -webkit-fill-available;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1,
|
||||||
|
.markdown h2,
|
||||||
|
.markdown h3,
|
||||||
|
.markdown h4,
|
||||||
|
.markdown h5,
|
||||||
|
.markdown h6 {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
134
src/components/markdown.tsx
Normal file
134
src/components/markdown.tsx
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import "./markdown.css";
|
||||||
|
|
||||||
|
import { ReactNode, forwardRef, useMemo } from "react";
|
||||||
|
import { Token, Tokens, marked } from "marked";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
interface MarkdownProps {
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Markdown = forwardRef<HTMLDivElement, MarkdownProps>((props: MarkdownProps, ref) => {
|
||||||
|
let ctr = 0;
|
||||||
|
function renderToken(t: Token): ReactNode {
|
||||||
|
try {
|
||||||
|
switch (t.type) {
|
||||||
|
case "paragraph": {
|
||||||
|
return <div key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</div>;
|
||||||
|
}
|
||||||
|
case "image": {
|
||||||
|
return <img key={ctr++} src={t.href} />;
|
||||||
|
}
|
||||||
|
case "heading": {
|
||||||
|
switch (t.depth) {
|
||||||
|
case 1:
|
||||||
|
return <h1 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h1>;
|
||||||
|
case 2:
|
||||||
|
return <h2 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h2>;
|
||||||
|
case 3:
|
||||||
|
return <h3 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h3>;
|
||||||
|
case 4:
|
||||||
|
return <h4 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h4>;
|
||||||
|
case 5:
|
||||||
|
return <h5 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h5>;
|
||||||
|
case 6:
|
||||||
|
return <h6 key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</h6>;
|
||||||
|
}
|
||||||
|
throw new Error("Invalid heading");
|
||||||
|
}
|
||||||
|
case "codespan": {
|
||||||
|
return <code key={ctr++}>{t.raw}</code>;
|
||||||
|
}
|
||||||
|
case "code": {
|
||||||
|
return <pre key={ctr++}>{t.raw}</pre>;
|
||||||
|
}
|
||||||
|
case "br": {
|
||||||
|
return <br key={ctr++} />;
|
||||||
|
}
|
||||||
|
case "hr": {
|
||||||
|
return <hr key={ctr++} />;
|
||||||
|
}
|
||||||
|
case "strong": {
|
||||||
|
return <b key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</b>;
|
||||||
|
}
|
||||||
|
case "blockquote": {
|
||||||
|
return <blockquote key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</blockquote>;
|
||||||
|
}
|
||||||
|
case "link": {
|
||||||
|
return (
|
||||||
|
<Link to={t.href} key={ctr++}>
|
||||||
|
{t.tokens ? t.tokens.map(renderToken) : t.raw}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case "list": {
|
||||||
|
if (t.ordered) {
|
||||||
|
return <ol key={ctr++}>{t.items.map(renderToken)}</ol>;
|
||||||
|
} else {
|
||||||
|
return <ul key={ctr++}>{t.items.map(renderToken)}</ul>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "list_item": {
|
||||||
|
return <li key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</li>;
|
||||||
|
}
|
||||||
|
case "em": {
|
||||||
|
return <em key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</em>;
|
||||||
|
}
|
||||||
|
case "del": {
|
||||||
|
return <s key={ctr++}>{t.tokens ? t.tokens.map(renderToken) : t.raw}</s>;
|
||||||
|
}
|
||||||
|
case "table": {
|
||||||
|
return (
|
||||||
|
<table className="table-auto border-collapse" key={ctr++}>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{(t.header as Tokens.TableCell[]).map(v => (
|
||||||
|
<th className="border" key={ctr++}>
|
||||||
|
{v.tokens ? v.tokens.map(renderToken) : v.text}
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{(t.rows as Tokens.TableCell[][]).map(v => (
|
||||||
|
<tr key={ctr++}>
|
||||||
|
{v.map((d, d_key) => (
|
||||||
|
<td className="border px-2 py-1" key={d_key}>
|
||||||
|
{d.tokens ? d.tokens.map(renderToken) : d.text}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case "text": {
|
||||||
|
if ("tokens" in t) {
|
||||||
|
return (t.tokens as Array<Token>).map(renderToken);
|
||||||
|
}
|
||||||
|
return t.raw;
|
||||||
|
}
|
||||||
|
case "space": {
|
||||||
|
return " ";
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
console.debug(`Unknown token ${t.type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = useMemo(() => {
|
||||||
|
return marked.lexer(props.content);
|
||||||
|
}, [props.content]);
|
||||||
|
return (
|
||||||
|
<div className="markdown" ref={ref}>
|
||||||
|
{parsed.filter(a => a.type !== "footnote" && a.type !== "footnotes").map(a => renderToken(a))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Markdown;
|
@ -10,6 +10,7 @@ import OrderPage from "./pages/order.tsx";
|
|||||||
import VmPage from "./pages/vm.tsx";
|
import VmPage from "./pages/vm.tsx";
|
||||||
import AccountPage from "./pages/account.tsx";
|
import AccountPage from "./pages/account.tsx";
|
||||||
import SignUpPage from "./pages/sign-up.tsx";
|
import SignUpPage from "./pages/sign-up.tsx";
|
||||||
|
import { TosPage } from "./pages/terms.tsx";
|
||||||
|
|
||||||
const system = new NostrSystem({
|
const system = new NostrSystem({
|
||||||
automaticOutboxModel: false,
|
automaticOutboxModel: false,
|
||||||
@ -46,6 +47,10 @@ const router = createBrowserRouter([
|
|||||||
path: "/vm/:action?",
|
path: "/vm/:action?",
|
||||||
element: <VmPage />,
|
element: <VmPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/tos",
|
||||||
|
element: <TosPage />,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -3,6 +3,7 @@ import { VmTemplate, LNVpsApi } from "../api";
|
|||||||
import Profile from "../components/profile";
|
import Profile from "../components/profile";
|
||||||
import VpsCard from "../components/vps-card";
|
import VpsCard from "../components/vps-card";
|
||||||
import { ApiUrl, NostrProfile } from "../const";
|
import { ApiUrl, NostrProfile } from "../const";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
const [offers, setOffers] = useState<Array<VmTemplate>>([]);
|
const [offers, setOffers] = useState<Array<VmTemplate>>([]);
|
||||||
@ -25,27 +26,29 @@ export default function HomePage() {
|
|||||||
<small>
|
<small>
|
||||||
All VPS come with 1x IPv4 and 1x IPv6 address and unmetered traffic
|
All VPS come with 1x IPv4 and 1x IPv6 address and unmetered traffic
|
||||||
</small>
|
</small>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-6">
|
||||||
<b>You can also find us on nostr: </b>
|
<a target="_blank" href={`https://snort.social/${NostrProfile.encode()}`}>
|
||||||
<a target="_blank" href={`nostr:${NostrProfile.encode()}`}>
|
|
||||||
<Profile link={NostrProfile} />
|
<Profile link={NostrProfile} />
|
||||||
</a>
|
</a>
|
||||||
<div>
|
<div className="text-center">
|
||||||
<a target="_blank" href="http://speedtest.v0l.io">
|
<a target="_blank" href="http://speedtest.v0l.io">
|
||||||
Speedtest
|
Speedtest
|
||||||
</a>
|
</a>
|
||||||
{" "}
|
{" | "}
|
||||||
<a href="/lnvps.asc">PGP</a>
|
<a href="/lnvps.asc">PGP</a>
|
||||||
{" "}
|
{" | "}
|
||||||
<a href="https://lnvps1.statuspage.io/" target="_blank">Status</a>
|
<a href="https://lnvps1.statuspage.io/" target="_blank">Status</a>
|
||||||
|
{" | "}
|
||||||
|
<Link to="/tos">Terms</Link>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-center text-neutral-400">
|
||||||
|
LNVPS is a trading name of Apex Strata Ltd, a company registered in Ireland.
|
||||||
|
<br />
|
||||||
|
Comany Number: 702423,
|
||||||
|
Address: Suite 10628, 26/27 Upper Pembroke Street, Dublin 2, D02 X361, Ireland
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-center text-neutral-400">
|
|
||||||
LNVPS is a trading name of Apex Strata Ltd, a company registered in Ireland.
|
|
||||||
<br />
|
|
||||||
Comany Number: 702423,
|
|
||||||
Address: Suite 10628, 26/27 Upper Pembroke Street, Dublin 2, D02 X361, Ireland
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
6
src/pages/terms.tsx
Normal file
6
src/pages/terms.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Markdown from "../components/markdown";
|
||||||
|
import TOS from "../../tos.md?raw";
|
||||||
|
|
||||||
|
export function TosPage() {
|
||||||
|
return <Markdown content={TOS} />
|
||||||
|
}
|
107
tos.md
Normal file
107
tos.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# Terms of Service
|
||||||
|
**LNVPS**
|
||||||
|
*Last Updated: February 26, 2025*
|
||||||
|
|
||||||
|
Welcome to LNVPS, a trading name of Apex Strata Ltd, a company registered in Ireland. These Terms of Service ("Terms") govern your use of our Virtual Private Server (VPS) hosting services, website, and related offerings (collectively, the "Services"). By accessing or using our Services, you agree to be bound by these Terms. If you do not agree, please do not use our Services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Company Information
|
||||||
|
LNVPS is a trading name of Apex Strata Ltd, a company registered in Ireland.
|
||||||
|
- **Company Registration Number**: 702423
|
||||||
|
- **Registered Office**: Suite 10628, 26/27 Upper Pembroke Street, Dublin 2, D02 X361, Ireland
|
||||||
|
- **Email**: sales@lnvps.net
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Definitions
|
||||||
|
- **"You" or "Customer"**: The individual or entity subscribing to or using the Services.
|
||||||
|
- **"We", "Us", or "LNVPS"**: Apex Strata Ltd, operating as LNVPS.
|
||||||
|
- **"Services"**: VPS hosting, support, and any additional features provided by LNVPS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Eligibility
|
||||||
|
You must be at least 18 years old and capable of entering into a legally binding agreement to use our Services. By signing up, you confirm that all information provided is accurate and that you are authorized to act on behalf of any entity you represent.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Services
|
||||||
|
LNVPS provides VPS hosting services, including server resources, bandwidth, and technical support, as outlined on our website ([lnvps.net](https://lnvps.net) or applicable domain). Specific features, pricing, and resource limits are detailed in your chosen service plan at the time of purchase.
|
||||||
|
|
||||||
|
- **Service Availability**: We strive for 99.9% uptime but do not guarantee uninterrupted service. Downtime may occur due to maintenance, upgrades, or unforeseen events.
|
||||||
|
- **Modifications**: We reserve the right to modify or discontinue any aspect of the Services with reasonable notice.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Account Responsibilities
|
||||||
|
- **Account Security**: You are responsible for maintaining the confidentiality of your account credentials and for all activities under your account.
|
||||||
|
- **Usage**: You agree to use the Services only for lawful purposes and in compliance with these Terms.
|
||||||
|
- **Notification**: You must notify us immediately of any unauthorized use of your account.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Acceptable Use Policy
|
||||||
|
You agree not to use the Services to:
|
||||||
|
- Host, store, or distribute illegal content, including but not limited to pirated software, child exploitation material, or content inciting violence or hate.
|
||||||
|
- Engage in spamming, phishing, or other abusive activities.
|
||||||
|
- Overload or disrupt our servers, networks, or other customers’ services (e.g., DDoS attacks).
|
||||||
|
- Violate intellectual property rights or privacy laws.
|
||||||
|
|
||||||
|
We reserve the right to suspend or terminate your Services without notice if we detect violations, subject to applicable law.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Payment and Billing
|
||||||
|
- **Fees**: You agree to pay the fees for your chosen plan as outlined at checkout. All prices are in Euro (€) and include VAT where applicable.
|
||||||
|
- **Billing Cycle**: Payments are due in advance (monthly, quarterly, or annually, depending on your plan).
|
||||||
|
- **Late Payment**: Overdue accounts may be suspended until payment is received.
|
||||||
|
- **Refunds**: Refunds are available within 7 days of initial purchase, provided no excessive usage has occurred, as determined by us.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Termination
|
||||||
|
- **By You**: You may terminate your account at any time via your control panel or by contacting us, subject to the billing cycle terms.
|
||||||
|
- **By Us**: We may suspend or terminate your Services for non-payment, violation of these Terms, or if required by law, with or without notice depending on the severity of the breach.
|
||||||
|
- **Effect of Termination**: Upon termination, your access to the Services ends, and we may delete your data after 7 days unless otherwise required by law.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Data and Privacy
|
||||||
|
- **Your Data**: You retain ownership of data uploaded to your VPS. We do not access it except as needed to provide the Services or comply with legal obligations.
|
||||||
|
- **Backups**: You are responsible for maintaining backups of your data unless a backup service is included in your plan.
|
||||||
|
- **GDPR Compliance**: We process personal data in accordance with our [Privacy Policy](#), which complies with the General Data Protection Regulation (GDPR).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Limitation of Liability
|
||||||
|
To the fullest extent permitted by Irish law:
|
||||||
|
- Our liability for any claim arising from the Services is limited to the amount you paid us in the previous 12 months.
|
||||||
|
- We are not liable for indirect, consequential, or incidental damages (e.g., loss of profits, data, or business opportunities).
|
||||||
|
- We are not responsible for issues beyond our reasonable control, such as force majeure events (e.g., natural disasters, cyber-attacks).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Intellectual Property
|
||||||
|
- **Our IP**: The LNVPS website, branding, and software remain our property or that of our licensors.
|
||||||
|
- **Your IP**: You grant us a limited license to use your content solely to provide the Services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Governing Law and Dispute Resolution
|
||||||
|
- These Terms are governed by the laws of Ireland.
|
||||||
|
- Any disputes will be subject to the exclusive jurisdiction of the courts of Ireland, though you may have additional rights under EU consumer law if applicable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Changes to Terms
|
||||||
|
We may update these Terms from time to time. We will notify you of significant changes via email or on our website. Continued use of the Services after changes constitutes acceptance of the updated Terms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Contact Us
|
||||||
|
For questions or support:
|
||||||
|
- **Email**: sales@lnvps.net
|
||||||
|
- **Address**: Suite 10628, 26/27 Upper Pembroke Street, Dublin 2, D02 X361, Ireland
|
||||||
|
|
||||||
|
---
|
@ -4,4 +4,5 @@ import react from "@vitejs/plugin-react";
|
|||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
assetsInclude: ["**/*.md"],
|
||||||
});
|
});
|
||||||
|
10
yarn.lock
10
yarn.lock
@ -2394,6 +2394,7 @@ __metadata:
|
|||||||
eslint-plugin-react-hooks: "npm:^5.1.0-rc.0"
|
eslint-plugin-react-hooks: "npm:^5.1.0-rc.0"
|
||||||
eslint-plugin-react-refresh: "npm:^0.4.9"
|
eslint-plugin-react-refresh: "npm:^0.4.9"
|
||||||
globals: "npm:^15.9.0"
|
globals: "npm:^15.9.0"
|
||||||
|
marked: "npm:^15.0.7"
|
||||||
postcss: "npm:^8.4.41"
|
postcss: "npm:^8.4.41"
|
||||||
prettier: "npm:^3.3.3"
|
prettier: "npm:^3.3.3"
|
||||||
qr-code-styling: "npm:^1.8.4"
|
qr-code-styling: "npm:^1.8.4"
|
||||||
@ -2470,6 +2471,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"marked@npm:^15.0.7":
|
||||||
|
version: 15.0.7
|
||||||
|
resolution: "marked@npm:15.0.7"
|
||||||
|
bin:
|
||||||
|
marked: bin/marked.js
|
||||||
|
checksum: 10c0/0b9d07bace37bbf0548bae356c4184765afa4d2296ed0be4418aa4bb0ce703f323dc1a475125d536581f9fe264797e6265dd0b57499d97c0fe0f29bc6d016343
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
|
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
|
||||||
version: 1.4.1
|
version: 1.4.1
|
||||||
resolution: "merge2@npm:1.4.1"
|
resolution: "merge2@npm:1.4.1"
|
||||||
|
Reference in New Issue
Block a user