diff --git a/.claude/rules/docs-style.md b/.claude/rules/docs-style.md new file mode 100644 index 0000000..301c438 --- /dev/null +++ b/.claude/rules/docs-style.md @@ -0,0 +1,50 @@ +# Docs and copy style + +## Tone + +Professional open-source developer tool: clean, technical, precise, +trustworthy. Not generic SaaS marketing, not AI-generated filler, not startup +hype, not fake enterprise. Write like the maintainer of a tool people trust +with their repositories and credentials. + +## Positioning to emphasize + +- Git-owned content and portability (plain `.md`/`.mdx` in the user's repo) +- Adapter/publisher architecture (one schema, many targets) +- Local/private control; credentials stay server-side +- Publishing confidence: validation, exact output preview, content QA, + publish checklist, demo mode + +## Competitors + +Respect Decap CMS, TinaCMS, CloudCannon, GitCMS, WordPress, and Ghost. State +plainly where they are stronger (maturity, hosting, ecosystems, visual +editing) and where SourceDraft differs. Never attack, never imply they are +bad choices, never invent their weaknesses. + +## Evidence rules + +- Feature claims must match shipped code; check `docs/project-status.md`. +- Acceptable sources: this repository, official docs of the tools discussed, + reputable open-source ecosystem guidance, neutral UX/product principles. +- Not acceptable as neutral evidence: vendor marketing pages, SEO listicles, + fabricated statistics, competitor sales pages. Real user/founder reviews may + be cited only as clearly-marked anecdotes. +- No fake screenshots, metrics, benchmarks, or testimonials. + +## UX writing principles + +Optimize docs and UI text for: fast first success, low cognitive load, clear +system status, obvious next action, recognition over recall, error +prevention, user control and recovery, progressive disclosure, transparent +limitations, and trust around credentials and publishing. The reader is +technical but may be new to Git-based CMS workflows. + +## Mechanics + +- Sentence-case headings, short paragraphs, tables for matrices. +- Every doc links onward to the next logical doc. +- Commands shown must actually work from the repo root (or state the cwd). +- Mark experimental/partial features inline, not only in a footnote. +- Keep "MVP password auth is intended for local/private use" warnings wherever + exposure to the public internet could be implied. diff --git a/.claude/rules/no-scope-creep.md b/.claude/rules/no-scope-creep.md new file mode 100644 index 0000000..b57ead2 --- /dev/null +++ b/.claude/rules/no-scope-creep.md @@ -0,0 +1,41 @@ +# No scope creep + +SourceDraft launches first as a genuinely useful free and open-source AGPL +project. The free version must not be artificially crippled, and monetization +is **not** implemented now. + +## Forbidden in the current phase + +Do not implement, scaffold, stub, or document as available: + +- Paywalls, billing, SaaS plans, license gates, or feature flags that gate + open-source functionality +- Telemetry or analytics collection of any kind +- OAuth, user accounts, team accounts, or RBAC +- Hosted / multi-tenant Studio +- Plugin marketplace +- AI writing tools +- Large UI redesigns + +Also forbidden: fake screenshots, fake metrics, fake benchmarks, and +production/enterprise overclaims in any doc or UI string. + +## Allowed to mention (roadmap only) + +Future commercial possibilities (hosted SourceDraft Cloud, managed onboarding, +OAuth/team accounts, RBAC, managed media, premium support, agency workspaces, +migration services, dual licensing) may appear in `docs/roadmap.md` as +clearly-labeled future options — never as current features, never as code. + +## Decision filter + +Classify every proposed change as one of: + +1. **True launch blocker** — broken, misleading, insecure, or missing piece + that would embarrass the project on day one. Do it. +2. **High-value polish** — improves first success, clarity, or trust with low + risk. Do it if cheap and in scope. +3. **Later roadmap** — useful but not now. Write it down in `docs/roadmap.md` + or an issue; do not implement. +4. **Explicitly not now** — anything on the forbidden list. Refuse, even if + requested casually, and point to this file. diff --git a/.claude/rules/release-gates.md b/.claude/rules/release-gates.md new file mode 100644 index 0000000..88979c5 --- /dev/null +++ b/.claude/rules/release-gates.md @@ -0,0 +1,45 @@ +# Release gates + +Before tagging a release, merging release-related PRs, or recommending any +public promotion, all gates below must pass. See `RELEASE_CHECKLIST.md` and +`docs/public-launch-checklist.md` for the full operator checklists. + +## Automated gates + +```bash +pnpm install --frozen-lockfile +pnpm build +pnpm test +pnpm test:e2e # required for releases and any UI/auth/publish change +``` + +- CI (`.github/workflows/ci.yml`) green: build, unit tests, studio e2e +- CodeQL: no open high-severity alerts on the release PR + +## Repository hygiene gates + +- `LICENSE` is AGPL-3.0-or-later; no stray MIT references anywhere +- `.env` / `.env.local` gitignored and not committed +- No-secrets scan clean on tracked files (tokens, passwords, private keys): + `git grep -nIiE 'ghp_[A-Za-z0-9]|gho_[A-Za-z0-9]|BEGIN [A-Z]+ PRIVATE KEY' -- ':!*.example*'` +- No QuBrite hardcoding in `*.ts` / `*.tsx` app logic + +## Honesty gates + +- README, `docs/project-status.md`, and `CHANGELOG.md` agree on shipped vs + experimental vs not-shipped +- Stated limitations still accurate: MVP password auth, in-memory sessions, + Contents API scale limits, `s3-compatible` upload not implemented, no post + list for Bitbucket/WordPress/Ghost +- No screenshots showing tokens, real repo secrets, or personal data +- No production/SaaS/enterprise claims anywhere + +## Manual gates (release only) + +- Demo mode walkthrough passes (`docs/manual-acceptance-test.md`) +- Real publish against a **test** GitHub repository: direct commit and + pull-request mode both verified +- Screenshots regenerated (`pnpm screenshots:generate`) if UI changed + +If any gate fails, the release stops. Document the failure; do not waive +gates silently. diff --git a/.claude/rules/source-draft-project-rules.md b/.claude/rules/source-draft-project-rules.md new file mode 100644 index 0000000..6387ad7 --- /dev/null +++ b/.claude/rules/source-draft-project-rules.md @@ -0,0 +1,38 @@ +# SourceDraft project rules + +SourceDraft is an open-source publishing Studio for Markdown, MDX, and +Git-backed content workflows, with an adapter/publisher architecture for +multiple static-site frameworks and CMS targets. License: AGPL-3.0-or-later. + +## Product identity + +- Target users: solo developers, technical bloggers, documentation-site + maintainers, Astro/Next.js/Hugo/Docusaurus/MkDocs/Nuxt Content users, and + small teams that want Git-owned content. +- Core promise: Git-owned, portable content; secrets server-side; publishing + confidence (validation, preview of exact output path/file, content QA). +- SourceDraft is **not** WordPress, not a site builder, not a hosted CMS. +- QuBrite.com is the origin story only. Never hardcode QuBrite (or any single + site) into core logic, defaults, or fixtures. + +## Engineering rules + +- Universal article schema lives in `@sourcedraft/core`; adapters and + publishers consume it through `adapterRegistry` / `publisherRegistry`. +- Secrets are read from `.env` in `apps/studio/server` only. Browser code must + never import publisher/media packages or see credential values. +- Keep modules typed, small, and testable. Prefer boring reliable code. +- No unnecessary comments, no unrelated refactors, no dependency additions + without explicit justification. +- Errors returned to Studio must be clear and actionable, without leaking + secret values. + +## Honesty rules + +- Docs and UI describe only what is implemented. Shipped vs experimental vs + not-shipped follows `docs/project-status.md` — update it when status + changes, and keep README/CHANGELOG consistent with it. +- No fake analytics, fake charts, fake metrics, fake screenshots, placeholder + features, or production/enterprise overclaims. +- Known limitations (MVP auth, in-memory sessions, Contents API scale limits, + S3 upload not implemented) stay visibly documented until fixed. diff --git a/.claude/worktrees/project-guidance b/.claude/worktrees/project-guidance new file mode 160000 index 0000000..e791f54 --- /dev/null +++ b/.claude/worktrees/project-guidance @@ -0,0 +1 @@ +Subproject commit e791f54723e8a630ae5316dbd6a14e0763924b51 diff --git a/.github/ISSUE_TEMPLATE/adapter_request.md b/.github/ISSUE_TEMPLATE/adapter_request.md new file mode 100644 index 0000000..60fc9ec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/adapter_request.md @@ -0,0 +1,36 @@ +--- +name: Adapter request +about: Request or propose a new file adapter (framework/static-site generator) +title: "adapter: " +labels: enhancement, adapter +assignees: "" +--- + +## Framework / generator + + + +## Frontmatter format + + + +## Field mapping + + + +## File path conventions + + + +## Example post file + +```markdown + +``` + +## Are you willing to implement it? + + diff --git a/.github/ISSUE_TEMPLATE/publisher_request.md b/.github/ISSUE_TEMPLATE/publisher_request.md new file mode 100644 index 0000000..96f78b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/publisher_request.md @@ -0,0 +1,37 @@ +--- +name: Publisher request +about: Request or propose a new publish target (Git host or CMS API) +title: "publisher: " +labels: enhancement, publisher +assignees: "" +--- + +## Target + + + +## Kind + + + +## Auth model + + + +## Capabilities expected + +- Publish new post: yes / no +- Update existing post: yes / no (how is the post identified?) +- Upload media: yes / no +- List/read posts: yes / no + +## Why not a plugin? + + + +## Are you willing to implement it? + + diff --git a/.github/ISSUE_TEMPLATE/security_hardening.md b/.github/ISSUE_TEMPLATE/security_hardening.md new file mode 100644 index 0000000..1239bea --- /dev/null +++ b/.github/ISSUE_TEMPLATE/security_hardening.md @@ -0,0 +1,30 @@ +--- +name: Security hardening +about: Propose a hardening improvement (NOT for reporting vulnerabilities) +title: "hardening: " +labels: security +assignees: "" +--- + + + +## Area + + + +## Current behavior + + + +## Proposed hardening + + + +## Trade-offs + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..dd9dfd3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,30 @@ +## What and why + + + +## Type of change + + + +- [ ] Bug fix +- [ ] Feature (adapter / publisher / Studio / server) +- [ ] Documentation +- [ ] Tests / CI +- [ ] Refactor (no behavior change) + +## Checklist + +- [ ] `pnpm build` passes +- [ ] `pnpm test` passes +- [ ] `pnpm test:e2e` passes (required if Studio UI, auth, demo mode, or publish flows changed) +- [ ] Tests added/updated for logic changes +- [ ] Docs updated if behavior or configuration changed (including compatibility matrices) +- [ ] No secrets in code, fixtures, tests, or screenshots; nothing credential-related in browser code +- [ ] No new dependencies (or justified below) +- [ ] In scope — no monetization, telemetry, OAuth/RBAC, or hosted features (see docs/roadmap.md "Explicitly not now") + +## Test notes + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f1950b9 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,90 @@ +# CLAUDE.md + +Guidance for AI assistants working in this repository. Detailed rules live in +`.claude/rules/`. + +## What SourceDraft is + +An open-source (AGPL-3.0-or-later) publishing Studio for Markdown, MDX, and +Git-backed content workflows. A local React Studio plus a server-side publish +API commit content and media to the user's own target — GitHub, GitLab, +Bitbucket, WordPress, or Ghost — through an adapter/publisher architecture. + +- **Adapters** render a validated universal article into platform-specific + file output (Astro MDX, Hugo, Docusaurus, MkDocs, Nuxt Content, …). +- **Publishers** send content to a target (Git file commit or remote CMS API). +- Content stays portable: plain `.md`/`.mdx` files in the user's repository. + +Status: early local/private MVP. Honest about limitations — see +`docs/project-status.md`. QuBrite.com is the origin story only, never a +dependency or hardcoded target. + +## Repository layout + +| Path | Contents | +|------|----------| +| `apps/studio` | React Studio UI + Express publish API (`server/`) | +| `packages/core` | Universal article schema and validation | +| `packages/adapter-*` | One package per file adapter (8 shipped) | +| `packages/adapters` | `adapterRegistry` | +| `packages/publishers` | `publisherRegistry` (GitLab, Bitbucket, WP, Ghost) | +| `packages/github-publisher` | GitHub Contents API client | +| `packages/media-providers` | Git media, Cloudinary, S3 (config-only) | +| `packages/plugins` | Server-side plugin loader | +| `packages/setup` | Setup wizard + config validation CLI | +| `examples/*` | Folder-layout integration examples (not runnable sites) | +| `docs/` | All user and contributor documentation | + +## Commands + +```bash +pnpm install # workspace install (pnpm 11+, Node 22+) +pnpm dev # Studio UI + publish API +pnpm build # build everything incl. studio server TS +pnpm test # unit tests across packages + studio +pnpm test:e2e # Playwright smoke tests (demo mode, no credentials) +pnpm setup # guided config wizard +pnpm validate:config # validate sourcedraft.config.json + .env +``` + +Run `pnpm build` and `pnpm test` before finishing any code change. Run +`pnpm test:e2e` when Studio UI, auth, demo mode, or publish flows change. + +## Hard rules + +1. **Secrets stay server-side.** Tokens, passwords, and API keys are read from + `.env` in `apps/studio/server` only. Never import publisher packages or + reference credentials in browser code. Never commit `.env`/`.env.local`. +2. **License is AGPL-3.0-or-later** everywhere. No MIT references. +3. **No scope creep** — see `.claude/rules/no-scope-creep.md`. No billing, + paywalls, telemetry, OAuth, RBAC, team accounts, hosted/multi-tenant + Studio, plugin marketplace, or AI writing features. +4. **No fabrication.** No fake screenshots, metrics, benchmarks, testimonials, + or placeholder features. Docs must describe what the code actually does. +5. **No new dependencies** unless absolutely necessary and justified in the + PR description. +6. **Honest status.** SourceDraft is an early local/private MVP, not a hosted + SaaS or production multi-user product. Keep all docs consistent with + `docs/project-status.md` (shipped / experimental / not shipped). +7. **No QuBrite hardcoding** in app logic. Generic core, per-site config. +8. **Do not push to `main`.** PRs only; CI and CodeQL must pass. + +## Code style + +- TypeScript, small typed modules, boring reliable code over clever + abstractions. +- New adapters/publishers go through the registries; follow the interfaces in + `docs/compatibility-roadmap.md`. +- Unit tests with `node --test` next to the source (`*.test.ts`). +- Match existing comment density (low); no comments that restate code. + +## Docs style + +See `.claude/rules/docs-style.md`. Short version: precise, technical, +trustworthy; respectful toward Decap/Tina/CloudCannon/WordPress/Ghost; +no SaaS hype, no overclaims; every feature claim must match shipped code. + +## Release gates + +See `.claude/rules/release-gates.md` and `RELEASE_CHECKLIST.md` before +tagging or promoting anything publicly. diff --git a/README.md b/README.md index 27dbd43..27a1f4b 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,9 @@ Your static site still builds and deploys exactly as before. SourceDraft creates ## What it does not do yet - Host your website or run your Astro build -- OAuth, user accounts, or role-based access +- OAuth, user accounts, role-based access, or hosted multi-tenant Studio - Full S3/R2 media upload (`s3-compatible` validates config only; use Cloudinary or git media today) - Post list in Studio for Bitbucket, WordPress, and Ghost publishers -- OAuth, team accounts, or hosted multi-tenant Studio Eight adapters ship today — see [docs/adapters.md](docs/adapters.md). See [docs/project-status.md](docs/project-status.md) for the full shipped vs experimental list. @@ -187,6 +186,9 @@ Issues and pull requests are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) fo - [Architecture](docs/architecture.md) - [Adapters](docs/adapters.md) - [Project status](docs/project-status.md) +- [How SourceDraft compares](docs/comparison.md) — Decap, Tina, CloudCannon, WordPress, Ghost +- [Roadmap](docs/roadmap.md) +- [Contributing roadmap](docs/contributing-roadmap.md) — good first issues - [Manual acceptance test](docs/manual-acceptance-test.md) - [Smoke tests (Playwright)](docs/getting-started.md#smoke-tests-playwright) - [Release checklist](RELEASE_CHECKLIST.md) diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md index afbb18e..2ecc8d0 100644 --- a/RELEASE_CHECKLIST.md +++ b/RELEASE_CHECKLIST.md @@ -1,6 +1,8 @@ # SourceDraft release checklist -Use this before tagging a public release or promoting the repository. +Use this before tagging a public release or promoting the repository. For +first-time public promotion (announcements, demos, screenshots), also run +[docs/public-launch-checklist.md](docs/public-launch-checklist.md). ## Automated checks @@ -32,7 +34,9 @@ pnpm test:e2e - [ ] 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/` +- [ ] Issue templates present under `.github/ISSUE_TEMPLATE/` (bug, feature, adapter, publisher, security hardening) +- [ ] `.github/pull_request_template.md` present +- [ ] `SECURITY.md` reporting instructions current ## Screenshots @@ -88,4 +92,4 @@ Only tag after automated checks pass and manual acceptance is satisfactory. - Post list in Studio for Bitbucket, WordPress, and Ghost - Git Trees API indexer for very large repos -Roadmap: [docs/compatibility-roadmap.md](docs/compatibility-roadmap.md) +Roadmap: [docs/roadmap.md](docs/roadmap.md) · [docs/compatibility-roadmap.md](docs/compatibility-roadmap.md) diff --git a/SECURITY.md b/SECURITY.md index f4012b1..b84444f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,5 +1,44 @@ # Security Policy -Do not report real secrets in public issues. +SourceDraft is an early open-source MVP intended for **local or private** +deployments. Its threat model and current limitations are documented in +[docs/security.md](docs/security.md) — read that first. -GitHub tokens and publishing credentials must stay server-side. +## Reporting a vulnerability + +Please do **not** open a public issue for security vulnerabilities. + +Report privately via [GitHub Security Advisories](https://github.com/bnz183/SourceDraft/security/advisories/new) +("Report a vulnerability" on the repository's Security tab). + +Include where practical: + +- Affected area (Studio UI, publish API, a specific publisher/adapter/media provider) +- Reproduction steps or proof of concept +- Impact assessment (what an attacker gains) + +You should receive an initial response within 7 days. This is a small +maintainer-run project — fixes are best-effort but security reports are +prioritized over feature work. + +## Scope notes + +Known, documented MVP limitations are not considered vulnerabilities on their +own (but bypasses of the documented protections are): + +- Single shared password auth with in-memory sessions (local/private use only) +- No CSRF tokens — `Sec-Fetch-Site`/`Origin` checks instead +- Studio is not hardened for public internet exposure + +## Handling secrets + +- GitHub/GitLab/Bitbucket tokens, WordPress/Ghost/Cloudinary credentials, and + the admin password live in `.env` and are read **server-side only**. +- Never commit `.env` or `.env.local`; never paste tokens, passwords, or + private repository details into issues, PRs, or screenshots. +- If you accidentally expose a token, revoke and rotate it immediately. + +## Automated checks + +CI runs build, unit tests, and Playwright smoke tests; GitHub CodeQL analyzes +JavaScript/TypeScript and Actions workflows on pushes and PRs to `main`. diff --git a/docs/architecture.md b/docs/architecture.md index 70576f9..a401ac6 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -13,7 +13,7 @@ Publish API (server) → validate (@sourcedraft/core) → adapt (adapterRegistry / @sourcedraft/adapters) → publish (publisherRegistry / @sourcedraft/publishers) - → GitHub repository file in contentDir + → Git repository file in contentDir, or remote CMS API (WordPress, Ghost) Your static site build (outside SourceDraft) → deployed site ``` @@ -26,8 +26,8 @@ Studio (browser) Publish API (server) → validate type, size, signature → sanitize filename - → publisher.uploadMedia (github publisher today) - → GitHub repository file in mediaDir + → media provider (git repo, Cloudinary) via publisher.uploadMedia or provider API + → repository file in mediaDir, or CDN URL Studio → publicPath for heroImage / Markdown body ``` @@ -48,10 +48,13 @@ Publish API (server) | Package | Role | |---------|------| | `@sourcedraft/core` | Article schema and validation | -| `@sourcedraft/adapter-*` | Platform-specific file output (Astro, Markdown, Next.js, Hugo, Eleventy/Jekyll) | +| `@sourcedraft/adapter-*` | Platform-specific file output (Astro MDX, Markdown, Next.js MDX, Hugo, Eleventy/Jekyll, Docusaurus, MkDocs, Nuxt Content) | | `@sourcedraft/adapters` | `adapterRegistry` — built-in adapter registration and dispatch | | `@sourcedraft/github-publisher` | Low-level GitHub Contents API client | -| `@sourcedraft/publishers` | `publisherRegistry` — typed publish/upload/list/read surface | +| `@sourcedraft/publishers` | `publisherRegistry` — GitHub, GitLab, Bitbucket, WordPress, Ghost publish/upload/list/read | +| `@sourcedraft/media-providers` | Git media, Cloudinary, S3-compatible (config validation only) | +| `@sourcedraft/plugins` | Server-side loader for custom adapters/publishers/media providers | +| `@sourcedraft/setup` | Setup wizard and `validate:config` CLI | | `@sourcedraft/config` | Load `sourcedraft.config.json` | ## Studio @@ -72,8 +75,8 @@ See [configuration.md](configuration.md), [adapters.md](adapters.md), [compatibi ## Adapters and publishers -**Adapters** turn a validated article into platform-specific file content. Registered in `adapterRegistry`. +**Adapters** turn a validated article into platform-specific file content. Registered in `adapterRegistry`. Eight ship today — see [adapters.md](adapters.md). -**Publishers** send content to a target. Registered in `publisherRegistry`. Shipped: GitHub (`github`). +**Publishers** send content to a target. Registered in `publisherRegistry`. Shipped: `github`, `gitlab`, `bitbucket` (Git file commits) and `wordpress`, `ghost` (remote CMS APIs) — see [publishers.md](publishers.md) for the capability matrix. -Future publishers (not implemented): WordPress API, Ghost API. +Custom adapters, publishers, and media providers can register through server-side [plugins](plugins.md). diff --git a/docs/brand-assets.md b/docs/brand-assets.md new file mode 100644 index 0000000..2c9373d --- /dev/null +++ b/docs/brand-assets.md @@ -0,0 +1,100 @@ +# Brand assets guide + +Direction for SourceDraft's visual identity. This is guidance for creating +real assets — it does not ship placeholder or fake assets. If an asset does +not exist yet, leave the slot empty rather than faking it. + +## Identity in one line + +A professional open-source developer tool: clean, technical, trustworthy. +Closer in spirit to Git, Vite, or Playwright than to a SaaS landing page. +The brand should signal "this tool respects your repository and your +credentials." + +## Logo direction + +- **Concept space:** drafting + source. Ideas worth exploring: a document + glyph merged with a commit node or branch line; a cursor/caret on a + Markdown `#`; a minimal "SD" monogram with a diff/branch accent. +- **Style:** flat, geometric, single-weight strokes. No gradients, no 3D, no + mascots, no AI-generated look. +- **Variants needed:** square mark (favicon/avatar, works at 32px), and a + horizontal lockup (mark + "SourceDraft" wordmark) for README and social + preview. +- **Wordmark:** a clean sans-serif or semi-mono face; "SourceDraft" set as + one word, capital S and D. +- **Format:** SVG source of truth; export PNG at 1x/2x. Keep SVGs hand-edited + or optimized (no embedded raster data). + +## Color and style direction + +- **Base:** near-black/near-white neutrals (editor chrome territory), one + restrained accent color used sparingly for actions and the logo accent. + Candidates: a desaturated teal/cyan or amber — pick one, use it everywhere, + avoid the default-blue-SaaS look and avoid purple-gradient AI clichés. +- **Semantic colors** stay conventional: green = success/shipped, amber = + warning/experimental, red = error. Don't repurpose them decoratively. +- **Typography in assets:** system/sans for UI text, monospace for paths, + frontmatter, and code — monospace is part of the identity (this is a tool + about files). +- Generous whitespace; no drop shadows heavier than the Studio UI itself. + +## Screenshot style + +Screenshots are the primary "brand" surface today and must stay honest: + +- Always generated from **demo mode** fixtures via `pnpm screenshots:generate` + (1280×900) — reproducible, never staged with fake content +- Show real UI states: actual warnings in the content QA panel, the real + demo banner, real setup-health rows +- Never include tokens, real repo names you don't want public, personal + paths, or email addresses +- No marketing annotations (arrows, circles, emoji) baked into committed + screenshots; annotate copies in blog posts if needed +- Same browser, same width, light theme consistently (until a dark theme + exists — don't fake one) + +Inventory and rules: [screenshots.md](screenshots.md). + +## Demo video style + +- Record the scripts in [demo-script.md](demo-script.md), demo mode only +- Screen-only capture at 1280px+ logical width; crop to the browser, hide + bookmarks/extensions +- Calm pacing — no jump cuts every two seconds, no stock music with a "growth + hacking" feel; quiet or no music is fine +- Captions or voiceover that states demo mode up front +- 60–90s for social embeds; the 3-minute cut for README/docs linking + +## GitHub social preview + +The 1280×640 image shown when the repo is shared: + +- Lockup (logo + "SourceDraft") + one line: "Open-source publishing Studio + for Markdown, MDX, and Git-backed content" — nothing else +- Solid neutral background or a *real* cropped screenshot as a muted backdrop +- No fake browser chrome around fake UI, no star counts, no badges + +## README hero + +- Keep the current approach: short text intro first, then the real + `studio-overview.png` — readers should meet honest claims before imagery +- When a logo exists, a small centered mark above the H1 is enough; do not + add a marketing banner image +- Badges (CI status, license) are fine; keep to one row, only badges that + reflect real automated state + +## Required vs optional + +| Asset | Status | Priority | +|-------|--------|----------| +| Studio screenshots (×9, generated) | Exists | Required — keep current | +| GitHub repo description + topics | Settings task | Required before promotion | +| Square logo mark (SVG + PNG) | Not created | Required before heavy promotion | +| Social preview image (1280×640) | Not created | Required before heavy promotion | +| Horizontal lockup | Not created | Optional | +| Demo video (60–90s) | Not created | Optional, high value | +| Dark-theme variants | Not applicable yet | Optional, later | + +Store finished assets under `docs/assets/brand/` with an `ATTRIBUTION.md` if +any external resources (fonts, icon bases) require it. diff --git a/docs/comparison.md b/docs/comparison.md new file mode 100644 index 0000000..d4613a5 --- /dev/null +++ b/docs/comparison.md @@ -0,0 +1,121 @@ +# How SourceDraft compares + +An honest comparison with tools you might be evaluating. All of these are +good projects with real strengths; SourceDraft is younger and smaller than +every tool on this page. The goal here is fit, not a winner. + +**Where SourceDraft sits:** a local/private Studio (editor + server-side +publish API) that writes plain `.md`/`.mdx` files to your own Git repository +through framework adapters, or publishes to WordPress/Ghost APIs. Content +stays portable; credentials stay on your server; nothing is hosted for you. + +Status caveat: SourceDraft is an early MVP — see +[project-status.md](project-status.md). If you need a mature, battle-tested +product today, several tools below are further along. + +## Quick orientation + +| Tool | Hosting model | Where content lives | Editing model | +|------|---------------|--------------------|---------------| +| **SourceDraft** | Self-run, local/private | `.md`/`.mdx` in your Git repo (or WP/Ghost via API) | Tiptap rich editor + source mode, adapter preview | +| **Decap CMS** | Embedded in your static site (`/admin`) | Files in your Git repo | Widget-based forms + Markdown editor | +| **TinaCMS** | Self-hosted or Tina Cloud backend | Files in your Git repo | Visual/inline editing on your site | +| **CloudCannon** | Commercial hosted platform | Files in your Git repo | Visual editing, hosted UI | +| **GitCMS** | Hosted editor UI | Files in your Git repo | Hosted Markdown editing | +| **WordPress admin** | Self-hosted or wordpress.com | WordPress database | Block editor (Gutenberg) | +| **Ghost admin** | Self-hosted or Ghost(Pro) | Ghost database | Koenig editor | + +## Decap CMS (formerly Netlify CMS) + +**Decap is stronger on:** maturity and community, running with zero extra +process (it ships as static files in your site's `/admin`), a large widget +ecosystem, editorial workflow (draft/review states backed by PRs), and Git +gateway auth options. + +**SourceDraft differs:** the Studio runs as its own local app with a +server-side publish API, so tokens never go through a browser-side Git +gateway and no `admin/config.yml` lives in your site repo. One universal +article schema renders through adapters for eight frameworks, with a preview +of the exact file path and frontmatter before each commit. If you want an +editor embedded in the deployed site itself, Decap is the better shape. + +## TinaCMS + +**Tina is stronger on:** visual/inline editing on your actual site, a typed +content schema with GraphQL queries, strong Next.js integration, and a +polished hosted backend (Tina Cloud) when you want auth and collaboration +without building it. + +**SourceDraft differs:** it is file-first rather than site-first — there is +no integration into your site's rendering at all, which means it works the +same for Astro, Hugo, MkDocs, or Nuxt Content without framework bindings. No +cloud account is involved; everything runs from your `.env`. If live visual +editing on the rendered page matters to you, Tina is the better fit. + +## CloudCannon + +**CloudCannon is stronger on:** being a complete commercial product — hosted +visual editor, team accounts and permissions, client-friendly editing, +support, and site hosting/builds. For agencies handing a site to +non-technical clients, it is a much more finished answer. + +**SourceDraft differs:** it is free, AGPL, and entirely under your control — +no vendor account, no hosted service touching your repository, credentials +only on your own machine or server. You trade CloudCannon's polish and team +features for ownership and zero platform dependency. + +## GitCMS + +**GitCMS is stronger on:** instant onboarding — connect a repo from the +browser and start editing without installing or running anything yourself. + +**SourceDraft differs:** it never asks you to grant a third-party service +access to your repository. The publish API runs where you run it, tokens stay +in your `.env`, and the adapter/publisher layer targets multiple frameworks +and remote CMS APIs rather than a single hosted editing surface. + +## WordPress admin + +**WordPress is stronger on:** almost everything a full CMS does — themes, +plugins, media management, scheduling, multi-user roles, and twenty years of +ecosystem. If your site *is* WordPress, its admin is the native tool. + +**SourceDraft differs:** it is not a CMS replacement; it is a Git-first +writing tool. Content is Markdown/MDX in your repo, not rows in a database, +so it diffs, reviews, and migrates like code. SourceDraft can also *publish +to* WordPress through its REST API — useful if you want one Markdown-first +editor in front of both a static site and a WordPress site (with documented +limits: no post list in Studio, body sent as-is without HTML conversion). + +## Ghost admin + +**Ghost is stronger on:** being a complete publishing platform — excellent +editor, memberships, newsletters, SEO handling, and hosting via Ghost(Pro). +For a standalone publication, Ghost is a far more complete product. + +**SourceDraft differs:** same trade as WordPress — Git-owned files first, +with an optional Ghost publisher (Admin API; same documented limits) when +part of your content lives in Ghost. + +## When SourceDraft is probably the wrong choice + +- You need hosted multi-user accounts, roles, or client access today +- You want visual editing on the rendered page +- Your writers are non-technical and no developer runs the Studio for them +- You need a mature product with a large plugin/community ecosystem +- You need to expose the editor on the public internet (MVP auth is + local/private only — see [security.md](security.md)) + +## When SourceDraft fits + +- You own a Git-backed Astro/Next.js/Hugo/Eleventy/Docusaurus/MkDocs/Nuxt + site and want one editor that writes correct frontmatter and file paths +- You want content portable as plain files, with commits (or PRs) you review +- You want publish credentials on a server you control, never in a browser + or third-party platform +- You want one schema to target several frameworks — or both files and a + remote CMS — through adapters and publishers + +See also: [project-status.md](project-status.md) · +[publishers.md](publishers.md) · [adapters.md](adapters.md) · +[roadmap.md](roadmap.md) diff --git a/docs/compatibility-roadmap.md b/docs/compatibility-roadmap.md index b6e3617..8bbe7a5 100644 --- a/docs/compatibility-roadmap.md +++ b/docs/compatibility-roadmap.md @@ -46,7 +46,7 @@ Defaults: `adapter: "astro-mdx"`, `publisher: "github"`. **Adapters:** `astro-mdx`, `markdown`, `nextjs-mdx`, `hugo-markdown`, `eleventy-jekyll-markdown`, `docusaurus-mdx`, `mkdocs-markdown`, `nuxt-content-markdown` -**Publishers:** `github` (wraps `@sourcedraft/github-publisher`) +**Publishers:** `github` (wraps `@sourcedraft/github-publisher`), `gitlab`, `bitbucket`, `wordpress`, `ghost` — see [publishers.md](publishers.md) for the capability matrix ## Studio integration points @@ -60,10 +60,10 @@ Defaults: `adapter: "astro-mdx"`, `publisher: "github"`. ## Future (not implemented) -- WordPress REST API publisher -- Ghost API publisher -- Plugin/marketplace loading - Git Trees API for large repos +- Post list/read in Studio for Bitbucket, WordPress, and Ghost +- Full S3/R2 media upload (`s3-compatible` validates config only today) +- Dedicated `listMedia` capability (media library reuses `listPosts`) ## Risks diff --git a/docs/contributing-roadmap.md b/docs/contributing-roadmap.md new file mode 100644 index 0000000..c587f28 --- /dev/null +++ b/docs/contributing-roadmap.md @@ -0,0 +1,92 @@ +# Contributing roadmap + +Concrete, scoped ways to contribute, ordered roughly by ramp-up cost. Read +[CONTRIBUTING.md](../CONTRIBUTING.md) first for setup, branch workflow, and +test requirements. When in doubt, open an issue before writing code. + +## Good first issues + +Small, self-contained, low-risk: + +- Fix unclear or outdated wording in any `docs/*.md` (file a PR directly) +- Improve a server-side error message to name the fix, not just the failure +- Add a unit test for an untested pure helper in `packages/*` +- Improve an empty state or loading message in Studio +- Add a troubleshooting row to [getting-started.md](getting-started.md) for a + problem you actually hit + +## Documentation tasks + +- A quickstart recipe for a framework/host combination you use + ([quickstart-recipes.md](quickstart-recipes.md)) +- Walkthrough improvements informed by a real first-run experience — note + where you got stuck, then fix that spot +- Verify a compatibility matrix row against the code and correct drift +- Translate confusing Git/CMS jargon into plainer language in + [non-technical-overview.md](non-technical-overview.md) + +## Adapter tasks + +Adapters are the friendliest code contribution — one package, clear +interface, pure functions, easy tests. See the interface in +[compatibility-roadmap.md](compatibility-roadmap.md) and copy the structure +of `packages/adapter-hugo-markdown`. + +- New adapter for a framework you run (propose via the adapter request + template first — include frontmatter format, path conventions, field + mapping) +- Additional `adapterOptions` for existing adapters where a real site needs + them (keep options minimal) +- `fromFrontmatter` edge cases: posts with unusual-but-valid frontmatter + that fail to load today, with tests + +## Publisher tasks + +Heavier — network APIs, capability declarations, error mapping: + +- **Post list/read for Bitbucket, WordPress, Ghost** (top roadmap item — + makes the Posts sidebar work for those targets) +- Clearer mapped errors from publisher APIs (rate limits, permissions, + protected branches) +- New publisher proposals via the publisher request template — include the + official API docs and auth model + +## Testing tasks + +- Unit tests for uncovered registry/server logic +- Playwright smoke tests for flows demo mode already exercises (keep them + credential-free and deterministic) +- Edge-case tests: huge bodies, unicode slugs, empty optional fields, + unusual dates + +## Security hardening tasks + +Use the security hardening issue template. Genuinely useful areas: + +- Durable session storage (in-memory today) +- CSRF token support beyond `Sec-Fetch-Site`/`Origin` checks +- Stricter upload validation or content sniffing improvements +- Reverse-proxy deployment guidance (HTTPS, headers, `STUDIO_ALLOWED_ORIGINS`) + +For exploitable vulnerabilities, **do not open an issue** — follow +[SECURITY.md](../SECURITY.md). + +## Maintainer expectations + +What you can expect: + +- Best-effort issue/PR responses — this is a solo-maintained project; days, + not hours +- Honest review: small focused PRs get reviewed quickly; large unsolicited + refactors may be declined even if good +- Security reports prioritized over features + +What is expected of you: + +- `pnpm build` and `pnpm test` pass before requesting review; `pnpm test:e2e` + when UI/auth/publish flows change +- Stay in scope: no monetization, telemetry, OAuth/RBAC, hosted features, or + dependency additions without prior discussion (see [roadmap.md](roadmap.md) + "Explicitly not now") +- No secrets in code, fixtures, screenshots, issues, or commits +- Contributions are licensed AGPL-3.0-or-later diff --git a/docs/demo-script.md b/docs/demo-script.md new file mode 100644 index 0000000..e8d1c0a --- /dev/null +++ b/docs/demo-script.md @@ -0,0 +1,84 @@ +# Demo scripts + +Scripts for live demos and screen recordings. All of them run entirely in +**demo mode** — no credentials, no real commits — so they are safe to record +and reproducible from fixtures. + +Setup before recording: fresh `pnpm dev`, browser at ~1280px width, no real +tokens anywhere on screen. Demo mode entry: leave GitHub vars unset and click +**Explore demo mode**, or set `SOURCEDRAFT_DEMO_MODE=true`. See +[demo-mode.md](demo-mode.md). Style guidance: [brand-assets.md](brand-assets.md). + +Honesty rule for every cut: if the recording shows demo mode, say so. Never +present a simulated publish as a real commit. + +## 60-second demo + +Goal: what SourceDraft is, in one breath. One take, no detours. + +1. **(0:00)** Sign-in screen. Say: "SourceDraft is an open-source Studio for + Markdown and MDX on Git-backed sites. This is demo mode — no credentials, + nothing gets committed." Click **Explore demo mode**. +2. **(0:10)** Posts sidebar. Open a sample post. "Posts are plain files in + your repo; Studio reads them back through the same adapters it writes with." +3. **(0:20)** Type in the editor; show the slash command menu briefly. +4. **(0:35)** Open the preview. "This is the exact file and repo path the + adapter will write — frontmatter included. Eight framework adapters: + Astro, Hugo, Next.js, Docusaurus, MkDocs, more." +5. **(0:50)** Click publish → **Publish simulated**. "Real mode commits to + GitHub — directly or as a pull request. Tokens stay server-side in `.env`. + It's an early MVP, AGPL, on GitHub." + +## 90-second demo + +The 60-second script plus trust beats. Insert after step 4: + +- **(+0:00)** Content quality panel: "Non-blocking QA — SEO length, alt + text, headings, links. Warnings, not gates; you stay in control." +- **(+0:15)** Settings → Setup health: "Studio tells you what's configured + and what's missing — booleans only, it never shows secret values." + +And extend the closing line: "What it doesn't do yet: no hosted service, no +multi-user accounts, single-password auth meant for local use. That's all +documented." + +## 3-minute demo + +Full walkthrough for a recorded video or a live audience. + +1. **(0:00) Framing.** Sign-in screen visible. "If you run an Astro, Hugo, or + Next.js blog, publishing means hand-writing frontmatter and committing + files. SourceDraft is a local Studio that does that for you — content + stays in your Git repo, credentials stay on your server. This whole demo + is demo mode: sample posts, simulated publishing, zero credentials." +2. **(0:20) Enter demo mode.** Point out the banner — the UI itself tells + you nothing will be committed. +3. **(0:35) Create a post.** New post → title, description, category, tags. + Show slash commands and the Markdown toolbar; flip to source mode briefly: + "rich editor or raw Markdown — your choice." +4. **(1:15) Content QA.** Open content quality. Leave description short or + an image alt empty so a real warning shows. "Recommendations, not + blockers." +5. **(1:35) Preview.** "The adapter renders the exact file: YAML frontmatter, + body, and the path under `contentDir`. Switch adapters and the same post + renders for Hugo or Docusaurus conventions instead." +6. **(2:00) Media.** Upload an image from fixtures; show it in the media + library and insert it. "In real mode this commits to your `mediaDir` or + uploads to Cloudinary; the URL uses your configured public path." +7. **(2:20) Publish.** Publish checklist → validation status, output path, + publish mode → **Simulate publish** → simulated success. "Real mode: + direct commit, or a pull request against a protected branch." +8. **(2:40) Secrets.** Open Settings → Setup health. "The browser never sees + tokens. The publish API reads `.env` on the server and reports only + booleans here." +9. **(2:50) Honest close.** "Early MVP: single-password auth for local or + private use, no OAuth or teams, some publisher features are partial — + the compatibility matrices in the docs say exactly what works. AGPL, + on GitHub, feedback welcome." + +## After recording + +- Check every frame for personal paths, emails, or anything token-shaped +- Keep claims within [project-status.md](project-status.md) +- Update or re-record when the UI changes materially (same rule as + screenshots — see [screenshots.md](screenshots.md)) diff --git a/docs/portfolio-case-study.md b/docs/portfolio-case-study.md new file mode 100644 index 0000000..09464b5 --- /dev/null +++ b/docs/portfolio-case-study.md @@ -0,0 +1,148 @@ +# SourceDraft — engineering case study + +A walkthrough of SourceDraft as a piece of engineering: the problem, the +architecture, the trade-offs, and what was deliberately left out. Written for +engineers, maintainers, and technical founders evaluating the project or its +author. + +## The problem + +Git-backed static sites (Astro, Hugo, Next.js, Docusaurus, MkDocs, Nuxt +Content, Eleventy/Jekyll) make publishing a developer workflow: hand-write +YAML frontmatter, get the filename convention right, commit, push. That is +fine for developers and hostile to everyone else — and error-prone even for +developers (wrong date format, duplicate slug, missing alt text, broken +frontmatter that fails the site build). + +Existing Git-based CMS options solve this with an editor embedded in the +deployed site (Decap), framework-coupled visual editing (Tina), or a hosted +platform that gets write access to your repository (CloudCannon, GitCMS). +Each is a good trade for someone. SourceDraft makes a different one: a +**local Studio with a server-side publish API**, so content stays plain +files in your repo and credentials never leave your own environment. + +SourceDraft began as an internal publishing tool for QuBrite.com and was +generalized into an open-source project. QuBrite is the origin story, not a +dependency — nothing in core references it. + +## Target users + +Solo developers, technical bloggers, documentation maintainers, and small +teams that want Git-owned content with a simpler writing workflow — people +comfortable running `pnpm dev` but tired of hand-editing frontmatter. + +## Architecture + +``` +Studio (React, browser) — editor, preview, no secrets ever + │ article JSON / multipart upload +Publish API (Express, server) — auth, validation, credentials from .env + │ +core ──► adapterRegistry ──► publisherRegistry ──► your target +schema renders file commits via Git API (GitHub, GitLab, ++ validation or calls CMS API Bitbucket, WP, Ghost) +``` + +The design rests on one schema and two registries: + +- **`@sourcedraft/core`** — a universal article schema (title, slug, dates, + category, tags, draft, body, optional SEO fields) with validation. Every + feature upstream and downstream speaks this type. +- **`adapterRegistry`** (`@sourcedraft/adapters`) — adapters render a + validated article into platform-specific output: frontmatter dialect + (YAML/TOML), field mapping (`pubDate` → `date` → `lastmod`), file + extension, and path convention (`slug`, `date-slug`, `index`). Adapters + also parse existing files back into the schema (`fromFrontmatter`), which + powers editing. +- **`publisherRegistry`** (`@sourcedraft/publishers`) — publishers move + content to a target and declare `capabilities` (publish, upload media, + list, read). Unsupported operations return typed `{ ok: false, error }` + results instead of throwing, so Studio can degrade clearly per target. + +Because adapters and publishers are orthogonal, the matrix multiplies +instead of adding: 8 adapters × 5 publishers from one editor, plus a +server-side plugin loader (`@sourcedraft/plugins`) for custom connectors +without forking. + +## Monorepo layout + +| Workspace | Role | +|-----------|------| +| `apps/studio` | React Studio UI + Express publish API | +| `packages/core` | Universal article schema and validation | +| `packages/adapter-*` (×8) | One package per framework adapter | +| `packages/adapters`, `packages/publishers` | Registries | +| `packages/github-publisher` | GitHub Contents API client (commit, PR, draft-PR modes) | +| `packages/media-providers` | Git media, Cloudinary, S3-compatible (config-only) | +| `packages/plugins` | Server-side plugin loader | +| `packages/setup` | Interactive setup wizard + config validation CLI | +| `examples/*` (×7) | Folder-layout integration references per framework | + +Plain TypeScript, `node --test` unit tests colocated with source, no +framework beyond React/Express/Tiptap. Boring on purpose. + +## Security model + +The central invariant: **secrets exist only in `.env`, read only by the +publish API**. Browser code never imports publisher packages. + +- Auth: single shared password (scrypt hash preferred, plaintext fallback for + local dev), HttpOnly `SameSite=Lax` session cookies, in-memory sessions. +- State-changing routes check `Sec-Fetch-Site`/`Origin`; rate limiting on + auth, publish, media, and read endpoints. +- Media uploads validate MIME type, size, and file signatures; filenames are + sanitized; path traversal blocked; no SVG/HTML/executables. +- Setup health endpoint reports config *presence* booleans, never values. +- Demo mode is a hard gate: when forced on, publish and upload simulate + success and remote calls never happen, even with credentials present. + +The docs say plainly what this is: MVP hardening for local/private use, not +production multi-user auth. That transparency is part of the design. + +## Quality engineering + +- CI on every push/PR: `pnpm build`, unit tests across all packages, and + Playwright e2e smoke tests that run entirely in demo mode — so CI needs no + live credentials and tests are deterministic from fixtures. +- GitHub CodeQL on JS/TS and Actions workflows. +- README screenshots are *generated* by Playwright from demo fixtures + (`pnpm screenshots:generate`) — reproducible, never staged or faked. +- A release checklist, manual acceptance script, and per-connector docs with + capability matrices that state what does **not** work. + +## Product-side details worth noting + +- **Publish confidence loop:** validation → content QA warnings (SEO, alt + text, headings, links) → preview of the exact output file and repo path → + publish checklist → publish, optionally as a PR against protected branches. +- **Setup detection:** scans a local project to suggest adapter and paths; + **content audit** scans existing posts read-only before you trust the tool + with them. +- **Demo mode** doubles as onboarding (try Studio with zero credentials) and + as the e2e test substrate. + +## Trade-offs and honest limitations + +| Decision | Cost accepted | +|----------|---------------| +| Local Studio + own API instead of hosted | No multi-user, no client access; you run it yourself | +| Shared-password MVP auth | Not safe for public exposure; in-memory sessions reset on restart | +| GitHub Contents API (no Trees indexer) | ~1000 entries/folder listing limit, ~1 MB inline files | +| No Markdown→HTML converter for WP/Ghost | Remote CMS bodies sent as-is; rendering depends on target | +| `s3-compatible` config validation only | No S3/R2 upload yet — documented, not hidden | +| File-first, no site rendering integration | No visual/inline editing on the deployed page | + +## Roadmap + +Near-term: deeper publisher capabilities (post list for Bitbucket/WP/Ghost), +Git Trees API for large repos, S3/R2 upload, durable sessions. Later: +self-host hardening for small teams. Possible commercial layer (hosted Cloud, +OAuth/teams) is explicitly future-only — see [roadmap.md](roadmap.md). + +## Where to look in the code + +- Schema and validation: `packages/core/src` +- A complete small adapter: `packages/adapter-hugo-markdown/src` +- Registry pattern: `packages/adapters/src`, `packages/publishers/src` +- API surface and auth middleware: `apps/studio/server` +- E2E approach: `apps/studio/e2e` + demo fixtures in `apps/studio/server/demo` diff --git a/docs/project-status.md b/docs/project-status.md index bf472e9..df0b62c 100644 --- a/docs/project-status.md +++ b/docs/project-status.md @@ -51,7 +51,7 @@ Early open-source MVP — usable for solo writing and publishing to Git or remot | **WordPress/Ghost admin** | Optional **publishers** — SourceDraft is not a full WP/Ghost replacement | Native CMS UI and media library | | **Static dashboard** | Validates universal schema, previews exact file path, multi-adapter | Often framework-specific or hosted | -SourceDraft fits when you want one editor for Markdown/MDX files **or** API publish to WP/Ghost, with secrets on the server only. +SourceDraft fits when you want one editor for Markdown/MDX files **or** API publish to WP/Ghost, with secrets on the server only. Full honest comparison: [comparison.md](comparison.md) ## Demo mode diff --git a/docs/public-launch-checklist.md b/docs/public-launch-checklist.md new file mode 100644 index 0000000..17b8070 --- /dev/null +++ b/docs/public-launch-checklist.md @@ -0,0 +1,136 @@ +# Public launch checklist + +Operator checklist for taking SourceDraft from "public repository" to +"actively promoted project". Complements [RELEASE_CHECKLIST.md](../RELEASE_CHECKLIST.md) +(per-release gates) — run both before the first announcement. + +## 1. Pre-public checks + +- [ ] `RELEASE_CHECKLIST.md` fully green for the current version +- [ ] README renders correctly on GitHub (images, tables, anchors) +- [ ] All README/doc links resolve (no 404s, no links to private resources) +- [ ] `docs/project-status.md` matches reality — shipped / experimental / not + shipped all still accurate +- [ ] No production/SaaS/enterprise overclaims anywhere in docs +- [ ] License consistent: AGPL-3.0-or-later in `LICENSE`, `package.json`, README +- [ ] GitHub repo settings: description, topics (`cms`, `markdown`, `mdx`, + `git-based-cms`, `static-site-generator`, `astro`), social preview image +- [ ] Issue templates and PR template work (open a draft issue to verify) +- [ ] `SECURITY.md` private reporting path works (Security tab → advisories enabled) + +## 2. Build and test + +```bash +pnpm install --frozen-lockfile +pnpm build +pnpm test +pnpm exec playwright install chromium # first time only +pnpm test:e2e +``` + +- [ ] All commands exit 0 locally +- [ ] CI green on `main` (build-and-test + studio-e2e jobs) +- [ ] CodeQL: no open high-severity alerts + +## 3. Security sanity checks + +- [ ] No-secrets scan on tracked files: + `git grep -nIiE 'ghp_[A-Za-z0-9]|gho_[A-Za-z0-9]|glpat-|BEGIN [A-Z ]*PRIVATE KEY' -- ':!*.example*'` → no hits +- [ ] `git ls-files | grep -E '^\.env'` → only `.env.example` +- [ ] `sourcedraft.config.example.json` and `.env.example` contain placeholders only +- [ ] Screenshots in `docs/assets/` show demo content, no tokens or personal data +- [ ] `docs/security.md` limitations section still matches the code + +## 4. Demo mode test (fresh-clone simulation) + +In a clean clone with no `.env`: + +- [ ] `pnpm install && pnpm dev` starts without errors +- [ ] Sign-in screen shows **Explore demo mode** +- [ ] Demo banner clearly states no commits are made +- [ ] Sample posts load; editing works; **Simulate publish** succeeds +- [ ] Settings → Setup health shows useful next actions, no secret values + +## 5. Manual GitHub publish test + +Against a **test** repository (never production): + +- [ ] Direct mode: publish a new post → file appears at the expected + `contentDir` path with correct frontmatter +- [ ] Upload an image → lands in `mediaDir`; URL in post uses `publicMediaPath` +- [ ] Edit the same post → same file updated, no duplicate +- [ ] Wrong token/repo produces a clear error, not a blank screen + +## 6. PR publish test + +On a test repo with branch protection on `main`: + +- [ ] `SOURCEDRAFT_PUBLISH_MODE=pull-request` → publish creates a PR with the + expected file path and branch prefix +- [ ] Optional: `draft-pull-request` mode creates a draft PR +- [ ] Merging the PR produces the correct file on `main` + +## 7. Screenshot / video checklist + +- [ ] `pnpm screenshots:generate` run after any UI change; diffs committed +- [ ] All nine README/doc screenshots current (see [screenshots.md](screenshots.md)) +- [ ] Optional demo video recorded from [demo-script.md](demo-script.md) — + demo mode only, 1280px+ width, no real credentials on screen +- [ ] Visual style follows [brand-assets.md](brand-assets.md) + +## 8. What NOT to promote yet + +Do not claim or imply any of the following in announcements: + +- Production-ready, enterprise-ready, or "secure for public deployment" +- Multi-user, teams, roles, or OAuth +- Hosted/cloud offering of any kind +- S3/R2 media uploads (config validation only today) +- Post list/editing in Studio for Bitbucket, WordPress, or Ghost +- Any metric you have not measured (users, stars, performance) + +Honest framing wins long-term trust and avoids day-one corrections from +commenters. + +## 9. Suggested announcement wording + +Adjust voice to the venue; keep claims within shipped scope. + +**Short (social / link aggregator title):** + +> SourceDraft — an open-source publishing Studio for Markdown/MDX and +> Git-backed sites. Local editor, server-side publish API, 8 framework +> adapters, 5 publish targets (GitHub/GitLab/Bitbucket/WordPress/Ghost). +> AGPL. Early MVP, feedback welcome. + +**Longer (Show HN / Reddit / blog post intro):** + +> I built SourceDraft, an open-source (AGPL) publishing Studio for +> Git-backed content workflows. You write Markdown/MDX in a local browser +> Studio (Tiptap editor, content QA, preview of the exact file and path), +> and a server-side publish API commits to your repo — direct or as a pull +> request — or publishes to WordPress/Ghost APIs. Adapters handle +> frontmatter and path conventions for Astro, Next.js, Hugo, +> Eleventy/Jekyll, Docusaurus, MkDocs, and Nuxt Content. +> +> Design goals: content stays plain files in your Git repo, credentials stay +> server-side in your `.env`, and no hosted service gets access to your +> repository. There's a demo mode that runs with zero credentials if you +> want to try it in two minutes. +> +> It's an early MVP and honest about it: single-password auth for +> local/private use, no multi-user/OAuth, some publisher capabilities are +> partial (documented in the compatibility matrices). Roadmap and +> limitations are in the repo. I'd appreciate feedback, especially from +> people running Decap/Tina/CloudCannon who can tell me what they'd miss. + +- [ ] Announcement drafted and checked against section 8 +- [ ] You (the maintainer) are available for ~48h after posting to answer + issues and comments + +## 10. After launch + +- [ ] Watch issues/discussions daily for the first week +- [ ] Label incoming issues; point newcomers to + [contributing-roadmap.md](contributing-roadmap.md) +- [ ] Note recurring confusion → docs fixes are the highest-leverage follow-up diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..081d32c --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,70 @@ +# Roadmap + +Where SourceDraft is heading, in honest tiers. Nothing here is a commitment +with a date; items move based on real usage and contributor interest. +Technical extension details live in +[compatibility-roadmap.md](compatibility-roadmap.md). + +The free, open-source AGPL version is the product. It will not be +artificially crippled to sell something later. + +## Near-term (open-source, current focus) + +Improvements to the existing local/private workflow: + +- **Post list/read for more publishers** — Bitbucket, WordPress, and Ghost + can publish but cannot list posts in Studio yet +- **S3/R2 media upload** — `s3-compatible` currently validates config only +- **Git Trees API indexer** — lift the Contents API limits (~1000 + entries/folder, ~1 MB inline files) for large repos +- **Media management** — delete/rename in the media library (upload + list today) +- **Better error surfaces** — keep improving actionable publisher/API errors +- **Docs and onboarding** — quickstart recipes, troubleshooting, more + framework examples +- **More adapters via community** — see + [contributing-roadmap.md](contributing-roadmap.md) + +## Later (self-hosted hardening) + +For people running Studio beyond a single laptop — still open source: + +- Durable sessions (survive API restarts) +- CSRF tokens and stricter request protection suitable for reverse-proxy + deployments +- Markdown→HTML conversion option for WordPress/Ghost bodies +- Scheduled/draft publishing workflows on top of PR modes +- Optional multi-password or per-writer identification (not full RBAC) + +## Future commercial possibilities (not built, not promised) + +If SourceDraft earns real adoption, a paid layer could fund maintenance. +Candidates, listed for transparency: + +- Hosted **SourceDraft Cloud** (managed Studio + publish API) +- Managed setup/onboarding and migration services +- OAuth, team accounts, RBAC, persistent sessions as managed features +- Managed media storage +- Agency/client workspaces +- Premium/commercial support; possible dual-license arrangements + +None of this exists, none of it is scheduled, and none of it will remove +functionality from the open-source version. + +## Explicitly not now + +Deliberately out of scope in the current phase: + +- Paywalls, billing, SaaS plans, license gates +- Telemetry or usage analytics +- OAuth / user accounts / RBAC implementations +- Hosted or multi-tenant Studio +- Plugin marketplace +- AI writing tools +- Site hosting or running your static-site build +- Large UI redesigns + +## Influence the roadmap + +Open an issue with the `feature_request`, `adapter_request`, or +`publisher_request` template. Real workflows beat hypotheticals — describe +what you publish, where, and what breaks today.