feat: add tunnel configuration tools
This commit is contained in:
64
app/card.tsx
64
app/card.tsx
@ -1,64 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
|
||||
export default function Card() {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const command = "ssh id.tunnl.live -p 2200 -R 443:localhost:8000"
|
||||
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard.writeText(command)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
return (
|
||||
<div className="mb-16">
|
||||
<h2 className="text-2xl font-bold mb-6">Connect with a single command</h2>
|
||||
<div className="relative">
|
||||
<div className="bg-gray-900 rounded-lg p-4 border border-gray-800 font-mono text-sm sm:text-base overflow-x-auto">
|
||||
<pre className="whitespace-pre-wrap break-all sm:break-normal">{command}</pre>
|
||||
</div>
|
||||
<button
|
||||
onClick={copyToClipboard}
|
||||
className="absolute right-3 top-3 h-8 w-8 flex items-center justify-center rounded-md text-gray-400 hover:text-white hover:bg-gray-800"
|
||||
aria-label="Copy command"
|
||||
>
|
||||
{copied ? (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
|
||||
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<p className="mt-4 text-sm text-gray-400">
|
||||
This command creates a secure tunnel from our server to your localhost:8000
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
185
app/page.tsx
185
app/page.tsx
@ -1,11 +1,23 @@
|
||||
import Card from "./card"
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import TunnelConfig, { type TunnelConfig as TunnelConfigType, type Server } from "@/components/tunnel-config"
|
||||
|
||||
const defaultConfig: TunnelConfigType = {
|
||||
type: "http",
|
||||
serverPort: 443,
|
||||
localPort: 8000,
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
const [selectedServer, setSelectedServer] = useState<Server | null>(null)
|
||||
const [tunnelConfig, setTunnelConfig] = useState<TunnelConfigType>(defaultConfig)
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-gray-950 text-white">
|
||||
<main className="flex-1 flex flex-col items-center justify-center px-4">
|
||||
<div className="w-full max-w-3xl mx-auto text-center">
|
||||
<div className="mb-12">
|
||||
<main className="flex-1 flex flex-col items-center justify-center px-4 py-8">
|
||||
<div className="w-full max-w-4xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl mb-6">
|
||||
<span className="text-emerald-400">tunnl</span>.live
|
||||
</h1>
|
||||
@ -13,85 +25,94 @@ export default function Home() {
|
||||
Expose your local services to the internet securely with our fast and reliable SSH tunneling service.
|
||||
</p>
|
||||
</div>
|
||||
<Card />
|
||||
<div className="grid gap-8 md:grid-cols-3 mb-16">
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" />
|
||||
<path d="M2 12h20" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Global Network</h3>
|
||||
<p className="text-gray-400">
|
||||
We offer low-latency, high-availability servers located in Singapore for optimal performance.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Secure by Default</h3>
|
||||
<p className="text-gray-400">
|
||||
End-to-end encryption with SSH ensures your data remains private and secure.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
|
||||
<polyline points="15 3 21 3 21 9" />
|
||||
<line x1="10" x2="21" y1="14" y2="3" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Easy Sharing</h3>
|
||||
<p className="text-gray-400">
|
||||
Share your local development with clients or teammates without complex setup.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mb-8">
|
||||
<h2 className="text-2xl font-bold mb-4">100% Free Service</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
No registration required. Just run the command and start using the tunnel immediately.
|
||||
</p>
|
||||
<TunnelConfig
|
||||
config={tunnelConfig}
|
||||
onConfigChange={setTunnelConfig}
|
||||
selectedServer={selectedServer}
|
||||
onServerSelect={setSelectedServer}
|
||||
/>
|
||||
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="grid gap-8 md:grid-cols-3 mb-16">
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" />
|
||||
<path d="M2 12h20" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Global Network</h3>
|
||||
<p className="text-gray-400">
|
||||
Choose from servers in US, Singapore, and Indonesia for optimal performance.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Secure by Default</h3>
|
||||
<p className="text-gray-400">
|
||||
End-to-end encryption with SSH ensures your data remains private and secure.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-gray-900 p-6 rounded-lg border border-gray-800">
|
||||
<div className="mb-4 inline-block rounded-full bg-emerald-950 p-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="text-emerald-400"
|
||||
>
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1-2-2h6" />
|
||||
<polyline points="15 3 21 3 21 9" />
|
||||
<line x1="10" x2="21" y1="14" y2="3" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">Flexible Configuration</h3>
|
||||
<p className="text-gray-400">
|
||||
Support for both HTTP/HTTPS and TCP tunneling with custom port configuration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mb-8">
|
||||
<h2 className="text-2xl font-bold mb-4">100% Free Service</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
No registration required. Just run the command and start using the tunnel immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
106
app/tunnel-not-found/page.tsx
Normal file
106
app/tunnel-not-found/page.tsx
Normal file
@ -0,0 +1,106 @@
|
||||
"use client"
|
||||
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
|
||||
export default function TunnelNotFound() {
|
||||
const exampleUrl = "example.com"
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-gray-950 text-white">
|
||||
<main className="flex-1 flex flex-col items-center justify-center px-4 py-8">
|
||||
<div className="w-full max-w-2xl mx-auto text-center">
|
||||
{/* Mascot */}
|
||||
<div className="mb-8">
|
||||
<Image
|
||||
src="/mascot-confused.png"
|
||||
alt="Confused tunnel mascot"
|
||||
width={200}
|
||||
height={200}
|
||||
className="mx-auto"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Error Message */}
|
||||
<div className="mb-12">
|
||||
<h1 className="text-4xl font-bold mb-6">Tunnel Not Found</h1>
|
||||
<p className="text-gray-400 mb-6 text-lg">We couldn't find an active tunnel for:</p>
|
||||
<div className="bg-gray-900 rounded-lg p-4 border border-gray-800 font-mono text-emerald-400 text-xl max-w-md mx-auto mb-8">
|
||||
{exampleUrl}
|
||||
</div>
|
||||
<p className="text-gray-300 text-lg">This means no SSH tunnel is currently running for this domain.</p>
|
||||
</div>
|
||||
|
||||
{/* Instructions */}
|
||||
<div className="bg-gray-900 rounded-lg p-8 border border-gray-800 mb-8 text-left">
|
||||
<h2 className="text-xl font-bold mb-6 text-center">To create a tunnel:</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="bg-emerald-600 text-white rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold flex-shrink-0 mt-1">
|
||||
1
|
||||
</span>
|
||||
<div>
|
||||
<p className="text-gray-300 font-medium">Go to the main page</p>
|
||||
<p className="text-gray-400 text-sm">Configure your tunnel settings and choose a server</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="bg-emerald-600 text-white rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold flex-shrink-0 mt-1">
|
||||
2
|
||||
</span>
|
||||
<div>
|
||||
<p className="text-gray-300 font-medium">Make sure your local service is running</p>
|
||||
<p className="text-gray-400 text-sm">Your application should be accessible on localhost</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="bg-emerald-600 text-white rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold flex-shrink-0 mt-1">
|
||||
3
|
||||
</span>
|
||||
<div>
|
||||
<p className="text-gray-300 font-medium">Run the SSH command</p>
|
||||
<p className="text-gray-400 text-sm">Copy and paste the generated command into your terminal</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4">
|
||||
<span className="bg-emerald-600 text-white rounded-full w-8 h-8 flex items-center justify-center text-sm font-bold flex-shrink-0 mt-1">
|
||||
4
|
||||
</span>
|
||||
<div>
|
||||
<p className="text-gray-300 font-medium">Access your tunnel</p>
|
||||
<p className="text-gray-400 text-sm">Your service will be available through the tunnel URL</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Call to Action */}
|
||||
<div className="space-y-4">
|
||||
<Link
|
||||
href="/"
|
||||
className="inline-flex items-center gap-3 bg-emerald-600 hover:bg-emerald-700 text-white px-6 py-3 rounded-lg font-medium transition-colors"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M5 12h14" />
|
||||
<path d="M12 5l7 7-7 7" />
|
||||
</svg>
|
||||
Create Your Tunnel
|
||||
</Link>
|
||||
|
||||
<p className="text-gray-400 text-sm">Need help? Check our documentation or contact support.</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user