Replace binary favicon with SVG asset
This commit is contained in:
parent
519c00643d
commit
c7b27b6d05
23 changed files with 620 additions and 0 deletions
11
landing/.gitignore
vendored
Normal file
11
landing/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# Fresh build directory
|
||||
_fresh/
|
||||
# npm dependencies
|
||||
node_modules/
|
||||
6
landing/.vscode/extensions.json
vendored
Normal file
6
landing/.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"denoland.vscode-deno",
|
||||
"bradlc.vscode-tailwindcss"
|
||||
]
|
||||
}
|
||||
20
landing/.vscode/settings.json
vendored
Normal file
20
landing/.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"deno.enable": true,
|
||||
"deno.lint": true,
|
||||
"editor.defaultFormatter": "denoland.vscode-deno",
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"css.customData": [
|
||||
".vscode/tailwind.json"
|
||||
]
|
||||
}
|
||||
55
landing/.vscode/tailwind.json
vendored
Normal file
55
landing/.vscode/tailwind.json
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"version": 1.1,
|
||||
"atDirectives": [
|
||||
{
|
||||
"name": "@tailwind",
|
||||
"description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@apply",
|
||||
"description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#apply"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@responsive",
|
||||
"description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@screen",
|
||||
"description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#screen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "@variants",
|
||||
"description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n",
|
||||
"references": [
|
||||
{
|
||||
"name": "Tailwind Documentation",
|
||||
"url": "https://tailwindcss.com/docs/functions-and-directives#variants"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
landing/README.md
Normal file
16
landing/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Fresh project
|
||||
|
||||
Your new Fresh project is ready to go. You can follow the Fresh "Getting
|
||||
Started" guide here: https://fresh.deno.dev/docs/getting-started
|
||||
|
||||
### Usage
|
||||
|
||||
Make sure to install Deno: https://deno.land/manual/getting_started/installation
|
||||
|
||||
Then start the project:
|
||||
|
||||
```
|
||||
deno task start
|
||||
```
|
||||
|
||||
This will watch the project directory and restart as necessary.
|
||||
12
landing/components/Button.tsx
Normal file
12
landing/components/Button.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { JSX } from "preact";
|
||||
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||
|
||||
export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
disabled={!IS_BROWSER || props.disabled}
|
||||
class="px-2 py-1 border-gray-500 border-2 rounded bg-white hover:bg-gray-200 transition-colors"
|
||||
/>
|
||||
);
|
||||
}
|
||||
48
landing/components/Header.tsx
Normal file
48
landing/components/Header.tsx
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
const DASHBOARD_URL = "https://dashboard.core.dev";
|
||||
|
||||
export default function Header() {
|
||||
const navItems = [
|
||||
{ href: "https://docs.core.dev", label: "Docs" },
|
||||
{ href: "https://status.core.dev", label: "Status" },
|
||||
{ href: "https://api.core.dev", label: "API" },
|
||||
];
|
||||
|
||||
return (
|
||||
<header class="backdrop-blur sticky top-0 z-20 border-b border-white/5 bg-surface/80">
|
||||
<div class="mx-auto flex max-w-6xl items-center justify-between px-6 py-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="h-10 w-10 rounded-lg border border-accent/30 bg-accent/10 text-accent shadow-inner shadow-accent/20 grid place-items-center font-semibold">
|
||||
CF
|
||||
</span>
|
||||
<div class="leading-tight">
|
||||
<p class="text-sm uppercase tracking-[0.18em] text-foreground/70">
|
||||
Core Landing
|
||||
</p>
|
||||
<p class="text-lg font-semibold text-foreground">
|
||||
Cloud Ops Console
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="hidden items-center gap-8 text-sm font-medium text-foreground/80 md:flex">
|
||||
{navItems.map((item) => (
|
||||
<a
|
||||
key={item.href}
|
||||
class="transition hover:text-foreground"
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
<a
|
||||
class="rounded-md border border-accent/50 bg-accent/10 px-4 py-2 text-accent shadow-[0_0_0_1px_rgba(34,211,238,0.2)] transition hover:-translate-y-0.5 hover:shadow-accent/40"
|
||||
href={DASHBOARD_URL}
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
39
landing/deno.json
Normal file
39
landing/deno.json
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"lock": false,
|
||||
"tasks": {
|
||||
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
|
||||
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
|
||||
"manifest": "deno task cli manifest $(pwd)",
|
||||
"start": "deno run -A --watch=static/,routes/ dev.ts",
|
||||
"build": "deno run -A dev.ts build",
|
||||
"preview": "deno run -A main.ts",
|
||||
"update": "deno run -A -r https://fresh.deno.dev/update ."
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"tags": [
|
||||
"fresh",
|
||||
"recommended"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"**/_fresh/*"
|
||||
],
|
||||
"imports": {
|
||||
"$fresh/": "https://deno.land/x/fresh@1.7.3/",
|
||||
"preact": "https://esm.sh/preact@10.22.0",
|
||||
"preact/": "https://esm.sh/preact@10.22.0/",
|
||||
"@preact/signals": "https://esm.sh/*@preact/signals@1.2.2",
|
||||
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1",
|
||||
"tailwindcss": "npm:tailwindcss@3.4.1",
|
||||
"tailwindcss/": "npm:/tailwindcss@3.4.1/",
|
||||
"tailwindcss/plugin": "npm:/tailwindcss@3.4.1/plugin.js",
|
||||
"$std/": "https://deno.land/std@0.216.0/"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact"
|
||||
},
|
||||
"nodeModulesDir": true
|
||||
}
|
||||
8
landing/dev.ts
Executable file
8
landing/dev.ts
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env -S deno run -A --watch=static/,routes/
|
||||
|
||||
import dev from "$fresh/dev.ts";
|
||||
import config from "./fresh.config.ts";
|
||||
|
||||
import "$std/dotenv/load.ts";
|
||||
|
||||
await dev(import.meta.url, "./main.ts", config);
|
||||
6
landing/fresh.config.ts
Normal file
6
landing/fresh.config.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { defineConfig } from "$fresh/server.ts";
|
||||
import tailwind from "$fresh/plugins/tailwind.ts";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tailwind()],
|
||||
});
|
||||
29
landing/fresh.gen.ts
Normal file
29
landing/fresh.gen.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// DO NOT EDIT. This file is generated by Fresh.
|
||||
// This file SHOULD be checked into source version control.
|
||||
// This file is automatically updated during development when running `dev.ts`.
|
||||
|
||||
import * as $_404 from "./routes/_404.tsx";
|
||||
import * as $_app from "./routes/_app.tsx";
|
||||
import * as $api_joke from "./routes/api/joke.ts";
|
||||
import * as $greet_name_ from "./routes/greet/[name].tsx";
|
||||
import * as $index from "./routes/index.tsx";
|
||||
import * as $Counter from "./islands/Counter.tsx";
|
||||
import * as $ServerStatus from "./islands/ServerStatus.tsx";
|
||||
import type { Manifest } from "$fresh/server.ts";
|
||||
|
||||
const manifest = {
|
||||
routes: {
|
||||
"./routes/_404.tsx": $_404,
|
||||
"./routes/_app.tsx": $_app,
|
||||
"./routes/api/joke.ts": $api_joke,
|
||||
"./routes/greet/[name].tsx": $greet_name_,
|
||||
"./routes/index.tsx": $index,
|
||||
},
|
||||
islands: {
|
||||
"./islands/Counter.tsx": $Counter,
|
||||
"./islands/ServerStatus.tsx": $ServerStatus,
|
||||
},
|
||||
baseUrl: import.meta.url,
|
||||
} satisfies Manifest;
|
||||
|
||||
export default manifest;
|
||||
16
landing/islands/Counter.tsx
Normal file
16
landing/islands/Counter.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import type { Signal } from "@preact/signals";
|
||||
import { Button } from "../components/Button.tsx";
|
||||
|
||||
interface CounterProps {
|
||||
count: Signal<number>;
|
||||
}
|
||||
|
||||
export default function Counter(props: CounterProps) {
|
||||
return (
|
||||
<div class="flex gap-8 py-6">
|
||||
<Button onClick={() => props.count.value -= 1}>-1</Button>
|
||||
<p class="text-3xl tabular-nums">{props.count}</p>
|
||||
<Button onClick={() => props.count.value += 1}>+1</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
landing/islands/ServerStatus.tsx
Normal file
54
landing/islands/ServerStatus.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { useEffect, useMemo } from "preact/hooks";
|
||||
import { useSignal } from "@preact/signals";
|
||||
|
||||
const latencySamples = [18, 21, 24, 19, 22, 27, 20, 23, 25];
|
||||
|
||||
function getLatency() {
|
||||
const jitter = Math.floor(Math.random() * 4) - 2; // -2..1
|
||||
const base =
|
||||
latencySamples[Math.floor(Math.random() * latencySamples.length)];
|
||||
return Math.max(12, base + jitter);
|
||||
}
|
||||
|
||||
export default function ServerStatus() {
|
||||
const latency = useSignal(getLatency());
|
||||
const status = useSignal<"online" | "warning">("online");
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const value = getLatency();
|
||||
latency.value = value;
|
||||
status.value = value > 28 ? "warning" : "online";
|
||||
}, 1400);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const statusLabel = useMemo(
|
||||
() => (status.value === "online" ? "Operacional" : "Oscilação"),
|
||||
[status.value],
|
||||
);
|
||||
|
||||
return (
|
||||
<div class="flex items-center justify-between rounded-xl border border-white/10 bg-white/5 px-5 py-4 text-sm text-foreground/90 shadow-lg shadow-black/30">
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="text-xs uppercase tracking-[0.2em] text-foreground/60">
|
||||
Ping em tempo real
|
||||
</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class={`h-2 w-2 rounded-full ${
|
||||
status.value === "online" ? "bg-accent" : "bg-amber-400"
|
||||
}`}
|
||||
/>
|
||||
<span class="font-semibold">{statusLabel}</span>
|
||||
<span class="text-foreground/60">cloudflare-edge-01</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-2xl font-bold text-foreground">{latency.value}ms</p>
|
||||
<p class="text-xs text-foreground/60">latência média</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
13
landing/main.ts
Normal file
13
landing/main.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
/// <reference lib="dom.asynciterable" />
|
||||
/// <reference lib="deno.ns" />
|
||||
|
||||
import "$std/dotenv/load.ts";
|
||||
|
||||
import { start } from "$fresh/server.ts";
|
||||
import manifest from "./fresh.gen.ts";
|
||||
import config from "./fresh.config.ts";
|
||||
|
||||
await start(manifest, config);
|
||||
27
landing/routes/_404.tsx
Normal file
27
landing/routes/_404.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { Head } from "$fresh/runtime.ts";
|
||||
|
||||
export default function Error404() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>404 - Page not found</title>
|
||||
</Head>
|
||||
<div class="px-4 py-8 mx-auto bg-[#86efac]">
|
||||
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
||||
<img
|
||||
class="my-6"
|
||||
src="/logo.svg"
|
||||
width="128"
|
||||
height="128"
|
||||
alt="the Fresh logo: a sliced lemon dripping with juice"
|
||||
/>
|
||||
<h1 class="text-4xl font-bold">404 - Page not found</h1>
|
||||
<p class="my-4">
|
||||
The page you were looking for doesn't exist.
|
||||
</p>
|
||||
<a href="/" class="underline">Go back home</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
37
landing/routes/_app.tsx
Normal file
37
landing/routes/_app.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { type PageProps } from "$fresh/server.ts";
|
||||
import Header from "../components/Header.tsx";
|
||||
|
||||
export default function App({ Component }: PageProps) {
|
||||
return (
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Cloudflare & GitHub DevOps Console</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Dashboard DevOps para Cloudflare Management e GitHub Ops. Unifique Workers, Pages e repositórios com automação confiável."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="Cloudflare Management, GitHub Ops, Dashboard DevOps, Workers, Pages, Repositórios"
|
||||
/>
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Cloudflare & GitHub DevOps Console"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Gerencie Cloudflare Workers, Pages e integrações GitHub em um único painel com foco em performance."
|
||||
/>
|
||||
<meta name="theme-color" content="#0f172a" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="/styles.css" />
|
||||
</head>
|
||||
<body class="min-h-screen">
|
||||
<Header />
|
||||
<Component />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
21
landing/routes/api/joke.ts
Normal file
21
landing/routes/api/joke.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { FreshContext } from "$fresh/server.ts";
|
||||
|
||||
// Jokes courtesy of https://punsandoneliners.com/randomness/programmer-jokes/
|
||||
const JOKES = [
|
||||
"Why do Java developers often wear glasses? They can't C#.",
|
||||
"A SQL query walks into a bar, goes up to two tables and says “can I join you?”",
|
||||
"Wasn't hard to crack Forrest Gump's password. 1forrest1.",
|
||||
"I love pressing the F5 key. It's refreshing.",
|
||||
"Called IT support and a chap from Australia came to fix my network connection. I asked “Do you come from a LAN down under?”",
|
||||
"There are 10 types of people in the world. Those who understand binary and those who don't.",
|
||||
"Why are assembly programmers often wet? They work below C level.",
|
||||
"My favourite computer based band is the Black IPs.",
|
||||
"What programme do you use to predict the music tastes of former US presidential candidates? An Al Gore Rhythm.",
|
||||
"An SEO expert walked into a bar, pub, inn, tavern, hostelry, public house.",
|
||||
];
|
||||
|
||||
export const handler = (_req: Request, _ctx: FreshContext): Response => {
|
||||
const randomIndex = Math.floor(Math.random() * JOKES.length);
|
||||
const body = JOKES[randomIndex];
|
||||
return new Response(body);
|
||||
};
|
||||
5
landing/routes/greet/[name].tsx
Normal file
5
landing/routes/greet/[name].tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { PageProps } from "$fresh/server.ts";
|
||||
|
||||
export default function Greet(props: PageProps) {
|
||||
return <div>Hello {props.params.name}</div>;
|
||||
}
|
||||
146
landing/routes/index.tsx
Normal file
146
landing/routes/index.tsx
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
import ServerStatus from "../islands/ServerStatus.tsx";
|
||||
|
||||
const DASHBOARD_URL = "https://dashboard.core.dev";
|
||||
|
||||
function GitHubIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" class="h-7 w-7">
|
||||
<path d="M12 .5a12 12 0 0 0-3.79 23.4c.6.11.82-.26.82-.58v-2.02c-3.34.73-4.04-1.61-4.04-1.61-.55-1.4-1.34-1.77-1.34-1.77-1.09-.74.08-.73.08-.73 1.2.09 1.83 1.24 1.83 1.24 1.07 1.83 2.81 1.3 3.5 1 .11-.78.42-1.3.76-1.6-2.67-.31-5.47-1.34-5.47-5.95 0-1.31.47-2.39 1.24-3.24-.13-.3-.54-1.55.12-3.23 0 0 1.01-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.66 1.68.25 2.93.12 3.23.77.85 1.23 1.93 1.23 3.24 0 4.62-2.8 5.63-5.48 5.94.43.38.81 1.12.81 2.25v3.34c0 .32.22.69.82.57A12 12 0 0 0 12 .5Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function CloudflareIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 192 192" fill="currentColor" class="h-7 w-7">
|
||||
<path d="M104.6 102.7c-1.2-6.7-7.6-12.2-14.4-12.2H73c-1.8 0-3.2 1.4-3.4 3.2l-1.1 8.9c0 .2 0 .5.1.7l.8 3.6c.3 1.3 1.5 2.3 2.9 2.3h31c2.1 0 3.7-2 3.3-4.1Zm69.6-26.1c-4.8 0-9.2 2-12.4 5.3-3.5-13-15.3-22.4-29.3-22.4-14.5 0-26.8 10.2-29.9 23.8-.3 1.5 1 3 2.5 3h17.6c6.7 0 13.2 5.5 14.4 12.2l2.2 12.5c.3 1.7 2.1 3 3.8 3h26.1c13.6 0 24.6-11 24.6-24.6 0-12.6-9.6-23-22.2-23Z" />
|
||||
<path d="M111.8 118.1H65.3c-.6 0-1.1.5-1.1 1.1v1.2c0 .6.5 1.1 1.1 1.1h46.5c.6 0 1.1-.5 1.1-1.1v-1.2c0-.6-.5-1.1-1.1-1.1Zm-53.7 0H23.1c-.6 0-1.1.5-1.1 1.1v1.2c0 .6.5 1.1 1.1 1.1h35c.6 0 1.1-.5 1.1-1.1v-1.2c0-.6-.5-1.1-1.1-1.1Zm42.4-10.8H68c-.6 0-1.1.5-1.1 1.1v1.2c0 .6.5 1.1 1.1 1.1h32.5c.6 0 1.1-.5 1.1-1.1v-1.2c0-.6-.5-1.1-1.1-1.1Zm-26.3 0H15.1c-.6 0-1.1.5-1.1 1.1v1.2c0 .6.5 1.1 1.1 1.1h58.9c.6 0 1.1-.5 1.1-1.1v-1.2c0-.6-.5-1.1-1.1-1.1Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main class="bg-[radial-gradient(circle_at_top_right,rgba(34,211,238,0.08),transparent_35%)]">
|
||||
<section class="relative mx-auto flex max-w-6xl flex-col gap-12 px-6 pb-16 pt-20 md:flex-row md:items-center md:justify-between">
|
||||
<div
|
||||
class="absolute inset-x-10 top-12 h-64 rounded-3xl bg-accent/10 blur-3xl"
|
||||
aria-hidden
|
||||
/>
|
||||
<div class="relative z-10 max-w-2xl space-y-6">
|
||||
<p class="text-sm uppercase tracking-[0.3em] text-accent">
|
||||
Orquestração
|
||||
</p>
|
||||
<h1 class="text-4xl font-bold leading-[1.1] text-foreground sm:text-5xl">
|
||||
Orquestração de Infraestrutura Centralizada
|
||||
</h1>
|
||||
<p class="max-w-xl text-lg text-foreground/80">
|
||||
Gerencie Workers, Pages e Repositórios em um único painel. Fluxos
|
||||
GitHub e Cloudflare operando lado a lado, com observabilidade
|
||||
nativa.
|
||||
</p>
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center">
|
||||
<a
|
||||
class="inline-flex items-center justify-center gap-2 rounded-lg bg-accent px-6 py-3 text-sm font-semibold text-surface shadow-lg shadow-accent/30 transition hover:-translate-y-0.5 hover:shadow-accent/50"
|
||||
href={DASHBOARD_URL}
|
||||
>
|
||||
Acessar Console
|
||||
</a>
|
||||
<div class="flex items-center gap-3 text-sm text-foreground/60">
|
||||
<span class="h-2 w-2 rounded-full bg-emerald-400 animate-pulse" />
|
||||
Deploy ativo em rede edge global
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative z-10 w-full max-w-sm rounded-2xl border border-white/10 bg-white/5 p-6 text-sm text-foreground/80 shadow-2xl shadow-black/40">
|
||||
<div class="mb-4 flex items-center justify-between text-xs uppercase tracking-[0.2em] text-foreground/60">
|
||||
<span>Edge workload</span>
|
||||
<span class="rounded-full bg-accent/10 px-3 py-1 text-accent">
|
||||
Live
|
||||
</span>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-foreground/70">Workers ativos</span>
|
||||
<span class="text-lg font-semibold text-foreground">128</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-foreground/70">Repos monitorados</span>
|
||||
<span class="text-lg font-semibold text-foreground">56</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-foreground/70">Páginas entregues</span>
|
||||
<span class="text-lg font-semibold text-foreground">324</span>
|
||||
</div>
|
||||
<div class="pt-2">
|
||||
<ServerStatus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mx-auto max-w-6xl px-6 pb-20">
|
||||
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<p class="text-sm uppercase tracking-[0.25em] text-accent">
|
||||
Integrações Suportadas
|
||||
</p>
|
||||
<h2 class="text-3xl font-semibold text-foreground">
|
||||
Pipelines prontos para GitHub e Cloudflare
|
||||
</h2>
|
||||
<p class="mt-2 max-w-2xl text-foreground/70">
|
||||
Conecte repositórios GitHub, sincronize ambientes e publique
|
||||
workers em minutos. Observabilidade e segurança alinhadas para
|
||||
equipes de plataforma.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
class="inline-flex items-center gap-2 text-sm font-semibold text-accent underline decoration-accent/40 underline-offset-4 transition hover:decoration-accent"
|
||||
href="https://status.core.dev"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Ver status em tempo real
|
||||
<span aria-hidden class="text-lg">↗</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-10 grid gap-6 md:grid-cols-2">
|
||||
<div class="rounded-2xl border border-white/10 bg-white/5 p-6 shadow-lg shadow-black/30">
|
||||
<div class="flex items-center gap-3 text-accent">
|
||||
<span class="rounded-lg bg-accent/10 p-2 text-accent">
|
||||
<GitHubIcon />
|
||||
</span>
|
||||
<p class="text-sm font-semibold uppercase tracking-[0.2em] text-foreground">
|
||||
GitHub Ops
|
||||
</p>
|
||||
</div>
|
||||
<h3 class="mt-4 text-xl font-semibold text-foreground">
|
||||
Releases controladas
|
||||
</h3>
|
||||
<p class="mt-2 text-foreground/70">
|
||||
Automatize PR checks, proteja branches principais e promova
|
||||
releases para edge com auditoria completa.
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-2xl border border-white/10 bg-white/5 p-6 shadow-lg shadow-black/30">
|
||||
<div class="flex items-center gap-3 text-accent">
|
||||
<span class="rounded-lg bg-accent/10 p-2 text-accent">
|
||||
<CloudflareIcon />
|
||||
</span>
|
||||
<p class="text-sm font-semibold uppercase tracking-[0.2em] text-foreground">
|
||||
Cloudflare
|
||||
</p>
|
||||
</div>
|
||||
<h3 class="mt-4 text-xl font-semibold text-foreground">
|
||||
Workers e Pages
|
||||
</h3>
|
||||
<p class="mt-2 text-foreground/70">
|
||||
Deploys paralelos, métricas em tempo real e roteamento inteligente
|
||||
com baixa latência.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
7
landing/static/favicon.svg
Normal file
7
landing/static/favicon.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Core DevOps">
|
||||
<rect width="64" height="64" rx="14" fill="#0f172a" />
|
||||
<circle cx="24" cy="24" r="6" fill="#22d3ee" />
|
||||
<circle cx="40" cy="40" r="6" fill="#22d3ee" />
|
||||
<path d="M24 24h16v4H24z" fill="#f8fafc" />
|
||||
<path d="m28 32-6 8h-6l6-8-6-8h6l6 8Zm8 0 6-8h6l-6 8 6 8h-6l-6-8Z" fill="#f8fafc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 394 B |
19
landing/static/logo.svg
Normal file
19
landing/static/logo.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M34.092 8.845C38.929 20.652 34.092 27 30 30.5c1 3.5-2.986 4.222-4.5 2.5-4.457 1.537-13.512 1.487-20-5C2 24.5 4.73 16.714 14 11.5c8-4.5 16-7 20.092-2.655Z"
|
||||
fill="#FFDB1E"
|
||||
/>
|
||||
<path
|
||||
d="M14 11.5c6.848-4.497 15.025-6.38 18.368-3.47C37.5 12.5 21.5 22.612 15.5 25c-6.5 2.587-3 8.5-6.5 8.5-3 0-2.5-4-5.183-7.75C2.232 23.535 6.16 16.648 14 11.5Z"
|
||||
fill="#fff"
|
||||
stroke="#FFDB1E"
|
||||
/>
|
||||
<path
|
||||
d="M28.535 8.772c4.645 1.25-.365 5.695-4.303 8.536-3.732 2.692-6.606 4.21-7.923 4.83-.366.173-1.617-2.252-1.617-1 0 .417-.7 2.238-.934 2.326-1.365.512-4.223 1.29-5.835 1.29-3.491 0-1.923-4.754 3.014-9.122.892-.789 1.478-.645 2.283-.645-.537-.773-.534-.917.403-1.546C17.79 10.64 23 8.77 25.212 8.42c.366.014.82.35.82.629.41-.14 2.095-.388 2.503-.278Z"
|
||||
fill="#FFE600"
|
||||
/>
|
||||
<path
|
||||
d="M14.297 16.49c.985-.747 1.644-1.01 2.099-2.526.566.121.841-.08 1.29-.701.324.466 1.657.608 2.453.701-.715.451-1.057.852-1.452 2.106-1.464-.611-3.167-.302-4.39.42Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
9
landing/static/styles.css
Normal file
9
landing/static/styles.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply bg-surface text-foreground antialiased;
|
||||
}
|
||||
}
|
||||
16
landing/tailwind.config.ts
Normal file
16
landing/tailwind.config.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { type Config } from "tailwindcss";
|
||||
|
||||
export default {
|
||||
content: [
|
||||
"{routes,islands,components}/**/*.{ts,tsx,js,jsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
surface: "#0f172a",
|
||||
foreground: "#f8fafc",
|
||||
accent: "#22d3ee",
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Config;
|
||||
Loading…
Reference in a new issue