diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0986bd..de442ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,25 @@ Edit `.env` with local values for development. **Do not commit `.env` or `.env.l 1. Fork the repository (or create a branch if you have write access). 2. Branch from `main` with a short descriptive name, for example `fix/post-list-error` or `docs/contributing`. 3. Keep changes focused — avoid unrelated refactors. -4. Open a pull request against `main` with a clear summary and test notes. +4. Open a **pull request** against `main` with a clear summary and test notes. +5. **Do not push directly to `main`.** Repository rules require PRs and passing checks (including CodeQL). + +### Commit messages + +Use clear, imperative subjects that explain *why* when helpful: + +- `feat: add hugo frontmatter adapter option` +- `fix: surface GitHub 403 on protected branch` +- `docs: document PR publish modes` +- `chore: update release checklist` + +Squash merges are typical for feature PRs. + +### Tests required + +- Run `pnpm build` and `pnpm test` before opening a PR. +- Run `pnpm test:e2e` when Studio UI, auth, or publish flows change. +- Add or update unit tests for logic changes in `packages/*` or `apps/studio/server` when practical. Before a release, see [RELEASE_CHECKLIST.md](RELEASE_CHECKLIST.md) and [docs/manual-acceptance-test.md](docs/manual-acceptance-test.md). @@ -39,6 +57,7 @@ From the repository root: pnpm install # install workspace dependencies pnpm build # build all packages and Studio (including server TypeScript) pnpm test # run unit tests +pnpm test:e2e # Playwright smoke tests (demo mode) pnpm dev # start Studio UI + publish API locally ``` diff --git a/README.md b/README.md index 6a188b9..27dbd43 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # SourceDraft -SourceDraft is a free, open-source editor for Markdown and MDX blogs. You write in the browser, upload images, check SEO metadata, preview the generated file, and publish to a Git repository or remote CMS (WordPress, Ghost). +SourceDraft is a free, open-source **Git-based CMS** for Markdown and MDX publishing. You write in the browser with a Tiptap editor and slash commands, upload images, run content QA checks, preview the generated file, and publish to a Git repository or remote CMS (WordPress, Ghost). + +Licensed under [AGPL-3.0-or-later](LICENSE). **Project status:** SourceDraft is an early local/private MVP for Git-backed Markdown and MDX publishing. It is usable for solo writing and GitHub commits, but it is not a hosted CMS, multi-user product, or finished SaaS. See [docs/project-status.md](docs/project-status.md) and [CHANGELOG.md](CHANGELOG.md). @@ -32,13 +34,18 @@ Your static site still builds and deploys exactly as before. SourceDraft creates ## What it does today -- Edit articles in Studio (title, slug, dates, category, tags, body, draft flag) +- Edit articles in Studio with a **Tiptap rich editor**, **slash commands**, and **source mode** for raw Markdown/MDX - List and edit existing posts from your GitHub `contentDir` - Validate fields against a universal article schema -- Preview Markdown or Astro MDX output and target file path before publishing +- **Content QA** — non-blocking warnings for SEO, alt text, headings, links, and body length +- **Publish checklist** — validation status, output path, publish mode, and warnings before publish +- Preview Markdown or MDX adapter output and target file path before publishing - Publish to Git hosts (GitHub, GitLab, Bitbucket) or remote CMS APIs (WordPress, Ghost) +- **GitHub PR publishing** — direct commit, pull request, or draft pull request for protected branches - Upload images to git `mediaDir`, Cloudinary, or (experimental) S3-compatible storage - Optional deploy hooks after publish (Vercel, Netlify, Cloudflare Pages, generic) +- **Setup detection** — scan local project files and suggest adapter, content, and media paths +- **Content audit** — read-only scan of existing posts (frontmatter, duplicate slugs, complex MDX) - Configure paths, adapter, and categories in `sourcedraft.config.json` - Protect Studio with a server-side admin password - **Demo mode** — explore Studio with sample posts without GitHub credentials @@ -170,6 +177,10 @@ Issues and pull requests are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) fo - [Ghost publishing](docs/ghost.md) - [Deploy hooks](docs/deploy-hooks.md) - [GitHub publishing](docs/github-publishing.md) +- [GitHub PR publishing](docs/github-pr-publishing.md) +- [Editor and source mode](docs/editor.md) +- [Setup detection](docs/setup-detection.md) +- [Content QA](docs/content-qa.md) - [Media uploads](docs/media.md) - [Configuration](docs/configuration.md) - [Astro integration example](docs/astro-blog-example.md) diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md index 7cfc8cb..afbb18e 100644 --- a/RELEASE_CHECKLIST.md +++ b/RELEASE_CHECKLIST.md @@ -1,44 +1,74 @@ -# SourceDraft v0.1 release checklist +# SourceDraft release checklist -Use this before tagging `v0.1.0` or promoting the repository publicly. +Use this before tagging a public release or promoting the repository. ## Automated checks ```bash -pnpm install --lockfile-only +pnpm install --frozen-lockfile pnpm build pnpm test +pnpm test:e2e ``` -- [ ] All three commands exit 0 +- [ ] All four commands exit 0 - [ ] Studio build includes server TypeScript (`tsc -p server/tsconfig.json` in `apps/studio` build) -- [ ] CI workflow (`.github/workflows/ci.yml`) runs the same build and test commands +- [ ] CI workflow (`.github/workflows/ci.yml`) runs build, test, and studio-e2e on pull requests +- [ ] **CodeQL** checks pass on the release PR (JavaScript/TypeScript + Actions; no open high-severity alerts) -## Repository +## Repository hygiene -- [ ] `LICENSE` present (AGPL-3.0-or-later) -- [ ] `CHANGELOG.md` has a `v0.1.0` section +- [ ] `LICENSE` present (**AGPL-3.0-or-later**) +- [ ] `CHANGELOG.md` updated for the release version - [ ] `CONTRIBUTING.md` present -- [ ] `.env` and `.env.local` are gitignored and not committed -- [ ] No real tokens or passwords in tracked files +- [ ] `.env` and `.env.local` are gitignored and **not committed** +- [ ] **No secrets check:** scan tracked files for tokens, passwords, or private keys (`rg -i 'ghp_|gho_|GITHUB_TOKEN=|password=' --glob '!*.example*'`) - [ ] `sourcedraft.config.example.json` is generic (no site-specific secrets) - [ ] No QuBrite hardcoding in `*.ts` / `*.tsx` app logic ## Documentation -- [ ] README quickstart matches current Studio UI and commands +- [ ] README describes Git-based Markdown/MDX publishing, adapters, publishers, PR publishing, editor, setup detection, content QA, and license - [ ] Docs state: early local/private MVP, not hosted SaaS, not production multi-user auth - [ ] GitHub Contents API limits documented - [ ] `mediaDir` vs `publicMediaPath` documented - [ ] Issue templates present under `.github/ISSUE_TEMPLATE/` +## Screenshots + +```bash +pnpm screenshots:generate +``` + +- [ ] Regenerate Studio screenshots when UI changed materially +- [ ] Commit updated images under `docs/assets/` if diffs are intentional + +## Smoke tests + +### Demo mode (automated) + +`pnpm test:e2e` covers demo login, editor, settings panels, publish simulation, and publish checklist. + +- [ ] E2E green locally and in CI + +### Protected-branch PR publishing (manual) + +On a **test** GitHub repo with branch protection on `main`: + +- [ ] Set `SOURCEDRAFT_PUBLISH_MODE=pull-request` in `.env` +- [ ] Publish a valid post from Studio +- [ ] PR is created with expected file path and branch prefix +- [ ] Optional: repeat with `draft-pull-request` + +Details: [docs/github-pr-publishing.md](docs/github-pr-publishing.md) + ## Manual acceptance -Run [docs/manual-acceptance-test.md](docs/manual-acceptance-test.md) against a **test** GitHub repository. +Run [docs/manual-acceptance-test.md](docs/manual-acceptance-test.md) against a test GitHub repository. - [ ] Login and logout work -- [ ] Settings show adapter, `contentDir`, `mediaDir`, `publicMediaPath` -- [ ] Create post, upload image, publish +- [ ] Settings show setup detection, content audit, and setup health +- [ ] Create post, upload image, publish (direct mode) - [ ] Edit existing post, publish update - [ ] Verify files in GitHub match expectations @@ -51,6 +81,11 @@ git push origin v0.1.0 Only tag after automated checks pass and manual acceptance is satisfactory. -## Known non-goals for v0.1 +## Known non-goals (document, do not block release) + +- OAuth, user accounts, hosted SaaS, team RBAC +- Full S3/R2 media upload (`s3-compatible` config validation only) +- Post list in Studio for Bitbucket, WordPress, and Ghost +- Git Trees API indexer for very large repos -Do not block release on: OAuth, user accounts, hosted SaaS, Cloudinary/S3/R2, Git Trees API, screenshots in repo, or Studio E2E test automation. +Roadmap: [docs/compatibility-roadmap.md](docs/compatibility-roadmap.md) diff --git a/docs/content-qa.md b/docs/content-qa.md new file mode 100644 index 0000000..79260fd --- /dev/null +++ b/docs/content-qa.md @@ -0,0 +1,50 @@ +# Content QA + +SourceDraft runs **non-blocking** editorial checks while you write. They do not block publish unless required-field validation fails. + +## Post details panel — Content quality + +Warnings and suggestions for the current draft: + +| Check | Type | +|-------|------| +| Meta title / description length | Guidance | +| Cover image alt text | Warning when hero is set | +| Image alt text in Markdown body | Warning | +| Duplicate H1 headings | Guidance | +| Long article without H2 sections | Guidance | +| Very short body | Guidance | +| Many external links | Guidance | +| Broken-looking internal links | Warning (vs loaded post slugs) | +| Missing social image when no hero | Guidance | + +Required-field validation errors (title, slug, dates, etc.) also appear here. + +## SEO / Sharing panel + +Optional `metaTitle`, `metaDescription`, `canonicalUrl`, `socialImage`, and cover alt feed into frontmatter on publish. Soft length warnings use the same guidance thresholds as content quality. + +## Publish checklist + +The publish bar shows a compact checklist before you click **Publish**: + +- Validation status +- Output path +- Publish mode and target branch / PR branch +- Draft vs live +- Media and SEO warning counts + +## Content audit (existing posts) + +Settings → **Content audit** scans posts already in your `contentDir` (read-only, no file changes): + +- Valid vs invalid frontmatter +- Missing required fields and unsupported frontmatter keys +- Duplicate slugs +- Invalid dates +- **Source-only** posts with complex MDX (imports, exports, JSX) +- Ignored non-`.md` / `.mdx` files + +Use the audit before importing an existing blog into SourceDraft editing workflows. + +See also: [seo-fields.md](seo-fields.md) · [setup-detection.md](setup-detection.md) diff --git a/docs/design-notes.md b/docs/design-notes.md index 3997657..82c1326 100644 --- a/docs/design-notes.md +++ b/docs/design-notes.md @@ -22,8 +22,8 @@ The writing canvas and preview are capped around 72ch width. Body text uses ~18p CSS variables live in `apps/studio/src/index.css` (`--font-ui`, `--font-writing`, `--font-mono`, and the `--text-*` scale). -## Markdown toolbar (v0.2) +## Body editor -Studio keeps a plain `