keyline-cli 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -34
- package/dist/keyline.js +3 -0
- package/package.json +13 -3
- package/keyline.js +0 -577
- package/update_schema.sql +0 -1
- package/website/README.md +0 -36
- package/website/app/favicon.ico +0 -0
- package/website/app/globals.css +0 -137
- package/website/app/layout.tsx +0 -29
- package/website/app/page.tsx +0 -345
- package/website/eslint.config.mjs +0 -18
- package/website/next.config.ts +0 -7
- package/website/package-lock.json +0 -6619
- package/website/package.json +0 -29
- package/website/postcss.config.mjs +0 -7
- package/website/public/file.svg +0 -1
- package/website/public/globe.svg +0 -1
- package/website/public/next.svg +0 -1
- package/website/public/vercel.svg +0 -1
- package/website/public/window.svg +0 -1
- package/website/tsconfig.json +0 -34
package/website/app/globals.css
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
|
|
3
|
-
:root {
|
|
4
|
-
--background: #000500;
|
|
5
|
-
--foreground: #00ff00;
|
|
6
|
-
--accent: #00ff41;
|
|
7
|
-
--muted: #003b00;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@theme inline {
|
|
11
|
-
--color-background: var(--background);
|
|
12
|
-
--color-foreground: var(--foreground);
|
|
13
|
-
--color-accent: var(--accent);
|
|
14
|
-
--color-muted: var(--muted);
|
|
15
|
-
--font-mono: var(--font-geist-mono);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
body {
|
|
19
|
-
background-color: var(--background);
|
|
20
|
-
color: var(--foreground);
|
|
21
|
-
font-family: var(--font-mono);
|
|
22
|
-
overflow-x: hidden;
|
|
23
|
-
cursor: none; /* Hide default for custom cursor */
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/* CRT Scanline Effect */
|
|
27
|
-
.scanline::before {
|
|
28
|
-
content: " ";
|
|
29
|
-
display: block;
|
|
30
|
-
position: fixed;
|
|
31
|
-
top: 0;
|
|
32
|
-
left: 0;
|
|
33
|
-
bottom: 0;
|
|
34
|
-
right: 0;
|
|
35
|
-
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
|
|
36
|
-
z-index: 50;
|
|
37
|
-
background-size: 100% 2px, 3px 100%;
|
|
38
|
-
pointer-events: none;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/* Flicker Animation */
|
|
42
|
-
@keyframes flicker {
|
|
43
|
-
0% { opacity: 0.97; }
|
|
44
|
-
5% { opacity: 0.95; }
|
|
45
|
-
10% { opacity: 0.9; }
|
|
46
|
-
15% { opacity: 0.95; }
|
|
47
|
-
20% { opacity: 1; }
|
|
48
|
-
25% { opacity: 0.95; }
|
|
49
|
-
30% { opacity: 1; }
|
|
50
|
-
70% { opacity: 0.9; }
|
|
51
|
-
100% { opacity: 1; }
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.flicker {
|
|
55
|
-
animation: flicker 0.15s infinite;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/* Glow Effect */
|
|
59
|
-
.glow {
|
|
60
|
-
text-shadow: 0 0 5px var(--foreground), 0 0 10px var(--foreground);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.glow-accent {
|
|
64
|
-
text-shadow: 0 0 5px var(--accent), 0 0 10px var(--accent);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* Glitch Effect */
|
|
68
|
-
.glitch {
|
|
69
|
-
position: relative;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.glitch::before,
|
|
73
|
-
.glitch::after {
|
|
74
|
-
content: attr(data-text);
|
|
75
|
-
position: absolute;
|
|
76
|
-
top: 0;
|
|
77
|
-
left: 0;
|
|
78
|
-
width: 100%;
|
|
79
|
-
height: 100%;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.glitch:hover::before {
|
|
83
|
-
left: 2px;
|
|
84
|
-
text-shadow: -2px 0 var(--accent);
|
|
85
|
-
clip: rect(44px, 450px, 56px, 0);
|
|
86
|
-
animation: glitch-anim 5s infinite linear alternate-reverse;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.glitch:hover::after {
|
|
90
|
-
left: -2px;
|
|
91
|
-
text-shadow: -2px 0 #ff00c1;
|
|
92
|
-
clip: rect(44px, 450px, 56px, 0);
|
|
93
|
-
animation: glitch-anim2 5s infinite linear alternate-reverse;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
@keyframes glitch-anim {
|
|
97
|
-
0% { clip: rect(31px, 9999px, 94px, 0); }
|
|
98
|
-
20% { clip: rect(62px, 9999px, 42px, 0); }
|
|
99
|
-
40% { clip: rect(16px, 9999px, 78px, 0); }
|
|
100
|
-
60% { clip: rect(1px, 9999px, 13px, 0); }
|
|
101
|
-
80% { clip: rect(85px, 9999px, 33px, 0); }
|
|
102
|
-
100% { clip: rect(53px, 9999px, 96px, 0); }
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
@keyframes glitch-anim2 {
|
|
106
|
-
0% { clip: rect(65px, 9999px, 100px, 0); }
|
|
107
|
-
20% { clip: rect(2px, 9999px, 50px, 0); }
|
|
108
|
-
40% { clip: rect(80px, 9999px, 20px, 0); }
|
|
109
|
-
60% { clip: rect(40px, 9999px, 90px, 0); }
|
|
110
|
-
80% { clip: rect(10px, 9999px, 30px, 0); }
|
|
111
|
-
100% { clip: rect(70px, 9999px, 60px, 0); }
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.custom-cursor {
|
|
115
|
-
position: fixed;
|
|
116
|
-
top: 0;
|
|
117
|
-
left: 0;
|
|
118
|
-
width: 20px;
|
|
119
|
-
height: 20px;
|
|
120
|
-
border: 1px solid var(--accent);
|
|
121
|
-
pointer-events: none;
|
|
122
|
-
z-index: 1000;
|
|
123
|
-
transform: translate(-50%, -50%);
|
|
124
|
-
display: flex;
|
|
125
|
-
align-items: center;
|
|
126
|
-
justify-content: center;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.custom-cursor::before,
|
|
130
|
-
.custom-cursor::after {
|
|
131
|
-
content: "";
|
|
132
|
-
position: absolute;
|
|
133
|
-
background: var(--accent);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.custom-cursor::before { width: 100%; height: 1px; }
|
|
137
|
-
.custom-cursor::after { width: 1px; height: 100%; }
|
package/website/app/layout.tsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { Metadata } from "next";
|
|
2
|
-
import { Geist_Mono } from "next/font/google";
|
|
3
|
-
import "./globals.css";
|
|
4
|
-
|
|
5
|
-
const geistMono = Geist_Mono({
|
|
6
|
-
variable: "--font-geist-mono",
|
|
7
|
-
subsets: ["latin"],
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
export const metadata: Metadata = {
|
|
11
|
-
title: "KeyLine | Secure Terminal Messaging",
|
|
12
|
-
description: "The next generation of encrypted terminal-to-terminal communication.",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default function RootLayout({
|
|
16
|
-
children,
|
|
17
|
-
}: Readonly<{
|
|
18
|
-
children: React.ReactNode;
|
|
19
|
-
}>) {
|
|
20
|
-
return (
|
|
21
|
-
<html lang="en" className="dark">
|
|
22
|
-
<body
|
|
23
|
-
className={`${geistMono.variable} antialiased scanline flicker min-h-screen`}
|
|
24
|
-
>
|
|
25
|
-
{children}
|
|
26
|
-
</body>
|
|
27
|
-
</html>
|
|
28
|
-
);
|
|
29
|
-
}
|
package/website/app/page.tsx
DELETED
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { motion, useSpring, useMotionValue } from "framer-motion";
|
|
4
|
-
import { Terminal, Shield, UserCheck, MessageSquare, Zap, ChevronRight, Github, Activity, Lock, Cpu } from "lucide-react";
|
|
5
|
-
import { useState, useEffect, useRef } from "react";
|
|
6
|
-
|
|
7
|
-
const CustomCursor = () => {
|
|
8
|
-
const mouseX = useMotionValue(0);
|
|
9
|
-
const mouseY = useMotionValue(0);
|
|
10
|
-
|
|
11
|
-
const springConfig = { damping: 20, stiffness: 150 };
|
|
12
|
-
const sx = useSpring(mouseX, springConfig);
|
|
13
|
-
const sy = useSpring(mouseY, springConfig);
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const handleMouseMove = (e: MouseEvent) => {
|
|
17
|
-
mouseX.set(e.clientX);
|
|
18
|
-
mouseY.set(e.clientY);
|
|
19
|
-
};
|
|
20
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
21
|
-
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
22
|
-
}, [mouseX, mouseY]);
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<>
|
|
26
|
-
<motion.div style={{ x: sx, y: sy }} className="custom-cursor" />
|
|
27
|
-
<motion.div
|
|
28
|
-
style={{ x: mouseX, y: mouseY }}
|
|
29
|
-
className="fixed w-4 h-4 rounded-full border border-accent/30 pointer-events-none z-[1001] translate-x-[-50%] translate-y-[-50%]"
|
|
30
|
-
/>
|
|
31
|
-
</>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const SystemLogStream = () => {
|
|
36
|
-
const [logs, setLogs] = useState<string[]>([]);
|
|
37
|
-
const logTypes = ["HANDSHAKE", "ENCRYPT", "PING", "AUTH", "SIG_SYNC", "DECODE"];
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
const interval = setInterval(() => {
|
|
41
|
-
const type = logTypes[Math.floor(Math.random() * logTypes.length)];
|
|
42
|
-
const id = Math.random().toString(16).slice(2, 10).toUpperCase();
|
|
43
|
-
const newLog = `[${new Date().toLocaleTimeString()}] ${type} :: NODE_${id} :: OK`;
|
|
44
|
-
setLogs(prev => [newLog, ...prev].slice(0, 10));
|
|
45
|
-
}, 2000);
|
|
46
|
-
return () => clearInterval(interval);
|
|
47
|
-
}, []);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div className="fixed bottom-12 right-12 w-64 text-xs space-y-1 opacity-90 hover:opacity-100 transition-opacity bg-black p-4 border-2 border-[#00ff41] z-50 pointer-events-none shadow-[0_0_20px_rgba(0,255,65,0.4)]">
|
|
51
|
-
<div className="border-b border-[#00ff41] pb-1 mb-2 font-bold flex items-center gap-2 text-[#00ff41]">
|
|
52
|
-
<Activity size={12} className="animate-pulse" /> SYSTEM_LOGS
|
|
53
|
-
</div>
|
|
54
|
-
{logs.map((log, i) => (
|
|
55
|
-
<motion.div
|
|
56
|
-
key={i}
|
|
57
|
-
initial={{ opacity: 0, x: 20 }}
|
|
58
|
-
animate={{ opacity: 1, x: 0 }}
|
|
59
|
-
className="whitespace-nowrap overflow-hidden text-ellipsis font-mono text-[#00ff41] font-bold shadow-[0_0_2px_#00ff41]"
|
|
60
|
-
>
|
|
61
|
-
{log}
|
|
62
|
-
</motion.div>
|
|
63
|
-
))}
|
|
64
|
-
</div>
|
|
65
|
-
);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
import createGlobe from "cobe";
|
|
69
|
-
|
|
70
|
-
const GlobeViz = () => {
|
|
71
|
-
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
72
|
-
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
let phi = 0;
|
|
75
|
-
|
|
76
|
-
if (!canvasRef.current) return;
|
|
77
|
-
|
|
78
|
-
const globe = createGlobe(canvasRef.current, {
|
|
79
|
-
devicePixelRatio: 2,
|
|
80
|
-
width: 600 * 2,
|
|
81
|
-
height: 600 * 2,
|
|
82
|
-
phi: 0,
|
|
83
|
-
theta: 0,
|
|
84
|
-
dark: 1,
|
|
85
|
-
diffuse: 1.2,
|
|
86
|
-
mapSamples: 16000,
|
|
87
|
-
mapBrightness: 6,
|
|
88
|
-
baseColor: [0.1, 0.1, 0.1],
|
|
89
|
-
markerColor: [0, 1, 0.25], // Neon Green
|
|
90
|
-
glowColor: [0, 1, 0.25],
|
|
91
|
-
markers: [
|
|
92
|
-
// Random "nodes"
|
|
93
|
-
{ location: [37.7595, -122.4367], size: 0.03 },
|
|
94
|
-
{ location: [40.7128, -74.0060], size: 0.03 },
|
|
95
|
-
{ location: [51.5074, -0.1278], size: 0.03 },
|
|
96
|
-
{ location: [35.6762, 139.6503], size: 0.03 },
|
|
97
|
-
{ location: [-33.8688, 151.2093], size: 0.03 },
|
|
98
|
-
{ location: [19.0760, 72.8777], size: 0.03 },
|
|
99
|
-
{ location: [55.7558, 37.6173], size: 0.03 },
|
|
100
|
-
{ location: [-23.5505, -46.6333], size: 0.03 },
|
|
101
|
-
{ location: [1.3521, 103.8198], size: 0.03 },
|
|
102
|
-
{ location: [52.5200, 13.4050], size: 0.03 },
|
|
103
|
-
],
|
|
104
|
-
onRender: (state) => {
|
|
105
|
-
// Called on every animation frame.
|
|
106
|
-
// `state` will be an empty object, return updated params.
|
|
107
|
-
state.phi = phi;
|
|
108
|
-
phi += 0.005; // Rotation speed
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return () => {
|
|
113
|
-
globe.destroy();
|
|
114
|
-
};
|
|
115
|
-
}, []);
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<div className="absolute left-[-100px] bottom-[-100px] opacity-60 pointer-events-none z-0 w-[600px] h-[600px] overflow-hidden grayscale contrast-125 brightness-125">
|
|
119
|
-
<canvas
|
|
120
|
-
ref={canvasRef}
|
|
121
|
-
style={{ width: 600, height: 600, maxWidth: "100%", aspectRatio: 1 }}
|
|
122
|
-
/>
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const MatrixRain = () => {
|
|
128
|
-
const [mounted, setMounted] = useState(false);
|
|
129
|
-
|
|
130
|
-
useEffect(() => {
|
|
131
|
-
setMounted(true);
|
|
132
|
-
}, []);
|
|
133
|
-
|
|
134
|
-
if (!mounted) return null;
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<div className="fixed inset-0 pointer-events-none z-0">
|
|
138
|
-
{/* Background layer */}
|
|
139
|
-
<div className="absolute inset-0 opacity-[0.02] flex justify-between gap-4 grayscale overflow-hidden">
|
|
140
|
-
{Array.from({ length: 20 }).map((_, i) => (
|
|
141
|
-
<motion.div
|
|
142
|
-
key={`bg-${i}`}
|
|
143
|
-
initial={{ y: -1000 }}
|
|
144
|
-
animate={{ y: 2000 }}
|
|
145
|
-
transition={{ duration: 30 + Math.random() * 20, repeat: Infinity, ease: "linear", delay: Math.random() * 5 }}
|
|
146
|
-
className="text-[8px] whitespace-pre"
|
|
147
|
-
>
|
|
148
|
-
{Array.from({ length: 60 }).map(() => String.fromCharCode(0x30A0 + Math.random() * 96) + "\n")}
|
|
149
|
-
</motion.div>
|
|
150
|
-
))}
|
|
151
|
-
</div>
|
|
152
|
-
{/* Middle layer */}
|
|
153
|
-
<div className="absolute inset-0 opacity-[0.04] flex justify-around gap-12 grayscale overflow-hidden scale-110">
|
|
154
|
-
{Array.from({ length: 15 }).map((_, i) => (
|
|
155
|
-
<motion.div
|
|
156
|
-
key={`mid-${i}`}
|
|
157
|
-
initial={{ y: -1000 }}
|
|
158
|
-
animate={{ y: 2000 }}
|
|
159
|
-
transition={{ duration: 15 + Math.random() * 10, repeat: Infinity, ease: "linear", delay: Math.random() * 2 }}
|
|
160
|
-
className="text-[12px] whitespace-pre font-bold"
|
|
161
|
-
>
|
|
162
|
-
{Array.from({ length: 40 }).map(() => String.fromCharCode(0x30A0 + Math.random() * 96) + "\n")}
|
|
163
|
-
</motion.div>
|
|
164
|
-
))}
|
|
165
|
-
</div>
|
|
166
|
-
{/* Foreground layer (New) */}
|
|
167
|
-
<div className="absolute inset-0 opacity-[0.03] flex justify-evenly gap-24 grayscale overflow-hidden scale-125 z-[-1]">
|
|
168
|
-
{Array.from({ length: 5 }).map((_, i) => (
|
|
169
|
-
<motion.div
|
|
170
|
-
key={`fg-${i}`}
|
|
171
|
-
initial={{ y: -1000 }}
|
|
172
|
-
animate={{ y: 2000 }}
|
|
173
|
-
transition={{ duration: 8 + Math.random() * 5, repeat: Infinity, ease: "linear", delay: Math.random() * 2 }}
|
|
174
|
-
className="text-[16px] whitespace-pre font-bold text-accent"
|
|
175
|
-
>
|
|
176
|
-
{Array.from({ length: 20 }).map(() => String.fromCharCode(0x30A0 + Math.random() * 96) + "\n")}
|
|
177
|
-
</motion.div>
|
|
178
|
-
))}
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
);
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
const FeatureCard = ({ icon: Icon, title, desc }: { icon: any, title: string, desc: string }) => (
|
|
185
|
-
<motion.div
|
|
186
|
-
whileHover={{ scale: 1.02 }}
|
|
187
|
-
className="border border-white/10 p-6 bg-black/40 backdrop-blur-sm relative group overflow-hidden rounded-sm hover:border-accent/40 transition-colors"
|
|
188
|
-
>
|
|
189
|
-
<div className="absolute top-0 left-0 w-1 h-full bg-accent scale-y-0 group-hover:scale-y-100 transition-transform duration-300 origin-top" />
|
|
190
|
-
<Icon className="w-8 h-8 mb-4 text-accent" />
|
|
191
|
-
<h3 className="text-xl font-bold mb-2 glow glitch" data-text={title}>{title}</h3>
|
|
192
|
-
<p className="text-muted-foreground leading-relaxed text-sm">{desc}</p>
|
|
193
|
-
</motion.div>
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
const Step = ({ num, text }: { num: string, text: string }) => (
|
|
197
|
-
<div className="flex gap-4 mb-4 items-baseline">
|
|
198
|
-
<span className="text-accent font-bold text-xs tracking-widest">[{num}]</span>
|
|
199
|
-
<p className="text-sm text-zinc-400">{text}</p>
|
|
200
|
-
</div>
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
export default function Home() {
|
|
204
|
-
return (
|
|
205
|
-
<div className="min-h-screen bg-black text-white selection:bg-accent selection:text-black font-mono">
|
|
206
|
-
<CustomCursor />
|
|
207
|
-
<SystemLogStream />
|
|
208
|
-
<MatrixRain />
|
|
209
|
-
|
|
210
|
-
<main className="relative z-10 px-6 py-12 lg:px-24">
|
|
211
|
-
{/* Header */}
|
|
212
|
-
<nav className="flex justify-between items-center mb-24 border-b border-white/10 pb-6">
|
|
213
|
-
<div className="flex items-center gap-2 group cursor-pointer relative">
|
|
214
|
-
<Terminal className="text-accent w-5 h-5" />
|
|
215
|
-
<span className="text-lg font-bold tracking-tighter">KEYLINE<span className="text-accent">_V1.0</span></span>
|
|
216
|
-
</div>
|
|
217
|
-
<div className="hidden md:flex gap-8 text-xs font-bold tracking-widest opacity-60">
|
|
218
|
-
<a href="#about" className="hover:text-accent transition-colors">[ABOUT]</a>
|
|
219
|
-
<a href="#features" className="hover:text-accent transition-colors">[PROTOCOL]</a>
|
|
220
|
-
<a href="#guide" className="hover:text-accent transition-colors">[MANUAL]</a>
|
|
221
|
-
</div>
|
|
222
|
-
</nav>
|
|
223
|
-
|
|
224
|
-
{/* Hero */}
|
|
225
|
-
<section id="about" className="mb-32 relative">
|
|
226
|
-
<GlobeViz />
|
|
227
|
-
<motion.div
|
|
228
|
-
initial={{ opacity: 0, y: 20 }}
|
|
229
|
-
animate={{ opacity: 1, y: 0 }}
|
|
230
|
-
className="max-w-4xl relative z-10"
|
|
231
|
-
>
|
|
232
|
-
<pre className="text-[10px] leading-none text-accent/40 mb-8 select-none">
|
|
233
|
-
{` _ __ _ _
|
|
234
|
-
| |/ / ___ _ _ | | (_) _ __ ___
|
|
235
|
-
| ' / / _ \\ | | | | | | | | | '_ \\ / _ \\
|
|
236
|
-
| . \\ | __/ | |_| | | |___ | | | | | | | __/
|
|
237
|
-
|_|\\_\\ \\___| \\__, | |_____| |_| |_| |_| \\___|
|
|
238
|
-
|___/ `}
|
|
239
|
-
</pre>
|
|
240
|
-
<h1 className="text-5xl md:text-8xl font-bold mb-8 tracking-tighter leading-none">
|
|
241
|
-
SECURE <span className="text-zinc-600">TERMINAL</span> <br />
|
|
242
|
-
<span className="text-accent glow-accent">COMMUNICATION</span>
|
|
243
|
-
</h1>
|
|
244
|
-
<p className="text-lg text-zinc-400 mb-10 max-w-xl leading-relaxed border-l-2 border-accent/20 pl-6">
|
|
245
|
-
KeyLine is a persistent, encrypted chat protocol for the terminal. No browsers. No trackers. Just raw, distributed messaging for the modern node.
|
|
246
|
-
</p>
|
|
247
|
-
<div className="flex gap-4">
|
|
248
|
-
<button className="bg-accent text-black px-8 py-4 font-bold text-sm tracking-widest hover:bg-white transition-all flex items-center gap-2 group">
|
|
249
|
-
EXECUTE SETUP <ChevronRight size={14} className="group-hover:translate-x-1 transition-transform" />
|
|
250
|
-
</button>
|
|
251
|
-
<button className="border border-white/20 px-8 py-4 font-bold text-sm tracking-widest hover:border-accent hover:text-accent transition-all bg-black/50 backdrop-blur-sm">
|
|
252
|
-
VIEW SOURCE
|
|
253
|
-
</button>
|
|
254
|
-
</div>
|
|
255
|
-
</motion.div>
|
|
256
|
-
</section>
|
|
257
|
-
|
|
258
|
-
{/* Features */}
|
|
259
|
-
<section id="features" className="mb-32 relative">
|
|
260
|
-
<div className="absolute right-0 top-0 opacity-5 pointer-events-none">
|
|
261
|
-
<Cpu size={300} strokeWidth={0.5} />
|
|
262
|
-
</div>
|
|
263
|
-
<h2 className="text-xs font-bold uppercase tracking-[0.5em] text-accent mb-12 flex items-center gap-4">
|
|
264
|
-
<span className="w-8 h-[1px] bg-accent"></span>
|
|
265
|
-
CORE_PROTOCOLS
|
|
266
|
-
</h2>
|
|
267
|
-
<div className="grid md:grid-cols-3 gap-6">
|
|
268
|
-
<FeatureCard
|
|
269
|
-
icon={Shield}
|
|
270
|
-
title="Encrypted Links"
|
|
271
|
-
desc="Every connection requires a handshake. No one joins your channel without your explicit authorization."
|
|
272
|
-
/>
|
|
273
|
-
<FeatureCard
|
|
274
|
-
icon={UserCheck}
|
|
275
|
-
title="Unique Identity"
|
|
276
|
-
desc="Generate persistent IDs (e.g., XYZ1234). Your display name can change, but your digital fingerprint is yours alone."
|
|
277
|
-
/>
|
|
278
|
-
<FeatureCard
|
|
279
|
-
icon={Zap}
|
|
280
|
-
title="Real-time Sub"
|
|
281
|
-
desc="Powered by low-latency streams. Messages are delivered instantly between terminals across the globe."
|
|
282
|
-
/>
|
|
283
|
-
</div>
|
|
284
|
-
</section>
|
|
285
|
-
|
|
286
|
-
{/* Guide */}
|
|
287
|
-
<section id="guide" className="mb-32 relative">
|
|
288
|
-
<div className="absolute left-[-10%] top-[-20%] opacity-5 pointer-events-none rotate-12">
|
|
289
|
-
<Lock size={400} />
|
|
290
|
-
</div>
|
|
291
|
-
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
|
292
|
-
<div>
|
|
293
|
-
<h2 className="text-sm uppercase tracking-[0.5em] text-accent mb-8 glitch" data-text="[ OPERATION_MANUAL ]">[ OPERATION_MANUAL ]</h2>
|
|
294
|
-
<h3 className="text-3xl font-bold mb-6">Infiltration Guide</h3>
|
|
295
|
-
<Step num="01" text="Setup and run the node using the CLI client." />
|
|
296
|
-
<Step num="02" text="Register your identity and verify your email signal." />
|
|
297
|
-
<Step num="03" text="Search peers by their Unique ID and transmit a request." />
|
|
298
|
-
<Step num="04" text="Establish the handshake and start the secure stream." />
|
|
299
|
-
</div>
|
|
300
|
-
<div className="bg-[#000800] border border-muted p-1 rounded-sm shadow-2xl relative group">
|
|
301
|
-
<div className="absolute -inset-1 bg-accent/20 blur opacity-0 group-hover:opacity-100 transition duration-500"></div>
|
|
302
|
-
<div className="relative">
|
|
303
|
-
<div className="flex gap-2 p-3 border-b border-muted bg-background">
|
|
304
|
-
<div className="w-3 h-3 rounded-full bg-red-500/50" />
|
|
305
|
-
<div className="w-3 h-3 rounded-full bg-yellow-500/50" />
|
|
306
|
-
<div className="w-3 h-3 rounded-full bg-green-500/50" />
|
|
307
|
-
<div className="ml-auto text-[10px] opacity-30">terminal.exe</div>
|
|
308
|
-
</div>
|
|
309
|
-
<pre className="p-6 text-xs md:text-sm text-accent overflow-x-auto bg-black/90">
|
|
310
|
-
<code>{`$ node client.js
|
|
311
|
-
[SYSTEM] INITIALIZING PROTOCOL...
|
|
312
|
-
? Select action: [LOGIN]
|
|
313
|
-
? Enter Email: madhav@keyline.io
|
|
314
|
-
✔ Access granted. Welcome back.
|
|
315
|
-
|
|
316
|
-
[USER]: Madhav | ID: ABC1234
|
|
317
|
-
COMMAND MENU:
|
|
318
|
-
> [SEARCH] Find user by ID
|
|
319
|
-
[REQUESTS] (2) Pending
|
|
320
|
-
[CHATS] Active channels`}</code>
|
|
321
|
-
</pre>
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
</section>
|
|
326
|
-
|
|
327
|
-
{/* Footer */}
|
|
328
|
-
<footer className="border-t border-muted pt-12 mt-32 flex flex-col md:flex-row justify-between items-center gap-6 opacity-60 text-sm">
|
|
329
|
-
<div className="flex gap-4">
|
|
330
|
-
<span>© 2024 KEYLINE_NETWORK</span>
|
|
331
|
-
<span className="text-accent flex items-center gap-2">
|
|
332
|
-
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
|
|
333
|
-
STATUS: NOMINAL
|
|
334
|
-
</span>
|
|
335
|
-
</div>
|
|
336
|
-
<div className="flex gap-8">
|
|
337
|
-
<a href="#" className="hover:text-accent transition-colors">TERMINAL_UX</a>
|
|
338
|
-
<a href="#" className="hover:text-accent transition-colors">END-TO-END_DOCS</a>
|
|
339
|
-
<a href="#" className="hover:text-accent transition-colors flex items-center gap-2"><Github size={16} /> REPO</a>
|
|
340
|
-
</div>
|
|
341
|
-
</footer>
|
|
342
|
-
</main>
|
|
343
|
-
</div>
|
|
344
|
-
);
|
|
345
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { defineConfig, globalIgnores } from "eslint/config";
|
|
2
|
-
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
3
|
-
import nextTs from "eslint-config-next/typescript";
|
|
4
|
-
|
|
5
|
-
const eslintConfig = defineConfig([
|
|
6
|
-
...nextVitals,
|
|
7
|
-
...nextTs,
|
|
8
|
-
// Override default ignores of eslint-config-next.
|
|
9
|
-
globalIgnores([
|
|
10
|
-
// Default ignores of eslint-config-next:
|
|
11
|
-
".next/**",
|
|
12
|
-
"out/**",
|
|
13
|
-
"build/**",
|
|
14
|
-
"next-env.d.ts",
|
|
15
|
-
]),
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
export default eslintConfig;
|