initial commit with existing content
This commit is contained in:
commit
f0860b52a2
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
.shuttle-storage
|
||||||
|
Secrets*.toml
|
1
.prettierrc.toml
Normal file
1
.prettierrc.toml
Normal file
@ -0,0 +1 @@
|
|||||||
|
tabWidth = 4
|
3184
Cargo.lock
generated
Normal file
3184
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "htmx-portfolio"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
askama = { version = "0.12.1", features = ["with-axum"] }
|
||||||
|
askama_axum = "0.4.0"
|
||||||
|
axum = "0.7.4"
|
||||||
|
serde = { version = "1.0.189", features = ["derive"] }
|
||||||
|
serde_json = "1.0.107"
|
||||||
|
shuttle-axum = "0.42.0"
|
||||||
|
shuttle-runtime = "0.42.0"
|
||||||
|
shuttle-shared-db = { version = "0.42.0", features = ["postgres", "sqlx"] }
|
||||||
|
sqlx = { version = "0.7.2", features = ["runtime-tokio-rustls", "postgres"] }
|
||||||
|
tokio = "1.28.2"
|
||||||
|
tokio-stream = { version = "0.1.14", features = ["sync"] }
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Axum + htmx
|
||||||
|
|
||||||
|
This is an example of how you can use Shuttle with Axum, Askama and htmx to create a frontend that's easily extendable and requires zero framework knowledge, while being able to easily inject variables from the backend into the frontend.
|
BIN
assets/favicon.png
Normal file
BIN
assets/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
4
migrations/0000_init.sql
Normal file
4
migrations/0000_init.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS todos (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
description TEXT NOT NULL
|
||||||
|
);
|
34
src/errors.rs
Normal file
34
src/errors.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use axum::http::StatusCode;
|
||||||
|
use axum::response::{IntoResponse, Response};
|
||||||
|
|
||||||
|
pub enum ApiError {
|
||||||
|
SQLError(sqlx::Error),
|
||||||
|
HTTPError(axum::http::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for ApiError {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
match self {
|
||||||
|
Self::SQLError(e) => {
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, format!("SQL error: {e}")).into_response()
|
||||||
|
}
|
||||||
|
Self::HTTPError(e) => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("HTTP error: {e}"),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<sqlx::Error> for ApiError {
|
||||||
|
fn from(e: sqlx::Error) -> Self {
|
||||||
|
Self::SQLError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<axum::http::Error> for ApiError {
|
||||||
|
fn from(e: axum::http::Error) -> Self {
|
||||||
|
Self::HTTPError(e)
|
||||||
|
}
|
||||||
|
}
|
12
src/main.rs
Normal file
12
src/main.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
mod errors;
|
||||||
|
mod models;
|
||||||
|
mod router;
|
||||||
|
mod routes;
|
||||||
|
mod templates;
|
||||||
|
|
||||||
|
#[shuttle_runtime::main]
|
||||||
|
async fn main() -> shuttle_axum::ShuttleAxum {
|
||||||
|
let router = router::init_router();
|
||||||
|
|
||||||
|
Ok(router.into())
|
||||||
|
}
|
2
src/models.rs
Normal file
2
src/models.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// use serde::{Deserialize, Serialize};
|
||||||
|
// put models here
|
32
src/router.rs
Normal file
32
src/router.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use axum::{routing::get, Router};
|
||||||
|
|
||||||
|
use crate::routes;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AppState {}
|
||||||
|
|
||||||
|
// put all notes routes here
|
||||||
|
pub fn init_notes_routes() -> Router {
|
||||||
|
Router::new().route("/", get(routes::notes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// put all tutorial routes here
|
||||||
|
pub fn init_tuts_routes() -> Router {
|
||||||
|
Router::new().route("/", get(routes::tuts))
|
||||||
|
}
|
||||||
|
|
||||||
|
// put any non nested routes here
|
||||||
|
pub fn init_utily_routes() -> Router {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(routes::portfolio))
|
||||||
|
.route("/styles.css", get(routes::styles))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_router() -> Router {
|
||||||
|
let routes: Router<()> = Router::<()>::new()
|
||||||
|
.nest("/tuts", init_tuts_routes())
|
||||||
|
.nest("/notes", init_notes_routes())
|
||||||
|
.nest("/", init_utily_routes());
|
||||||
|
|
||||||
|
Router::new().nest("/", routes)
|
||||||
|
}
|
27
src/routes.rs
Normal file
27
src/routes.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use axum::{
|
||||||
|
http::StatusCode,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{errors::ApiError, templates};
|
||||||
|
|
||||||
|
pub async fn portfolio() -> impl IntoResponse {
|
||||||
|
templates::Portfolio
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn notes() -> impl IntoResponse {
|
||||||
|
templates::Notes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tuts() -> impl IntoResponse {
|
||||||
|
templates::Tuts
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn styles() -> Result<impl IntoResponse, ApiError> {
|
||||||
|
let response = Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header("Content-Type", "text/css")
|
||||||
|
.body(include_str!("../templates/styles.css").to_owned())?;
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
|
}
|
13
src/templates.rs
Normal file
13
src/templates.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use askama::Template;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "portfolio.html")]
|
||||||
|
pub struct Portfolio;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "notes.html")]
|
||||||
|
pub struct Notes;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "tuts.html")]
|
||||||
|
pub struct Tuts;
|
23
templates/base.html
Normal file
23
templates/base.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<script
|
||||||
|
src="https://unpkg.com/htmx.org@1.9.6"
|
||||||
|
integrity="sha384-FhXw7b6AlE/jyjlZH5iHa/tTe9EpJ1Y55RjcgPbjeWMskSxZt1v9qkxLJWNJaGni"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<link rel="stylesheet" href="/styles.css" />
|
||||||
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css"
|
||||||
|
/>
|
||||||
|
<title>{% block title %}{{ title }} - My Site{% endblock %}</title>
|
||||||
|
{% block head %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}
|
||||||
|
<p>Placeholder content</p>
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
31
templates/index.html
Normal file
31
templates/index.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{% extends "base.html" %} {% block title %}Index{% endblock %} {% block content
|
||||||
|
%}
|
||||||
|
<h1>Shuttle Todos - Home</h1>
|
||||||
|
<a href="/stream">Event stream</a>
|
||||||
|
<h1>Shuttle Todos</h1>
|
||||||
|
<form id="add-form">
|
||||||
|
<input
|
||||||
|
placeholder="Your todo description..."
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
name="description"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
hx-post="/todos"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#todos-content"
|
||||||
|
hx-swap="beforeend"
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<div
|
||||||
|
id="list"
|
||||||
|
hx-get="/todos"
|
||||||
|
hx-target="this"
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
12
templates/notes.html
Normal file
12
templates/notes.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% extends "base.html" %} {% block title %}Notes{% endblock %} {% block content
|
||||||
|
%}
|
||||||
|
<nav>
|
||||||
|
<small>
|
||||||
|
<a href="/"><~ back</a>
|
||||||
|
</small>
|
||||||
|
</nav>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h1>Notes</h1>
|
||||||
|
<p>Here all my notes go</p>
|
||||||
|
{% endblock content%}
|
211
templates/portfolio.html
Normal file
211
templates/portfolio.html
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
{% extends "base.html" %} {% block title %}Portfolio{% endblock %} {% block
|
||||||
|
content %}
|
||||||
|
<nav>
|
||||||
|
<small>
|
||||||
|
<a href="/tuts">Micro Tuts</a> / <a href="/notes">Notes</a> /
|
||||||
|
<a href="https://tristonarmstrong.com/social" target="_blank">Social</a>
|
||||||
|
</small>
|
||||||
|
</nav>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h1>Triston Armstrong 🫰</h1>
|
||||||
|
<p>
|
||||||
|
Full Stack Software Developer
|
||||||
|
<a target="_blank" href="https://ventrahealth.com">@VentraHealth</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I am a self taught Full Stack Software Developer with an unhealthy addiction
|
||||||
|
to solving problems using code.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>🤹 Skills</h2>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="https://www.typescriptlang.org/docs/handbook/intro.html"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: none !important"
|
||||||
|
>Typescript</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://docs.python.org/3/"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: none !important"
|
||||||
|
>Python</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://doc.rust-lang.org/std/index.html"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: none !important"
|
||||||
|
>Rust</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://developer.mozilla.org/en-US/docs/Web/javascript#reference"
|
||||||
|
target="_blank"
|
||||||
|
style="text-decoration: none !important"
|
||||||
|
>Javascript</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>💼 Jobs</h2>
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
Ventra Health
|
||||||
|
<small style="font-weight: normal"><i> / May '23 - Present</i></small>
|
||||||
|
</h3>
|
||||||
|
<p>Maintaining and iterating on an internal web application</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
Randstad Technologies<small style="font-weight: normal"
|
||||||
|
><i> / May '22 - May '23</i></small
|
||||||
|
>
|
||||||
|
</h3>
|
||||||
|
<p>Built Web Applications for external clients</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
Damiano Global Corporation<small style="font-weight: normal"
|
||||||
|
><i> / July '20 - Nov. '21</i></small
|
||||||
|
>
|
||||||
|
</h3>
|
||||||
|
<p>Built Web Applications for external clients</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
Makers Ladder LLC<small style="font-weight: normal"
|
||||||
|
><i> / Dec. '19 - Apr. '22</i></small
|
||||||
|
>
|
||||||
|
</h3>
|
||||||
|
<p>Did some thangs</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>🚧 Projects</h2>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/SolarBatteryMonitorApi"
|
||||||
|
target="_blank"
|
||||||
|
>Solar Battery Monitor API</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/armstrong-editor"
|
||||||
|
target="_blank"
|
||||||
|
>Armstrong Editor</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/web-window-manager"
|
||||||
|
target="_blank"
|
||||||
|
>Web Window Manager</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/component-test-helper"
|
||||||
|
target="_blank"
|
||||||
|
>Component Test Helper</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/tristonarmstrong/hive-dapp" target="_blank"
|
||||||
|
>Hive DAPP</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/KivyTwistedInputCapture"
|
||||||
|
target="_blank"
|
||||||
|
>Kivy Twisted Input Capture</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/PlantMonitorNodeMCU"
|
||||||
|
target="_blank"
|
||||||
|
>Plant Monitor Node MCU</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/oppo_bdp_103_CLI"
|
||||||
|
target="_blank"
|
||||||
|
>Oppo BDP 103 CLI</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/tristonarmstrong/sony_bravia_pro_display_mock_server"
|
||||||
|
target="_blank"
|
||||||
|
>Sony Bravia Pro Server</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/tristonarmstrong/chat.io" target="_blank"
|
||||||
|
>Chat IO</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a href="https://github.com/tristonarmstrong/zipapp" target="_blank"
|
||||||
|
>Zip Code Distance App</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>🧰 Tools</h2>
|
||||||
|
<p>
|
||||||
|
<a href="" target="_blank">CSS-Tricks</a>
|
||||||
|
|
|
||||||
|
<a href="" target="_blank">Indie Hackers</a>
|
||||||
|
|
|
||||||
|
<a href="" target="_blank">W3Schools</a>
|
||||||
|
|
|
||||||
|
<a href="https://simpleicons.org" target="_blank">Simple Icons</a>
|
||||||
|
|
|
||||||
|
<a href="https://heroicons.com" target="_blank">Hero Icons</a>
|
||||||
|
|
|
||||||
|
<a href="https://nerdcave.com/tailwind-cheat-sheet" target="_blank"
|
||||||
|
>Tailwind Cheatsheet</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a href="https://tw-elements.com" target="_blank">Tailwind Elements</a>
|
||||||
|
|
|
||||||
|
<a href="https://tailwindcomponents.com" target="_blank"
|
||||||
|
>Tailwind Components</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>🎨 NoCss</h2>
|
||||||
|
<p>
|
||||||
|
<a href="https://watercss.kognise.dev" target="_blank">Water CSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://andybrewer.github.io/mvp/" target="_blank">MPV CSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://hakanalpay.com/bahunya/" target="_blank">Bahunya</a>
|
||||||
|
|
|
||||||
|
<a href="https://mblode.github.io/marx/" target="_blank">Marx</a>
|
||||||
|
|
|
||||||
|
<a href="https://oxal.org/projects/sakura/" target="_blank">Sakura</a>
|
||||||
|
|
|
||||||
|
<a href="https://yegor256.github.io/tacit/" target="_blank">Tacit</a>
|
||||||
|
|
|
||||||
|
<a href="https://newcss.net" target="_blank">New CSS</a>
|
||||||
|
|
|
||||||
|
<a href="https://marcop135.github.io/bullframe.css/" target="_blank"
|
||||||
|
>Bullframe CSS</a
|
||||||
|
>
|
||||||
|
|
|
||||||
|
<a href="https://markdowncss.github.io/modest/" target="_blank"
|
||||||
|
>Markdown CSS (modest)</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<a href="https://github.com/tristonarmstrong">Github</a>
|
||||||
|
|
|
||||||
|
<a href="https://www.linkedin.com/in/triston95strong/">LinkedIn</a>
|
||||||
|
|
|
||||||
|
<a href="https://gitlab.com/Tarmstrong95">GitLab</a>
|
||||||
|
|
|
||||||
|
<a href="https://twitter.com/triston_armstr">Twitter</a>
|
||||||
|
|
|
||||||
|
<a href="https://fosstodon.org/@TristonArmstrong">Fosstodon</a>
|
||||||
|
<p><small>©2023-2024 Triston Armstrong. All rights reserved.</small></p>
|
||||||
|
</footer>
|
||||||
|
{% endblock %}
|
17
templates/styles.css
Normal file
17
templates/styles.css
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
:root {
|
||||||
|
--background-body: #0d1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table,
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
11
templates/tuts.html
Normal file
11
templates/tuts.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %} {% block title %}Micro Tuts{% endblock %} {% block
|
||||||
|
content %}
|
||||||
|
<nav>
|
||||||
|
<small>
|
||||||
|
<a href="/"><~ back</a>
|
||||||
|
</small>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>Notes</h1>
|
||||||
|
<p>Here all my Micro Tuts go</p>
|
||||||
|
{% endblock content%}
|
Loading…
Reference in New Issue
Block a user