Skip to content

Commit 9698269

Browse files
committed
Add GitHub Pages landing page
1 parent 74a7d11 commit 9698269

7 files changed

Lines changed: 292 additions & 9 deletions

File tree

.github/workflows/pages.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Pages
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: true
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Setup Node
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 20
29+
cache: npm
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
34+
- name: Build GitHub Pages site
35+
env:
36+
GITHUB_PAGES: "true"
37+
run: npm run build:pages
38+
39+
- name: Setup Pages
40+
uses: actions/configure-pages@v5
41+
42+
- name: Upload artifact
43+
uses: actions/upload-pages-artifact@v3
44+
with:
45+
path: dist
46+
47+
deploy:
48+
runs-on: ubuntu-latest
49+
needs: build
50+
environment:
51+
name: github-pages
52+
url: ${{ steps.deployment.outputs.page_url }}
53+
steps:
54+
- name: Deploy to GitHub Pages
55+
id: deployment
56+
uses: actions/deploy-pages@v4

index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
5+
<link rel="icon" type="image/svg+xml" href="./tauri.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<meta
8+
name="description"
9+
content="DevStack is a Windows desktop environment for managing Apache, PHP, MySQL, Redis, Node and local project workflows."
10+
/>
711
<title>DevStack</title>
812
</head>
913

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"scripts": {
77
"dev": "vite",
88
"build": "vite build",
9+
"build:pages": "vite build",
910
"preview": "vite preview",
1011
"tauri": "tauri",
1112
"version:bump": "powershell -ExecutionPolicy Bypass -File .\\scripts\\bump-version.ps1",

src/index.css

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,18 @@
1212
font-family: 'Syne', sans-serif;
1313
margin: 0;
1414
padding: 0;
15+
min-height: 100vh;
16+
background-image: radial-gradient(circle at 50% 0%, rgba(0, 229, 160, 0.03) 0%, transparent 50%);
17+
}
18+
19+
body[data-shell='tauri'] {
1520
overflow: hidden;
1621
height: 100vh;
17-
background-image: radial-gradient(circle at 50% 0%, rgba(0, 229, 160, 0.03) 0%, transparent 50%);
22+
}
23+
24+
body[data-shell='web'] {
25+
overflow-x: hidden;
26+
overflow-y: auto;
1827
}
1928

2029
::-webkit-scrollbar {
@@ -296,4 +305,4 @@
296305
.shadow-glow {
297306
box-shadow: 0 0 24px rgba(0, 229, 160, 0.15), inset 0 0 10px rgba(0, 229, 160, 0.05);
298307
}
299-
}
308+
}

src/main.jsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
import React from "react";
22
import ReactDOM from "react-dom/client";
3-
import App from "./App";
3+
import LandingPage from "./pages/LandingPage";
44
import "./index.css";
55

6-
ReactDOM.createRoot(document.getElementById("root")).render(
7-
<React.StrictMode>
8-
<App />
9-
</React.StrictMode>,
10-
);
6+
const isTauriRuntime = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
7+
8+
document.body.dataset.shell = isTauriRuntime ? "tauri" : "web";
9+
10+
if (!isTauriRuntime) {
11+
document.title = "DevStack | Windows local development environment";
12+
}
13+
14+
const root = ReactDOM.createRoot(document.getElementById("root"));
15+
16+
async function bootstrap() {
17+
const RootComponent = isTauriRuntime
18+
? (await import("./App")).default
19+
: LandingPage;
20+
21+
root.render(
22+
<React.StrictMode>
23+
<RootComponent />
24+
</React.StrictMode>,
25+
);
26+
}
27+
28+
bootstrap();

src/pages/LandingPage.jsx

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
import React from "react";
2+
import appIcon from "../../src-tauri/icons/icon.png";
3+
4+
const features = [
5+
{
6+
title: "All-in-one control panel",
7+
description: "Quản lý Apache, PHP, MySQL, Redis, Node và project services trong một giao diện desktop thống nhất.",
8+
},
9+
{
10+
title: "Native Windows performance",
11+
description: "Tauri v2 + Rust backend giúp app nhẹ, khởi động nhanh và xử lý service ổn định hơn Electron-style shells.",
12+
},
13+
{
14+
title: "Built for local workflows",
15+
description: "Tạo site local, đổi runtime version, đọc log, cấu hình port và xử lý quick config mà không phải nhớ quá nhiều lệnh.",
16+
},
17+
];
18+
19+
const sections = [
20+
"Apache và PHP version switching cho nhiều dự án local",
21+
"MySQL management, query nhanh và theo dõi trạng thái dịch vụ",
22+
"Sites, virtual hosts, tunnel integrations và log viewer",
23+
"Cấu hình tập trung cho ports, startup, editor và update",
24+
];
25+
26+
function LandingPage() {
27+
return (
28+
<div className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(0,229,160,0.16),_transparent_35%),linear-gradient(180deg,#08110f_0%,#0b0f14_45%,#05070a_100%)] text-slate-100">
29+
<div className="mx-auto flex min-h-screen w-full max-w-7xl flex-col px-6 py-8 sm:px-10 lg:px-12">
30+
<header className="flex flex-col gap-5 border-b border-white/10 pb-6 sm:flex-row sm:items-center sm:justify-between">
31+
<div className="flex items-center gap-4">
32+
<div className="flex h-14 w-14 items-center justify-center rounded-2xl border border-emerald-400/30 bg-white/5 shadow-[0_0_30px_rgba(0,229,160,0.18)]">
33+
<img src={appIcon} alt="DevStack icon" className="h-10 w-10" />
34+
</div>
35+
<div>
36+
<div className="font-mono text-xs uppercase tracking-[0.32em] text-emerald-300/80">DevStack</div>
37+
<div className="text-sm text-slate-300">Windows local development environment</div>
38+
</div>
39+
</div>
40+
<div className="flex flex-wrap gap-3">
41+
<a
42+
href="https://github.com/holdon1996/dev-stack/releases/latest"
43+
className="rounded-full border border-emerald-300/30 bg-emerald-300 px-5 py-2 text-sm font-semibold text-slate-950 transition hover:-translate-y-0.5 hover:bg-emerald-200"
44+
>
45+
Download latest release
46+
</a>
47+
<a
48+
href="https://github.com/holdon1996/dev-stack"
49+
className="rounded-full border border-white/15 px-5 py-2 text-sm font-semibold text-slate-100 transition hover:-translate-y-0.5 hover:border-white/30 hover:bg-white/5"
50+
>
51+
View on GitHub
52+
</a>
53+
</div>
54+
</header>
55+
56+
<main className="flex-1 py-10 sm:py-14">
57+
<section className="grid gap-10 lg:grid-cols-[1.2fr_0.8fr] lg:items-center">
58+
<div>
59+
<div className="mb-4 inline-flex rounded-full border border-emerald-300/20 bg-emerald-300/10 px-3 py-1 font-mono text-xs uppercase tracking-[0.28em] text-emerald-200">
60+
Desktop tool for PHP stacks
61+
</div>
62+
<h1 className="max-w-4xl font-display text-5xl font-bold leading-[0.95] text-white sm:text-6xl lg:text-7xl">
63+
DevStack giúp môi trường local trên Windows gọn hơn, nhanh hơn và dễ kiểm soát hơn.
64+
</h1>
65+
<p className="mt-6 max-w-2xl text-lg leading-8 text-slate-300">
66+
Một app desktop tập trung để quản lý Apache, PHP, MySQL, Redis, tunnels và cấu hình dự án local mà không cần ghép nhiều công cụ rời rạc.
67+
</p>
68+
<div className="mt-8 flex flex-wrap gap-4">
69+
<a
70+
href="https://github.com/holdon1996/dev-stack/releases/latest"
71+
className="rounded-2xl border border-emerald-300/25 bg-emerald-300 px-6 py-3 font-semibold text-slate-950 shadow-[0_18px_50px_rgba(0,229,160,0.2)] transition hover:-translate-y-0.5 hover:bg-emerald-200"
72+
>
73+
Tải bản phát hành mới nhất
74+
</a>
75+
<a
76+
href="https://github.com/holdon1996/dev-stack#quick-start"
77+
className="rounded-2xl border border-white/15 bg-white/5 px-6 py-3 font-semibold text-white transition hover:-translate-y-0.5 hover:border-white/30 hover:bg-white/10"
78+
>
79+
Xem hướng dẫn cài đặt
80+
</a>
81+
</div>
82+
</div>
83+
84+
<div className="relative">
85+
<div className="absolute inset-0 rounded-[32px] bg-emerald-300/10 blur-3xl" />
86+
<div className="relative overflow-hidden rounded-[32px] border border-white/10 bg-slate-950/70 p-6 shadow-[0_20px_80px_rgba(0,0,0,0.45)] backdrop-blur">
87+
<div className="mb-5 flex items-center gap-2">
88+
<span className="h-3 w-3 rounded-full bg-rose-400" />
89+
<span className="h-3 w-3 rounded-full bg-amber-300" />
90+
<span className="h-3 w-3 rounded-full bg-emerald-400" />
91+
</div>
92+
<div className="space-y-4">
93+
<div className="rounded-2xl border border-white/8 bg-white/5 p-4">
94+
<div className="font-mono text-xs uppercase tracking-[0.24em] text-slate-400">Managed services</div>
95+
<div className="mt-3 flex flex-wrap gap-2">
96+
{["Apache", "PHP", "MySQL", "Redis", "Node"].map((service) => (
97+
<span
98+
key={service}
99+
className="rounded-full border border-emerald-300/20 bg-emerald-300/10 px-3 py-1 text-sm text-emerald-100"
100+
>
101+
{service}
102+
</span>
103+
))}
104+
</div>
105+
</div>
106+
<div className="grid gap-3 sm:grid-cols-2">
107+
<div className="rounded-2xl border border-white/8 bg-white/5 p-4">
108+
<div className="text-sm text-slate-400">Focus</div>
109+
<div className="mt-2 text-xl font-semibold text-white">Local PHP workflow</div>
110+
</div>
111+
<div className="rounded-2xl border border-white/8 bg-white/5 p-4">
112+
<div className="text-sm text-slate-400">Runtime</div>
113+
<div className="mt-2 text-xl font-semibold text-white">Tauri v2 + React</div>
114+
</div>
115+
</div>
116+
<div className="rounded-2xl border border-white/8 bg-[linear-gradient(135deg,rgba(0,229,160,0.15),rgba(255,255,255,0.04))] p-4">
117+
<div className="font-mono text-xs uppercase tracking-[0.24em] text-emerald-100/80">Why it matters</div>
118+
<p className="mt-3 text-sm leading-7 text-slate-200">
119+
Khi local stack nằm trong một nơi duy nhất, việc đổi version, đọc log và sửa cấu hình bớt rời rạc hơn rất nhiều.
120+
</p>
121+
</div>
122+
</div>
123+
</div>
124+
</div>
125+
</section>
126+
127+
<section className="mt-16 grid gap-5 md:grid-cols-3">
128+
{features.map((feature) => (
129+
<article
130+
key={feature.title}
131+
className="rounded-[28px] border border-white/10 bg-white/5 p-6 backdrop-blur-sm transition hover:-translate-y-1 hover:border-emerald-300/30 hover:bg-white/[0.07]"
132+
>
133+
<h2 className="text-2xl font-semibold text-white">{feature.title}</h2>
134+
<p className="mt-4 text-sm leading-7 text-slate-300">{feature.description}</p>
135+
</article>
136+
))}
137+
</section>
138+
139+
<section className="mt-16 grid gap-6 lg:grid-cols-[0.95fr_1.05fr]">
140+
<div className="rounded-[32px] border border-white/10 bg-[#0a1110]/80 p-7">
141+
<div className="font-mono text-xs uppercase tracking-[0.3em] text-emerald-200/80">What you can do</div>
142+
<ul className="mt-6 space-y-4">
143+
{sections.map((item) => (
144+
<li key={item} className="flex items-start gap-3 text-slate-200">
145+
<span className="mt-2 h-2.5 w-2.5 rounded-full bg-emerald-300 shadow-[0_0_18px_rgba(0,229,160,0.8)]" />
146+
<span className="leading-7">{item}</span>
147+
</li>
148+
))}
149+
</ul>
150+
</div>
151+
152+
<div className="rounded-[32px] border border-white/10 bg-white/5 p-7">
153+
<div className="font-mono text-xs uppercase tracking-[0.3em] text-slate-400">Project stack</div>
154+
<div className="mt-6 grid gap-4 sm:grid-cols-2">
155+
{[
156+
["Frontend", "React 19 + Tailwind CSS"],
157+
["Desktop shell", "Tauri v2"],
158+
["Backend", "Rust commands + system integration"],
159+
["Distribution", "GitHub Releases + updater support"],
160+
].map(([label, value]) => (
161+
<div key={label} className="rounded-2xl border border-white/8 bg-slate-950/40 p-4">
162+
<div className="text-sm text-slate-400">{label}</div>
163+
<div className="mt-2 text-lg font-semibold text-white">{value}</div>
164+
</div>
165+
))}
166+
</div>
167+
<div className="mt-6 rounded-2xl border border-amber-300/15 bg-amber-300/10 p-4 text-sm leading-7 text-amber-50">
168+
Hiện tại DevStack hướng đến Windows và tối ưu cho quy trình local development truyền thống của PHP stack.
169+
</div>
170+
</div>
171+
</section>
172+
</main>
173+
174+
<footer className="flex flex-col gap-4 border-t border-white/10 pt-6 text-sm text-slate-400 sm:flex-row sm:items-center sm:justify-between">
175+
<div>DevStack is open source and distributed through GitHub Releases.</div>
176+
<div className="flex flex-wrap gap-4">
177+
<a href="https://github.com/holdon1996/dev-stack/issues" className="transition hover:text-white">
178+
Issues
179+
</a>
180+
<a href="https://github.com/holdon1996/dev-stack/releases" className="transition hover:text-white">
181+
Releases
182+
</a>
183+
<a href="https://github.com/holdon1996/dev-stack" className="transition hover:text-white">
184+
Repository
185+
</a>
186+
</div>
187+
</footer>
188+
</div>
189+
</div>
190+
);
191+
}
192+
193+
export default LandingPage;

vite.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import react from "@vitejs/plugin-react";
33

44
// @ts-expect-error process is a nodejs global
55
const host = process.env.TAURI_DEV_HOST;
6+
const isPagesBuild = process.env.GITHUB_PAGES === "true";
67

78
// https://vite.dev/config/
89
export default defineConfig(async () => ({
910
plugins: [react()],
11+
base: isPagesBuild ? "/dev-stack/" : "./",
1012

1113
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
1214
//

0 commit comments

Comments
 (0)