diff --git a/README.md b/README.md index 1ed4a19..71e9523 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ The GitHub token never reaches the browser. It is read from `.env` on the server Details: [docs/github-publishing.md](docs/github-publishing.md) · [docs/media.md](docs/media.md) +v0.1 uses the GitHub Contents API — suitable for typical blogs; very large content folders are a known MVP limitation. + ## Quickstart Requirements: Node.js 22+, pnpm 11+ diff --git a/apps/studio/server/media.ts b/apps/studio/server/media.ts index 7f129e3..887bf28 100644 --- a/apps/studio/server/media.ts +++ b/apps/studio/server/media.ts @@ -257,12 +257,16 @@ export async function uploadMedia( path: repoPath, contentBase64: parsed.buffer.toString("base64"), message: `Upload media: ${repoFilename}`, + purpose: "media", }); if (!result.ok) { return { status: 502, - body: { ok: false, error: result.error }, + body: { + ok: false, + error: result.error || "Media upload to GitHub failed.", + }, }; } diff --git a/apps/studio/server/posts.ts b/apps/studio/server/posts.ts index 21c4fbc..e0b5114 100644 --- a/apps/studio/server/posts.ts +++ b/apps/studio/server/posts.ts @@ -175,11 +175,11 @@ export async function listPosts( ): Promise<{ status: number; body: PostsListResponse }> { const publisher = createPublisher(env); const contentDir = normalizeContentDir(env.contentDir); - const listed = await publisher.listFiles({ path: contentDir }); + const listed = await publisher.listFiles({ path: contentDir, contentDir }); if (!listed.ok) { return { - status: 502, + status: listed.status === 404 ? 404 : 502, body: { ok: false, error: listed.error }, }; } @@ -246,8 +246,9 @@ export async function loadPost( const loaded = await publisher.readFile({ path: safe.path }); if (!loaded.ok) { + const status = loaded.status === 404 ? 404 : 502; return { - status: loaded.status === 404 ? 404 : 502, + status, body: { ok: false, error: loaded.error }, }; } diff --git a/apps/studio/server/publish.ts b/apps/studio/server/publish.ts index 8756682..423a9e2 100644 --- a/apps/studio/server/publish.ts +++ b/apps/studio/server/publish.ts @@ -100,12 +100,13 @@ export async function publishArticle( path, content, message: `Publish: ${article.slug}`, + purpose: "post", }); if (!result.ok) { const errorBody: PublishErrorResponse = { ok: false, - error: result.error, + error: result.error || "Publish to GitHub failed.", }; if (result.status !== undefined) { diff --git a/apps/studio/src/App.tsx b/apps/studio/src/App.tsx index 1b3d03c..09e24bf 100644 --- a/apps/studio/src/App.tsx +++ b/apps/studio/src/App.tsx @@ -256,7 +256,9 @@ function App() { } const action = result.created ? "Created" : "Updated"; - setPublishSuccess(`${action} ${result.path} (${result.commitSha.slice(0, 7)})`); + setPublishSuccess( + `${action} output file ${result.path} (commit ${result.commitSha.slice(0, 7)}).`, + ); setEditingPath(result.path); await refreshPosts(); } catch { @@ -269,7 +271,9 @@ function App() { if (!authChecked) { return (
Checking session...
++ Checking session… +
- {loadPostError} -
+Could not open post
+{loadPostError}
+
- Editing {editingPath}. Publishing will update this
- file in GitHub.
-
Editing an existing post
+
+ Changes will update output file{" "}
+ {editingPath} on GitHub.
+
- Paths and categories from sourcedraft.config.json. GitHub - target from .env. + Project paths from config · GitHub target from .env
- Publishing requires a GitHub token with write access to the
- target repository. The token is read only by the server when you
- publish.
+ These values are read-only here. Edit{" "}
+ sourcedraft.config.json for folders and categories, and{" "}
+ .env for GitHub credentials. The token never reaches
+ the browser.
{githubReady - ? "GitHub repo configured in .env" - : "Set GITHUB_OWNER and GITHUB_REPO in .env to publish"} + ? "Connected to your GitHub repository" + : "Finish GitHub setup in .env to publish"}
+
{loading - ? "Loading from GitHub..." + ? "Loading posts from GitHub…" : `${posts.length} post${posts.length === 1 ? "" : "s"} in your content folder`}
Loading posts…
++ Fetching posts from your GitHub content folder. This may take a moment + for larger sites. +
+GitHub is not configured yet
+
+ Set GITHUB_OWNER and GITHUB_REPO in{" "}
+ .env, then open Settings to confirm the
+ target repository. You can still write drafts locally.
+
{error}
+Could not load posts
+{error}
+
+ Check your GitHub token, repository settings, and{" "}
+ contentDir in Settings. Use Refresh list after fixing
+ configuration.
+
No posts yet
+No posts found
- Use New Article to write your first post. After you - publish, it will show up here so you can edit it later. + {githubReady + ? "Nothing matched your content folder yet. Open Write to draft a post, then publish to GitHub. Published posts appear here for editing." + : "Configure GitHub in Settings, then open Write to create your first post."}
| Title | -Date | -Category | -Status | -+ | Title | +Date | +Category | +Status | ++ Actions + |
|---|---|---|---|---|---|---|---|---|---|
{post.title}
- {post.path}
+ {post.path}
|
{post.pubDate} | {post.category} | @@ -77,7 +113,7 @@ export function ArticlePipeline({ : "article-pipeline__badge article-pipeline__badge--ready" } > - {post.draft ? "Draft" : "Published"} + {post.draft ? "Draft" : "Live"}
diff --git a/apps/studio/src/components/AstroMdxPreview.tsx b/apps/studio/src/components/AstroMdxPreview.tsx
index 5aa94b2..2643ce9 100644
--- a/apps/studio/src/components/AstroMdxPreview.tsx
+++ b/apps/studio/src/components/AstroMdxPreview.tsx
@@ -12,7 +12,7 @@ type AstroMdxPreviewProps = {
};
function previewLabel(adapter: string): string {
- return adapter === "markdown" ? "Markdown output" : "Astro MDX output";
+ return adapter === "markdown" ? "Markdown preview" : "MDX preview";
}
export function AstroMdxPreview({
@@ -40,20 +40,22 @@ export function AstroMdxPreview({
: null;
return (
-
-
{valid && resolvedOutputPath && fileOutput ? (
{previewLabel(adapter)}++ {previewLabel(adapter)} +{valid - ? "Preview of the file that will be committed" - : "Fix validation issues to preview output"} + ? "Review the file that will be saved to GitHub" + : "Complete post details and body to preview"}
- Output path
+ Output file
{resolvedOutputPath}
@@ -61,14 +63,27 @@ export function AstroMdxPreview({
+ {issues.length === 0 ? (
+
)}
+ Add a title, description, dates, category, and body to continue. + + ) : ( + <> ++ Fix these items before publishing: + +
SourceDraft Studio -Markdown / MDX writing workspace +Write, preview, and publish to GitHub
-
Body-MDX / Markdown +Write+Markdown or MDX body |