docs: combine landing page and docusaurus together and deploy as one image

This commit is contained in:
Pasha Sviderski
2025-07-31 18:43:06 +10:00
parent cac1550b7d
commit 4fe360c573
47 changed files with 19097 additions and 19102 deletions
-4
View File
@@ -1,6 +1,5 @@
CORROSION_IMAGE ?= ghcr.io/psviderski/corrosion:latest
UCIND_IMAGE ?= ghcr.io/psviderski/ucind:latest
DOCS_IMAGE ?= ghcr.io/psviderski/uncloud-docs:latest
update-dev:
GOOS=linux GOARCH=amd64 go build -o uncloudd-linux-amd64 ./cmd/uncloudd && \
@@ -112,6 +111,3 @@ _lint:
# Uncloud daemon won't likely support OS other than Linux anytime soon, so for now we can rely on that.
GOOS=linux golangci-lint run $(ARGS)
.PHONY: docs-image-push
docs-image-push:
docker buildx build --push --platform linux/amd64,linux/arm64 -t "$(DOCS_IMAGE)" ./docs
+11 -11
View File
@@ -1,10 +1,10 @@
<div align="center">
<img src="./website/images/logo.svg" height="100" width="100" alt="Uncloud logo"/>
<img src="./website/landing/images/logo.svg" height="100" width="100" alt="Uncloud logo"/>
<h1>Uncloud</h1>
<p><strong>Docker simplicity. Multi-machine power.</strong></p>
<p>
<a href="https://docs.uncloud.run"><img src="https://img.shields.io/badge/Docs-blue.svg?style=for-the-badge&logo=gitbook&logoColor=white" alt="Documentation"></a>
<a href="https://uncloud.run/docs"><img src="https://img.shields.io/badge/Docs-blue.svg?style=for-the-badge&logo=gitbook&logoColor=white" alt="Documentation"></a>
<a href="https://discord.gg/eR35KQJhPu"><img src="https://img.shields.io/badge/discord-5865F2.svg?style=for-the-badge&logo=discord&logoColor=white" alt="Join Discord"></a>
<a href="https://x.com/psviderski"><img src="https://img.shields.io/badge/follow-black?style=for-the-badge&logo=X&logoColor=while" alt="Follow on X"></a>
<a href="https://github.com/sponsors/psviderski"><img src="https://img.shields.io/badge/Donate-EA4AAA.svg?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Donate"></a>
@@ -52,11 +52,11 @@ complexity of Kubernetes.
## 🎬 Quick demo
The screenshot below demonstrates how I use Uncloud to deploy the [Uncloud Documentation](https://docs.uncloud.run)
website to 2 remote machines (why not?) from the [`compose.yaml`](docs/compose.yaml) file on my local machine.
The screenshot below demonstrates how I use Uncloud to deploy https://uncloud.run website to 2 remote machines from
the [`compose.yaml`](website/compose.yaml) file on my local machine.
It exposes the container port `8000/tcp` as HTTPS on the domain `docs.uncloud.run`, served by the Caddy reverse proxy on
the remote machines. All managed by Uncloud.
It exposes the container port `8000/tcp` as HTTPS on the domain `uncloud.run`, served by the Caddy reverse proxy on the
remote machines. All managed by Uncloud.
![Uncloud compose deployment demo](.github/images/compose-deploy.jpg)
@@ -96,8 +96,8 @@ platform, whether you're running on a $5 VPS, a spare Mac mini, or a rack of bar
# or using curl (macOS/Linux)
curl -fsS https://get.uncloud.run/install.sh | sh
```
See [Installation](https://docs.uncloud.run/getting-started/install-cli) for more options.
See [Installation](https://uncloud.run/docs/getting-started/install-cli) for more options.
2. Initialise your first machine:
@@ -130,15 +130,15 @@ platform, whether you're running on a $5 VPS, a spare Mac mini, or a rack of bar
uncloud-uninstall
```
View the [Documentation](https://docs.uncloud.run) for more information.
View the [Documentation](https://uncloud.run/docs) for more information.
## ⚙️ How it works
Check out the [design document](docs/design.md) to understand Uncloud's design philosophy and goals.
Check out the [design document](misc/design.md) to understand Uncloud's design philosophy and goals.
Here is a diagram of an Uncloud multi-provider cluster of 3 machines:
![Diagram: multi-provider cluster of 3 machines](website/images/diagram.webp)
![Diagram: multi-provider cluster of 3 machines](website/landing/images/diagram.webp)
<details>
<summary>Peek under the hood to see what happens when you run certain commands.</summary>
-41
View File
@@ -1,41 +0,0 @@
# Website
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ yarn
```
### Local Development
```
$ yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ yarn build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true yarn deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> yarn deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
-8
View File
@@ -1,8 +0,0 @@
services:
uncloud-docs:
image: ghcr.io/psviderski/uncloud-docs:latest
pull_policy: always
user: nobody
x-ports:
- docs.uncloud.run:8000/https
scale: 2
-18434
View File
File diff suppressed because it is too large Load Diff
-45
View File
@@ -1,45 +0,0 @@
{
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@easyops-cn/docusaurus-search-local": "^0.49.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.7.0"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}
View File
@@ -2,7 +2,9 @@
*
# Allow files and directories.
!blog2/
!docs/
!landing/
!src/
!static/
!pkg/
+1 -1
View File
@@ -5,5 +5,5 @@
:8000 {
root * /usr/share/caddy
file_server
try_files {path} /index.html
log
}
+4 -1
View File
@@ -19,9 +19,12 @@ RUN npm ci
## Build the static site.
RUN npm run build
# Stage 3: Serve static site with Caddy.
# Stage 3: Serve static Docusaurus site and landing page with Caddy.
FROM caddy:2.10.0-alpine AS caddy
## Copy the Caddyfile.
COPY ./Caddyfile /etc/caddy/Caddyfile
## Copy the Docusaurus build output.
COPY --from=prod /opt/docusaurus/build /usr/share/caddy
# Copy the landing page assets.
COPY landing/images /usr/share/caddy/images
COPY landing/index.html landing/style.css /usr/share/caddy/
+5
View File
@@ -0,0 +1,5 @@
WEBSITE_IMAGE ?= ghcr.io/psviderski/uncloud-website:latest
.PHONY: website-image-push
website-image-push:
docker buildx build --push --platform linux/amd64,linux/arm64 -t "$(WEBSITE_IMAGE)" .
+52
View File
@@ -0,0 +1,52 @@
# Website
## Landing page
Landing page is a single static HTML file located at [`./landing/index.html`](./landing/index.html). It is built
using [Tailwind CSS](https://tailwindcss.com/).
### Local development
```shell
cd landing
open index.html
# Watch the Tailwind CSS class changes and rebuild style.css
npm run dev
```
## Docs and Blog
`/docs` and `/blog` are built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
### Local Development
```
npm start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without
having to restart the server.
## Deployment
Both the landing page and Docusaurus site are built into a single Docker image that runs Caddy web server to serve the
static files.
Before building a production image, test the build locally:
```shell
docker compose -f compose.local.yaml up --build
```
Verify:
* http://localhost:8000 — should show the landing page
* http://localhost:3000/docs/ — should show the docs generated by Docusaurus
* http://localhost:3000/blog/ — should show the blog generated by Docusaurus
### Deploy to production
```shell
make website-image-push
uc deploy
```
+6
View File
@@ -0,0 +1,6 @@
services:
website:
build: .
user: nobody
ports:
- "8000:8000"
+8
View File
@@ -0,0 +1,8 @@
services:
uncloud-website:
image: ghcr.io/psviderski/uncloud-website:latest
pull_policy: always
user: nobody
x-ports:
- uncloud.run:8000/https
scale: 2

Before

Width:  |  Height:  |  Size: 389 KiB

After

Width:  |  Height:  |  Size: 389 KiB

@@ -54,12 +54,13 @@ const config = {
({
docs: {
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/psviderski/uncloud/edit/main/docs/',
editUrl: 'https://github.com/psviderski/uncloud/edit/main/website/',
// Serve the docs at the site's root.
// routeBasePath: '/',
showLastUpdateTime: true,
sidebarPath: './sidebars.js',
},
blog: false,
// blog: {
// showReadingTime: true,
// feedOptions: {
@@ -100,6 +101,7 @@ const config = {
logo: {
alt: 'Uncloud Logo',
src: 'img/logo.svg',
href: 'https://uncloud.run',
},
items: [
{
@@ -108,10 +110,11 @@ const config = {
label: 'Docs',
position: 'left',
},
{
to: 'blog',
label: 'Blog',
position: 'left'},
// {
// to: 'blog',
// label: 'Blog',
// position: 'left',
// },
{
type: 'search',
position: 'right',
@@ -158,20 +161,6 @@ const config = {
//darkTheme: prismThemes.dracula,
},
}),
plugins: [
[
'@docusaurus/plugin-client-redirects',
{
redirects: [
{
from: '/',
to: '/new-index.html',
},
],
},
],
],
};
export default config;
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 341 B

@@ -32,6 +32,13 @@
content="Take your Docker Compose apps to production with zero-downtime deployments, automatic HTTPS, and cross-machine scaling. Self-hosting made reliable without the complexity.">
<meta name="twitter:image" content="https://uncloud.run/images/logo-wide.png">
<meta name="twitter:image:alt" content="Uncloud logo - Self-host web apps with ease">
<style>
/* Prevent all inline SVGs from appearing full screen */
svg {
max-width: 24px;
max-height: 24px;
}
</style>
</head>
<body class="font-inter antialiased bg-white text-zinc-900 tracking-tight">
@@ -45,8 +52,9 @@
<div class="flex items-center justify-between h-14">
<!-- Site branding -->
<div class="shrink-0 mr-4">
<a class="flex items-center" href="index.html">
<img class="w-8 h-8 rounded shadow-sm shadow-zinc-950/20" src="./images/logo.svg" alt="Logo">
<a class="flex items-center" href="/">
<img class="w-8 h-8 rounded shadow-sm shadow-zinc-950/20" src="./images/logo.svg" alt="Logo"
width="32" height="32">
<span class="ml-2 font-semibold text-lg text-zinc-900">uncloud</span>
</a>
</div>
@@ -56,7 +64,7 @@
<ul class="flex grow justify-end flex-wrap items-center">
<li>
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-3 lg:px-5 py-2 flex items-center transition"
href="https://docs.uncloud.run">
href="/docs">
<svg class="w-4 h-4 mr-1 fill-current hidden sm:inline"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
@@ -713,11 +721,11 @@
<ul class="text-sm space-y-2">
<li>
<a class="text-zinc-500 hover:text-zinc-900 transition"
href="https://docs.uncloud.run/#use-cases">Use cases</a>
href="/docs/#use-cases">Use cases</a>
</li>
<li>
<a class="text-zinc-500 hover:text-zinc-900 transition"
href="https://docs.uncloud.run/getting-started/quick-start">Quick start</a>
href="/docs/getting-started/deploy-demo-app">Quick start</a>
</li>
</ul>
</div>
+1031
View File
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
{
"name": "gray-html",
"description": "Gray HTML template - Cruip.com",
"version": "1.0.0",
"homepage": "https://cruip.com",
"author": "Pasquale Vitiello",
"license": "https://cruip.com/terms/",
"scripts": {
"dev": "npx tailwindcss -i ./css/style.css -o ./style.css --watch",
"build": "npx tailwindcss -i ./css/style.css -o ./style.css"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
"tailwindcss": "^3.3.6"
}
}
+11 -70
View File
@@ -41,10 +41,8 @@ html {
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
@@ -374,13 +372,6 @@ textarea {
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
@@ -443,9 +434,7 @@ video {
}
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
@@ -472,11 +461,6 @@ video {
border-color: #2563eb;
}
input::-moz-placeholder, textarea::-moz-placeholder{
color: #6b7280;
opacity: 1;
}
input::placeholder,textarea::placeholder{
color: #6b7280;
opacity: 1;
@@ -521,9 +505,7 @@ select{
}
[type='checkbox'],[type='radio']{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
@@ -531,7 +513,6 @@ select{
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
@@ -577,9 +558,7 @@ select{
@media (forced-colors: active) {
[type='checkbox']:checked{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -589,9 +568,7 @@ select{
@media (forced-colors: active) {
[type='radio']:checked{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -611,9 +588,7 @@ select{
@media (forced-colors: active) {
[type='checkbox']:indeterminate{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -772,9 +747,7 @@ select{
}
.form-input,.form-textarea,.form-select,.form-multiselect{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
appearance: none;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
@@ -801,11 +774,6 @@ select{
border-color: #2563eb;
}
.form-input::-moz-placeholder, .form-textarea::-moz-placeholder{
color: #6b7280;
opacity: 1;
}
.form-input::placeholder,.form-textarea::placeholder{
color: #6b7280;
opacity: 1;
@@ -850,9 +818,7 @@ select{
}
.form-checkbox,.form-radio{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
@@ -860,7 +826,6 @@ select{
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
@@ -906,9 +871,7 @@ select{
@media (forced-colors: active) {
.form-checkbox:checked{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -918,9 +881,7 @@ select{
@media (forced-colors: active) {
.form-radio:checked{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -940,9 +901,7 @@ select{
@media (forced-colors: active) {
.form-checkbox:indeterminate{
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
appearance: auto;
}
}
@@ -1097,11 +1056,6 @@ input[type="search"]::-webkit-search-results-decoration {
color: rgb(82 82 91 / var(--tw-text-opacity));
}
.form-input::-moz-placeholder, .form-textarea::-moz-placeholder{
--tw-placeholder-opacity: 1;
color: rgb(161 161 170 / var(--tw-placeholder-opacity));
}
.form-input::placeholder,
.form-textarea::placeholder{
--tw-placeholder-opacity: 1;
@@ -1185,14 +1139,6 @@ input[type="search"]::-webkit-search-results-decoration {
transition: y 0.1s ease-out, transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1), width 0.1s ease-out;
}
.visible{
visibility: visible;
}
.collapse{
visibility: collapse;
}
.absolute{
position: absolute;
}
@@ -1418,13 +1364,8 @@ input[type="search"]::-webkit-search-results-decoration {
flex-grow: 1;
}
.transform{
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.select-none{
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
+17881 -448
View File
File diff suppressed because it is too large Load Diff
+39 -10
View File
@@ -1,16 +1,45 @@
{
"name": "gray-html",
"description": "Gray HTML template - Cruip.com",
"version": "1.0.0",
"homepage": "https://cruip.com",
"author": "Pasquale Vitiello",
"license": "https://cruip.com/terms/",
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "npx tailwindcss -i ./css/style.css -o ./style.css --watch",
"build": "npx tailwindcss -i ./css/style.css -o ./style.css"
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@easyops-cn/docusaurus-search-local": "^0.49.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
"tailwindcss": "^3.3.6"
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.7.0"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}
+9
View File
@@ -0,0 +1,9 @@
import React from 'react';
import Layout from '@theme/Layout';
export default function Hello() {
return (
<Layout>
</Layout>
);
}

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 341 B

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB