Initial Commit

This commit is contained in:
Robin Bärtschi 2025-02-13 15:20:52 +01:00
commit 47453b8a02
13 changed files with 251 additions and 0 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
node_modules
Dockerfile*
docker-compose*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode
Makefile
helm-charts
.env
.editorconfig
.idea
coverage*

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# deps
node_modules/

38
Dockerfile Normal file
View File

@ -0,0 +1,38 @@
# use the official Bun image
# see all versions at https://hub.docker.com/r/oven/bun/tags
FROM oven/bun:1 AS base
WORKDIR /usr/src/app
# install dependencies into temp directory
# this will cache them and speed up future builds
FROM base AS install
RUN mkdir -p /temp/dev
COPY package.json bun.lock /temp/dev/
RUN cd /temp/dev && bun install --frozen-lockfile
# install with --production (exclude devDependencies)
RUN mkdir -p /temp/prod
COPY package.json bun.lock /temp/prod/
RUN cd /temp/prod && bun install --frozen-lockfile --production
# copy node_modules from temp directory
# then copy all (non-ignored) project files into the image
FROM base AS prerelease
COPY --from=install /temp/dev/node_modules node_modules
COPY . .
# [optional] tests & build
ENV NODE_ENV=production
RUN bun test
RUN bun run build
# copy production dependencies and source code into final image
FROM base AS release
COPY --from=install /temp/prod/node_modules node_modules
COPY --from=prerelease /usr/src/app/index.ts .
COPY --from=prerelease /usr/src/app/package.json .
# run the app
USER bun
EXPOSE 3000/tcp
ENTRYPOINT [ "bun", "run", "index.ts" ]

11
README.md Normal file
View File

@ -0,0 +1,11 @@
To install dependencies:
```sh
bun install
```
To run:
```sh
bun run dev
```
open http://localhost:3000

32
bun.lock Normal file
View File

@ -0,0 +1,32 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "dockyfied",
"dependencies": {
"hono": "^4.7.1",
},
"devDependencies": {
"@types/bun": "latest",
"typed-htmx": "^0.3.1",
},
},
},
"packages": {
"@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="],
"@types/node": ["@types/node@22.13.2", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg=="],
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
"bun-types": ["bun-types@1.2.2", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg=="],
"hono": ["hono@4.7.1", "", {}, "sha512-V3eWoPkBxoNgFCkSc5Y5rpLF6YoQQx1pkYO4qrF6YfOw8RZbujUNlJLZCxh0z9gZct70+je2Ih7Zrdpv21hP9w=="],
"typed-html": ["typed-html@3.0.1", "", {}, "sha512-JKCM9zTfPDuPqQqdGZBWSEiItShliKkBFg5c6yOR8zth43v763XkAzTWaOlVqc0Y6p9ee8AaAbipGfUnCsYZUA=="],
"typed-htmx": ["typed-htmx@0.3.1", "", { "dependencies": { "typed-html": "^3.0.1" } }, "sha512-6WSPsukTIOEMsVbx5wzgVSvldLmgBUVcFIm2vJlBpRPtcbDOGC5y1IYrCWNX1yUlNsrv1Ngcw4gGM8jsPyNV7w=="],
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
}
}

13
package.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "dockyfied",
"scripts": {
"dev": "bun run --watch src/index.tsx"
},
"dependencies": {
"hono": "^4.7.1"
},
"devDependencies": {
"@types/bun": "latest",
"typed-htmx": "^0.3.1"
}
}

28
src/BaseDocument.tsx Normal file
View File

@ -0,0 +1,28 @@
import { html } from 'hono/html';
import { Child, } from 'hono/jsx';
interface SiteData {
title: string;
children?: Child;
}
function BaseDocument(props: SiteData) {
return html`
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="utf-8" />
<meta name="viewport" content='width=device-width, initial-scale=1' />
<link rel="stylesheet" href="/static/style.css"/>
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<title>${props.title}</title>
</head>
<body hx-boost="true">
${props.children}
</body>
</html>
`
};
export default BaseDocument;

10
src/global.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
import "typed-htmx";
//
// A demo of how to augment foreign types with htmx attributes.
// In this case, Hono sources its types from its own namespace, so we do the same
// and directly extend its namespace.
declare module 'hono/jsx' {
namespace JSX {
interface HTMLAttributes extends HtmxAttributes { }
}
}

49
src/index.tsx Normal file
View File

@ -0,0 +1,49 @@
import { Hono } from 'hono';
import { serveStatic } from 'hono/bun';
import { logger } from 'hono/logger';
import BaseDocument from './BaseDocument';
function ImageButton() {
return <button hx-get='/image' hx-target='this' hx-swap="outerHTML">See Image</button>;
}
const app = new Hono();
app.use(logger())
app.use('/static/*', serveStatic({ root: './' }));
app.get('/', (c) => {
return c.html(
<BaseDocument title='Dockyfied'>
<h1>This is a Dockyfied website</h1>
<p>Build using <a href='https://htmx.org/'>htmx</a>.</p>
<ImageButton />
</BaseDocument>
);
});
app.get(
'/image',
c => {
return c.html(
<div id="image">
<img hx-get='/image-button' id="image-button" hx-swap='outerHTML' style={'height: 250px;'} src='/static/image.png' hx-target='#image' />
<p>&uarr;</p>
<p>Click the image above to replace with the button again.</p>
<br />
<p id='secret' hx-swap='outerHTML' hx-get='/image2'>Another image?</p>
</div>
);
}
);
app.get('/image2',
c => c.html(<img style={'height: 190px;'} src='/static/image2.png' />)
);
app.get(
'/image-button',
c => c.html(<ImageButton />)
);
export default app;

BIN
static/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

BIN
static/image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

29
static/style.css Normal file
View File

@ -0,0 +1,29 @@
body {
font-family: Arial, Helvetica, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
#image {
height: fit-content;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#image-button:hover {
cursor: pointer;
}
#secret {
font-size: 0.4em;
}
#secret:hover {
cursor: pointer;
}

24
tsconfig.json Normal file
View File

@ -0,0 +1,24 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES6",
"strict": true,
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"module": "node16",
"moduleResolution": "node16",
"allowJs": true,
"checkJs": true,
"noEmit": true,
"rootDir": ".",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true,
},
"include": [
"src/**/*"
]
}
}