Compare commits
No commits in common. "bab35d0ad556ce790805107c7c84ff8d505aeca8" and "ae3e95a0c357a1bf824fbce7f5e6bb94e53a667a" have entirely different histories.
bab35d0ad5
...
ae3e95a0c3
BIN
public/server.png
Normal file
BIN
public/server.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
27
src/App.tsx
27
src/App.tsx
|
@ -1,14 +1,27 @@
|
||||||
import { Route, Routes } from "react-router-dom";
|
import React from 'react'
|
||||||
import Main from "./pages/Main";
|
import { Route, Routes } from 'react-router-dom'
|
||||||
import About from "./pages/About";
|
import Main from './pages/Main'
|
||||||
|
import About from './pages/About'
|
||||||
|
import SelfHosting from './pages/SelfHosting'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" index element={<Main />} />
|
<Route
|
||||||
<Route path="/about" element={<About />} />
|
path="/"
|
||||||
|
index
|
||||||
|
element={<Main />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/about"
|
||||||
|
element={<About />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/about/selfhosting"
|
||||||
|
element={<SelfHosting />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
:root {
|
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
|
|
||||||
color: var(--text-color);
|
|
||||||
background-color: var(--background);
|
|
||||||
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
|
|
||||||
--background: rgb(0, 0, 0);
|
|
||||||
--main: rgb(250, 95, 0);
|
|
||||||
--primary: rgb(40, 40, 40);
|
|
||||||
--secondary: rgb(100, 100, 100);
|
|
||||||
--tertiary: rgb(30, 30, 30);
|
|
||||||
--text-color: rgb(255, 255, 255);
|
|
||||||
--shadow-color: rgba(40, 40, 40, 0.5);
|
|
||||||
--shadow: 5px 5px 7px var(--shadow-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
--background: rgb(220, 220, 220);
|
|
||||||
--main: rgb(250, 95, 0);
|
|
||||||
--primary: rgb(255, 255, 255);
|
|
||||||
--secondary: rgb(170, 170, 170);
|
|
||||||
--tertiary: rgb(100, 100, 100);
|
|
||||||
--text-color: rgb(0, 0, 0);
|
|
||||||
--shadow: 5px 5px 7px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { ReactNode } from "react";
|
|
||||||
|
|
||||||
interface BoldProps {
|
|
||||||
children: ReactNode;
|
|
||||||
col?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const B = ({ children, col = "var(--textcolor)" }: BoldProps) => {
|
|
||||||
return <span style={{ fontWeight: "bold", color: col }}>{children}</span>;
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
import { Children, ReactNode } from "react";
|
|
||||||
|
|
||||||
interface BulletProps {
|
|
||||||
indents?: number;
|
|
||||||
children: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Bullet({ indents, children }: BulletProps) {
|
|
||||||
return (
|
|
||||||
<div style={{ textIndent: indents ? `${indents}em` : "0em" }}>
|
|
||||||
• {children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Bullet;
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ReactNode } from "react";
|
import React, { ReactNode } from "react";
|
||||||
import { TextProps } from "../types";
|
import { TextProps } from "../types";
|
||||||
|
|
||||||
export interface DescriptionProps extends TextProps {
|
export interface DescriptionProps extends TextProps {
|
||||||
|
@ -7,15 +7,11 @@ export interface DescriptionProps extends TextProps {
|
||||||
noBackground?: boolean;
|
noBackground?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Description = ({
|
export const Description = ({ noBackground, main, children }: DescriptionProps) => {
|
||||||
noBackground,
|
|
||||||
main,
|
|
||||||
children,
|
|
||||||
}: DescriptionProps) => {
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={noBackground ? "description no-background" : "description"}
|
className={noBackground ? "description no-background" : "description"}
|
||||||
style={main ? { margin: "14px" } : {}}
|
style={main ? {margin: "14px"} : {}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,8 +15,7 @@ export interface TextLinks extends GenericProps {
|
||||||
export const Header = ({ fadeIn, links }: TextLinks) => {
|
export const Header = ({ fadeIn, links }: TextLinks) => {
|
||||||
return (
|
return (
|
||||||
<div className={fadeIn ? "header fade-in" : "header"}>
|
<div className={fadeIn ? "header fade-in" : "header"}>
|
||||||
{links &&
|
{links && links.map((link) => {
|
||||||
links.map((link) => {
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className="header-link"
|
className="header-link"
|
||||||
|
|
|
@ -6,5 +6,11 @@ export interface MessageProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Message = ({ className, children }: MessageProps) => {
|
export const Message = ({ className, children }: MessageProps) => {
|
||||||
return <div className={"message zoom-in" + " " + className}>{children}</div>;
|
return (
|
||||||
|
<div
|
||||||
|
className={"message zoom-in" + " " + className}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const Title = ({ children, noBackground, glow }: TitleProps) => {
|
||||||
let result = "title";
|
let result = "title";
|
||||||
|
|
||||||
if (noBackground) {
|
if (noBackground) {
|
||||||
result += " no-background";
|
result += " no-background"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glow) {
|
if (glow) {
|
||||||
|
@ -20,9 +20,10 @@ export const Title = ({ children, noBackground, glow }: TitleProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className={determineClasses()}>{children}</p>
|
<p className={determineClasses()}>{children}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
export * from "./B";
|
|
||||||
export * from "./ButtonRow";
|
|
||||||
export * from "./Description";
|
|
||||||
export * from "./DoubleSpace";
|
|
||||||
export * from "./Header";
|
export * from "./Header";
|
||||||
export * from "./Message";
|
|
||||||
export * from "./Title";
|
export * from "./Title";
|
||||||
|
export * from "./Description";
|
||||||
|
export * from "./ButtonRow";
|
||||||
|
export * from "./Message";
|
||||||
|
export * from "./DoubleSpace";
|
||||||
|
|
|
@ -1,16 +1,34 @@
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
|
||||||
|
color: var(--text-color);
|
||||||
|
background-color: var(--background);
|
||||||
|
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
|
||||||
|
--background: rgb(0, 0, 0);
|
||||||
|
--main: rgb(250, 95, 0);
|
||||||
|
--primary: rgb(40, 40, 40);
|
||||||
|
--secondary: rgb(100, 100, 100);
|
||||||
|
--tertiary: rgb(30, 30, 30);
|
||||||
|
--text-color: rgb(255, 255, 255);
|
||||||
|
--shadow-color: rgba(40, 40, 40, 0.5);
|
||||||
|
--shadow: 5px 5px 7px var(--shadow-color);
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
animation: zoom-in 0.3s;
|
animation: zoom-in 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.at:link,
|
.at:link, .at:visited {
|
||||||
.at:visited {
|
|
||||||
color: var(--main);
|
color: var(--main);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition:
|
transition: opacity 0.15s, transform 0.15s;
|
||||||
opacity 0.15s,
|
|
||||||
transform 0.15s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.at:hover {
|
.at:hover {
|
||||||
|
@ -35,12 +53,6 @@ body {
|
||||||
color 0s;
|
color 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reg-link:link,
|
|
||||||
.reg-link:visited {
|
|
||||||
color: var(--main);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -161,8 +173,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
width: 100%;
|
width: 75%;
|
||||||
margin: 20px auto;
|
margin: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
@ -177,3 +189,15 @@ body {
|
||||||
.small-font {
|
.small-font {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--background: rgb(220, 220, 220);
|
||||||
|
--main: rgb(250, 95, 0);
|
||||||
|
--primary: rgb(255, 255, 255);
|
||||||
|
--secondary: rgb(170, 170, 170);
|
||||||
|
--tertiary: rgb(100, 100, 100);
|
||||||
|
--text-color: rgb(0, 0, 0);
|
||||||
|
--shadow: 5px 5px 7px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,58 +1,22 @@
|
||||||
import { Link } from "react-router-dom";
|
import React from 'react'
|
||||||
import {
|
import { Link } from 'react-router-dom'
|
||||||
B,
|
import { Description, Header, Message, Title, DoubleSpace, ButtonRow, Buttons, TextLink } from '../components'
|
||||||
Description,
|
|
||||||
Header,
|
|
||||||
Message,
|
|
||||||
Title,
|
|
||||||
TextLink,
|
|
||||||
} from "../components";
|
|
||||||
import Bullet from "../components/Bullet";
|
|
||||||
|
|
||||||
function About() {
|
function About() {
|
||||||
const links: TextLink[] = [
|
const links: TextLink[] = [
|
||||||
{
|
{
|
||||||
text: "Back",
|
text: "Back",
|
||||||
link: "/",
|
link: "/"
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const buttons: Buttons[] = [
|
||||||
|
{
|
||||||
|
name: "Self-Hosting",
|
||||||
|
link: "/about/selfhosting",
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const serverLink = (
|
|
||||||
<Link
|
|
||||||
className="reg-link"
|
|
||||||
target="_blank"
|
|
||||||
to="https://git.povario.com/powermaker450/simple-review-server"
|
|
||||||
>
|
|
||||||
Server
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
const clientLink = (
|
|
||||||
<Link
|
|
||||||
className="reg-link"
|
|
||||||
target="_blank"
|
|
||||||
to="https://git.povario.com/powermaker450/simple-review-client"
|
|
||||||
>
|
|
||||||
Client
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
const assistantLink = (
|
|
||||||
<Link
|
|
||||||
className="reg-link"
|
|
||||||
target="_blank"
|
|
||||||
to="https://git.povario.com/powermaker450/Tailchat-Assistant"
|
|
||||||
>
|
|
||||||
Tailchat-Assistant
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
const neovimLink = (
|
|
||||||
<Link className="reg-link" target="_blank" to="https://neovim.io">
|
|
||||||
Neovim
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header links={links} />
|
<Header links={links} />
|
||||||
|
@ -62,56 +26,20 @@ function About() {
|
||||||
|
|
||||||
<Description>
|
<Description>
|
||||||
<p>
|
<p>
|
||||||
I'm <B col="var(--main)">powermaker450</B>.
|
You've probably met me online and checked out my website, I know you IRL, or you're interested in me.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You've probably met me online and checked out my website, I know you
|
In the wise words of Lester Crest, "don't dawdle!" and read on.
|
||||||
IRL, or you're interested in me.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
I got very interested in programming at young age, and while my
|
|
||||||
skills have improved a lot, I'm only 16 and got a lot to learn.
|
|
||||||
Despite that, I'm proud of what I've done and learned so far.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
You can check out some of my favorite projects, like Simple Review{" "}
|
|
||||||
{serverLink} + {clientLink}, and {assistantLink}.
|
|
||||||
</p>
|
</p>
|
||||||
</Description>
|
</Description>
|
||||||
</Message>
|
</Message>
|
||||||
|
|
||||||
<Message>
|
<DoubleSpace />
|
||||||
<Description>
|
|
||||||
<p>So far, I've managed to famaliarize myself with these...</p>
|
|
||||||
|
|
||||||
<B>Languages:</B>
|
<ButtonRow buttons={buttons} fadeIn />
|
||||||
<Bullet>HTML/CSS</Bullet>
|
|
||||||
<Bullet>TypeScript/Javascript</Bullet>
|
|
||||||
<Bullet>Python</Bullet>
|
|
||||||
<Bullet>Lua (minimally, only for Neovim)</Bullet>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<B>Tools:</B>
|
|
||||||
<Bullet>Git</Bullet>
|
|
||||||
<Bullet>React</Bullet>
|
|
||||||
<Bullet>Material UI (for React)</Bullet>
|
|
||||||
<Bullet>OpenAI API</Bullet>
|
|
||||||
<Bullet>SQLite</Bullet>
|
|
||||||
<Bullet>Regular Expressions</Bullet>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<p>
|
|
||||||
And my main/only editor is {neovimLink}. I love it until I don't. :)
|
|
||||||
</p>
|
|
||||||
</Description>
|
|
||||||
</Message>
|
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default About;
|
export default About;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import "../colors.css";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Buttons,
|
Buttons,
|
||||||
ButtonRow,
|
ButtonRow,
|
||||||
|
@ -30,8 +30,8 @@ function Main() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "About",
|
text: "About",
|
||||||
link: "/about",
|
link: "/about"
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const buttons: Buttons[] = [
|
const buttons: Buttons[] = [
|
||||||
|
@ -48,7 +48,7 @@ function Main() {
|
||||||
link: "https://github.com/powermaker450",
|
link: "https://github.com/powermaker450",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Projects",
|
name: "Forgejo",
|
||||||
link: "https://git.povario.com/powermaker450",
|
link: "https://git.povario.com/powermaker450",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -69,21 +69,11 @@ function Main() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div id="loader" style={{ display: displayed === "" ? "none" : "flex" }}>
|
<div id="loader" style={{display: displayed === "" ? "none" : "flex"}}>
|
||||||
<img
|
<img src="/three-dots.svg" height={48} style={{display: "block", marginLeft: "auto", marginRight: "auto", marginTop: "20%", width: "50%"}}/>
|
||||||
src="/three-dots.svg"
|
|
||||||
height={48}
|
|
||||||
style={{
|
|
||||||
display: "block",
|
|
||||||
marginLeft: "auto",
|
|
||||||
marginRight: "auto",
|
|
||||||
marginTop: "20%",
|
|
||||||
width: "50%",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="main" style={{ display: displayed }}>
|
<div id="main" style={{display: displayed}}>
|
||||||
<Header links={links} fadeIn />
|
<Header links={links} fadeIn />
|
||||||
|
|
||||||
<div className="easter-egg-box">
|
<div className="easter-egg-box">
|
||||||
|
@ -97,26 +87,22 @@ function Main() {
|
||||||
height={130}
|
height={130}
|
||||||
src="/potato.png"
|
src="/potato.png"
|
||||||
/>
|
/>
|
||||||
<p
|
<p className={checkTimesClicked() ? "easter-egg" : "easter-egg hidden"}>
|
||||||
className={checkTimesClicked() ? "easter-egg" : "easter-egg hidden"}
|
|
||||||
>
|
|
||||||
Stop that!
|
Stop that!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="head zoom-in">
|
<div className="head zoom-in">
|
||||||
<Title noBackground glow>
|
<Title noBackground glow>@powermaker450</Title>
|
||||||
@powermaker450
|
|
||||||
</Title>
|
|
||||||
|
|
||||||
<Description noBackground main>
|
<Description noBackground main>Professional Linux Enjoyer + Self Hosts a Lot</Description>
|
||||||
Professional FOSS Enjoyer
|
|
||||||
</Description>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ButtonRow buttons={buttons} fadeIn />
|
<ButtonRow buttons={buttons} fadeIn />
|
||||||
|
|
||||||
<Message>
|
<Message>
|
||||||
|
<Title>Welcome!</Title>
|
||||||
|
|
||||||
<Description>
|
<Description>
|
||||||
<p>You've reached my homepage.</p>
|
<p>You've reached my homepage.</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
76
src/pages/SelfHosting.tsx
Normal file
76
src/pages/SelfHosting.tsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { Description, DoubleSpace, Header, Message, TextLink, Title } from '../components'
|
||||||
|
|
||||||
|
function SelfHosting() {
|
||||||
|
const links: TextLink[] = [
|
||||||
|
{
|
||||||
|
text: "Back",
|
||||||
|
link: "/about"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header links={links} />
|
||||||
|
|
||||||
|
<Message>
|
||||||
|
<Title>Self-Hosting</Title>
|
||||||
|
|
||||||
|
<Description>
|
||||||
|
<p>
|
||||||
|
Getting the more obvious stuff out of the way, I like self-hosting. I started my self-hosting journey back in
|
||||||
|
2021, when all I was was fed up with Netflix not having all the shows I wanted to watch.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Eventually, that grew into something much bigger, and suddenly this machine I got from a dumpster was my key
|
||||||
|
to a privacy suite.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<img style={{display: "block", margin: "auto", width: "350px"}} src="/public/server.png" />
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Yep. Did I say it was from a dumpster? It's beautiful in it's own way.
|
||||||
|
</p>
|
||||||
|
</Description>
|
||||||
|
|
||||||
|
<DoubleSpace />
|
||||||
|
|
||||||
|
<Description>
|
||||||
|
<p>
|
||||||
|
Managing your own server is a learning experience in itself, and with time I learned the
|
||||||
|
cold, hard, basic skills of being a Linux sysadmin.
|
||||||
|
Not to say it hasn't paid off.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
I've learned my way around the terminal, and can comfortably surf through it without worry,
|
||||||
|
and if I do come across something I don't know, I'll figure out how to do it.
|
||||||
|
Not to mention the money saved not paying for cloud services. Money's not exactly something that get's thrown at me in my life.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Instead of the Google Suite, I use <Link className="at" to="https://nextcloud.com" target="_blank">Nextcloud</Link>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Instead of Spotify, I use <Link className="at" to="https://navidrome.org" target="_blank">Navidrome</Link>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Instead of paying for game hosting, I use <Link className="at" to="https://www.pufferpanel.com">Pufferpanel</Link>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
And so on. Between becoming comfortable with the ways of Linux, and saving my family money in the long run, this server
|
||||||
|
has been a worthwhile investment of my time and effort.
|
||||||
|
</p>
|
||||||
|
</Description>
|
||||||
|
</Message>
|
||||||
|
|
||||||
|
<DoubleSpace />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelfHosting;
|
Loading…
Reference in a new issue