Skip to content

Commit 65eb33a

Browse files
committed
Improve landing page
1 parent ece91a2 commit 65eb33a

File tree

4 files changed

+148
-120
lines changed

4 files changed

+148
-120
lines changed

README.md

Lines changed: 22 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,34 @@
1-
# hyperwave 🌊
1+
# hyperwave
22

3-
hyperwave is a server-side framework for building web applications.
3+
hyperwave combines the benefits of traditional server-rendered applications with the flexibility of modern client-side frameworks.
44

5-
- fast: tiny payloads with no bloated client side rendering
6-
- productive: build _really_ fast with htmx, tailwind, tsx, hyperscript
7-
- ergonomic: best tooling of modern tooling combined with rock solid app architecture
8-
- portable: compile a binary to deploy anywhere
5+
- **Performance:** Server-side rendering ensures fast, responsive applications, tailored to produce the smallest possible bundles.
6+
- **Developer experience:** HTMX and Tailwind provide a minimalistic and declarative approach to building user interfaces
7+
- **Deployment:** bun applications can be easily deployed on any platform as portable binaries
98

10-
### Motivation
9+
## Getting started
1110

12-
- Drastically reduce time from idea to rendered UI
13-
- Very little cognitive friction to creating something new, after initial learning curve
11+
Follow these steps to start developing with hyperwave:
1412

15-
### Comparison
13+
1. Clone the repository:
1614

17-
![image](https://github.com/tireymorris/hyperwave/assets/3528600/561b5536-5660-469d-b80a-9883f45ab676)
15+
```sh
16+
git clone https://github.com/tireymorris/hyperwave.git
17+
cd hyperwave
18+
```
1819

19-
### Setup
20+
2. Install dependencies:
2021

21-
`bun dev`
22+
```sh
23+
bun install
24+
```
2225

23-
Visit port 1234 and edit `server.tsx`
26+
3. Start the development server:
2427

25-
---
28+
```sh
29+
bun dev
30+
```
2631

27-
### Example
32+
4. Visit `http://localhost:1234` in your browser.
2833

29-
This is the endpoint serving an example landing page:
30-
31-
```typescript
32-
app.get("/", ({ html }) =>
33-
html(
34-
<Layout title="hyperwave 🌊">
35-
<section class="flex flex-col gap-8">
36-
<div>
37-
<button
38-
class="bg-blue-100 p-4 text-sm font-bold rounded-md shadow-sm"
39-
hx-get="/instructions"
40-
hx-target="closest div"
41-
_="on click toggle .loading"
42-
>
43-
fetch instructions from <code>/instructions</code>
44-
</button>
45-
</div>
46-
</section>
47-
</Layout>,
48-
),
49-
);
50-
```
51-
52-
- The API serves a full HTML document to the client, which includes Tailwind classes and HTMX attributes
53-
- The response is wrapped in a `<Layout />` tag, a server-rendered functional component, which takes a `title` prop
54-
- The button, when clicked, will issue a `GET` request to `/instructions` and replace the content of its parent div with the response.
55-
- Includes a tiny hyperscript to toggle a class when the button is clicked
56-
57-
---
58-
59-
### Deployment
60-
61-
Build an executable for your current architecture with `bun run build`
62-
63-
`PORT` environment variable is available if needed (default is 1234)
64-
65-
Note: deploy `public/` with the executable, it contains the generated UnoCSS build.
66-
67-
---
68-
69-
### Components
70-
71-
- [bun](https://bun.sh/) provides the bundler, runtime, test runner, and package manager.
72-
- [SQLite](https://bun.sh/docs/api/sqlite) is production-ready and built into Bun.
73-
- [hono](https://hono.dev) is a robust web framework with great DX and performance
74-
- [unoCSS](https://unocss.dev/integrations/cli) is Tailwind-compatible and generates only the styles used in application code.
75-
- [htmx](https://htmx.org/reference/) gives 99% of the client-side interactivity most apps need.
76-
- [hyperscript](http://hyperscript.org) is a scripting library for rapid application development.
77-
- [zod](https://zod.dev/) is a powerful runtime validation library.
78-
79-
---
80-
81-
### Why switch?
82-
83-
**Speed and performance**
84-
85-
- hyperwave is designed to generate the smallest possible payloads
86-
- hono generally benchmarks better than any comparable server
87-
88-
**Simplicity**
89-
90-
- Bun saves us a ton of time and effort fighting tooling issues
91-
- SPAs are over-prescribed and inherently introduce serious costs
92-
93-
**Developer experience**
94-
95-
- Better primitives for quickly building UX
96-
- Uniform interface simplifies writing and reading code
97-
98-
**Architectural benefit**
99-
100-
- Can scale backend and product independently, loosely coupled
101-
- Deployment is as simple as compiling and running a binary 😎
34+
5. Start editing `server.tsx` to see your changes live.

public/styles/uno.css

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,80 @@
1919
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
2020
}
2121

22+
/* layer: shortcuts */
23+
.container{width:100%;}
24+
@media (min-width: 640px){
25+
.container{max-width:640px;}
26+
}
27+
@media (min-width: 768px){
28+
.container{max-width:768px;}
29+
}
30+
@media (min-width: 1024px){
31+
.container{max-width:1024px;}
32+
}
33+
@media (min-width: 1280px){
34+
.container{max-width:1280px;}
35+
}
36+
@media (min-width: 1536px){
37+
.container{max-width:1536px;}
38+
}
2239
/* layer: default */
2340
.m-0{margin:0;}
24-
.m-auto{margin:auto;}
41+
.mx-auto{margin-left:auto;margin-right:auto;}
42+
.mb-4{margin-bottom:1rem;}
43+
.mb-6{margin-bottom:1.5rem;}
44+
.mt-4{margin-top:1rem;}
45+
.mt-6{margin-top:1.5rem;}
2546
.h-8{height:2rem;}
26-
.h-full{height:100%;}
47+
.h-auto{height:auto;}
48+
.max-w-4xl{max-width:56rem;}
49+
.min-h-screen{min-height:100vh;}
50+
.w-full{width:100%;}
2751
.flex{display:flex;}
28-
.flex-col{flex-direction:column;}
2952
.cursor-pointer{cursor:pointer;}
53+
.list-disc{list-style-type:disc;}
54+
.list-inside{list-style-position:inside;}
3055
.items-center{align-items:center;}
3156
.justify-center{justify-content:center;}
3257
.gap-3{gap:0.75rem;}
33-
.gap-8{gap:2rem;}
3458
.border{border-width:1px;}
3559
.border-gray-2{--un-border-opacity:1;border-color:rgb(229 231 235 / var(--un-border-opacity));}
3660
.focus\:border-blue-200:focus{--un-border-opacity:1;border-color:rgb(191 219 254 / var(--un-border-opacity));}
61+
.rounded{border-radius:0.25rem;}
62+
.rounded-lg{border-radius:0.5rem;}
3763
.rounded-md{border-radius:0.375rem;}
3864
.border-none{border-style:none;}
3965
.border-solid{border-style:solid;}
40-
.bg-blue-100{--un-bg-opacity:1;background-color:rgb(219 234 254 / var(--un-bg-opacity));}
41-
.bg-blue-200{--un-bg-opacity:1;background-color:rgb(191 219 254 / var(--un-bg-opacity));}
4266
.bg-blue-300{--un-bg-opacity:1;background-color:rgb(147 197 253 / var(--un-bg-opacity));}
43-
.bg-slate-200{--un-bg-opacity:1;background-color:rgb(226 232 240 / var(--un-bg-opacity));}
67+
.bg-purple-600{--un-bg-opacity:1;background-color:rgb(147 51 234 / var(--un-bg-opacity));}
4468
.bg-transparent{background-color:transparent;}
69+
.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity));}
4570
.hover\:bg-blue-400:hover{--un-bg-opacity:1;background-color:rgb(96 165 250 / var(--un-bg-opacity));}
46-
.p-0{padding:0;}
47-
.px-10{padding-left:2.5rem;padding-right:2.5rem;}
71+
.hover\:bg-purple-700:hover{--un-bg-opacity:1;background-color:rgb(126 34 206 / var(--un-bg-opacity));}
72+
.active\:bg-purple-800:active{--un-bg-opacity:1;background-color:rgb(107 33 168 / var(--un-bg-opacity));}
73+
.from-blue-300{--un-gradient-from-position:0%;--un-gradient-from:rgb(147 197 253 / var(--un-from-opacity, 1)) var(--un-gradient-from-position);--un-gradient-to-position:100%;--un-gradient-to:rgb(147 197 253 / 0) var(--un-gradient-to-position);--un-gradient-stops:var(--un-gradient-from), var(--un-gradient-to);}
74+
.via-purple-300{--un-gradient-via-position:50%;--un-gradient-to:rgb(216 180 254 / 0);--un-gradient-stops:var(--un-gradient-from), rgb(216 180 254 / var(--un-via-opacity, 1)) var(--un-gradient-via-position), var(--un-gradient-to);}
75+
.to-pink-300{--un-gradient-to-position:100%;--un-gradient-to:rgb(249 168 212 / var(--un-to-opacity, 1)) var(--un-gradient-to-position);}
76+
.bg-gradient-to-br{--un-gradient-shape:to bottom right;--un-gradient:var(--un-gradient-shape), var(--un-gradient-stops);background-image:linear-gradient(var(--un-gradient));}
77+
.p-8{padding:2rem;}
4878
.px-4{padding-left:1rem;padding-right:1rem;}
4979
.py-1{padding-top:0.25rem;padding-bottom:0.25rem;}
80+
.py-10{padding-top:2.5rem;padding-bottom:2.5rem;}
5081
.py-2{padding-top:0.5rem;padding-bottom:0.5rem;}
51-
.py-8{padding-top:2rem;padding-bottom:2rem;}
5282
.pl-3{padding-left:0.75rem;}
5383
.pr-10{padding-right:2.5rem;}
84+
.text-2xl{font-size:1.5rem;line-height:2rem;}
5485
.text-base{font-size:1rem;line-height:1.5rem;}
5586
.text-sm{font-size:0.875rem;line-height:1.25rem;}
87+
.text-blue-600{--un-text-opacity:1;color:rgb(37 99 235 / var(--un-text-opacity));}
88+
.text-gray-900{--un-text-opacity:1;color:rgb(17 24 39 / var(--un-text-opacity));}
5689
.text-neutral-500{--un-text-opacity:1;color:rgb(115 115 115 / var(--un-text-opacity));}
90+
.text-purple-600{--un-text-opacity:1;color:rgb(147 51 234 / var(--un-text-opacity));}
5791
.text-slate-900{--un-text-opacity:1;color:rgb(15 23 42 / var(--un-text-opacity));}
92+
.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity));}
5893
.font-bold{font-weight:700;}
59-
.font-lato{font-family:"Lato";}
94+
.font-semibold{font-weight:600;}
95+
.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";}
96+
.shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgb(0 0 0 / 0.1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgb(0 0 0 / 0.1));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
6097
.shadow-md{--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgb(0 0 0 / 0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgb(0 0 0 / 0.1));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
6198
.outline{outline-style:solid;}

src/components/Layout.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
type Props = {
1+
export type LayoutProps = {
22
title: string;
33
currentPath?: string;
44
children: any;
55
};
66

7-
export default function Layout({ title, children }: Props) {
7+
export default function Layout({ title, children }: LayoutProps) {
88
return (
99
<html lang="en" hx-boost="true" hx-swap="outerHTML transition:true">
1010
<head>
@@ -21,9 +21,10 @@ export default function Layout({ title, children }: Props) {
2121
<script>htmx.config.globalViewTransitions = true</script>
2222
<script src="https://unpkg.com/[email protected]"></script>
2323
</head>
24-
2524
<style>{`* { box-sizing: border-box; margin: 0; outline: none; color: unset; }`}</style>
26-
<body class="font-lato m-0 bg-blue-100 p-0 text-base">{children}</body>
25+
<body class="font-sans m-0 bg-gradient-to-br from-blue-300 via-purple-300 to-pink-300 text-gray-900 min-h-screen">
26+
{children}
27+
</body>
2728
</html>
2829
);
2930
}

src/server.tsx

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,89 @@
11
import { Hono } from "hono";
22
import { serveStatic } from "hono/bun";
33
import { logger } from "hono/logger";
4+
import Button from "./components/Button.tsx";
45
import Layout from "./components/Layout.tsx";
56

67
const app = new Hono();
78

89
app.use("/styles/*", serveStatic({ root: "./public/" }));
910
app.use("*", logger());
1011

11-
app.get("/", (c) =>
12-
c.html(
12+
app.get("/", async (c) => {
13+
return c.html(
1314
<Layout title="hyperwave">
14-
<main class="m-auto flex h-full flex-col items-center gap-8 px-10 py-8">
15-
<h1>🌊 welcome to hyperwave</h1>
16-
<pre class="rounded-md bg-blue-200 px-4 py-2">
17-
⌨️ edit <code class="bg-slate-200">src/server.tsx</code>
18-
</pre>
19-
<pre class="rounded-md bg-blue-200 px-4 py-2">
20-
📚 read the{" "}
21-
<a href="https://github.com/tireymorris/hyperwave?tab=readme-ov-file#hyperwave-">
22-
friendy manual
23-
</a>
24-
!
25-
</pre>
15+
<main class="container mx-auto py-10 px-4">
16+
<div class="max-w-4xl mx-auto bg-white shadow-lg rounded-lg p-8">
17+
<section class="mb-6">
18+
<h2 class="text-2xl font-semibold text-blue-600 mb-4">
19+
What is hyperwave?
20+
</h2>
21+
<p class="mb-4">
22+
hyperwave combines the benefits of traditional server-rendered
23+
applications with the flexibility of modern client-side
24+
frameworks. This blend results in fast load times, efficient
25+
development workflows, and easy deployment.
26+
</p>
27+
<ul class="list-disc list-inside">
28+
<li>Minimal payloads for quick load times</li>
29+
<li>
30+
Built with HTMX, Tailwind, and TSX for streamlined development
31+
</li>
32+
<li>Deployable as a binary for flexibility</li>
33+
</ul>
34+
</section>
35+
<section class="mb-6">
36+
<h2 class="text-2xl font-semibold text-purple-600 mb-4">
37+
Benefits of hyperwave
38+
</h2>
39+
<p class="mb-4">
40+
hyperwave offers several advantages that cater to modern web
41+
development needs:
42+
</p>
43+
<ul class="list-disc list-inside">
44+
<li>
45+
<strong>Performance:</strong> Server-side rendering ensures
46+
fast, responsive applications by reducing client-side
47+
processing.
48+
</li>
49+
<li>
50+
<strong>Developer Experience:</strong> HTMX and Tailwind CSS
51+
provide a minimalistic and declarative approach to building user
52+
interfaces.
53+
</li>
54+
<li>
55+
<strong>Deployment:</strong> hyperwave applications can be
56+
compiled into binaries, making them easy to deploy across
57+
different environments.
58+
</li>
59+
</ul>
60+
</section>
61+
<Button
62+
class="bg-purple-600 hover:bg-purple-700 active:bg-purple-800 text-white font-bold py-2 px-4 rounded mt-4"
63+
hx-get="/comparison"
64+
hx-target="#content"
65+
hx-swap="innerHTML"
66+
>
67+
See comparison
68+
</Button>
69+
<div id="content" class="mt-6"></div>
70+
</div>
2671
</main>
2772
</Layout>,
28-
),
29-
);
73+
);
74+
});
75+
76+
app.get("/comparison", async (c) => {
77+
return c.html(
78+
<div class="max-w-4xl mx-auto bg-white shadow-lg rounded-lg p-8">
79+
<img
80+
src="https://github.com/tireymorris/hyperwave/assets/3528600/561b5536-5660-469d-b80a-9883f45ab676"
81+
alt="Comparison"
82+
class="mb-4 rounded w-full h-auto"
83+
/>
84+
</div>,
85+
);
86+
});
3087

3188
export default {
3289
port: process.env.PORT || 1234,

0 commit comments

Comments
 (0)