diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
new file mode 100644
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -0,0 +1,57 @@
+name: Bug report
+description: Report a reproducible problem in the ArtCraft desktop apps.
+title: '[Bug]: '
+body:
+  - type: dropdown
+    id: app
+    attributes:
+      label: Application
+      options:
+        - ArtCraft desktop (Tauri)
+        - ArtCraft native (experimental Rust UI)
+        - Shared library or developer tooling
+    validations:
+      required: true
+  - type: input
+    id: version
+    attributes:
+      label: App version or commit
+      description: Include the release version or Git commit used to reproduce it.
+    validations:
+      required: true
+  - type: dropdown
+    id: platform
+    attributes:
+      label: Platform
+      options:
+        - macOS
+        - Windows
+        - Linux
+        - Multiple platforms
+    validations:
+      required: true
+  - type: textarea
+    id: reproduce
+    attributes:
+      label: Steps to reproduce
+      description: Include the page, model/provider if relevant, and the smallest sequence that reproduces the problem.
+    validations:
+      required: true
+  - type: textarea
+    id: expected
+    attributes:
+      label: Expected behavior
+    validations:
+      required: true
+  - type: textarea
+    id: actual
+    attributes:
+      label: Actual behavior
+      description: Include the exact error or a screenshot when useful.
+    validations:
+      required: true
+  - type: textarea
+    id: evidence
+    attributes:
+      label: Logs, regression range, or related issues
+      description: Optional supporting evidence. Remove credentials and personal information from logs.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@
+blank_issues_enabled: true
diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml
new file mode 100644
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature.yml
@@ -0,0 +1,45 @@
+name: Feature request
+description: Propose an improvement to an ArtCraft workflow.
+title: '[Feature]: '
+body:
+  - type: dropdown
+    id: area
+    attributes:
+      label: Area
+      options:
+        - Image or video generation
+        - Audio generation
+        - 2D canvas
+        - 3D stage
+        - Library and media management
+        - Experimental native app
+        - Developer tooling
+        - Another ArtCraft workflow
+    validations:
+      required: true
+  - type: textarea
+    id: problem
+    attributes:
+      label: What are you trying to do?
+      description: Describe the workflow and what makes it difficult today.
+    validations:
+      required: true
+  - type: textarea
+    id: proposal
+    attributes:
+      label: Proposed behavior
+      description: Explain the desired interaction or result, with examples if helpful.
+    validations:
+      required: true
+  - type: textarea
+    id: acceptance
+    attributes:
+      label: How would you know it works?
+      description: Suggest observable success criteria for the feature.
+    validations:
+      required: true
+  - type: textarea
+    id: alternatives
+    attributes:
+      label: Alternatives and related requests
+      description: Optional workarounds, related issues, screenshots, or design references.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,15 @@
+## Problem and resulting behavior
+
+Describe the user-visible bug or workflow improvement. Link the issue; distinguish
+whole-issue fixes from partial audit findings.
+
+## Validation
+
+List the relevant commands/tests and their results, plus any manual reproduction.
+State what could not be tested and any remaining limitations.
+
+## Submission
+
+Confirm the base branch and final diff. Check CI for the latest pushed commit.
+The temporary Netlify docs skip is not application test coverage; see
+[the contribution guide](../CONTRIBUTING.md).
diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml
new file mode 100644
--- /dev/null
+++ b/.github/workflows/pr-checks.yml
@@ -0,0 +1,57 @@
+name: PR regression checks
+
+on:
+  pull_request:
+  push:
+  workflow_dispatch:
+
+permissions:
+  contents: read
+
+concurrency:
+  group: pr-checks-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  rust-libraries:
+    runs-on: ubuntu-latest
+    timeout-minutes: 20
+    env:
+      SQLX_OFFLINE: 'true'
+      CARGO_INCREMENTAL: '0'
+      CARGO_PROFILE_DEV_DEBUG: '0'
+      CARGO_PROFILE_TEST_DEBUG: '0'
+    steps:
+      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+        with:
+          persist-credentials: false
+      - uses: dtolnay/rust-toolchain@686976e191b89faba57d3206551f0f330d8cb249 # stable
+        with:
+          toolchain: stable
+      - name: Install native library build prerequisites
+        run: |
+          sudo apt-get update
+          sudo apt-get install --yes pkg-config libssl-dev
+      - name: Test offline SQLite, cookie handling, and API bindings
+        run: cargo test --locked -p sqlite_tasks -p cookie_store_wrapper -p artcraft_client
+
+  frontend:
+    runs-on: ubuntu-latest
+    timeout-minutes: 15
+    defaults:
+      run:
+        working-directory: frontend
+    steps:
+      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+        with:
+          persist-credentials: false
+      - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
+        with:
+          node-version: '24'
+          cache: npm
+          cache-dependency-path: frontend/package-lock.json
+      - run: npm ci --ignore-scripts
+      - name: Test desktop state and media adapters
+        run: npx vitest run --config apps/artcraft/vitest.config.ts
+      - name: Test 3D viewer and resource disposal
+        run: npx vitest run --config libs/components/viewer-3d/vite.config.ts
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,81 @@
+# Contributing to ArtCraft
+
+This repository contains the Tauri desktop app, the experimental Rust native app,
+and their shared libraries. Backend services and website/documentation deployments
+live in [artcraft-services](https://github.com/storytold/artcraft-services).
+See [_docs/dev_setup.md](_docs/dev_setup.md) and
+[frontend/README.md](frontend/README.md) for development prerequisites and launchers.
+
+## Choose and reproduce a change
+
+Check open issues and pull requests before starting. Large audit issues often contain
+several independent findings; name the part you are fixing and link existing related
+PRs. Use `Fixes #123` only when the entire issue is resolved; use `Addresses #123`
+for a partial fix. Keep unrelated fixes in separate commits or PRs.
+
+Record the app version/commit, platform, reproducible steps, and expected behavior.
+For a feature, explain the workflow it improves and how a reviewer can verify it.
+Prefer local fixtures and regression tests over paid generation requests.
+
+## Run the relevant checks
+
+The PR workflow runs a deliberately limited foundation of tests on clean Linux
+runners. It requires no application credentials, production services, signing keys,
+or MySQL database. From the repository root:
+
+```sh
+SQLX_OFFLINE=true cargo test --locked -p sqlite_tasks -p cookie_store_wrapper -p artcraft_client
+```
+
+Then from `frontend/` (Node.js 24 is used in CI):
+
+```sh
+npm ci --ignore-scripts
+npx vitest run --config apps/artcraft/vitest.config.ts
+npx vitest run --config libs/components/viewer-3d/vite.config.ts
+```
+
+These commands use source exports and do not require building every library's
+`dist/` directory. For other frontend changes, run the affected library's Vitest
+configuration and its lint/type checks where available. The foundation workflow
+is not a whole-workspace type check or a desktop release build.
+
+Run the relevant desktop checks for Rust changes beyond the foundation:
+
+```sh
+SQLX_OFFLINE=true cargo test -p artcraft --lib <test_filter>
+cargo test -p artcraft_native <test_filter>
+cargo check --offline -p artcraft_client
+```
+
+`--offline` assumes dependencies have already been fetched. Tests marked ignored
+may contact live providers or need special tools; inspect them before opting in.
+For login bridge changes, run `SQLX_OFFLINE=true cargo test --offline -p artcraft
+--lib login_bridge_tests`. For playback changes with FFmpeg installed, the native
+`probes_and_decodes_a_generated_clip` test can be run explicitly with `-- --ignored`.
+Report platform limitations and commands that could not run.
+
+## Submit and verify the actual pull request
+
+1. Fetch upstream `main`, create a focused branch, and check your remotes with
+   `git remote -v`. Preserve unrelated work and local caches.
+2. Review `git diff --check` and the final diff. Include the problem, resulting
+   behavior, linked issue, validation, and remaining limitations in the PR body.
+3. Push the branch to your fork. Open the PR against `storytold/artcraft:main`;
+   a branch pushed to a fork alone is not a submitted upstream PR.
+4. Verify the upstream PR URL, head branch/commit, base branch, changed files,
+   mergeability, and checks. After pushing a fix, inspect checks for the **new head**.
+5. A fork's first Actions run may require maintainer approval. State that accurately;
+   do not describe a pending/skipped check as passing application tests. The workflow
+   also runs on pushes so contributors can verify it in their own fork.
+
+### The obsolete Netlify documentation check
+
+[PR #2248](https://github.com/storytold/artcraft/pull/2248) explains why the
+`storyteller-docs` site was trying to run a build script that moved to the services
+repository. The root `netlify.toml` guard intentionally skips that stale build.
+Keep that guard unchanged while the site remains attached; do not add a dummy docs
+build script or remove failing test commands to make a PR look green. A successful
+Netlify deploy-preview status with neutral subsidiary checks means the obsolete
+deploy was skipped, **not** that the application passed tests. Maintainers can
+remove the guard after repointing or disconnecting that site.
diff --git a/netlify.toml b/netlify.toml
new file mode 100644
--- /dev/null
+++ b/netlify.toml
@@ -0,0 +1,7 @@
+# The `storyteller-docs` Netlify site still builds this repository, but its
+# build command (./script/netlify_build_docs.sh) and the docs themselves now
+# live in storytold/artcraft-services, so every deploy preview here fails.
+# Skip those builds until the Netlify site is repointed or disconnected, then
+# delete this file.
+[build]
+  ignore = "exit 0"
