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
1 change: 1 addition & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ui:
- "packages/app/src/components/**"
- "packages/ui/**"
- "**/*.tsx"
- "site/**"

harness:
- changed-files:
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: deploy-site

on:
push:
branches: [dev]
paths:
- "site/**"

# Build-check the site on PRs that touch it; deploy step is skipped (see below)
pull_request:
paths:
- "site/**"

# Allow manual trigger for first deploy or re-deploy without code change
workflow_dispatch:

concurrency:
group: deploy-site-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
build-and-deploy:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
persist-credentials: false

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # oven-sh/setup-bun@v2
with:
# Load-bearing for `bun audit` exit semantics; do not bump without re-verifying advisory exit codes.
bun-version: "1.3.14"

- run: bun install --frozen-lockfile
working-directory: site

- run: bun run build
working-directory: site

# Deploy only when on dev (push to dev or manual dispatch from dev). PRs and
# manual runs from other branches stop after the build-check steps above, so
# the fixed --branch=dev below can never publish non-dev content.
- uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3
if: github.ref == 'refs/heads/dev'
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy site/dist --project-name=pawwork --branch=dev
1 change: 1 addition & 0 deletions packages/opencode/test/github/bun-version-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe("GitHub workflow Bun version pin", () => {
".github/workflows/ci.yml:unit-ui:step-3:bun-version: \"1.3.14\"",
".github/workflows/ci.yml:unit-opencode:step-3:bun-version: \"1.3.14\"",
".github/workflows/ci.yml:unit-desktop:step-3:bun-version: \"1.3.14\"",
".github/workflows/deploy-site.yml:build-and-deploy:step-2:bun-version: \"1.3.14\"",
".github/workflows/desktop-smoke.yml:smoke-macos-arm64:step-3:bun-version: \"1.3.14\"",
".github/workflows/dev-dep-audit.yml:dev-dep-audit:step-3:bun-version: \"1.3.14\"",
".github/workflows/e2e-artifacts.yml:e2e-artifacts:step-3:bun-version: \"1.3.14\"",
Expand Down
13 changes: 13 additions & 0 deletions site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
# environment
.env
.env.production
# macOS
.DS_Store
31 changes: 31 additions & 0 deletions site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# PawWork site

Download landing page for PawWork. Built with [Astro](https://astro.build/) (plain CSS, no UI framework). Deploys as a static site to Cloudflare Pages, independent of the desktop app build.

## Develop

```sh
bun install
bun run dev # http://localhost:4321
bun run build # outputs to dist/
bun run preview # serve the production build locally
```

## Structure

```text
src/
pages/index.astro page markup; English first paint + client-side CN/EN switch
layouts/Base.astro <head>, SEO tags, anti-flash theme script
styles/global.css all styling; light/dark via [data-theme], CN/EN via [data-lang]
i18n.ts EN/CN copy dictionary (single source of truth)
config.ts download links and repo URLs
public/
app-icon.svg favicon + brand mark
```

## Notes

- **Language**: first paint renders English for basic SEO; the client switches to Chinese based on browser language or the EN/中 toggle. Choice persists in `localStorage`. Per-language routes for SEO are deferred.
- **Download links**: `config.ts` currently points every button at the GitHub Releases page. Swap in China-hosted direct links (R2 / COS) once the updater fallback (issue #219) lands.
- **OG image**: `Base.astro` uses the app icon as a placeholder; replace with a dedicated 1200×630 share image.
8 changes: 8 additions & 0 deletions site/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from "astro/config";

// Landing page; deploys as a static site to Cloudflare Pages, decoupled from the
// desktop app build. `site` provides the absolute origin for canonical / og:url;
// the production domain may change once registration is sorted out.
export default defineConfig({
site: "https://pawwork.ai",
});
669 changes: 669 additions & 0 deletions site/bun.lock

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions site/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@pawwork/site",
"type": "module",
"version": "0.0.0",
"private": true,
"description": "PawWork download landing page",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"check": "astro check"
},
"dependencies": {
"astro": "6.4.2"
}
}
16 changes: 16 additions & 0 deletions site/public/app-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions site/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Site-level constants. Download links currently point at the GitHub Releases
// page, where users pick the installer themselves. Once China-hosted storage
// (R2 / COS) and the updater fallback (issue #219) land, swap mac / macIntel /
// win for the per-platform direct links — nothing else on the page changes.

export const REPO_URL = "https://github.com/Astro-Han/pawwork";
export const RELEASES_URL = `${REPO_URL}/releases/latest`;

export const DOWNLOAD = {
mac: RELEASES_URL,
macIntel: RELEASES_URL,
win: RELEASES_URL,
};
75 changes: 75 additions & 0 deletions site/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// EN/CN copy dictionary: single source of truth.
// The server renders EN on first paint (basic SEO); the client swaps to the
// chosen language. Values carry a few inline tags (<b> <span> <u> <br>) and are
// injected as HTML.

export type Lang = "en" | "cn";

export type Dict = Record<string, string>;

export const I18N: Record<Lang, Dict> = {
en: {
title: "PawWork — Real work, done on your desktop",
brand: "PawWork",
"nav.feat": "What it does",
tag: "Open-source · Free to use",
h1: 'Real work, done on your <span class="o">desktop</span>',
Comment thread
Astro-Han marked this conversation as resolved.
sub: "<b>No terminal. No API key. No paid plan.</b> Open PawWork, choose a folder, and ask in plain language.",
"dl.mac.t": "Download for macOS",
"dl.mac.s": "Apple Silicon",
"dl.intel.t": "macOS",
"dl.intel.s": "Intel",
"dl.win.t": "Windows",
"dl.win.s": "x64",
gh2: "On GitHub? <u>Grab the latest release →</u>",
wnote:
'<b>Windows:</b> If SmartScreen shows a warning on first launch, click "More info" → "Run anyway". The macOS build is signed and notarized — just open and go.',
shotnote: "Illustration, not a screenshot",
"mock.title": "PawWork — new task",
"mock.you": "Turn these 12 invoices into a spreadsheet I can review.",
"mock.ch": "Working on it…",
"mock.s1": "Read 12 PDFs",
"mock.s2": "Extracted vendor, date, total",
"mock.s3": "Building spreadsheet…",
"mock.rd": "ready to review",
"cap1.h": "Documents & data",
"cap1.p": "Extract invoice fields into a spreadsheet, generate a CSV summary, merge multiple PDFs.",
"cap2.h": "Research & writing",
"cap2.p": "Search the web, compare multiple pages and compile a memo, turn rough notes into a clean draft.",
"cap3.h": "Code & technical",
"cap3.p": "Understand a codebase, review a pull request, debug issues using logs and source code.",
foot: "Apache-2.0 · Built on OpenCode",
},
cn: {
title: "爪印 — 真能干活,跑在你电脑上",
brand: "爪印",
"nav.feat": "功能",
tag: "开源 · 下载即用",
h1: '<span class="o">真能干活</span>,<br>跑在你电脑上',
Comment thread
Astro-Han marked this conversation as resolved.
sub: "<b>不用终端,不用 API key,不用付费。</b>打开爪印,选个文件夹,直接告诉它你要什么。",
"dl.mac.t": "下载 macOS 版",
"dl.mac.s": "Apple 芯片",
"dl.intel.t": "macOS",
"dl.intel.s": "Intel",
"dl.win.t": "Windows",
"dl.win.s": "x64",
gh2: "有 GitHub?<u>去 Releases 下最新版 →</u>",
wnote:
"<b>Windows 用户</b>首次打开时如果弹出 SmartScreen 提示,点「更多信息」→「仍要运行」。macOS 版已签名公证,不会出现此提示。",
shotnote: "示意,非实拍",
"mock.title": "爪印 — 新任务",
"mock.you": "帮我把这 12 张发票整理成一张表格,方便逐笔核对。",
"mock.ch": "正在处理…",
"mock.s1": "读完 12 个 PDF",
"mock.s2": "抽出供应商、日期、金额",
"mock.s3": "正在生成表格…",
"mock.rd": "待核对",
"cap1.h": "文档与数据",
"cap1.p": "从发票提取信息填入表格、为 CSV 生成摘要、合并多个 PDF。",
"cap2.h": "研究与写作",
"cap2.p": "上网查资料、对比多篇网页整理成备忘、把零散笔记写成一篇稿子。",
"cap3.h": "代码与技术",
"cap3.p": "理解一个项目、review 他人的 PR、根据日志和源码定位错误。",
foot: "Apache-2.0 · 基于 OpenCode",
},
};
57 changes: 57 additions & 0 deletions site/src/layouts/Base.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
// Page shell: basic SEO tags in <head> plus the anti-flash theme script.
// Language switching happens on the client; first paint renders English.
import "../styles/global.css";

interface Props {
title: string;
description: string;
image?: string;
}

const { title, description, image = "/app-icon.svg" } = Astro.props;
const canonical = new URL(Astro.url.pathname, Astro.site).href;
const ogImage = new URL(image, Astro.site).href;
---

<!doctype html>
<html lang="en" data-theme="light" data-lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/app-icon.svg" />
<link rel="canonical" href={canonical} />
<title>{title}</title>
<meta name="description" content={description} />
<meta name="theme-color" content="#ff5910" />

<meta property="og:type" content="website" />
<meta property="og:site_name" content="PawWork" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonical} />
{/* TODO: replace with a dedicated 1200×630 share image; app icon is a placeholder */}
<meta property="og:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />

{/* Set the theme before first paint so dark-mode users don't see a light flash */}
<script is:inline>
(function () {
try {
var qs = new URLSearchParams(location.search);
var stored = localStorage.getItem("pw-theme");
var mq = window.matchMedia("(prefers-color-scheme: dark)");
var theme = qs.get("theme") || stored || (mq.matches ? "dark" : "light");
if (theme !== "dark" && theme !== "light") theme = "light";
document.documentElement.setAttribute("data-theme", theme);
} catch (e) {}
})();
</script>
</head>
<body>
<slot />
</body>
</html>
Loading