Action
Send Draft To Readwise
Posted by FlohGro,
Last update
3 days ago
created by @FlohGro / more on my Blog
Send to Readwise Reader
Send the current draft’s Markdown content to your Readwise Reader inbox.
Configuration
The action uses Drafts’ built-in Credential system to store your Readwise access token. You’ll be prompted on first run. Get your token at readwise.io/access_token.
Usage
- Open or create a draft with Markdown content.
- Run the action.
- A prompt lets you review and edit the title and tags before sending.
- Tap Send to push it to Readwise Reader.
The first line of the draft is used as the document title (stripping any leading #). The rest of the content is converted to HTML and sent as the document body.
—
If you find this useful and want to support me you can donate or buy me a coffee
Steps
-
script
// SendToReadwise.js // Sends the current draft's Markdown content to Readwise Reader // as a document in the inbox. Uses the Readwise Reader API v3. // // Configuration (override): // READWISE_CATEGORY — document category (default: "article") // READWISE_TAGS — array of tags to apply (default: ["drafts"]) // READWISE_LOCATION — "new" (inbox), "later", "archive" (default: "new") // // Token stored via Drafts' Credential system. // Get yours at: https://readwise.io/access_token if (typeof READWISE_CATEGORY === "undefined") var READWISE_CATEGORY = "article"; if (typeof READWISE_TAGS === "undefined") var READWISE_TAGS = []; if (typeof READWISE_LOCATION === "undefined") var READWISE_LOCATION = "new"; function sendToReadwise() { var content = draft.content; if (!content || content.trim().length === 0) { app.displayWarningMessage("Draft is empty."); return; } // --- Get API token via Credential system --- var cred = Credential.create("Readwise Reader", "Enter your Readwise access token.\nGet it at readwise.io/access_token"); cred.addPasswordField("token", "Access Token"); if (!cred.authorize()) { app.displayErrorMessage("Readwise token not provided."); context.fail(); return; } var token = cred.getValue("token"); if (!token || token.trim().length === 0) { app.displayErrorMessage("Readwise token is empty."); context.fail(); return; } // --- Extract title from first line and body without it --- var lines = content.split("\n"); var title = lines[0].replace(/^#+\s*/, "").trim(); if (title.length === 0) { title = "Draft from " + new Date().toISOString().substring(0, 10); } // Remove the title line from the body to avoid duplication in Readwise var bodyLines = lines.slice(1); // Also strip leading blank lines after the title while (bodyLines.length > 0 && bodyLines[0].trim() === "") { bodyLines.shift(); } var bodyMd = bodyLines.join("\n"); // --- Unique URL (Readwise deduplicates by URL) --- var fakeUrl = "https://drafts.app/d/" + draft.uuid + "#" + Date.now(); // --- Prompt user to review before sending --- var p = Prompt.create(); p.title = "Send to Readwise Reader"; p.message = "Review before sending:"; p.addTextField("title", "Title", title); p.addTextField("tags", "Tags (comma-separated)", READWISE_TAGS.join(", ")); //p.addTextField("summary", "Summary (optional)", ""); //p.addTextField("notes", "Notes (optional)", ""); p.addButton("Send"); p.addButton("Cancel"); if (!p.show() || p.buttonPressed === "Cancel") { context.cancel(); return; } var finalTitle = p.fieldValues["title"] || title; var tagsStr = p.fieldValues["tags"] || ""; var finalTags = tagsStr.split(",").map(function (t) { return t.trim(); }).filter(function (t) { return t.length > 0; }); //var summary = p.fieldValues["summary"] || null; //var notes = p.fieldValues["notes"] || null; // --- Convert body Markdown to HTML via Drafts built-in --- var md = new GitHubMarkdown(); var htmlContent = "<div>" + md.render(bodyMd) + "</div>"; // --- Build request payload --- var payload = { "url": fakeUrl, "title": finalTitle, "html": htmlContent, //"category": READWISE_CATEGORY, "location": READWISE_LOCATION, "saved_using": "Drafts App" }; if (finalTags.length > 0) { payload["tags"] = finalTags; } //if (summary && summary.trim().length > 0) { // payload["summary"] = summary.trim(); //} //if (notes && notes.trim().length > 0) { // payload["notes"] = notes.trim(); //} // --- Send to Readwise Reader API --- var http = HTTP.create(); var response = http.request({ "url": "https://readwise.io/api/v3/save/", "method": "POST", "encoding": "json", "data": payload, "headers": { "Authorization": "Token " + token, "Content-Type": "application/json" } }); if (response.success) { console.log("Readwise: HTTP " + response.statusCode + " — " + (response.responseText || "")); app.displaySuccessMessage("Sent to Readwise Reader!"); } else { console.log("Readwise error: HTTP " + response.statusCode); console.log("Response: " + (response.responseText || "(empty)")); console.log("Payload URL: " + payload["url"]); console.log("Title: " + payload["title"]); console.log("HTML length: " + htmlContent.length); var errorMsg = "Readwise failed (HTTP " + response.statusCode + ")"; try { var errData = JSON.parse(response.responseText); if (errData.detail) errorMsg += ": " + errData.detail; } catch (e) { } app.displayErrorMessage(errorMsg); context.fail(); } } sendToReadwise();
Options
-
After Success Default Notification None Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.