277 lines
8.1 KiB
Markdown
277 lines
8.1 KiB
Markdown
# 🎪 hype
|
|
|
|
░▒▓███████████████████████████████████████████████▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░░▒▓████████▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
|
|
░▒▓████████▓▒░░▒▓██████▓▒░░▒▓███████▓▒░░▒▓██████▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
|
|
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░
|
|
░▒▓███████████████████████████████████████████████▓▒░
|
|
|
|
`hype` wraps `hono` with useful features for fast prototyping:
|
|
|
|
- HTTP logging (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/js/blah.ts` via `website.com/js/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
|
|
│ ├── js
|
|
│ │ ├── about.ts
|
|
│ │ └── main.ts
|
|
│ ├── shared
|
|
│ │ └── utils.ts
|
|
│ ├── pages
|
|
│ │ ├── _layout.tsx
|
|
│ │ ├── about.tsx
|
|
│ │ └── index.tsx
|
|
│ └── server.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 `_`.
|
|
|
|
### 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.
|
|
|
|
Using the default layout, you can put TS in `./src/js/main.ts` and css in `./src/css/main.css`
|
|
and they'll automatically work in your app.
|
|
|
|
Here's a starting point:
|
|
|
|
```tsx
|
|
export default ({ children, title }: any) => (
|
|
<html lang="en">
|
|
<head>
|
|
<title>{title ?? "hype"}</title>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
<link href="/css/main.css" rel="stylesheet" />
|
|
<script src="/js/main.ts" type="module"></script>
|
|
</head>
|
|
<body>
|
|
<main>{children}</main>
|
|
</body>
|
|
</html>
|
|
)
|
|
```
|
|
|
|
### 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
|
|
<link href="/css/pico.css" rel="stylesheet" />
|
|
```
|
|
|
|
### css
|
|
|
|
CSS can be accessed via `/css/main.css`:
|
|
|
|
```html
|
|
<link href="/css/main.css" rel="stylesheet" />
|
|
```
|
|
|
|
Or written inline using the `css` template tag:
|
|
|
|
```tsx
|
|
import { css } from "hype"
|
|
|
|
export default () => (
|
|
<div>
|
|
{css`
|
|
* {
|
|
color: red;
|
|
}
|
|
`}
|
|
<h1>Hello</h1>
|
|
</div>
|
|
)
|
|
```
|
|
|
|
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
|
|
<link href="/css/reset.css" rel="stylesheet" />
|
|
```
|
|
|
|
### js
|
|
|
|
JS can be accessed (and transpiled) via `/js/main.ts` or `/shared/utils.ts`:
|
|
|
|
```html
|
|
<script src="/js/main.ts" type="module"></script>
|
|
```
|
|
|
|
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 () => (
|
|
<div>
|
|
{js`
|
|
window.onload = () => alert(welcomeMsg(Date.now()))
|
|
|
|
function welcomeMsg(time: number): string {
|
|
return "Welcome to my website!"
|
|
}
|
|
`}
|
|
<h1>Hello!</h1>
|
|
</div>
|
|
)
|
|
```
|
|
|
|
Install the `vscode-styled-components` VSCode extension to highlight inline `js` tags!
|
|
|
|
### pub
|
|
|
|
Anything in `pub/` is served as-is. Simple stuff.
|
|
|
|
### 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 `<style>` tag
|
|
- `darkenColor(hex: string, opacity: number): string` - Darken a hex color by blending with black. opacity 1 = original, 0 = black
|
|
- `isDarkMode(): boolean` - Check if the user prefers dark mode
|
|
- `js` Template Tag - Lets you inline JavaScript in your TSX. Transpiles and returns a `<script>` tag
|
|
- `lightenColor(hex: string, opacity: number): string` - Lighten a hex color by blending with white. opacity 1 = original, 0 = white
|
|
- `rand(end = 2, startAtZero = false): number` - Generate random integer. `rand(2)` flips a coin, `rand(6)` rolls a die, `rand(20)` rolls d20
|
|
- `randIndex<T>(list: T[]): number | undefined` - Get a random index from an array. `randIndex([5, 7, 9])` returns `0`, `1`, or `2`
|
|
- `randItem<T>(list: T[]): T | undefined` - Get a random item from an array. `randItem([5, 7, 9])` returns `5`, `7`, or `9`
|
|
- `randomId(): string` - Generate a 6 character random ID
|
|
- `randRange(start = 0, end = 12): number` - Generate random integer in range. `randRange(1, 6)` rolls a die
|
|
- `redirectBack(c: Context, fallback = "/"): Response` - Redirect to the referrer, or fallback if no referrer
|
|
- `times(n: number): number[]` - Generate array of integers. `times(3)` returns `[1, 2, 3]`
|
|
- `transpile(path: string): Promise<string>` - Transpile a TypeScript file at `path` to JavaScript (cached by mtime)
|
|
- `unique<T>(array: T[]): T[]` - Remove duplicates from array. `unique([1,1,2,2,3,3])` returns `[1,2,3]`
|
|
- `weightedRand(): number` - Generate random number between 1 and 10 with decreasing probability (1 is most likely, 10 is least)
|
|
|
|
## Setup
|
|
|
|
0. Add the dependency to your project:
|
|
|
|
```sh
|
|
bun add git+https://git.nose.space/defunkt/hype
|
|
```
|
|
|
|
1. Add `dev` and `start` to `package.json`:
|
|
|
|
```json
|
|
"scripts": {
|
|
"start": "bun run src/server.ts",
|
|
"dev": "bun run --hot src/server.ts"
|
|
},
|
|
```
|
|
|
|
2. Use our `tsconfig.json`:
|
|
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"lib": ["ESNext", "DOM"],
|
|
"target": "ESNext",
|
|
"module": "Preserve",
|
|
"moduleDetection": "force",
|
|
"jsx": "react-jsx",
|
|
"jsxImportSource": "hono/jsx",
|
|
"allowJs": true,
|
|
"moduleResolution": "bundler",
|
|
"allowImportingTsExtensions": true,
|
|
"verbatimModuleSyntax": true,
|
|
"noEmit": true,
|
|
"strict": true,
|
|
"skipLibCheck": true,
|
|
"noFallthroughCasesInSwitch": true,
|
|
"noUncheckedIndexedAccess": true,
|
|
"noImplicitOverride": true,
|
|
"noUnusedLocals": false,
|
|
"noUnusedParameters": false,
|
|
"noPropertyAccessFromIndexSignature": false,
|
|
"baseUrl": ".",
|
|
"paths": {
|
|
"#*": ["src/*"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
3. Use `Hype` just like `Hono` in your `src/server.ts`, exporting `app.defaults`:
|
|
|
|
```typescript
|
|
import { Hype } from "hype"
|
|
|
|
const app = new Hype()
|
|
|
|
app.get("/my-custom-routes", (c) => c.text("wild, wild stuff"))
|
|
|
|
export default app.defaults
|
|
```
|
|
|
|
4. Enter dev mode
|
|
|
|
```sh
|
|
bun install
|
|
bun dev
|
|
```
|