m/cup
1
0
mirror of https://github.com/sergi0g/cup.git synced 2025-11-10 22:23:48 -05:00

Upgrade docs

This commit is contained in:
Sergio
2025-02-01 13:41:21 +02:00
parent b5aa0309ee
commit a5bbdd0e33
76 changed files with 981 additions and 6326 deletions

2
docs/.prettierignore Normal file
View File

@@ -0,0 +1,2 @@
.next
.node_modules

View File

@@ -1,3 +0,0 @@
{
"plugins": ["prettier-plugin-tailwindcss"]
}

View File

@@ -1 +0,0 @@
nodejs 22.8.0

View File

@@ -1 +1,37 @@
This is where Cup's documentation lives. It's created with [Nextra](https://nextra.site). # Cup Documentation
## Architecture
The docs are built with [Nextra](https://nextra.site). We use [Bun](https://bun.sh) as a package manager and Node.js as a runtime (Next.js and Bun don't play well together at the moment). Docs pages are written in [MDX](https://mdxjs.com) and any custom components are written in TypeScript with TSX.
## Development
Prerequisites:
- A recent Node.js version (22 recommended)
- [Bun](https://bun.sh)
```bash
git clone https://github.com/sergi0g/cup
cd cup/docs
bun install
```
You're ready to go!
## Scripts
The available scripts are:
- `bun dev` starts the development server. Note that making changes to MDX pages will probably require a full reload.
- `bun run build` creates a static production build, ready to be deployed.
- `bun lint` checks for errors in your code.
- `bun fmt` formats your code with Prettier, so it becomes... prettier.
## Contributing
Our documentation is always evolving, so, we constantly need to update this repository with new guides and configuration options. If you have any ideas of a guide or suggestions on how to improve them, feel free to open a pull request or create an issue. All contributions are welcome!
## License
The documentation is licensed under the MIT License. TL;DR — You are free to use, copy, modify, merge, publish, distribute, sublicense, and sell copies of the software. However, the software is provided "as is," without warranty of any kind. You must include the original license in all copies or substantial portions of the software.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

BIN
docs/bun.lockb Executable file

Binary file not shown.

View File

@@ -1,23 +0,0 @@
import React, { ReactNode } from "react";
export function Step({
children,
title,
number,
}: {
children: ReactNode;
title: string;
number: number;
}) {
return (
<div className="mb-2 flex grow-0 items-baseline">
<p className="m-2 flex size-10 items-center justify-center rounded-full bg-neutral-100 dark:bg-neutral-900">
{number}
</p>
<div>
<p className="text-xl font-bold">{title}</p>
<div className="my-6">{children}</div>
</div>
</div>
);
}

View File

@@ -1,174 +0,0 @@
import React, { useState, useEffect } from "react";
import {
IconAdjustments,
IconArrowRight,
IconBolt,
IconBraces,
IconCheck,
IconClipboard,
IconDevices,
IconFeather,
IconLockCheck,
} from "@tabler/icons-react";
import { GitHubIcon } from "../../assets/GitHubIcon";
import { GridPattern } from "../GridPattern";
import { Section } from "../Section";
import { GradientText } from "../GradientText";
import Image from "next/image";
import screenshot_light from "../../assets/screenshot_light.png";
import screenshot_dark from "../../assets/screenshot_dark.png";
import { Step } from "../Step";
import { Card } from "../Card";
export function Home() {
const [copySuccess, setCopySuccess] = useState(false);
const [isBrowser, setIsBrowser] = useState(false); // To prevent hydration mismatch
useEffect(() => setIsBrowser(true));
const handleCopy = (text: string) => {
return () => {
navigator.clipboard.writeText(text).then(() => {
setCopySuccess(true);
setTimeout(() => {
setCopySuccess(false);
}, 3000);
});
};
};
return (
<div className="home-animation" style={{ opacity: 0 }}>
<div className="relative h-full overflow-x-hidden p-4 pt-10 lg:pt-20">
<GridPattern />
<div className="mx-auto h-full min-h-svh w-full max-w-screen-xl md:h-[46rem] md:min-h-0">
<div className="grid gap-8 lg:grid-cols-2">
<div className="flex max-w-3xl flex-col gap-8">
<div className="text-6xl font-extrabold leading-none tracking-tighter sm:text-7xl">
The easiest way to manage your
<GradientText
text="container updates."
innerClassName="bg-gradient-to-r from-blue-500 to-green-500"
blur={30}
/>
</div>
<h3 className="text-xl text-neutral-600 dark:text-neutral-400">
Cup is a small utility with a big impact. Simplify your
container management workflow with fast and efficient update
checking, a full-featured CLI and web inteface, and more.
</h3>
<div className="*:-0 mt-auto grid w-fit grid-cols-2 gap-4 *:flex *:items-center *:gap-2 *:rounded-lg *:px-3 *:py-2">
<a
href="/docs"
className="hide-focus group h-full bg-black text-white dark:bg-white dark:text-black"
>
Get started
<IconArrowRight className="ml-auto mr-1 transition-transform duration-300 ease-out group-hover:translate-x-1 group-focus:translate-x-1 dark:!text-black" />
</a>
<a
href="https://github.com/sergi0g/cup"
target="_blank"
className="hide-focus h-full text-nowrap border border-neutral-400 transition-colors duration-200 ease-in-out hover:border-neutral-600 focus:border-neutral-600 dark:border-neutral-600 hover:dark:border-neutral-400 hover:dark:shadow-sm hover:dark:shadow-neutral-600 focus:dark:border-neutral-400"
>
Star on GitHub
<GitHubIcon className="ml-auto size-4 md:size-5" />
</a>
</div>
</div>
<div className="h-full">
<div className="max-h-[33.75rem] max-w-full overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-800">
<Image
src={screenshot_light}
alt="Screenshot of Cup's web interface"
className="dark:hidden"
/>
<Image
src={screenshot_dark}
alt="Screenshot of Cup's web interface"
className="hidden dark:block"
/>
</div>
</div>
</div>
</div>
</div>
<Section
title="Powerful at its core."
className="bg-gradient-to-r from-red-500 to-amber-500"
>
<Card
name="100% Safe Code"
icon={IconLockCheck}
description="Built with safe Rust and Typescript to ensure security and reliability."
/>
<Card
name="Lightning Fast Performance"
icon={IconBolt}
description="Heavily optimized to squeeze out every last drop of performance. Each release is extensively benchmarked and profiled so that you'll never have to stare at a loading spinner for long."
/>
<Card
name="Lightweight"
icon={IconFeather}
description="No runtimes or libraries are needed. All you need is the 5.1 MB static binary that works out of the box on any system."
/>
</Section>
<Section
title="Efficient, yet flexible."
className="bg-gradient-to-r from-blue-500 to-indigo-500"
>
<Card
name="JSON output"
description="Connect Cup to your favorite intergrations with JSON output for the CLI and an API for the server. Now go make that cool dashboard you've been dreaming of!"
icon={IconBraces}
/>
<Card
name="Both CLI and web interface"
description="Whether you prefer the command line, or the web, Cup runs wherever you choose."
icon={IconDevices}
/>
<Card
name="Configurable"
description="The simple configuration file provides you with all the tools you need to specify a custom Docker socket, manage registry connection options, choose a theme for the web interface and more."
icon={IconAdjustments}
/>
</Section>
<div className="relative py-24">
<GridPattern />
<div className="mx-auto flex w-full max-w-screen-xl flex-col items-center">
<p className="mb-8 text-center text-3xl font-bold">
Still not convinced? Try it out now!
</p>
<div>
<Step title="Open a terminal and run" number={1}>
<div className="group relative mx-auto flex max-w-screen-xl items-center rounded-lg bg-neutral-100 px-3 py-2 font-mono text-neutral-700 dark:bg-neutral-950 dark:text-neutral-300">
<p className="overflow-scroll">
docker run --rm -t -v /var/run/docker.sock:/var/run/docker.sock -p 8000:8000 ghcr.io/sergi0g/cup serve
</p>
{isBrowser &&
navigator.clipboard &&
(copySuccess ? (
<IconCheck className="absolute right-3 size-7 bg-neutral-100 pl-2 dark:bg-neutral-950" />
) : (
<button
className="duration-50 absolute right-3 bg-neutral-100 pl-2 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-neutral-950"
onClick={handleCopy(
"docker run --rm -t -v /var/run/docker.sock:/var/run/docker.sock -p 8000:8000 ghcr.io/sergi0g/cup serve",
)}
>
<IconClipboard className="size-5" />
</button>
))}
</div>
</Step>
<Step number={2} title="Open the dashboard in your browser">
<p>
Visit{" "}
<a href="http://localhost:8000" className="underline">
http://localhost:8000
</a>{" "}
in your browser to try it out!
</p>
</Step>
</div>
</div>
</div>
</div>
);
}

21
docs/eslint.config.mjs Normal file
View File

@@ -0,0 +1,21 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{
rules: {
"import/no-anonymous-default-export": "off",
},
},
];
export default eslintConfig;

2
docs/next-env.d.ts vendored
View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -1,16 +0,0 @@
const withNextra = require("nextra")({
theme: "nextra-theme-docs",
themeConfig: "./theme.config.jsx",
});
module.exports = withNextra({
output: "export",
images: {
unoptimized: true,
},
transpilePackages: ["geist", "framer-motion"],
basePath: process.env.NODE_ENV == "production" ? "/cup" : "",
});
// If you have other Next.js configurations, you can pass them as the parameter:
// module.exports = withNextra({ /* other next.js config */ })

19
docs/next.config.ts Normal file
View File

@@ -0,0 +1,19 @@
import nextra from "nextra";
const withNextra = nextra({
defaultShowCopyCode: true,
});
export default withNextra({
output: "export",
transpilePackages: ["geist"],
images: {
unoptimized: true,
remotePatterns: [
{
protocol: "https",
hostname: "raw.githubusercontent.com",
},
],
},
});

View File

@@ -1,28 +1,38 @@
{ {
"name": "cup-docs",
"version": "0.1.0",
"private": true,
"scripts": { "scripts": {
"dev": "next", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"fmt": "prettier --ignore-path ../.gitignore --write ." "lint": "next lint",
"fmt": "bun prettier --write ."
}, },
"dependencies": { "dependencies": {
"@tabler/icons-react": "^3.11.0", "@heroicons/react": "^2.2.0",
"clsx": "^2.1.1", "@tabler/icons-react": "^3.29.0",
"geist": "^1.3.1", "geist": "^1.3.1",
"next": "^14.2.10", "next": "15.1.5",
"nextra": "^2.13.4", "nextra": "^4.1.0",
"nextra-theme-docs": "^2.13.4", "nextra-theme-docs": "^4.1.0",
"react": "^18.3.1", "react": "^19.0.0",
"react-dom": "^18.3.1" "react-dom": "^19.0.0",
"tailwind-merge": "^2.6.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "22.10.2", "@eslint/eslintrc": "^3.2.0",
"autoprefixer": "^10.4.19", "@tailwindcss/postcss": "^4.0.1",
"postcss": "^8.4.39", "@types/node": "^22.10.7",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3",
"eslint": "^9.18.0",
"eslint-config-next": "15.1.5",
"postcss": "^8.5.1",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9", "prettier-plugin-tailwindcss": "^0.6.11",
"tailwindcss": "^3.4.5", "tailwindcss": "^4.0.1",
"typescript": "5.7.2" "typescript": "^5.7.3"
}, },
"packageManager": "pnpm@9.10.0+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c" "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
} }

View File

@@ -1,12 +0,0 @@
import "../styles.css";
import "nextra-theme-docs/style.css";
import { GeistSans } from "geist/font/sans";
export default function App({ Component, pageProps }) {
return (
<main className={GeistSans.className}>
<Component {...pageProps} />
</main>
);
}

View File

@@ -1,45 +0,0 @@
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import type { DocumentInitialProps, DocumentContext } from "next/document";
class DocumentProMax extends Document {
static async getInitialProps(
ctx: DocumentContext,
): Promise<DocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
return (
<Html lang="en">
<Head>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta
name="theme-color"
media="(prefers-color-scheme: light)"
content="#ffffff"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#111111"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default DocumentProMax;

View File

@@ -1,14 +0,0 @@
{
"docs": {
"title": "Documentation",
"type": "page"
},
"index": {
"type": "page",
"title": "Cup - The easiest way to manage your container updates",
"display": "hidden",
"theme": {
"layout": "raw"
}
}
}

View File

@@ -1,23 +0,0 @@
{
"index": {
"title": "Introduction"
},
"installation": {
"title": "Installation"
},
"configuration": {
"title": "Configuration"
},
"usage": {
"title": "Usage"
},
"community-resources": {
"title": "Community Resources"
},
"nightly": {
"title": "Using the latest version"
},
"contributing": {
"title": "Contributing"
}
}

View File

@@ -1,8 +0,0 @@
{
"docker": {
"title": "With Docker"
},
"binary": {
"title": "As a binary"
}
}

View File

@@ -1,11 +0,0 @@
import { IconServer, IconTerminal } from "@tabler/icons-react";
import { Cards, Card } from "nextra-theme-docs";
# Usage
You can use Cup in 2 different ways. As a CLI or as a server. You can learn more about each mode in its corresponding page
<Cards>
<Card icon={<IconTerminal />} title="CLI" href="/docs/usage/cli" />
<Card icon={<IconServer />} title="Server" href="/docs/usage/server" />
</Cards>

View File

@@ -1,57 +0,0 @@
import { Callout } from "nextra-theme-docs";
# Server
The server provides the `cup serve` command.
## Basic usage
```ansi
$ cup serve
2024-07-17T09:08:38.724922Z   INFO  xitca_server::net  :  Started Tcp listening on: Some(0.0.0.0:8000)
2024-07-17T09:08:38.725076Z   WARN  xitca_server::server::future  :  ServerFuture::wait is called from within tokio context. It would block current thread from handling async tasks
2024-07-17T09:08:38.725248Z   INFO  xitca_server::worker  :  Started xitca-server-worker-0
2024-07-17T09:08:38.725343Z   INFO  xitca_server::worker  :  Started xitca-server-worker-1
2024-07-17T09:08:38.725580Z   INFO  xitca_server::worker  :  Started xitca-server-worker-2
2024-07-17T09:08:38.725607Z   INFO  xitca_server::worker  :  Started xitca-server-worker-3
2024-07-17T09:08:41.390783Z   INFO  request  {  method  = GET uri  = / }  :  on_request  :  serving request
2024-07-17T09:08:41.390905Z   INFO  request  {  method  = GET uri  = / }  :  on_response  :  sending response
```
This will launch the server on port `8000`. To access it, visit `http://<YOUR_IP>:8000` (replace `<YOUR_IP>` with the IP address of the machine running Cup.)
<Callout>
The URL `http://<YOUR_IP>:8000/api/v3/json` is also available for usage with integrations.
</Callout>
## Use a different port
Pass the `-p` argument with the port you want to use
```ansi
$ cup serve -p 9000
2024-07-17T09:08:38.724922Z   INFO  xitca_server::net  :  Started Tcp listening on: Some(0.0.0.0:9000)
2024-07-17T09:08:38.725076Z   WARN  xitca_server::server::future  :  ServerFuture::wait is called from within tokio context. It would block current thread from handling async tasks
2024-07-17T09:08:38.725248Z   INFO  xitca_server::worker  :  Started xitca-server-worker-0
2024-07-17T09:08:38.725343Z   INFO  xitca_server::worker  :  Started xitca-server-worker-1
2024-07-17T09:08:38.725580Z   INFO  xitca_server::worker  :  Started xitca-server-worker-2
2024-07-17T09:08:38.725607Z   INFO  xitca_server::worker  :  Started xitca-server-worker-3
2024-07-17T09:08:41.390783Z   INFO  request  {  method  = GET uri  = / }  :  on_request  :  serving request
2024-07-17T09:08:41.390905Z   INFO  request  {  method  = GET uri  = / }  :  on_response  :  sending response
```
## Usage with Docker
If you're using the Docker image, just replace all occurences of `cup` in the examples with `docker run -tv /var/run/docker.sock:/var/run/docker.sock -p <PORT>:<PORT> ghcr.io/sergi0g/cup`, where `<PORT>` is the port Cup will be using.
For example, this:
```bash /serve -p 9000/
$ cup serve -p 9000
```
becomes:
```bash /serve -p 9000/
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock -p 9000:9000 ghcr.io/sergi0g/cup serve -p 9000
```

5680
docs/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

8
docs/postcss.config.mjs Normal file
View File

@@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -0,0 +1,27 @@
import { generateStaticParamsFor, importPage } from "nextra/pages";
import { useMDXComponents } from "@/mdx-components";
export const generateStaticParams = generateStaticParamsFor("mdxPath");
interface Props {
params: { mdxPath: string[] };
}
export async function generateMetadata(props: Props) {
const params = await props.params;
const { metadata } = await importPage(params.mdxPath);
return metadata;
}
/* eslint-disable-next-line */
const Wrapper = useMDXComponents({}).wrapper;
export default async function Page(props: Props) {
const params = await props.params;
const result = await importPage(params.mdxPath);
const { default: MDXContent, toc, metadata } = result;
return (
<Wrapper toc={toc} metadata={metadata}>
<MDXContent {...props} params={params} />
</Wrapper>
);
}

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
import Link from "next/link";
import { ReactNode } from "react";
import { twMerge } from "tailwind-merge";
interface ButtonProps {
href: string;
className?: string;
children: ReactNode;
}
export default function Button({ href, className, children }: ButtonProps) {
return (
<Link
href={href}
className={twMerge(
"flex items-center justify-center rounded-md border border-transparent px-8 py-3 text-base font-medium no-underline transition-colors duration-200 md:text-lg md:leading-6",
className,
)}
>
{children}
</Link>
);
}

View File

@@ -1,20 +1,17 @@
import { ReactNode, createElement } from "react"; import { Icon as IconType } from "@tabler/icons-react";
export function Card({ export function Card({
name, name,
icon, icon: Icon,
description, description,
}: { }: {
name: string; name: string;
icon: ReactNode; icon: IconType;
description: string; description: string;
}) { }) {
const iconElement = createElement(icon, {
className: "text-black size-7 dark:text-white inline mr-2",
});
return ( return (
<div> <div>
{iconElement} <Icon className="text-black size-7 dark:text-white inline mr-2" />
<span className="align-middle text-2xl font-bold text-black dark:text-white"> <span className="align-middle text-2xl font-bold text-black dark:text-white">
{name} {name}
</span> </span>

View File

@@ -0,0 +1,28 @@
"use client";
import { IconCopy, IconCopyCheck } from "@tabler/icons-react";
import { useState } from "react";
export default function CopyableCode({ children }: { children: string }) {
const [success, setSuccess] = useState(false);
const handleClick = () => {
navigator.clipboard.writeText(children);
setSuccess(true);
setTimeout(() => setSuccess(false), 3000);
};
return (
<div className="relative rounded-md xl:w-auto">
<button
className="hover:bg-black/10 dark:hover:bg-black/60 flex w-full items-center justify-center gap-4 rounded-md border border-black/10 bg-black/5 px-8 py-3 font-mono text-sm font-medium text-black/70 transition-colors duration-200 md:px-10 md:py-3 md:text-base md:leading-6 dark:border-white/15 dark:bg-black dark:text-gray-300 backdrop-blur-md"
onClick={handleClick}
>
{children}
{success ? (
<IconCopyCheck className="stroke-black/40 dark:stroke-white/50" />
) : (
<IconCopy className="stroke-black/40 dark:stroke-white/50" />
)}
</button>
</div>
);
}

View File

@@ -14,7 +14,9 @@ export function GradientText({
}) { }) {
return ( return (
<div className={clsx("relative", className)}> <div className={clsx("relative", className)}>
<p className={clsx("bg-clip-text text-transparent", innerClassName)}> <p
className={clsx("bg-clip-text text-transparent w-fit", innerClassName)}
>
{text} {text}
</p> </p>
<p <p

View File

@@ -16,8 +16,8 @@ export function GridPattern() {
width={SIZE} width={SIZE}
height={SIZE} height={SIZE}
patternUnits="userSpaceOnUse" patternUnits="userSpaceOnUse"
x={0} x={-1}
y={0} y={-1}
> >
<path <path
d={`M.5 ${SIZE}V.5H${SIZE}`} d={`M.5 ${SIZE}V.5H${SIZE}`}

View File

@@ -0,0 +1,29 @@
"use client";
import { Head as NextraHead } from "nextra/components";
export function Head() {
return (
<NextraHead>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta
name="theme-color"
media="(prefers-color-scheme: light)"
content="#ffffff"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#111111"
/>
<meta
name="og:image"
content="https://raw.githubusercontent.com/sergi0g/cup/main/docs/public/cup-og.png"
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="https://cup.sergi0g.dev" />
<meta name="apple-mobile-web-app-title" content="Cup" />
</NextraHead>
);
}

View File

@@ -0,0 +1,57 @@
export default function Logo() {
return (
<svg
viewBox="0 0 128 128"
style={{ height: "calc(var(--nextra-navbar-height) * 0.6)" }}
>
<path
style={{ fill: "#A6CFD6" }}
d="M65.12,17.55c-17.6-0.53-34.75,5.6-34.83,14.36c-0.04,5.2,1.37,18.6,3.62,48.68s2.25,33.58,3.5,34.95
c1.25,1.37,10.02,8.8,25.75,8.8s25.93-6.43,26.93-8.05c0.48-0.78,1.83-17.89,3.5-37.07c1.81-20.84,3.91-43.9,3.99-45.06
C97.82,30.66,94.2,18.43,65.12,17.55z"
/>
<path
style={{ fill: "#DCEDF6" }}
d="M41.4,45.29c-0.12,0.62,1.23,24.16,2.32,27.94c1.99,6.92,9.29,7.38,10.23,4.16
c0.9-3.07-0.38-29.29-0.38-29.29s-3.66-0.3-6.43-0.84C44,46.63,41.4,45.29,41.4,45.29z"
/>
<path
style={{ fill: "#6CA4AE" }}
d="M33.74,32.61c-0.26,8.83,20.02,12.28,30.19,12.22c13.56-0.09,29.48-4.29,29.8-11.7
S79.53,21.1,63.35,21.1C49.6,21.1,33.96,25.19,33.74,32.61z"
/>
<path
style={{ fill: "#DC0D27" }}
d="M84.85,13.1c-0.58,0.64-9.67,30.75-9.67,30.75s2.01-0.33,4-0.79c2.63-0.61,3.76-1.06,3.76-1.06
s7.19-22.19,7.64-23.09c0.45-0.9,21.61-7.61,22.31-7.93c0.7-0.32,1.39-0.4,1.46-0.78c0.06-0.38-2.34-6.73-3.11-6.73
C110.47,3.47,86.08,11.74,84.85,13.1z"
/>
<path
style={{ fill: "#8A1F0F" }}
d="M110.55,7.79c1.04,2.73,2.8,3.09,3.55,2.77c0.45-0.19,1.25-1.84,0.01-4.47
c-0.99-2.09-2.17-2.74-2.93-2.61C110.42,3.6,109.69,5.53,110.55,7.79z"
/>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M91.94,18.34c-0.22,0-0.44-0.11-0.58-0.3l-3.99-5.77c-0.22-0.32-0.14-0.75,0.18-0.97
c0.32-0.22,0.76-0.14,0.97,0.18l3.99,5.77c0.22,0.32,0.14,0.75-0.18,0.97C92.21,18.3,92.07,18.34,91.94,18.34z"
/>
</g>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M90.28,19.43c-0.18,0-0.35-0.07-0.49-0.2l-5.26-5.12c-0.28-0.27-0.28-0.71-0.01-0.99
c0.27-0.28,0.71-0.28,0.99-0.01l5.26,5.12c0.28,0.27,0.28,0.71,0.01,0.99C90.64,19.36,90.46,19.43,90.28,19.43z"
/>
</g>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M89.35,21.22c-0.12,0-0.25-0.03-0.36-0.1l-5.6-3.39c-0.33-0.2-0.44-0.63-0.24-0.96
c0.2-0.33,0.63-0.44,0.96-0.24l5.6,3.39c0.33,0.2,0.44,0.63,0.24,0.96C89.82,21.1,89.59,21.22,89.35,21.22z"
/>
</g>
</svg>
);
}

View File

@@ -11,7 +11,7 @@ export function Section({
children: ReactNode; children: ReactNode;
}) { }) {
return ( return (
<div className="border-t bg-neutral-50 py-32 dark:border-t-neutral-600/30 dark:bg-neutral-950"> <div className="border-t border-t-neutral-300 bg-neutral-50 py-32 dark:border-t-neutral-600/30 dark:bg-neutral-950">
<div className="mx-auto w-full max-w-screen-xl"> <div className="mx-auto w-full max-w-screen-xl">
<GradientText <GradientText
text={title} text={title}

View File

@@ -0,0 +1,136 @@
import React from "react";
import "./styles.css";
import CopyableCode from "../CopyableCode";
import { Browser } from "../Browser";
import { Card } from "../Card";
import {
IconAdjustments,
IconArrowRight,
IconBolt,
IconBraces,
IconDevices,
IconFeather,
IconLockCheck,
} from "@tabler/icons-react";
import { GitHubIcon } from "nextra/icons";
import { GridPattern } from "../GridPattern";
import { GradientText } from "../GradientText";
import { Section } from "../Section";
import { Steps } from "nextra/components";
import Link from "next/link";
export default async function Home() {
return (
<>
<div className="relative">
<GridPattern />
<div className="px-4 pt-16 pb-8 sm:pt-24 lg:px-8">
<div className="flex w-full flex-col items-center justify-between">
<div>
<h1 className="mx-auto max-w-2xl text-center text-6xl leading-none font-extrabold tracking-tighter text-black sm:text-7xl dark:text-white">
The easiest way to manage your
<GradientText
text="container updates."
className="mx-auto w-fit"
innerClassName="bg-linear-to-r/oklch from-blue-500 to-green-500"
blur={30}
/>
</h1>
<h3 className="mx-auto mt-6 max-w-3xl text-center text-xl leading-tight font-medium text-gray-400">
Cup is a small utility with a big impact. Simplify your
container management workflow with fast and efficient update
checking, a full-featured CLI and web inteface, and more.
</h3>
</div>
<div className="mt-8 grid w-fit grid-cols-2 gap-4 *:flex *:items-center *:gap-2 *:rounded-lg *:px-3 *:py-2">
<Link
href="/docs"
className="hide-focus group h-full bg-black text-white dark:bg-white dark:text-black"
>
Get started
<IconArrowRight className="ml-auto mr-1 transition-transform duration-300 ease-out group-hover:translate-x-1 group-focus:translate-x-1 dark:!text-black" />
</Link>
<a
href="https://github.com/sergi0g/cup"
target="_blank"
className="hide-focus h-full text-nowrap border border-neutral-400 transition-colors duration-200 ease-in-out hover:border-neutral-600 focus:border-neutral-600 dark:border-neutral-600 hover:dark:border-neutral-400 hover:dark:shadow-sm hover:dark:shadow-neutral-600 focus:dark:border-neutral-400"
>
Star on GitHub
<GitHubIcon className="ml-auto size-4 md:size-5" />
</a>
</div>
</div>
</div>
<div className="py-10 flex translate-y-32 justify-center" id="hero">
<Browser />
</div>
</div>
<Section
title="Powerful at its core."
className="bg-gradient-to-r from-red-500 to-amber-500"
>
<Card
name="100% Safe Code"
icon={IconLockCheck}
description="Built with safe Rust and Typescript to ensure security and reliability."
/>
<Card
name="Lightning Fast Performance"
icon={IconBolt}
description="Heavily optimized to squeeze out every last drop of performance. Each release is extensively benchmarked and profiled so that you'll never have to stare at a loading spinner for long."
/>
<Card
name="Lightweight"
icon={IconFeather}
description="No runtimes or libraries are needed. All you need is the 5.1 MB static binary that works out of the box on any system."
/>
</Section>
<Section
title="Efficient, yet flexible."
className="bg-gradient-to-r from-blue-500 to-indigo-500"
>
<Card
name="JSON output"
description="Connect Cup to your favorite intergrations with JSON output for the CLI and an API for the server. Now go make that cool dashboard you've been dreaming of!"
icon={IconBraces}
/>
<Card
name="Both CLI and web interface"
description="Whether you prefer the command line, or the web, Cup runs wherever you choose."
icon={IconDevices}
/>
<Card
name="Configurable"
description="The simple configuration file provides you with all the tools you need to specify a custom Docker socket, manage registry connection options, choose a theme for the web interface and more."
icon={IconAdjustments}
/>
</Section>
<div className="relative py-24 border-t border-t-neutral-300 dark:border-t-neutral-600/30 text-black dark:text-white">
<GridPattern />
<div className="mx-auto flex w-full max-w-screen-xl flex-col items-center">
<p className="mb-8 text-center text-3xl font-bold">
Still not convinced? Try it out now!
</p>
<div>
<Steps>
<h3 className="mb-2">Open a terminal and run</h3>
<CopyableCode>
docker run --rm -t -v /var/run/docker.sock:/var/run/docker.sock
-p 8000:8000 ghcr.io/sergi0g/cup serve
</CopyableCode>
<h3 className="mb-2">Open the dashboard in your browser</h3>
<p>
Visit{" "}
<a href="http://localhost:8000" className="underline">
http://localhost:8000
</a>{" "}
in your browser to try it out!
</p>
</Steps>
</div>
</div>
</div>
</>
);
}

View File

@@ -0,0 +1,36 @@
/* Override nextra styles restricting width */
:root {
--nextra-content-width: unset !important;
}
header.nextra-navbar {
--nextra-content-width: 90rem;
}
article {
padding-inline: 0 !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
article div.x\:mt-16:last-child:empty {
margin-top: 0;
}
#hero {
animation-name: hero;
animation-duration: 1500ms;
animation-delay: 500ms;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
@keyframes hero {
from {
translate: 0 8rem;
}
to {
translate: 0 0;
}
}

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

17
docs/src/app/globals.css Normal file
View File

@@ -0,0 +1,17 @@
@import "tailwindcss";
@variant dark (&:where(.dark, .dark *));
.nextra-card .tabler-icon:hover {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon {
color: rgb(55 65 81 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon:is(.dark *) {
color: rgb(229 229 229 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon:is(.dark *):hover {
color: rgb(250 250 250 / var(--tw-text-opacity));
}

55
docs/src/app/layout.tsx Normal file
View File

@@ -0,0 +1,55 @@
import type { Metadata } from "next";
import { Footer, Layout, Navbar, ThemeSwitch } from "nextra-theme-docs";
import { getPageMap } from "nextra/page-map";
import { GeistSans } from "geist/font/sans";
import "nextra-theme-docs/style.css";
import "./globals.css";
import { Head } from "./components/Head";
import Logo from "./components/Logo";
export const metadata: Metadata = {
title: "Cup",
description: "The easiest way to manage your container updates",
};
const logo = (
<div className="flex items-center">
<Logo />
<h1 className="ml-2 font-bold">Cup</h1>
</div>
);
const navbar = (
<Navbar logo={logo} projectLink="https://github.com/sergi0g/cup">
<ThemeSwitch lite className="cursor-pointer" />
</Navbar>
);
const footer = <Footer> </Footer>;
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
dir="ltr"
suppressHydrationWarning
className={`${GeistSans.className} antialiased`}
>
<Head />
<body>
<Layout
navbar={navbar}
pageMap={await getPageMap()}
footer={footer}
docsRepositoryBase="https://github.com/sergi0g/cup"
>
<div>{children}</div>
</Layout>
</body>
</html>
);
}

View File

@@ -3,6 +3,6 @@ title: Cup - The easiest way to manage your container updates
description: Simple, fast, efficient Docker image update checking description: Simple, fast, efficient Docker image update checking
--- ---
import { Home } from "../components/pages/Home"; import Home from "@/app/components/pages/home";
<Home /> <Home />

17
docs/src/content/_meta.ts Normal file
View File

@@ -0,0 +1,17 @@
export default {
index: {
theme: {
sidebar: false,
toc: false,
breadcrumb: false,
pagination: false,
timestamp: false,
layout: "full",
},
display: "hidden",
},
docs: {
type: "page",
title: "Documentation",
},
};

View File

@@ -0,0 +1,5 @@
export default {
installation: {},
usage: {},
configuration: {},
};

View File

@@ -1,6 +1,6 @@
import Image from "next/image"; import Image from "next/image";
import widget1 from "../../../assets/350767810-42eccc89-bdfd-426a-a113-653abe7483d8.png"; import widget1 from "@/app/assets/350767810-42eccc89-bdfd-426a-a113-653abe7483d8.png";
import widget2 from "../../../assets/358304960-e9f26767-51f7-4b5a-8b74-a5811019497b.jpeg"; import widget2 from "@/app/assets/358304960-e9f26767-51f7-4b5a-8b74-a5811019497b.jpeg";
# Homepage Widget # Homepage Widget

View File

@@ -1,4 +1,4 @@
import { Callout } from "nextra-theme-docs"; import { Callout } from "nextra/components";
# Authentication # Authentication

View File

@@ -1,4 +1,8 @@
import { Steps, Callout, Card, Cards } from "nextra-theme-docs"; ---
asIndexPage: true
---
import { Steps, Callout, Cards } from "nextra/components";
import { import {
IconPaint, IconPaint,
IconLockOpen, IconLockOpen,
@@ -14,13 +18,13 @@ Sometimes, there may be a need to specify a custom docker socket. Cup provides t
For example, if using Podman, you might do For example, if using Podman, you might do
``` ```bash
$ cup -s /run/user/1000/podman/podman.sock check $ cup -s /run/user/1000/podman/podman.sock check
``` ```
This option is also available in the configuration file and it's best to put it there. This option is also available in the configuration file and it's best to put it there.
<Card <Cards.Card
icon={<IconPlug />} icon={<IconPlug />}
title="Custom Docker socket" title="Custom Docker socket"
href="/docs/configuration/socket" href="/docs/configuration/socket"
@@ -40,17 +44,21 @@ If you're running with Docker, you can create a `cup.json` in the directory you'
Follow the guides below to customize your `cup.json` Follow the guides below to customize your `cup.json`
<Cards> <Cards>
<Card <Cards.Card
icon={<IconKey />} icon={<IconKey />}
title="Authentication" title="Authentication"
href="/docs/configuration/authentication" href="/docs/configuration/authentication"
/> />
<Card <Cards.Card
icon={<IconLockOpen />} icon={<IconLockOpen />}
title="Insecure registries" title="Insecure registries"
href="/docs/configuration/insecure-registries" href="/docs/configuration/insecure-registries"
/> />
<Card icon={<IconPaint />} title="Theme" href="/docs/configuration/theme" /> <Cards.Card
icon={<IconPaint />}
title="Theme"
href="/docs/configuration/theme"
/>
</Cards> </Cards>
Here's a full example: Here's a full example:
@@ -67,8 +75,10 @@ Here's a full example:
``` ```
<Callout> <Callout>
If you want autocompletions and error checking for your editor, there is a JSON schema available. If you want autocompletions and error checking for your editor, there is a
Use it by adding a `"$schema": "https://raw.githubusercontent.com/sergi0g/cup/main/cup.schema.json"` entry in your `cup.json` file. JSON schema available. Use it by adding a `"$schema":
"https://raw.githubusercontent.com/sergi0g/cup/main/cup.schema.json"` entry in
your `cup.json` file.
</Callout> </Callout>
### Run Cup with the new configuration file ### Run Cup with the new configuration file

View File

@@ -1,4 +1,4 @@
import { Callout } from "nextra-theme-docs"; import { Callout } from "nextra/components";
# Insecure registries # Insecure registries
@@ -27,6 +27,6 @@ Here's what it looks like:
<Callout emoji="⚠️"> <Callout emoji="⚠️">
When configuring an insecure registry that doesn't run on port 80, don't When configuring an insecure registry that doesn't run on port 80, don't
forget to specify the port (i.e. use `localhost:5000` instead of `localhost` if your forget to specify the port (i.e. use `localhost:5000` instead of `localhost`
registry is running on port `5000`) if your registry is running on port `5000`)
</Callout> </Callout>

View File

@@ -16,4 +16,4 @@ You can also specify a TCP socket if you're using a remote Docker host or a [pro
"socket": "tcp://localhost:2375" "socket": "tcp://localhost:2375"
// Other options // Other options
} }
``` ```

View File

@@ -1,8 +1,8 @@
import { Callout } from "nextra-theme-docs"; import { Callout } from "nextra/components";
import Image from "next/image"; import Image from "next/image";
import blue from "../../../assets/blue_theme.png"; import blue from "@/app/assets/blue_theme.png";
import neutral from "../../../assets/neutral_theme.png"; import neutral from "@/app/assets/hero-dark.png";
# Theme # Theme
@@ -27,3 +27,5 @@ Here's an example:
// Other options // Other options
} }
``` ```
Note that the difference between the 2 themes is almost impossible to perceive when your system is in light mode.

View File

@@ -1,3 +1,5 @@
import { Steps } from "nextra/components";
# Contributing # Contributing
First of all, thanks for taking time to contribute to Cup! This guide will help you set up a development environment and make your first contribution. First of all, thanks for taking time to contribute to Cup! This guide will help you set up a development environment and make your first contribution.
@@ -10,10 +12,26 @@ Requirements:
- Rust (usually installed from https://rustup.rs/) - Rust (usually installed from https://rustup.rs/)
- Node.js 22+ and Bun 1+ - Node.js 22+ and Bun 1+
1. Fork the repository. This is where you'll be pushing your changes before you create a pull request. Make sure to _create a new branch_ for your changes. <Steps>
2. Clone your fork with `git clone https://github.com/<YOUR_USERNAME>/cup` (if you use SSH, `git clone git@github.com:<YOUR_USERNAME>/cup`) and open your editor ### Fork the repository
3. Switch to your newly created branch (e.g. if your branch is called `improve-logging`, run `git checkout improve-logging`) This is where you'll be pushing your changes before you create a pull request. Make sure to _create a new branch_ for your changes.
4. Run `bun install` in `web/` and `./build.sh` to set up the frontend ### Clone your fork
```bash
git clone https://github.com/<YOUR_USERNAME>/cup
```
If you use SSH:
```bash
git clone git@github.com:<YOUR_USERNAME>/cup`)
```
### Switch to your newly created branch (e.g. if your branch is called `improve-logging`, run `git checkout improve-logging`)
### Set up the frontend
```bash
$ cd web
$ bun install
$ cd ..
$ ./build.sh
```
</Steps>
You're ready to go! You're ready to go!

View File

@@ -1,11 +1,11 @@
import Image from "next/image"; import Image from "next/image";
import cup from "../../assets/cup.gif"; import cup from "@/app/assets/cup.gif";
import { Cards, Card } from "nextra-theme-docs"; import { Cards } from "nextra/components";
import { IconBrandDocker, IconPackage } from "@tabler/icons-react"; import { IconBrandDocker, IconPackage } from "@tabler/icons-react";
# Introduction # Introduction
<Image src={cup} unoptimized /> <Image src={cup} alt="Animated GIF of Cup's CLI in action" unoptimized />
Cup is a lightweight alternative to [What's up Docker?](https://github.com/getwud/wud) written in Rust. Cup is a lightweight alternative to [What's up Docker?](https://github.com/getwud/wud) written in Rust.
@@ -21,12 +21,12 @@ Cup is a lightweight alternative to [What's up Docker?](https://github.com/getwu
# Installation # Installation
<Cards> <Cards>
<Card <Cards.Card
icon={<IconBrandDocker />} icon={<IconBrandDocker />}
title="With Docker" title="With Docker"
href="/docs/installation/docker" href="/docs/installation/docker"
/> />
<Card <Cards.Card
icon={<IconPackage />} icon={<IconPackage />}
title="As a binary" title="As a binary"
href="/docs/installation/binary" href="/docs/installation/binary"

View File

@@ -0,0 +1,8 @@
export default {
docker: {
title: "With Docker",
},
binary: {
title: "As a binary",
},
};

View File

@@ -1,4 +1,4 @@
import { Callout, Card, Steps } from "nextra-theme-docs"; import { Callout, Cards, Steps } from "nextra/components";
import { IconFileDescription } from "@tabler/icons-react"; import { IconFileDescription } from "@tabler/icons-react";
# As a binary # As a binary
@@ -25,4 +25,4 @@ Move the binary you downloaded to a directory in your path. You can usually get
That's it! Cup is ready to be used. Head over to the Usage page to get started. That's it! Cup is ready to be used. Head over to the Usage page to get started.
<br /> <br />
<Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" /> <Cards.Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" />

View File

@@ -1,4 +1,4 @@
import { Callout, Card } from "nextra-theme-docs"; import { Callout, Cards } from "nextra/components";
import { IconFileDescription } from "@tabler/icons-react"; import { IconFileDescription } from "@tabler/icons-react";
# With Docker # With Docker
@@ -16,12 +16,12 @@ $ docker pull ghcr.io/sergi0g/cup
``` ```
<Callout emoji="⚠️"> <Callout emoji="⚠️">
If you aren't in the `docker` group, please ensure you run all commands as a If you aren't a member of the `docker` group, please ensure you run all
user who does. In most cases, you'll just need to prefix the `docker` commands commands as a user who is. In most cases, you'll just need to prefix the
with `sudo` `docker` commands with `sudo`
</Callout> </Callout>
That's it! Cup is ready to be used. Head over to the Usage page to get started. That's it! Cup is ready to be used. Head over to the Usage page to get started.
<br /> <br />
<Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" /> <Cards.Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" />

View File

@@ -1,4 +1,4 @@
import { Callout } from "nextra-theme-docs"; import { Callout } from "nextra/components";
# Using the latest version # Using the latest version
@@ -13,7 +13,7 @@ Cup's nightly version always contains the latest changes in the main branch.
breaking changes or a bad commit and it may not work properly. Install nightly breaking changes or a bad commit and it may not work properly. Install nightly
only if you know what you are doing. These instructions will assume you have only if you know what you are doing. These instructions will assume you have
the technical know-how to follow them. If you do not, please use the stable the technical know-how to follow them. If you do not, please use the stable
release release!
</Callout> </Callout>
## With Docker ## With Docker

View File

@@ -1,5 +1,5 @@
import Image from "next/image"; import Image from "next/image";
import cup from "../../../assets/cup.gif"; import cup from "@/app/assets/cup.gif";
# CLI # CLI
@@ -72,6 +72,6 @@ $ cup check node:latest
becomes: becomes:
```bash ```bash
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock ghcr.io/sergi0g/cup check node:latest $ docker run -tv /var/run/docker.sock:/var/run/docker.sock ghcr.io/sergi0g/cup check node:latest
``` ```

View File

@@ -0,0 +1,15 @@
---
asIndexPage: true
---
import { IconServer, IconTerminal } from "@tabler/icons-react";
import { Cards } from "nextra/components";
# Usage
You can use Cup in 2 different ways. As a CLI or as a server. You can learn more about each mode in its corresponding page
<Cards>
<Cards.Card icon={<IconTerminal />} title="CLI" href="/docs/usage/cli" />
<Cards.Card icon={<IconServer />} title="Server" href="/docs/usage/server" />
</Cards>

View File

@@ -0,0 +1,55 @@
import { Callout } from "nextra/components";
# Server
The server provides the `cup serve` command.
## Basic usage
```ansi
$ cup serve
INFO Starting server, please wait...
INFO ✨ Checked 8 images in 8862ms
INFO Ready to start!
HTTP GET / 200 in 0ms
HTTP GET /assets/index.js 200 in 3ms
HTTP GET /assets/index.css 200 in 0ms
HTTP GET /api/v3/json 200 in 0ms
```
This will launch the server on port `8000`. To access it, visit `http://<YOUR_IP>:8000` (replace `<YOUR_IP>` with the IP address of the machine running Cup.)
<Callout>
The URL `http://<YOUR_IP>:8000/api/v3/json` is also available for usage with integrations.
</Callout>
## Use a different port
Pass the `-p` argument with the port you want to use
```ansi
$ cup serve -p 9000
INFO Starting server, please wait...
INFO ✨ Checked 8 images in 8862ms
INFO Ready to start!
HTTP GET / 200 in 0ms
HTTP GET /assets/index.js 200 in 3ms
HTTP GET /assets/index.css 200 in 0ms
HTTP GET /api/v3/json 200 in 0ms
```
## Usage with Docker
If you're using the Docker image, just replace all occurences of `cup` in the examples with `docker run -tv /var/run/docker.sock:/var/run/docker.sock -p <PORT>:<PORT> ghcr.io/sergi0g/cup`, where `<PORT>` is the port Cup will be using.
For example, this:
```bash
$ cup serve -p 9000
```
becomes:
```bash
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock -p 9000:9000 ghcr.io/sergi0g/cup serve -p 9000
```

View File

@@ -0,0 +1,13 @@
import { useMDXComponents as getThemeComponents } from "nextra-theme-docs";
import { MDXComponents } from "nextra/mdx-components";
// Get the default MDX components
const themeComponents = getThemeComponents();
// Merge components
export function useMDXComponents(components: MDXComponents) {
return {
...themeComponents,
...components,
};
}

View File

@@ -1,54 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.nextra-card .tabler-icon:hover {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon {
color: rgb(55 65 81 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon:is(.dark *) {
color: rgb(229 229 229 / var(--tw-text-opacity));
}
.nextra-card .tabler-icon:is(.dark *):hover {
color: rgb(250 250 250 / var(--tw-text-opacity));
}
.home-animation {
animation-name: fade-in;
animation-delay: 300ms;
animation-duration: 500ms;
animation-fill-mode: forwards;
animation-timing-function: ease-in;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.hide-focus:focus {
outline: none;
box-shadow: none;
}
.home-pattern {
background-color: white;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23000000' fill-opacity='0.15'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
mask-image: radial-gradient(ellipse at top, white, transparent);
translate: 0 -0.5rem;
}
.home-pattern:is(.dark *) {
background-color: #111111;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.1'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
mask-image: radial-gradient(ellipse at top, #111111, transparent);
translate: 0 -0.5rem;
}

View File

@@ -1,9 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: "class",
content: ["theme.config.jsx", "components/**/*.tsx"],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -1,116 +0,0 @@
import { ThemeSwitch } from "nextra-theme-docs";
import { useRouter } from "next/router";
import { useConfig } from "nextra-theme-docs";
export default {
docsRepositoryBase: "https://github.com/sergi0g/cup/tree/main/docs",
useNextSeoProps() {
const { asPath } = useRouter();
if (asPath !== "/") {
return {
titleTemplate: "Cup %s",
};
} else {
return {
titleTemplate: "%s"
}
}
},
head: () => {
const { asPath } = useRouter();
const { frontMatter } = useConfig();
const url = "https://sergi0g.github.io/cup/docs/" + `/${asPath}`;
return (
<>
<meta property="og:url" content={url} />
<meta property="og:title" content={frontMatter.title || "Cup"} />
<meta
property="og:description"
content={
frontMatter.description ||
"The easiest way to manage your container updates"
}
/>
</>
);
},
logo: (
<div className="flex items-center">
<Logo />
<h1 className="ml-2 font-bold">Cup</h1>
</div>
),
logoLink: "/",
project: {
link: "https://github.com/sergi0g/cup/",
},
navbar: {
extraContent: <ThemeSwitch lite className="[&_span]:hidden" />,
},
toc: {
backToTop: true,
},
footer: {
text: null,
},
navigation: false,
};
function Logo() {
return (
<svg
viewBox="0 0 128 128"
style={{ height: "calc(var(--nextra-navbar-height) * 0.6)" }}
>
<path
style={{ fill: "#A6CFD6" }}
d="M65.12,17.55c-17.6-0.53-34.75,5.6-34.83,14.36c-0.04,5.2,1.37,18.6,3.62,48.68s2.25,33.58,3.5,34.95
c1.25,1.37,10.02,8.8,25.75,8.8s25.93-6.43,26.93-8.05c0.48-0.78,1.83-17.89,3.5-37.07c1.81-20.84,3.91-43.9,3.99-45.06
C97.82,30.66,94.2,18.43,65.12,17.55z"
/>
<path
style={{ fill: "#DCEDF6" }}
d="M41.4,45.29c-0.12,0.62,1.23,24.16,2.32,27.94c1.99,6.92,9.29,7.38,10.23,4.16
c0.9-3.07-0.38-29.29-0.38-29.29s-3.66-0.3-6.43-0.84C44,46.63,41.4,45.29,41.4,45.29z"
/>
<path
style={{ fill: "#6CA4AE" }}
d="M33.74,32.61c-0.26,8.83,20.02,12.28,30.19,12.22c13.56-0.09,29.48-4.29,29.8-11.7
S79.53,21.1,63.35,21.1C49.6,21.1,33.96,25.19,33.74,32.61z"
/>
<path
style={{ fill: "#DC0D27" }}
d="M84.85,13.1c-0.58,0.64-9.67,30.75-9.67,30.75s2.01-0.33,4-0.79c2.63-0.61,3.76-1.06,3.76-1.06
s7.19-22.19,7.64-23.09c0.45-0.9,21.61-7.61,22.31-7.93c0.7-0.32,1.39-0.4,1.46-0.78c0.06-0.38-2.34-6.73-3.11-6.73
C110.47,3.47,86.08,11.74,84.85,13.1z"
/>
<path
style={{ fill: "#8A1F0F" }}
d="M110.55,7.79c1.04,2.73,2.8,3.09,3.55,2.77c0.45-0.19,1.25-1.84,0.01-4.47
c-0.99-2.09-2.17-2.74-2.93-2.61C110.42,3.6,109.69,5.53,110.55,7.79z"
/>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M91.94,18.34c-0.22,0-0.44-0.11-0.58-0.3l-3.99-5.77c-0.22-0.32-0.14-0.75,0.18-0.97
c0.32-0.22,0.76-0.14,0.97,0.18l3.99,5.77c0.22,0.32,0.14,0.75-0.18,0.97C92.21,18.3,92.07,18.34,91.94,18.34z"
/>
</g>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M90.28,19.43c-0.18,0-0.35-0.07-0.49-0.2l-5.26-5.12c-0.28-0.27-0.28-0.71-0.01-0.99
c0.27-0.28,0.71-0.28,0.99-0.01l5.26,5.12c0.28,0.27,0.28,0.71,0.01,0.99C90.64,19.36,90.46,19.43,90.28,19.43z"
/>
</g>
<g>
<path
style={{ fill: "#8A1F0F" }}
d="M89.35,21.22c-0.12,0-0.25-0.03-0.36-0.1l-5.6-3.39c-0.33-0.2-0.44-0.63-0.24-0.96
c0.2-0.33,0.63-0.44,0.96-0.24l5.6,3.39c0.33,0.2,0.44,0.63,0.24,0.96C89.82,21.1,89.59,21.22,89.35,21.22z"
/>
</g>
</svg>
);
}

View File

@@ -1,18 +1,27 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": false, "strict": true,
"noEmit": true, "noEmit": true,
"incremental": true,
"module": "esnext",
"esModuleInterop": true, "esModuleInterop": true,
"moduleResolution": "node", "module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve" "jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }