This commit is contained in:
Josh 2026-01-09 00:24:04 +02:00
commit 91a950e72f
17 changed files with 2724 additions and 0 deletions

90
templates/go.go Normal file
View file

@ -0,0 +1,90 @@
// WriteKit Plugin Template - Go
// Hooks: post.published, post.updated, comment.validate, comment.created,
// member.subscribed, content.render, asset.uploaded, analytics.sync
package main
import (
"strings"
"github.com/extism/go-pdk"
)
// Secrets holds your configured secret values
// Field names will be converted to UPPER_SNAKE_CASE for config lookup
type Secrets struct {
SlackWebhook string
// Add more secrets as needed
}
// Event types
type PostPublishedEvent struct {
Post struct {
Slug string `json:"slug"`
Title string `json:"title"`
URL string `json:"url"`
Excerpt string `json:"excerpt"`
PublishedAt string `json:"publishedAt"`
Tags []string `json:"tags"`
} `json:"post"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
Blog struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"blog"`
}
type CommentInput struct {
Content string `json:"content"`
AuthorName string `json:"authorName"`
AuthorEmail string `json:"authorEmail"`
PostSlug string `json:"postSlug"`
ParentID string `json:"parentId,omitempty"`
}
type ValidationResult struct {
Allowed bool `json:"allowed"`
Reason string `json:"reason,omitempty"`
}
// Called when a post is published
func OnPostPublished(event PostPublishedEvent, secrets Secrets) error {
pdk.Log(pdk.LogInfo, "Post published: "+event.Post.Title)
// Example: Send Slack notification
body := []byte(`{"text":"New post: ` + event.Post.Title + `\n` + event.Post.URL + `"}`)
req := pdk.NewHTTPRequest(pdk.MethodPost, secrets.SlackWebhook)
req.SetHeader("Content-Type", "application/json")
req.SetBody(body)
resp := req.Send()
if resp.Status() >= 400 {
pdk.Log(pdk.LogError, "HTTP request failed")
}
return nil
}
// Called to validate a comment before creation
// Return ValidationResult{Allowed: false, Reason: "..."} to reject
func ValidateComment(input CommentInput, secrets Secrets) (ValidationResult, error) {
// Example: Simple spam check
spamWords := []string{"buy now", "click here", "free money"}
content := strings.ToLower(input.Content)
for _, word := range spamWords {
if strings.Contains(content, word) {
return ValidationResult{
Allowed: false,
Reason: "Comment flagged as spam",
}, nil
}
}
return ValidationResult{Allowed: true}, nil
}
func main() {}

53
templates/typescript.ts Normal file
View file

@ -0,0 +1,53 @@
// WriteKit Plugin Template - TypeScript
// Hooks: post.published, post.updated, comment.validate, comment.created,
// member.subscribed, content.render, asset.uploaded, analytics.sync
import { Host, Config } from "@writekit/sdk";
// Declare your secrets (you'll get autocomplete in the editor!)
interface Secrets {
SLACK_WEBHOOK: string;
// Add more secrets as needed
}
// Called when a post is published
export function onPostPublished(event: PostPublishedEvent, secrets: Secrets): void {
Host.log(`Post published: ${event.post.title}`);
// Example: Send Slack notification
Host.httpRequest({
url: secrets.SLACK_WEBHOOK,
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: `New post: ${event.post.title}\n${event.post.url}`,
}),
});
}
// Called to validate a comment before it's created
// Return { allowed: false, reason: "..." } to reject
export function validateComment(input: CommentInput, secrets: Secrets): ValidationResult {
// Example: Simple spam check
const spamWords = ["buy now", "click here", "free money"];
const isSpam = spamWords.some(word =>
input.content.toLowerCase().includes(word)
);
if (isSpam) {
return { allowed: false, reason: "Comment flagged as spam" };
}
return { allowed: true };
}
// Called to transform rendered HTML before display
export function renderContent(input: ContentRenderInput): ContentRenderOutput {
// Example: Add copy button to code blocks
const html = input.html.replace(
/<pre><code/g,
'<pre class="relative group"><button class="copy-btn">Copy</button><code'
);
return { html };
}