# 🎪 hype
░▒▓███████████████████████████████████████████████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░░▒▓████████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
░▒▓████████▓▒░░▒▓██████▓▒░░▒▓███████▓▒░░▒▓██████▓▒░
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░
░▒▓███████████████████████████████████████████████▓▒░
`hype` wraps `hono` with useful features for fast prototyping:
- HTTP logging to the console (disable with `NO_HTTP_LOG` env variable)
- Static files served from `pub/`
- Page-based routing to `.tsx` files that export a `JSX` function in `./src/pages`
- Transpile `.ts` files in `src/client/blah.ts` via `website.com/client/blah.ts`
- Helpers like `css` and `js` template tags.
- Default, simple HTML5 layout with working frontend transpilation/bundling, or supply your own.
- Optional CSS reset.
- Optional pico.css.
## Overview
Your project structure should be:
```
.
├── README.md
├── package.json
├── pub
│  ├── asset.txt
│  └── img
│  └── logo.png
├── src
│  ├── css
│  │  └── main.css
│  ├── client
│  │  ├── about.ts
│  │  └── main.ts
│  ├── shared
│  │  └── utils.ts
│  ├── pages
│  │  ├── _layout.tsx
│  │  ├── about.tsx
│  │  └── index.tsx
│  └── server
│  └── index.ts
└── tsconfig.json
```
### URLs
In the above, `/about` will render `./src/pages/about.tsx`.
The `req` JSX prop will be given the `Hono` request:
export default ({ req }) => `Query Param 'id': ${req.query('id')}`
To put a file in `./src/pages` but prevent it from being server, preface it with `_`.
### SPA Shell Mode
If `src/client/index.tsx` (or `src/client/index.ts`) exists, hype automatically serves a minimal HTML shell at `/` - no `src/pages/index.tsx` needed.
```
src/
client/
index.tsx <- This triggers SPA shell mode!
server/
index.ts
```
The shell HTML served at `/`:
```html
App
```
Your client code mounts to `#app`:
```tsx
// src/client/index.tsx
import { render } from 'hono/jsx/dom'
function App() {
return
Hello from the SPA!
}
render(, document.getElementById('app')!)
```
See `examples/spa-shell` for a complete example.
### Layout
`hype` will wrap everything in a simple default layout unless `./src/pages/_layout.tsx` exists,
in which case it'll use the default export in that file.
You can also create hype with `new Hype({ layout: false })` to disable Hype's default.
Using the default layout, you can put TS in `./src/client/main.ts` and css in `./src/css/main.css`.
They'll automatically work in your app.
Here's a starting point:
```tsx
export default ({ children, title }: any) => (
{title ?? "hype"}{children}
)
```
### pico.css
To use pico.css with the default layout, create `Hype` with `{ pico: true }`:
```typescript
import { Hype } from "hype"
const app = new Hype({ pico: true })
```
You can also use pico in your custom layouts:
```html
```
### css
CSS can be accessed via `/css/main.css`:
```html
```
Or written inline using the `css` template tag:
```tsx
import { css } from "hype"
export default () => (
{css`
* {
color: red;
}
`}
Hello
)
```
Install the `vscode-styled-components` VSCode extension to highlight inline `css` tags!
### css reset
To use reset.css with the default layout, create `Hype` with `{ reset: true }`:
```typescript
import { Hype } from "hype"
const app = new Hype({ reset: true })
```
You can also use the css reset in your custom layouts:
```html
```
### js
JS can be accessed (and transpiled) via `/client/main.ts` or `/shared/utils.ts`:
```html
```
import your modules relatively, for example in `main.ts`:
```typescript
import { initAbout } from "./about"
import utils from "./shared/utils"
```
Or written inline as transpiled typescript using the `js` template tag:
```tsx
import { js } from "hype"
export default () => (
{js`
window.onload = () => alert(welcomeMsg(Date.now()))
function welcomeMsg(time: number): string {
return "Welcome to my website!"
}
`}
Hello!
)
```
Install the `vscode-styled-components` VSCode extension to highlight inline `js` tags!
### pub
Anything in `pub/` is served as-is. Simple stuff.
### Server-Sent Events (SSE)
`hype` provides a simple `app.sse()` helper for streaming data to clients:
```typescript
import { Hype } from "hype"
const app = new Hype()
// Stream current time every second
app.sse('/api/time', (send) => {
send({ time: Date.now() })
const interval = setInterval(() => send({ time: Date.now() }), 1000)
return () => clearInterval(interval) // cleanup on disconnect
})
```
The `send()` function:
- Automatically JSON.stringify's objects (strings are sent as-is)
- Accepts an optional second parameter for named events: `send(data, 'eventName')`
The handler can return a cleanup function that's called when the client disconnects.
You also have access to the Hono context as the second parameter:
```typescript
app.sse('/api/user-events', (send, c) => {
const userId = c.req.query('userId')
// ... subscribe to user-specific events
})
```
**Client-side usage:**
```typescript
const events = new EventSource('/api/time')
events.onmessage = (e) => {
const data = JSON.parse(e.data)
console.log('Time:', data.time)
}
// For named events:
events.addEventListener('eventName', (e) => {
console.log('Got event:', e.data)
})
```
Test with curl:
```sh
curl -N http://localhost:3000/api/time
```
### utils
`hype` includes helpful utils for your webapp:
- `capitalize(str: string): string` - Capitalizes a word
- `css` Template Tag - Lets you inline CSS in your TSX. Returns a `