diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c76b71..30de1e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: Planer CI on: workflow_dispatch: push: - branches: [develop, main] + branches: [develop] pull_request: branches: [develop, main] @@ -24,6 +24,7 @@ jobs: node-version: 22 cache: npm - run: npm ci + - run: npm run check:version - run: npm run lint - run: npm run build @@ -41,7 +42,7 @@ jobs: - run: npm run tauri build - uses: actions/upload-artifact@v4 with: - name: Planer-0.1.0-Windows + name: Planer-Windows-${{ github.sha }} path: | src-tauri/target/release/bundle/nsis/*.exe src-tauri/target/release/bundle/msi/*.msi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a8a57c2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,89 @@ +name: Publish Planer Release + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: planer-release + cancel-in-progress: false + +jobs: + quality: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + tag: ${{ steps.version.outputs.tag }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run check:version + - run: npm run lint + - run: npm run build + - id: version + shell: bash + run: | + version=$(node -p "require('./package.json').version") + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "tag=v$version" >> "$GITHUB_OUTPUT" + + windows-installer: + runs-on: windows-latest + needs: quality + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - uses: dtolnay/rust-toolchain@stable + - run: npm ci + - run: npm run tauri build + - name: Collect release installers + shell: pwsh + run: | + New-Item -ItemType Directory -Path release-assets -Force | Out-Null + Copy-Item src-tauri/target/release/bundle/nsis/*.exe release-assets/ + Copy-Item src-tauri/target/release/bundle/msi/*.msi release-assets/ + - uses: actions/upload-artifact@v4 + with: + name: Planer-${{ needs.quality.outputs.version }}-Windows + path: release-assets/* + if-no-files-found: error + + publish: + runs-on: ubuntu-latest + needs: [quality, windows-installer] + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ needs.quality.outputs.tag }} + RELEASE_VERSION: ${{ needs.quality.outputs.version }} + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: Planer-${{ needs.quality.outputs.version }}-Windows + path: release-assets + - name: Refuse duplicate release versions + shell: bash + run: | + if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + echo "Release $RELEASE_TAG already exists. Bump the version before publishing another installer." + exit 1 + fi + - name: Publish GitHub Release + shell: bash + run: | + gh release create "$RELEASE_TAG" release-assets/* \ + --repo "$GITHUB_REPOSITORY" \ + --target "$GITHUB_SHA" \ + --title "Planer $RELEASE_VERSION" \ + --generate-notes diff --git a/CHANGELOG.md b/CHANGELOG.md index b043e9f..6ed36db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ All notable changes to Planer are documented here. - `.planer` and `.excalidraw` JSON exports. - Windows CI workflow for lint, web build, and Tauri installer artifacts. - Manual CI dispatch, concurrency protection, and repository governance documents. +- Automated version consistency validation across npm, Tauri, and Cargo metadata. +- GitHub Release publishing with attached Windows NSIS and MSI installers. ### Removed diff --git a/README.md b/README.md index 6736cec..a744dd5 100644 --- a/README.md +++ b/README.md @@ -2,65 +2,67 @@ # Planer -**A focused, local-first visual planning workspace for Windows.** +### Visual planning, without the overhead. + +**A fast, local-first Windows workspace for diagrams, workflows, architecture, and visual thinking.** Open → Draw → Connect → Organize → Explain → Export -![Version](https://img.shields.io/badge/version-0.1.0-2563eb) -![Platform](https://img.shields.io/badge/platform-Windows-0f172a) +[![Latest release](https://img.shields.io/github/v/release/sufyanaser/Planer?display_name=tag&sort=semver&label=release&color=2563eb)](https://github.com/sufyanaser/Planer/releases/latest) +[![Planer CI](https://github.com/sufyanaser/Planer/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/sufyanaser/Planer/actions/workflows/ci.yml) +![Windows](https://img.shields.io/badge/platform-Windows-0f172a) +![Local first](https://img.shields.io/badge/data-local--first-16a34a) ![Tauri](https://img.shields.io/badge/Tauri-v2-24c8db) -![Development](https://img.shields.io/badge/status-active%20development-f59e0b) + +**[Download the latest Windows release](https://github.com/sufyanaser/Planer/releases/latest)** · [Product blueprint](docs/PLANER_PRODUCT_BLUEPRINT_V1.md) · [Changelog](CHANGELOG.md) > [!IMPORTANT] -> Planer is currently an early `0.1.0` baseline. The core workspace is functional, but the application is not yet a stable public release. Active development happens on `develop`; verified releases are promoted to `main`. +> Planer is in early development. Version `0.1.0` establishes the desktop, project, board, canvas, autosave, and export foundation. Back up important work using `.planer` export while the native file workflow is still evolving. -## What is Planer? +## Why Planer exists -Planer is a lightweight desktop application for visual thinking, diagramming, and workflow planning. It combines the Excalidraw canvas engine with a dedicated project and multi-board workspace while keeping data on the user's device. +Most diagram tools force a choice between a generic drawing surface and a heavy project platform. Planer is being built for the space between them: an immediate infinite canvas wrapped in a focused project and multi-board workflow. -It is designed for work such as: +It is intended for: - flowcharts, mind maps, and concept maps; - system, API, database, and user-flow diagrams; - broadcast, studio, and production workflows; -- project architecture and feature planning; -- visual notes and technical explanations. - -Planer is inspired by the speed and directness of modern infinite-canvas tools, but it is being developed as an independent product rather than an Excalidraw fork or a draw.io derivative. - -## Available in `0.1.0` +- product architecture and feature planning; +- visual notes, technical explanations, and decision maps. -### Workspace +Planer uses the Excalidraw package as its canvas engine, but it is an independent product—not an Excalidraw fork and not a continuation of the repository's former draw.io scaffold. -- Infinite canvas powered by `@excalidraw/excalidraw`. -- Standard drawing, text, connector, selection, grouping, alignment, zoom, and editing tools provided by the canvas engine. -- Focused desktop shell with light and dark appearance modes. -- Project and active-board identity in the workspace header. +## What works today -### Projects and boards +| Area | Available in `0.1.0` | +| --- | --- | +| Canvas | Infinite canvas, shapes, text, connectors, free draw, image, eraser, frames, selection, grouping, alignment, zoom, pan, undo, and redo through Excalidraw | +| Projects | Local launcher; create, open, rename, and delete projects | +| Boards | Multiple independent boards; create, switch, rename, duplicate, and delete | +| Persistence | Debounced autosave to local IndexedDB | +| Appearance | Light and dark workspace modes | +| Export | Complete project as `.planer` JSON; active board as `.excalidraw` JSON | +| Privacy | No account, login, telemetry, cloud sync, or network dependency for normal use | +| Desktop | Tauri v2 Windows application with MSI and NSIS installer targets | -- Local project launcher with recent projects. -- Create, open, rename, and delete projects. -- Multiple boards inside each project. -- Create, switch, rename, duplicate, and delete boards. -- Independent scene data for every board. +## Install on Windows -### Local data and export +1. Open [GitHub Releases](https://github.com/sufyanaser/Planer/releases/latest). +2. Download the `.exe` installer for the simplest setup, or the `.msi` package for managed Windows deployment. +3. Run the installer and launch **Planer**. -- Automatic local persistence through IndexedDB. -- Debounced autosave while editing. -- Export an entire project as `.planer` JSON. -- Export the active board as `.excalidraw` JSON. -- No account, login, cloud service, or network dependency for normal workspace use. +Every published release is built by GitHub Actions from the verified `main` branch. Development builds and temporary CI artifacts are not treated as releases. -## Product model +> [!NOTE] +> Windows may show a reputation warning for early unsigned builds. Verify that the installer came from this repository's Releases page before continuing. -A Planer project is a portable visual workspace containing its metadata, settings, and boards: +## The Planer workflow ```text -NAS APP.planer +Project ├── Overview ├── Architecture ├── User Flow @@ -68,37 +70,59 @@ NAS APP.planer └── Notes ``` -The current `.planer` export is JSON-based. Import, packaged assets, migration guarantees, and a finalized public file specification remain future work; do not treat the `0.1.0` structure as a stable interchange contract yet. +Each board owns its own canvas scene. Switching boards preserves the scene inside the active project, and project changes are saved automatically on the device. + +The current `.planer` format is readable JSON containing project metadata, settings, boards, and their scene data. It is an early format: native import, packaged assets, migrations, and a stable public file specification are still planned. -## Privacy and offline behavior +## Data, privacy, and backups -Planer follows a local-first model: +Planer is local-first by design: -- project state is stored in the application's local IndexedDB database; -- canvas changes are saved automatically on the device; -- no telemetry, analytics, account system, or cloud synchronization is implemented; -- deleting application data or browser/WebView storage may remove locally saved projects. +- project state lives in the application's local IndexedDB database; +- canvas edits are autosaved on the device; +- no telemetry or analytics are implemented; +- no Planer account or remote service is required; +- clearing application/WebView data can remove locally stored projects. -Until native file import and backup workflows are completed, export important projects regularly as `.planer` files. +Until native open/import and backup recovery are complete, regularly export important projects as `.planer` files and keep those files in a separate backed-up folder. -## Installation +## Architecture -Planer targets Windows through Tauri v2. The repository includes CI configuration for NSIS and MSI installers, but `0.1.0` should be considered development software until a verified installer is published under [Releases](../../releases). +```mermaid +flowchart TD + A["Planer AppShell"] --> B["Project Launcher"] + A --> C["Workspace"] + C --> D["Board Management"] + C --> E["Excalidraw Canvas"] + D --> F["Zustand Store"] + E --> F + F --> G["IndexedDB Autosave"] + F --> H["Planer / Excalidraw Export"] +``` -For development builds, follow the setup below. +| Layer | Technology | Responsibility | +| --- | --- | --- | +| Desktop | Tauri v2 | Native window, Windows runtime, MSI and NSIS packaging | +| UI | React 18 + TypeScript | Launcher, workspace, board bar, and actions | +| Build | Vite 7 | Development server and production frontend bundle | +| Canvas | Excalidraw 0.18 | Scene rendering and drawing interaction | +| State | Zustand 5 | Active view, theme, project, and board state | +| Persistence | IndexedDB | Local project storage and autosave | +| Icons | Lucide React | Product interface icons | -## Development setup +## Development ### Requirements - Node.js 20 or newer - npm 10 or newer - Rust stable toolchain -- Tauri v2 Windows prerequisites, including Microsoft C++ Build Tools and WebView2 +- Tauri v2 platform prerequisites +- On Windows: Microsoft C++ Build Tools and WebView2 -See the official [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/) for platform-specific setup. +See the official [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/) for complete platform setup. -### Run the web workspace +### Start the web workspace ```bash git clone https://github.com/sufyanaser/Planer.git @@ -108,102 +132,79 @@ npm ci npm run dev ``` -Vite serves the application at `http://localhost:1420` by default. +The Vite development server runs at `http://localhost:1420` by default. -### Run the desktop application +### Start the desktop application ```bash npm run tauri dev ``` -### Quality gates - -Every meaningful change must pass both checks before it is committed or pushed: +### Validate a change ```bash +npm run check:version npm run lint npm run build ``` ### Build Windows installers -On a configured Windows development machine: - ```bash npm run tauri build ``` -Tauri produces the configured NSIS and MSI bundles under `src-tauri/target/release/bundle/`. +Installers are produced under `src-tauri/target/release/bundle/nsis/` and `src-tauri/target/release/bundle/msi/`. -## Scripts +## Commands | Command | Purpose | | --- | --- | | `npm run dev` | Start the Vite development server | -| `npm run build` | Type-check and build the production web bundle | +| `npm run build` | Type-check and build the production frontend | | `npm run lint` | Run ESLint with zero warnings allowed | -| `npm run preview` | Preview the production web build | -| `npm run tauri dev` | Run Planer in the Tauri desktop shell | -| `npm run tauri build` | Build native desktop installers | +| `npm run check:version` | Verify npm, Tauri, and Cargo versions are identical | +| `npm run preview` | Preview the production frontend | +| `npm run tauri dev` | Run the native desktop shell in development | +| `npm run tauri build` | Build the native desktop installers | -## Architecture - -```mermaid -flowchart TD - A[Planer AppShell] --> B[Project Launcher] - A --> C[Workspace] - C --> D[Board Management] - C --> E[Excalidraw Canvas] - D --> F[Zustand Store] - E --> F - F --> G[IndexedDB Persistence] - F --> H[Planer / Excalidraw Export] -``` - -| Layer | Technology | Responsibility | -| --- | --- | --- | -| Desktop shell | Tauri v2 | Native Windows window and installer packaging | -| Interface | React 18 + TypeScript | Launcher, workspace, board bar, and contextual actions | -| Build system | Vite 7 | Development server and production frontend bundle | -| Canvas | Excalidraw 0.18 | Drawing and scene interaction engine | -| State | Zustand 5 | Project, board, theme, and active-view state | -| Persistence | IndexedDB | Local project storage and autosave | -| Icons | Lucide React | Application interface icons | - -## Repository structure +## Repository layout ```text Planer/ -├── .github/workflows/ # Quality checks and Windows packaging +├── .github/workflows/ # CI and release publishing ├── docs/ # Product and architecture documents +├── scripts/ # Repository validation scripts ├── src/ │ ├── components/ # Launcher, workspace, canvas, and board UI │ ├── services/ # Project creation and local persistence -│ ├── store/ # Zustand application state -│ ├── styles/ # Application styles -│ └── types.ts # Project and board data contracts -├── src-tauri/ # Tauri configuration, Rust shell, and icons +│ ├── store/ # Zustand state +│ ├── styles/ # Product styling +│ └── types.ts # Project and board contracts +├── src-tauri/ # Rust shell, Tauri config, and app icons ├── CHANGELOG.md └── package.json ``` -## Development workflow +## Branch and release policy -| Branch | Role | +| Branch | Purpose | | --- | --- | | `develop` | Source of truth for active development | -| `main` | Verified stable versions only | +| `main` | Verified release source only | + +A release is not merely an Actions artifact. The repository follows this gate: -The project is developed in small operational phases: +1. make a focused change from `develop`; +2. keep `package.json`, `src-tauri/tauri.conf.json`, and `src-tauri/Cargo.toml` versions aligned; +3. update `CHANGELOG.md`; +4. pass version check, lint, and production build; +5. build both Windows installer formats in CI; +6. promote the verified commit to `main`; +7. create the version tag and GitHub Release; +8. attach the `.exe` and `.msi` installers to the Release. -1. make a focused change on `develop`; -2. run `npm run lint`; -3. run `npm run build`; -4. inspect Git status and the final diff; -5. bump the version when the change produces a new installed build; -6. update `CHANGELOG.md`; -7. commit and push only after all gates pass; -8. build and verify the Windows installer before promoting a release. +Failed validation or packaging blocks publication. A new installed build must use a new version number. ## Roadmap @@ -215,17 +216,17 @@ The project is developed in small operational phases: - [x] Project and multi-board state model - [x] IndexedDB autosave baseline - [x] `.planer` and `.excalidraw` export -- [ ] Verified Windows installer release +- [x] Automated Windows installer and Release pipeline - [ ] Native project open/import and backup workflow -### Core product layer +### Core product -- [ ] Stable `.planer` file specification and migrations +- [ ] Stable `.planer` specification and migrations - [ ] Native filesystem persistence through Tauri - [ ] Board reordering and project-level search -- [ ] PNG, SVG, PDF, and clipboard export workflows -- [ ] Grid and snap controls integrated into the Planer shell -- [ ] Automated tests and end-to-end desktop verification +- [ ] PNG, SVG, PDF, and clipboard export +- [ ] Planer-level grid and snap controls +- [ ] Automated UI and desktop end-to-end tests ### Structured planning @@ -235,31 +236,25 @@ The project is developed in small operational phases: - [ ] Templates - [ ] Search across boards -The complete product definition is documented in [`docs/PLANER_PRODUCT_BLUEPRINT_V1.md`](docs/PLANER_PRODUCT_BLUEPRINT_V1.md). +The detailed scope and product boundaries live in the [Planer Product Blueprint](docs/PLANER_PRODUCT_BLUEPRINT_V1.md). ## Deliberate V1 boundaries -To protect speed and stability, V1 does not include accounts, cloud sync, team workspaces, real-time collaboration, chat, video, AI, a plugin marketplace, Kanban management, 3D, animation, or a presentation engine. +V1 does not include accounts, cloud sync, team workspaces, real-time collaboration, chat, video, AI, a plugin marketplace, Kanban management, 3D, animation, or a presentation engine. These exclusions protect startup speed and the stability of the core canvas and data model. -## Contributing +## Contributing and security -Planer is in active foundational development. Before proposing a large feature, open an issue to confirm that it fits the product scope and current phase. Keep pull requests focused and include the validation commands used. +Planer is still in foundational development. Discuss large features in an issue before implementation, keep changes focused, and report the validation commands used. -Security issues must not be reported through a public issue. Use [GitHub's private vulnerability reporting](https://github.com/sufyanaser/Planer/security/advisories/new) instead. - -## Changelog - -Release history and notable changes are recorded in [`CHANGELOG.md`](CHANGELOG.md). +Do not report security vulnerabilities in a public issue. Use [GitHub private vulnerability reporting](https://github.com/sufyanaser/Planer/security/advisories/new). ## License -No open-source license has been selected yet. Until a license is added, the repository is **not** implicitly open source and no permission is granted to copy, modify, or redistribute the code beyond rights provided by applicable law. - -Legacy draw.io files and licensing metadata were removed when the current Planer architecture replaced the previous scaffold. +No open-source license has been selected. Unless a license is added, no permission is granted to copy, modify, or redistribute the source beyond rights provided by applicable law. ---
Planer
- Visual planning that stays focused and stays local. + Focused visual planning. Local by default.
diff --git a/package.json b/package.json index 1d33d66..e9c4fb0 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", + "check:version": "node scripts/check-version.mjs", "lint": "eslint . --max-warnings 0", "preview": "vite preview", "tauri": "tauri" diff --git a/scripts/check-version.mjs b/scripts/check-version.mjs new file mode 100644 index 0000000..cfa5b22 --- /dev/null +++ b/scripts/check-version.mjs @@ -0,0 +1,23 @@ +import { readFile } from "node:fs/promises"; + +const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")); +const tauriConfig = JSON.parse( + await readFile(new URL("../src-tauri/tauri.conf.json", import.meta.url), "utf8"), +); +const cargoToml = await readFile(new URL("../src-tauri/Cargo.toml", import.meta.url), "utf8"); +const cargoVersion = cargoToml.match(/^version\s*=\s*"([^"]+)"/m)?.[1]; + +const versions = { + package: packageJson.version, + tauri: tauriConfig.version, + cargo: cargoVersion, +}; + +const uniqueVersions = new Set(Object.values(versions)); + +if (!cargoVersion || uniqueVersions.size !== 1) { + console.error("Planer version mismatch:", versions); + process.exit(1); +} + +console.log(`Planer version ${packageJson.version} is consistent.`);