Public
Like
6
postherous
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data β all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v103View latest version
A modern blog platform inspired by Posterous that allows publishing posts via email.
Your email blog platform is fully functional! Send an email to start publishing.
- π§ Email-to-Publish: Send an email to publish posts instantly
- π¨ Multi-format Support: HTML and plain text posts
- π‘ RSS Feed: Full RSS 2.0 support for syndication
- π WebSub: Real-time feed updates via WebSub protocol (configured)
- π ActivityPub: Full federated social networking with followers, likes, and shares β
- π¦ AT Protocol: Bluesky integration for cross-platform syndication (configured)
- π SEO Friendly: Clean URLs with slugified titles
- π± Responsive Design: Mobile-first responsive interface with TailwindCSS
- β‘ Fast: Built on Val Town with SQLite storage and static HTML generation
- π No JavaScript: Pure HTML/CSS frontend for maximum performance
index.ts- Main Hono server with HTML generation and API routes βdatabase/- SQLite schema and query functions βservices/- External service integrations β
- Email trigger handler for processing incoming posts β
- Server-side HTML rendering with TailwindCSS β
- No client-side JavaScript dependencies β
- Fast loading and SEO optimized β
- Publish via Email: Send email to your Val Town email address
- View Blog: Visit your backend HTTP val URL
- RSS Feed: Access
/rssfor syndication - Individual Posts: Visit
/post/[slug]
See SETUP.md for detailed setup instructions and ACTIVITYPUB.md for ActivityPub federation details.
WEBSUB_HUB_URL- WebSub hub URLACTIVITYPUB_DOMAIN- Domain for ActivityPub federationATPROTO_HANDLE- AT Protocol handleATPROTO_PASSWORD- AT Protocol app password
GET /- Main blog interfaceGET /post/:slug- Individual post pageGET /rss- RSS 2.0 feedGET /api/posts- JSON API for postsGET /api/posts/:slug- JSON API for single postGET /websub- WebSub subscription endpointGET /.well-known/webfinger- WebFinger discovery for ActivityPub βGET /actor- ActivityPub actor document βGET /outbox- ActivityPub outbox (published activities) βGET /followers- ActivityPub followers collection βGET /following- ActivityPub following collection βPOST /inbox- ActivityPub inbox (processes Follow, Like, Announce, Undo) βGET /api/posts/:slug/activities- Get activity counts (likes, shares, replies) βGET /health- Health check
Use /test-publish.ts to create sample posts for testing.
Send an email like this:
To: your-email-val@val.town
Subject: My Amazing Blog Post
Body: <h2>Hello World!</h2><p>This post was published via email!</p>
The post will appear instantly on your blog with:
- Title: "My Amazing Blog Post"
- Slug: "my-amazing-blog-post"
- Content: Rendered HTML
- Author: Extracted from email address
- Edit HTML generation functions in
/backend/index.ts - Modify CSS styles in the
getCustomCSS()function - Update branding in HTML templates
- Configure federation services via environment variables
Posts are automatically syndicated to:
- RSS feed (always enabled)
- WebSub subscribers (if configured)
- ActivityPub followers (with full interaction support) β
- AT Protocol/Bluesky (if configured)
Your blog is now fully federated with ActivityPub! Users can:
- Follow your blog from Mastodon, Pleroma, and other ActivityPub platforms
- Like your blog posts (shows β€οΈ count on posts)
- Share/Boost your posts (shows π count on posts)
- Reply to your posts (shows π¬ count on posts)
Discovery formats:
- WebFinger:
@blog@your-domain.com - Direct actor URL:
https://your-domain.com/actor
Real-time interaction tracking:
- All likes, shares, and replies are stored and displayed on individual post pages
- Follower count is maintained and accurate
- Full ActivityPub inbox processing for Follow/Unfollow activities
Example: If your blog is at myblog.web.val.run, users can follow @blog@myblog.web.val.run from their Mastodon client and interact with your posts!
Ready to blog via email? Send your first post now! π§β¨