Compare commits
10 Commits
7ddb9e61a6
...
33ef0b3c0b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
33ef0b3c0b | ||
d44b5aff13 | |||
5ac952787f | |||
5142d1968c | |||
72f5b61360 | |||
6f3d9b4a19 | |||
d4e157f1fa | |||
e6cdf3a977 | |||
cc8fe27935 | |||
6f0c4620d7 |
@ -3,9 +3,11 @@
|
|||||||
"version": "1.0.50",
|
"version": "1.0.50",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"dev": "bun run --watch src/index.ts"
|
"dev": "bun run --watch src/index.tsx"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@elysiajs/html": "^0.8.0",
|
||||||
|
"@elysiajs/static": "^0.8.1",
|
||||||
"elysia": "latest"
|
"elysia": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
15
src/app.tsx
Normal file
15
src/app.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Elysia } from "elysia";
|
||||||
|
import { Index, selectPage } from "./frontend";
|
||||||
|
|
||||||
|
export const app = new Elysia()
|
||||||
|
.get("/", (context) => isHTMXResponse( context, "/"))
|
||||||
|
.get("/blog", (context) => isHTMXResponse( context, "/blog"))
|
||||||
|
.get("/projects", (context) => isHTMXResponse( context, "/projects"))
|
||||||
|
.get("/content/post", () => "I'm from the server")
|
||||||
|
|
||||||
|
function isHTMXResponse ( context: any, path: string) {
|
||||||
|
if (context.headers["hx-request"] === "true") {
|
||||||
|
return selectPage(path);
|
||||||
|
}
|
||||||
|
return Index(path);
|
||||||
|
}
|
15
src/frontend/components/Header.tsx
Normal file
15
src/frontend/components/Header.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export function Header() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<header hx-boost="true">
|
||||||
|
<span>Caleb Braaten</span>
|
||||||
|
<nav>
|
||||||
|
<a hx-target="main" href="/">Home</a>
|
||||||
|
<a hx-target="main" href="/blog">Blog</a>
|
||||||
|
<a hx-target="main" href="/projects">Projects</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
60
src/frontend/components/icons.tsx
Normal file
60
src/frontend/components/icons.tsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
export function GithubIcon(props: any) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
|
||||||
|
<path d="M9 18c-4.51 2-5-2-7-2" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LinkedinIcon(props: any) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
|
||||||
|
<rect width="4" height="12" x="2" y="9" />
|
||||||
|
<circle cx="4" cy="4" r="2" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function XIcon(props: any) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 1200 1227"
|
||||||
|
preserveAspectRatio="none"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z" fill="black" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
35
src/frontend/index.tsx
Normal file
35
src/frontend/index.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { Header } from "./components/Header";
|
||||||
|
import { Home } from "./pages/home";
|
||||||
|
import { Blog } from "./pages/blog";
|
||||||
|
import { Projects } from "./pages/projects";
|
||||||
|
|
||||||
|
export function Index(path: string) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<script defer src="./htmx.min.js"></script>
|
||||||
|
<title>Caleb's Blog</title>
|
||||||
|
<link rel="stylesheet" href="./styles.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Header />
|
||||||
|
<main>
|
||||||
|
{selectPage(path)}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectPage(path: string) {
|
||||||
|
switch (path) {
|
||||||
|
case '/':
|
||||||
|
return <Home />
|
||||||
|
case '/blog':
|
||||||
|
return <Blog />
|
||||||
|
case '/projects':
|
||||||
|
return <Projects />
|
||||||
|
}
|
||||||
|
}
|
50
src/frontend/pages/blog.tsx
Normal file
50
src/frontend/pages/blog.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
export function Blog(){
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<article>
|
||||||
|
<h2>Blog Post Title</h2>
|
||||||
|
<div>Posted on January 1, 2024</div>
|
||||||
|
<p>Google Chrome is a web browser developed by Google, released in 2008. Chrome is the world's most popular web browser today!</p>
|
||||||
|
<a href="/post/3">Read More</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h2>Another Blog Post Title</h2>
|
||||||
|
<div>Posted on December 1, 2023</div>
|
||||||
|
<p>Mozilla Firefox is an open-source web browser developed by Mozilla. Firefox has been the second most popular web browser since January, 2018.</p>
|
||||||
|
<a href="/post/2">Read More</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h2>The First Blog Post</h2>
|
||||||
|
<div>Posted on November 1, 2023</div>
|
||||||
|
<p>Microsoft Edge is a web browser developed by Microsoft, released in 2015. Microsoft Edge replaced Internet Explorer.</p>
|
||||||
|
<a href="/post/1">Read More</a>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
<aside>
|
||||||
|
<div>
|
||||||
|
<h3>About Me</h3>
|
||||||
|
<p>I'm a software engineer</p>
|
||||||
|
|
||||||
|
<h3>Connect with me</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Twitter</li>
|
||||||
|
<li>GitHub</li>
|
||||||
|
<li>LinkedIn</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>Categories</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Web Development</li>
|
||||||
|
<li>UI/UX Design</li>
|
||||||
|
<li>Productivity</li>
|
||||||
|
<li>Career</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
41
src/frontend/pages/home.tsx
Normal file
41
src/frontend/pages/home.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { GithubIcon, LinkedinIcon, XIcon } from "../components/icons"
|
||||||
|
|
||||||
|
export function Home(){
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<article class="post-spotlight">
|
||||||
|
<h2>Most Recent Blog Post Title</h2>
|
||||||
|
<div>Posted on January 1, 2024</div>
|
||||||
|
<p>Google Chrome is a web browser developed by Google, released in 2008. Chrome is the world's most popular web browser today!</p>
|
||||||
|
<a href="/post/3">Continue Reading...</a>
|
||||||
|
</article>
|
||||||
|
<hr />
|
||||||
|
<aside>
|
||||||
|
<div class="about">
|
||||||
|
<h3>About Me</h3>
|
||||||
|
<p>I'm a software engineer</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href=""><XIcon /></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href=""><GithubIcon /></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href=""><LinkedinIcon /></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="content-categories">
|
||||||
|
<h3>Categories</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Web Development</li>
|
||||||
|
<li>UI/UX Design</li>
|
||||||
|
<li>Productivity</li>
|
||||||
|
<li>Career</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
18
src/frontend/pages/projects.tsx
Normal file
18
src/frontend/pages/projects.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export function Projects(){
|
||||||
|
return (
|
||||||
|
<div class="projects">
|
||||||
|
<div>
|
||||||
|
<img src="https://via.placeholder.com/150" />
|
||||||
|
<h2>This Site</h2>
|
||||||
|
<p>Project 1 description</p>
|
||||||
|
<a href="/project/1">Git Repo</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="https://via.placeholder.com/150" />
|
||||||
|
<h2>Home Server</h2>
|
||||||
|
<p>Project 1 description</p>
|
||||||
|
<a href="/project/1">Git Repo</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
1
src/frontend/public/htmx.min.js
vendored
Normal file
1
src/frontend/public/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
97
src/frontend/public/styles.css
Normal file
97
src/frontend/public/styles.css
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
body, a {
|
||||||
|
margin: 0px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
padding: 15px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header span {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 0px;
|
||||||
|
opacity: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-spotlight {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin: 30px;
|
||||||
|
padding: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
font-family: 'Arial Narrow Bold', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > h2 {
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > div {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > a {
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
color: black;
|
||||||
|
text-align: end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside h3 {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
import { Elysia } from "elysia";
|
|
||||||
|
|
||||||
const app = new Elysia().get("/", () => "Hello Elysia").listen(3000);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
|
|
||||||
);
|
|
20
src/index.tsx
Normal file
20
src/index.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Elysia } from "elysia";
|
||||||
|
import { html } from "@elysiajs/html";
|
||||||
|
import { staticPlugin } from "@elysiajs/static";
|
||||||
|
import { app } from "./app";
|
||||||
|
|
||||||
|
const index = new Elysia()
|
||||||
|
.use(html())
|
||||||
|
.use(staticPlugin({
|
||||||
|
assets: './src/frontend/public',
|
||||||
|
prefix: '/'
|
||||||
|
}))
|
||||||
|
.use(app)
|
||||||
|
.onRequest(({ request }) => {
|
||||||
|
console.log(`Request ${request.method} ${request.url}`);
|
||||||
|
})
|
||||||
|
.listen(3000);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`🦊 Elysia is running at ${index.server?.hostname}:${index.server?.port}`
|
||||||
|
);
|
@ -13,11 +13,11 @@
|
|||||||
/* Language and Environment */
|
/* Language and Environment */
|
||||||
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
"jsx": "react", /* Specify what JSX code is generated. */
|
||||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
"jsxFactory": "Html.createElement", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
"jsxFragmentFactory": "Html.Fragment", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
@ -98,6 +98,6 @@
|
|||||||
|
|
||||||
/* Completeness */
|
/* Completeness */
|
||||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
"skipLibCheck": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user