Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ All notable changes to taskflow are documented here. This project follows [Keep
and saved flows from the library. `safeParse()` for LLM output remains
strict. Re-exported from the `taskflow-core` barrel as `parseJsonc`.

## [0.1.6] — 2026-07-06
## [0.1.5] — 2026-07-03

### Added
- **Scoring gates (`score` on `gate` phases).** Deterministic, composable,
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<a href="./README.zh-CN.md">简体中文</a>
</p>

<p align="center">
<a href="https://heggria.github.io/taskflow/en"><img src="https://img.shields.io/badge/📖_Read_the_docs-heggria.github.io%2Ftaskflow-4B4ACF?style=for-the-badge&labelColor=2D2F5A" alt="Read the docs — heggria.github.io/taskflow"></a>
</p>

<p><strong>A declarative, verifiable <em>graph of tasks</em> for coding-agent subagents.</strong><br/>
Not a workflow you script — a DAG you declare. Fan out · gate · loop · tournament · resume · save as a command — intermediate results stay out of your context.<br/>
Runs on the <a href="https://pi.dev">Pi</a> coding agent, on <a href="https://github.com/openai/codex">OpenAI Codex</a>, on <a href="https://claude.com/product/claude-code">Claude Code</a>, and on <a href="https://opencode.ai">OpenCode</a>.</p>
Expand Down
4 changes: 4 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
<a href="./docs/i18n/README.ru.md">Русский</a>
</p>

<p align="center">
<a href="https://heggria.github.io/taskflow/zh-cn"><img src="https://img.shields.io/badge/📖_阅读文档-heggria.github.io%2Ftaskflow-4B4ACF?style=for-the-badge&labelColor=2D2F5A" alt="阅读文档 — heggria.github.io/taskflow"></a>
</p>

<p><strong>面向编码智能体子代理(subagent)的声明式、可验证的「任务图」。</strong><br/>
不是你要去「写脚本」的 workflow——而是你去「声明」的一张 DAG。并发分发(fan out)· 门控(gate)· 恢复(resume)· 保存为命令——中间结果始终远离你的上下文窗口(context window)。<br/>
可运行于 <a href="https://pi.dev">Pi</a> 编码智能体、<a href="https://github.com/openai/codex">OpenAI Codex</a>、<a href="https://claude.com/product/claude-code">Claude Code</a> 与 <a href="https://opencode.ai">OpenCode</a>。</p>
Expand Down
23 changes: 22 additions & 1 deletion website/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ const site = {
// Example: 'abc123...'
const GOOGLE_SITE_VERIFICATION = process.env.GOOGLE_SITE_VERIFICATION || '';

// The site is deployed under a GitHub Pages subpath (/taskflow), so every
// metadata asset URL (favicon, apple-touch-icon, manifest, icon PNGs) must be
// prefixed with the configured basePath. Next.js does NOT apply basePath to
// <link rel="icon"> / <link rel="manifest"> under `output: export`, so we do
// it explicitly here. Locally (TASKFLOW_BASE_PATH unset) this is just ''.
const base = process.env.TASKFLOW_BASE_PATH || '';

export async function generateMetadata({
params,
}: {
Expand All @@ -48,8 +55,22 @@ export async function generateMetadata({
},
},
icons: {
icon: [{ url: '/favicon.svg', type: 'image/svg+xml' }],
// Explicit basePath — Next.js omits it for <link> under output:export.
icon: [{ url: `${base}/favicon.svg`, type: 'image/svg+xml' }],
apple: [{ url: `${base}/apple-icon`, sizes: '180x180', type: 'image/png' }],
},
// themeColor + appleWebApp pair with app/manifest.ts and app/apple-icon.tsx
// so Safari/iOS/Android render a branded tab, splash, and home-screen icon.
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#fff7ed' },
{ media: '(prefers-color-scheme: dark)', color: '#1c1917' },
],
appleWebApp: {
title: 'taskflow',
statusBarStyle: 'default',
capable: true,
},
manifest: `${base}/manifest.webmanifest`,
verification: GOOGLE_SITE_VERIFICATION
? { google: GOOGLE_SITE_VERIFICATION }
: undefined,
Expand Down
75 changes: 75 additions & 0 deletions website/app/apple-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Apple touch icon (Next.js metadata file route → <link rel="apple-touch-icon">).
// Used by iOS Safari bookmarks, "Add to Home Screen", and Safari pinned tabs.
// iOS renders this full-bleed then masks it to the platform's squircle itself,
// so we fill the whole canvas (no rounded corners here) and keep the DAG motif
// generously inset so it isn't clipped by the mask. Same orange gradient as
// icon.tsx / favicon.svg for brand consistency.
import { ImageResponse } from 'next/og';

// `output: export` requires routes to be statically renderable.
export const dynamic = 'force-static';

export const size = { width: 180, height: 180 };
export const contentType = 'image/png';
export const alt = 'taskflow';

export default function AppleIcon() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#fb923c',
backgroundImage:
'linear-gradient(160deg, #fb923c 0%, #ea580c 100%)',
}}
>
<svg
width="104"
height="104"
viewBox="0 0 100 100"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="28"
y1="32"
x2="72"
y2="32"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
<line
x1="28"
y1="32"
x2="50"
y2="70"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
<line
x1="72"
y1="32"
x2="50"
y2="70"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
<circle cx="28" cy="32" r="10" fill="#fff" />
<circle cx="72" cy="32" r="10" fill="#fff" />
<circle cx="50" cy="72" r="12" fill="#fff" />
</svg>
</div>
),
{
...size,
},
);
}
82 changes: 82 additions & 0 deletions website/app/icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Favicon / browser-tab icon (Next.js metadata file route).
// Emits /icon (with basePath applied automatically) as a PNG that modern
// browsers pick up via the injected <link rel="icon">. We also keep
// public/favicon.svg as an SVG fallback; this PNG is the canonical tab icon
// (renders identically in Safari, which still prefers PNG over SVG favicons).
//
// The DAG motif matches favicon.svg and the plugin icons: an orange rounded
// tile with three white nodes joined into a downward graph.
import { ImageResponse } from 'next/og';

// `output: export` requires routes to be statically renderable.
export const dynamic = 'force-static';

export const size = { width: 180, height: 180 };
export const contentType = 'image/png';
export const alt = 'taskflow';

export default function Icon() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#fb923c',
backgroundImage:
'linear-gradient(160deg, #fb923c 0%, #ea580c 100%)',
borderRadius: 40,
boxShadow: '0 6px 20px rgba(194, 65, 12, 0.3)',
}}
>
<svg
width="108"
height="108"
viewBox="0 0 100 100"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
{/* top crossbar edge */}
<line
x1="28"
y1="32"
x2="72"
y2="32"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
{/* downstroke edges into the bottom node */}
<line
x1="28"
y1="32"
x2="50"
y2="70"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
<line
x1="72"
y1="32"
x2="50"
y2="70"
stroke="#fff"
strokeWidth="7"
strokeLinecap="round"
/>
{/* three nodes */}
<circle cx="28" cy="32" r="10" fill="#fff" />
<circle cx="72" cy="32" r="10" fill="#fff" />
<circle cx="50" cy="72" r="12" fill="#fff" />
</svg>
</div>
),
{
...size,
},
);
}
42 changes: 42 additions & 0 deletions website/app/manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Web App Manifest (Next.js metadata file route → /manifest.webmanifest).
// Enables install-to-home-screen, the Android "maskable" adaptive icon, and a
// branded splash color when the site is added to a device. Icon srcs point at
// the metadata file routes (app/icon.tsx, app/apple-icon.tsx); Next.js applies
// the configured basePath automatically, so no manual prefix here.
import type { MetadataRoute } from 'next';

// `output: export` requires routes to be statically renderable.
export const dynamic = 'force-static';

export default function manifest(): MetadataRoute.Manifest {
// basePath must be prepended manually — manifest is emitted as a static
// asset under output:export, so icon srcs won't get the prefix otherwise.
const base = process.env.TASKFLOW_BASE_PATH || '';
return {
name: 'taskflow — declarative agent orchestration',
short_name: 'taskflow',
description:
'A declarative, verifiable graph of task nodes for coding-agent subagents. Fan out, gate, loop, resume, and save as a command.',
start_url: `${base}/`,
display: 'standalone',
background_color: '#fff7ed',
theme_color: '#ea580c',
icons: [
{
// any-purpose icon (browser tab + Android standard)
src: `${base}/icon`,
sizes: '180x180',
type: 'image/png',
purpose: 'any',
},
{
// maskable: Android adaptive icon — the orange tile fills the
// safe zone so the platform mask yields a clean squircle.
src: `${base}/apple-icon`,
sizes: '180x180',
type: 'image/png',
purpose: 'maskable',
},
],
};
}
Loading