diff --git a/docs/package.json b/docs/package.json index de0bae5..2ab6dd3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@orama/orama": "^3.1.18", + "clsx": "^2.1.1", "fumadocs-core": "16.8.5", "fumadocs-mdx": "14.3.2", "fumadocs-ui": "16.8.5", diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 1d783a4..7142474 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@orama/orama': specifier: ^3.1.18 version: 3.1.18 + clsx: + specifier: ^2.1.1 + version: 2.1.1 fumadocs-core: specifier: 16.8.5 version: 16.8.5(@mdx-js/mdx@3.1.1)(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.14)(lucide-react@1.14.0(react@19.2.5))(next@16.2.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(zod@4.4.2) @@ -104,24 +107,28 @@ packages: engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [musl] '@biomejs/cli-linux-arm64@2.4.14': resolution: {integrity: sha512-2TELhZnW5RSLL063l9rc5xLpA0ZIw0Ccwy/0q384rvNAgFw3yI76bd59547yxowdQr5MNPET/xDLrLuvgSeeWQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [glibc] '@biomejs/cli-linux-x64-musl@2.4.14': resolution: {integrity: sha512-R6BWgJdQOwW9ulJatuTVrQkjnODjqHZkKNOqb1sz++3Noe5LYd0i3PchnOBUCYAPHoPWHhjJqbdZlHEu0hpjdA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [musl] '@biomejs/cli-linux-x64@2.4.14': resolution: {integrity: sha512-zHrlQZDBDUz4OLAraYpWKcnLS6HOewBFWYOzY91d1ZjdqZwibOyb6BEu6WuWLugyo0P3riCmsbV9UqV1cSXwQg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [glibc] '@biomejs/cli-win32-arm64@2.4.14': resolution: {integrity: sha512-M3EH5hqOI/F/FUA2u4xcLoUgmxd218mvuj/6JL7Hv2toQvr2/AdOvKSpGkoRuWFCtQPVa+ZqkEV3Q5xBA9+XSA==} @@ -374,89 +381,105 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -523,24 +546,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@next/swc-linux-arm64-musl@16.2.4': resolution: {integrity: sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@next/swc-linux-x64-gnu@16.2.4': resolution: {integrity: sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@next/swc-linux-x64-musl@16.2.4': resolution: {integrity: sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@next/swc-win32-arm64-msvc@16.2.4': resolution: {integrity: sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow==} @@ -998,24 +1025,28 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.4': resolution: {integrity: sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.4': resolution: {integrity: sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.4': resolution: {integrity: sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.4': resolution: {integrity: sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==} @@ -1966,24 +1997,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} diff --git a/docs/src/app/(home)/_sections/_window-dots.tsx b/docs/src/app/(home)/_sections/_window-dots.tsx new file mode 100644 index 0000000..46047ab --- /dev/null +++ b/docs/src/app/(home)/_sections/_window-dots.tsx @@ -0,0 +1,14 @@ +export function WindowDots({ filename }: { filename: string }) { + return ( + <> +
| + Property + | ++ {COMPARISON.taskito.label} + | ++ {COMPARISON.celery.label} + | +
|---|---|---|
| + {row.label} + | ++ {row.taskito} + | ++ {row.celery} + | +
+ {CTA_CONTENT.description} +
+
+ {part.slice(1, -1)}
+
+ );
+ }
+ return part;
+ });
+}
diff --git a/docs/src/app/(home)/_sections/features.tsx b/docs/src/app/(home)/_sections/features.tsx
new file mode 100644
index 0000000..98a70c7
--- /dev/null
+++ b/docs/src/app/(home)/_sections/features.tsx
@@ -0,0 +1,36 @@
+import { SectionHeader } from "@/components/ui";
+import {
+ FEATURES,
+ FEATURES_DESCRIPTION,
+ FEATURES_TITLE,
+ type LandingFeature,
+} from "@/lib/landing-content";
+
+export function Features() {
+ return (
+ {body}
++ {HERO.description} +
+
- {children}
-
- ),
- },
- });
-}
-
-function CodePanel({
- label,
- caption,
- tone,
- children,
-}: {
- label: string;
- caption: string;
- tone: Tone;
- children: React.ReactNode;
-}) {
- const accent =
- tone === "primary" ? "border-t-fd-primary" : "border-t-fd-border";
- return (
- | - Property - | -- taskito - | -- Celery + Redis - | -
|---|---|---|
| - {row.label} - | -- {row.taskito} - | -- {row.celery} - | -
- Rust-powered task queue for Python. Replace Celery without Redis or - RabbitMQ. Start with SQLite, scale to Postgres. -
-
-
-
- # pip install taskito
-
- {"\n"}
- from{" "}
- taskito{" "}
- import{" "}
- Queue{"\n\n"}
- queue ={" "}
- Queue
- (db_path=
-
- "tasks.db"
-
- ){"\n\n"}
- @queue.task()
- {"\n"}
- def{" "}
- add(a, b):
- {"\n"}
- {" "}
- return a
- + b{"\n\n"}
- job = add.
- delay(
- 2,{" "}
- 3){"\n"}
- print(job.
- result())
- {" "}
- # 5
-
-
- - The convenience of Celery, the performance of Rust, the simplicity of - SQLite. -
-- {body} -
-- The same task, two stacks. Side by side, with the operational delta. -
-pip install to your
- first job.
- - The quickstart walks you through defining a task, enqueuing it, and - watching the worker run it — no Redis, no broker, no config. -
-{description}
+ ) : null} +
+ {children}
+
+ ),
+ },
+ });
+}
diff --git a/docs/src/lib/landing-content.tsx b/docs/src/lib/landing-content.tsx
new file mode 100644
index 0000000..295aeb6
--- /dev/null
+++ b/docs/src/lib/landing-content.tsx
@@ -0,0 +1,214 @@
+import {
+ Activity,
+ Cpu,
+ Layers,
+ type LucideIcon,
+ Shield,
+ Workflow,
+ Zap,
+} from "lucide-react";
+
+export type CtaTarget = {
+ href: string;
+ label: string;
+};
+
+export type LandingHero = {
+ badge: string;
+ headline: string[];
+ description: string;
+ primaryCta: CtaTarget;
+ secondaryCta: CtaTarget;
+ ghostCta: CtaTarget;
+ preview: {
+ filename: string;
+ code: string;
+ };
+};
+
+export type LandingFeature = {
+ icon: LucideIcon;
+ title: string;
+ body: string;
+};
+
+export type ComparisonRow = {
+ label: string;
+ taskito: string;
+ celery: string;
+};
+
+export type ComparisonStack = {
+ label: string;
+ caption: string;
+ code: string;
+};
+
+export type LandingComparison = {
+ title: string;
+ description: string;
+ taskito: ComparisonStack;
+ celery: ComparisonStack;
+ rows: ComparisonRow[];
+};
+
+export type LandingCta = {
+ title: string;
+ description: string;
+ primary: CtaTarget;
+ secondary: CtaTarget;
+};
+
+export const HERO: LandingHero = {
+ badge: "v0.12 — Rust core, native async, DAG workflows",
+ headline: ["Task queue", "without the broker."],
+ description:
+ "Rust-powered task queue for Python. Replace Celery without Redis or RabbitMQ. Start with SQLite, scale to Postgres.",
+ primaryCta: {
+ href: "/docs/getting-started/quickstart",
+ label: "Quickstart",
+ },
+ secondaryCta: {
+ href: "/docs/getting-started/installation",
+ label: "Install",
+ },
+ ghostCta: {
+ href: "https://github.com/ByteVeda/taskito",
+ label: "GitHub →",
+ },
+ preview: {
+ filename: "tasks.py",
+ code: `# pip install taskito
+from taskito import Queue
+
+queue = Queue(db_path="tasks.db")
+
+@queue.task()
+def add(a, b):
+ return a + b
+
+job = add.delay(2, 3)
+print(job.result()) # 5`,
+ },
+};
+
+export const FEATURES_TITLE = "What you get";
+export const FEATURES_DESCRIPTION =
+ "The convenience of Celery, the performance of Rust, the simplicity of SQLite.";
+
+export const FEATURES: LandingFeature[] = [
+ {
+ icon: Zap,
+ title: "Brokerless",
+ body: "No Redis, no RabbitMQ. Everything in a single SQLite file — queue, results, rate limits, schedules. Just `pip install` and go.",
+ },
+ {
+ icon: Cpu,
+ title: "Rust-powered",
+ body: "The scheduler, dispatcher, and storage engine are all Rust. Tokio runtime, OS-thread worker pool, thin PyO3 boundary keeps the Python overhead negligible.",
+ },
+ {
+ icon: Activity,
+ title: "Async-first",
+ body: "`async def` tasks dispatch onto a dedicated event loop — no `asyncio.run()` wrapping, no thread-pool bridging. Sync and async tasks coexist transparently.",
+ },
+ {
+ icon: Workflow,
+ title: "DAG workflows",
+ body: "Multi-step pipelines as directed acyclic graphs. Fan-out, fan-in, conditions, approval gates, sub-workflows, incremental re-runs, Mermaid visualization.",
+ },
+ {
+ icon: Layers,
+ title: "Resource system",
+ body: "Inject database connections, HTTP clients, and cloud SDKs by name. Three-layer pipeline: argument interception, worker DI, transparent proxy reconstruction.",
+ },
+ {
+ icon: Shield,
+ title: "Production-ready",
+ body: "Retries with exponential backoff, dead letter queue, rate limits, circuit breakers, distributed locks, structured logs, OTel/Sentry/Prometheus middleware.",
+ },
+];
+
+export const COMPARISON: LandingComparison = {
+ title: "Less to operate",
+ description:
+ "The same task, two stacks. Side by side, with the operational delta.",
+ taskito: {
+ label: "taskito",
+ caption: "Brokerless · single process",
+ code: `from taskito import Queue
+
+queue = Queue(db_path="tasks.db")
+
+@queue.task(max_retries=3, rate_limit="100/m")
+def send_email(to, subject, body):
+ smtp.send(to, subject, body)
+
+# Enqueue
+send_email.delay("alice@example.com", "Hi", "Body")
+
+# Run the worker
+# $ taskito worker --app tasks:queue`,
+ },
+ celery: {
+ label: "Celery + Redis",
+ caption: "Requires Redis · 3 processes",
+ code: `from celery import Celery
+
+app = Celery(
+ "myapp",
+ broker="redis://localhost:6379/0",
+ backend="redis://localhost:6379/1",
+)
+app.conf.task_default_rate_limit = "100/m"
+
+@app.task(bind=True, max_retries=3)
+def send_email(self, to, subject, body):
+ try:
+ smtp.send(to, subject, body)
+ except SMTPError as exc:
+ raise self.retry(exc=exc, countdown=60)
+
+# Enqueue
+send_email.delay("alice@example.com", "Hi", "Body")
+
+# Run the worker (in a separate terminal, plus Redis)
+# $ celery -A myapp worker --loglevel=info`,
+ },
+ rows: [
+ {
+ label: "Install",
+ taskito: "pip install taskito",
+ celery: "pip install celery[redis] + run Redis daemon",
+ },
+ {
+ label: "Background services",
+ taskito: "1 (worker)",
+ celery: "3 (worker, beat, Redis)",
+ },
+ {
+ label: "Default storage",
+ taskito: "SQLite file (built-in)",
+ celery: "Redis (separate daemon)",
+ },
+ {
+ label: "Retry config in the example above",
+ taskito: "max_retries=3 decorator arg",
+ celery: "try/except + self.retry(exc=…)",
+ },
+ ],
+};
+
+export const CTA: LandingCta = {
+ title: "Five minutes from `pip install` to your first job.",
+ description:
+ "The quickstart walks you through defining a task, enqueuing it, and watching the worker run it — no Redis, no broker, no config.",
+ primary: {
+ href: "/docs/getting-started/quickstart",
+ label: "Start the quickstart",
+ },
+ secondary: {
+ href: "/docs/more/comparison",
+ label: "See the full comparison",
+ },
+};