- Complete Astro + Alpine.js implementation - Docker Compose setup with Caddy reverse proxy - Dual platform: Anonymous & Named Storytellers - Interactive features: voting, comments, filtering - Categories page with search functionality - Content collections for markdown stories - Responsive design with accessibility features - Environment variable configuration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
story-teller.ink - Astro + Alpine.js Version
🏔️🚀 Lightning Fast Storytelling Platform
This is the Astro + Alpine.js implementation of story-teller.ink - a dual platform connecting seniors through storytelling with zero-JS-by-default performance and 15kb total JavaScript.
🎯 Why Astro + Alpine.js?
Performance for Seniors
- ~20kb total per story page (vs 300kb+ React)
- Instant story loading - static HTML with no hydration delay
- 15kb Alpine.js only loads for interactive features
- Works on ancient devices - no modern JS features required
Accessibility First
- HTML-first - stories load immediately, work with JS disabled
- Progressive enhancement - Alpine adds interactivity gracefully
- Screen reader perfect - semantic HTML from the start
- High contrast & reduced motion support built-in
Content Management
- Markdown stories - easy to write and maintain
- Content collections - organized by platform (nevertell/dignity)
- Static generation - stories become permanent web pages
- Type-safe frontmatter with Zod validation
🏗️ Architecture Overview
src/
├── content/
│ ├── nevertell/ # Anonymous stories (markdown)
│ │ ├── elvis-concert-1956.md
│ │ └── college-roommate-prank.md
│ └── dignity/ # Named stories (markdown)
│ ├── martha-navy-nurse.md
│ └── dorothy-civil-rights.md
├── pages/
│ ├── index.astro # Main landing page
│ ├── nevertell/
│ │ ├── index.astro # Anonymous story list + Alpine filtering
│ │ └── [slug].astro # Static story + Alpine comments
│ └── dignity/
│ ├── index.astro # Named story list
│ └── [slug].astro # Static story + Alpine interactions
├── layouts/
│ ├── BaseLayout.astro # Global Alpine.js setup
│ ├── NevertellLayout.astro
│ └── DignityLayout.astro
└── styles/
└── global.css # Tailwind + accessibility styles
🌟 Key Features
Dual Platform Architecture
- Anonymous Storytellers 🤫 - Anonymous stories with mischievous tone
- Named Storytellers 🏆 - Named stories with respectful tone
- Cross-platform promotion - community can encourage anonymous→named
Static + Interactive
- Static story pages load instantly
- Alpine.js islands for voting, comments, filtering
- Progressive enhancement - works without JavaScript
- Real-time interactions where needed
Senior-Optimized
- Large fonts (18px base, scalable to 20px+)
- 44px minimum touch targets for mobile
- High contrast mode support
- Keyboard navigation optimized
- Reduced motion preferences honored
🚀 Getting Started
Prerequisites
- Node.js 18+
- npm or yarn
Installation
cd story-bridge-astro
npm install
Development
npm run dev
# Visit http://localhost:4321
Build for Production
npm run build
npm run preview
📖 Content Management
Adding New Stories
Anonymous Story
---
# src/content/nevertell/new-story.md
title: "The Time I..."
excerpt: "Brief description..."
tags: ["1960s", "college", "pranks"]
location: "Senior Center, City State"
dateOfEvent: "Summer 1965"
upvotes: 0
promotionVotes: 0
publishedAt: 2024-01-20T00:00:00.000Z
commentCount: 0
---
Your amazing story content here in beautiful markdown...
Named Story
---
# src/content/dignity/new-story.md
title: "Hero's Journey"
excerpt: "Brief description..."
authorName: "John Smith"
authorAge: 87
tags: ["WWII", "service", "heroism"]
location: "Veterans Home, City State"
dateOfEvent: "1943-1945"
upvotes: 0
publishedAt: 2024-01-20T00:00:00.000Z
commentCount: 0
---
Their incredible story of service and sacrifice...
Content Validation
All story frontmatter is validated with Zod schemas in src/content/config.ts
.
⚡ Performance Metrics
Page Load Sizes
- Main page: ~25kb (HTML + CSS + 15kb Alpine)
- Story pages: ~20kb (mostly static HTML content)
- Story list: ~30kb (static HTML + Alpine filtering)
Performance Benefits
- 0ms hydration - stories load as static HTML
- Instant navigation - no client-side routing delays
- Offline reading - cached HTML works without connection
- SEO perfect - fully rendered HTML for search engines
🎨 Styling & Themes
Platform-Specific Themes
/* Anonymous Storytellers - playful, mischievous */
nevertell: {
primary: '#6366f1', // indigo
secondary: '#ec4899', // pink
accent: '#f59e0b', // amber
}
/* Named Storytellers - warm, respectful */
dignity: {
primary: '#059669', // emerald
secondary: '#dc2626', // red
accent: '#d97706', // amber
}
Accessibility Features
- Large fonts with scalable sizing
- High contrast mode support
- Reduced motion preferences
- Focus indicators for keyboard navigation
- Screen reader optimized markup
🌐 Deployment
Vercel (Recommended)
npm install -g vercel
vercel --prod
Netlify
npm run build
# Upload dist/ folder to Netlify
Static Hosting
npm run build
# Serve dist/ folder from any static host
Domain Configuration
Configure story-teller.ink
for hosting. The platform handles both anonymous and named storytellers on the same domain with different routes.
🔧 Alpine.js Features
Global Stores
// Utility functions available everywhere
Alpine.store('utils', {
formatDate(dateString),
formatRelativeTime(dateString),
truncateText(text, maxLength)
});
// API functions for voting and comments
Alpine.store('api', {
vote(storyId, type),
submitComment(storyId, content, authorName),
loadComments(storyId)
});
Interactive Components
- Story filtering with real-time search and tag selection
- Voting systems for upvotes and promotions
- Comment systems with threaded discussions
- Form validation and submission handling
🎯 Mission Statement
We're building bridges between the generation that invented rock & roll and the generation that invented the internet.
The Story Bridge Effect
- Stories flow out (resident → internet)
- Connections flow back (internet → resident)
- Social energy flows within (resident ↔ other residents)
🤝 Contributing
Adding Features
- Static content goes in
src/pages/
andsrc/content/
- Interactive features use Alpine.js data functions
- Maintain accessibility standards
- Test on mobile and with keyboard navigation
Content Guidelines
- Anonymous stories should be fun, engaging, authentic
- Named stories should be respectful, honoring, dignified
- All stories must have proper frontmatter and tags
- Excerpts should be compelling and draw readers in
📊 Analytics & Monitoring
Metrics to Track
- Story reading time (engagement)
- Comment engagement (community building)
- Cross-platform promotions (success indicator)
- Mobile vs desktop usage (senior preferences)
- Accessibility feature usage
Success Indicators
- Stories being shared outside the platform
- Comments creating real connections
- Anonymous stories being promoted to named storytellers
- Seniors discussing stories in their facilities
🔮 Future Enhancements
Planned Features
- RSS feeds for story subscriptions
- Story search with full-text indexing
- Related stories based on tags and themes
- Email notifications for story responses
- Print-friendly story formats
- Audio narration for accessibility
Technical Improvements
- Progressive Web App features
- Offline story caching
- Image optimization for story photos
- CDN integration for global performance
Built with ❤️ for the generation that has the best stories to tell.
Performance: Astro ⚡ Interactivity: Alpine.js 🏔️ Accessibility: Senior-first ♿
Description
Languages
Astro
91.8%
CSS
3.4%
JavaScript
2.6%
TypeScript
1.5%
Shell
0.4%
Other
0.3%