Enable dev mode for React app with proxy support; refine build, styles, and UI.
- Adjusted `package.json` scripts for Bun dev server and build flow. - Added `dev.html` for standalone web development with hot-reload enabled. - Introduced `WebDisableEmbedded` and `WebDevProxyURL` configurations to support proxying non-API paths. - Refactored server logic to handle reverse proxy for development mode. - Updated `App.jsx` structure, styles, and layout for responsiveness and dynamic padding. - Improved login interface with logo support and cleaner design. - Enhanced development flow documentation in `README.md`.
This commit is contained in:
@@ -9,12 +9,41 @@ This is a React web application that uses Bun for building and bundling, and is
|
||||
|
||||
## Development
|
||||
|
||||
To run the development server:
|
||||
There are two ways to develop the web app:
|
||||
|
||||
1) Standalone (recommended for hot reload)
|
||||
- Start the Go relay with the embedded web UI disabled so the React app can run on its own dev server with HMR.
|
||||
- Configure the relay via environment variables:
|
||||
|
||||
```bash
|
||||
# In another shell at repo root
|
||||
export ORLY_WEB_DISABLE=true
|
||||
# Optional: if you want same-origin URLs, you can set a proxy target and access the relay on the same port
|
||||
# export ORLY_WEB_DEV_PROXY_URL=http://localhost:5173
|
||||
|
||||
# Start the relay as usual
|
||||
go run .
|
||||
```
|
||||
|
||||
- Then start the React dev server:
|
||||
|
||||
```bash
|
||||
cd app/web
|
||||
bun install
|
||||
bun run dev
|
||||
bun dev
|
||||
```
|
||||
|
||||
When ORLY_WEB_DISABLE=true is set, the Go server still serves the API and websocket endpoints and sends permissive CORS headers, so the dev server can access them cross-origin. If ORLY_WEB_DEV_PROXY_URL is set, the Go server will reverse-proxy non-/api paths to the dev server so you can use the same origin.
|
||||
|
||||
2) Embedded (no hot reload)
|
||||
- Build the web app and run the Go server with defaults:
|
||||
|
||||
```bash
|
||||
cd app/web
|
||||
bun install
|
||||
bun run build
|
||||
cd ../../
|
||||
go run .
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "bun run --hot src/index.jsx",
|
||||
"build": "bun build ./src/index.jsx --outdir ./dist --minify && mkdir -p dist && cp -r public/* dist/",
|
||||
"start": "bun run dist/index.js"
|
||||
"dev": "bun --hot --port 5173 public/dev.html",
|
||||
"build": "rm -rf dist && bun build ./public/index.html --outdir ./dist --minify --splitting && cp -r public/tailwind.min.css dist/",
|
||||
"preview": "bun x serve dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
|
||||
13
app/web/public/dev.html
Normal file
13
app/web/public/dev.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Nostr Relay (Dev)</title>
|
||||
<link rel="stylesheet" href="tailwind.min.css" />
|
||||
</head>
|
||||
<body class="bg-white">
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
||||
function App() {
|
||||
const [user, setUser] = useState(null);
|
||||
@@ -8,6 +8,23 @@ function App() {
|
||||
|
||||
const [checkingAuth, setCheckingAuth] = useState(true);
|
||||
|
||||
// Login view layout measurements
|
||||
const titleRef = useRef(null);
|
||||
const [loginPadding, setLoginPadding] = useState(16); // default fallback padding in px
|
||||
|
||||
useEffect(() => {
|
||||
function updatePadding() {
|
||||
if (titleRef.current) {
|
||||
const h = titleRef.current.offsetHeight || 0;
|
||||
// Pad area around the text by half the title text height
|
||||
setLoginPadding(Math.max(0, Math.round(h / 2)));
|
||||
}
|
||||
}
|
||||
updatePadding();
|
||||
window.addEventListener('resize', updatePadding);
|
||||
return () => window.removeEventListener('resize', updatePadding);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Check authentication status on page load
|
||||
(async () => {
|
||||
@@ -357,22 +374,35 @@ function App() {
|
||||
</div>
|
||||
) : (
|
||||
// Not logged in view - shows the login form
|
||||
<div className="max-w-3xl mx-auto mt-5 p-6 bg-gray-100 rounded">
|
||||
<h1 className="text-2xl font-bold mb-2">Nostr Relay Authentication</h1>
|
||||
<p className="mb-4">Connect to this Nostr relay using your private key or browser extension.</p>
|
||||
<div className="w-full min-h-screen bg-gray-100">
|
||||
<div
|
||||
className="max-w-full"
|
||||
style={{ padding: `${loginPadding}px` }}
|
||||
>
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<img
|
||||
src="/orly.png"
|
||||
alt="Orly logo"
|
||||
className="object-contain"
|
||||
style={{ width: '4rem', height: '4rem' }}
|
||||
onError={(e) => {
|
||||
// fallback to repo docs image if public asset missing
|
||||
e.currentTarget.onerror = null;
|
||||
e.currentTarget.src = "/docs/orly.png";
|
||||
}}
|
||||
/>
|
||||
<h1 ref={titleRef} className="text-2xl font-bold p-2">ORLY🦉 Dashboard Login</h1>
|
||||
</div>
|
||||
|
||||
<div className={statusClassName()}>
|
||||
{status}
|
||||
</div>
|
||||
<p className="mb-4">Connect to this Nostr relay using your browser extension.</p>
|
||||
|
||||
<div className="mb-5">
|
||||
<button className="bg-blue-600 text-white px-5 py-3 rounded hover:bg-blue-700" onClick={loginWithExtension}>Login with Browser Extension (NIP-07)</button>
|
||||
</div>
|
||||
<div className={statusClassName()}>
|
||||
{status}
|
||||
</div>
|
||||
|
||||
<div className="mb-5">
|
||||
<label className="block mb-1 font-bold" htmlFor="nsec">Or login with private key (nsec):</label>
|
||||
<input className="w-full p-2 border border-gray-300 rounded" type="password" id="nsec" placeholder="nsec1..." />
|
||||
<button className="mt-2 bg-red-600 text-white px-5 py-2 rounded hover:bg-red-700" onClick={() => updateStatus('Private key login not implemented in this basic interface. Please use a proper Nostr client or extension.', 'error')}>Login with Private Key</button>
|
||||
<div className="mb-5">
|
||||
<button className="bg-blue-600 text-white px-5 py-3 rounded hover:bg-blue-700" onClick={loginWithExtension}>Login with Browser Extension (NIP-07)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
||||
Reference in New Issue
Block a user