DEV Community

sneh1117
sneh1117

Posted on • Edited on

I Wanted to Go Beyond "Todo App" — So I Built This Instead

I wanted to go beyond a basic CRUD app.

So I built StitchTales — a full-stack blogging platform designed for creators to publish tutorials and stories, complete with authentication, REST APIs, image storage, visitor analytics, and production deployment.

🔗 Live: https://stitchtales.onrender.com/
🔗 GitHub: https://github.com/sneh1117/stitchtales


🏗 Tech Stack

  • Django 5.2
  • Django REST Framework
  • PostgreSQL (Railway)
  • Supabase Storage (custom backend)
  • HTMX
  • Whitenoise
  • django-allauth
  • Token + session + OAuth authentication

✨ What It Supports

  • Full blog CRUD with draft → publish workflow
  • Slug-based URLs + SEO fields
  • Categories, tags, view tracking
  • Comment moderation + like system (HTMX)
  • Profile system with avatars + social links
  • Google OAuth — login and register via Google account
  • Post-OAuth profile completion flow (username + avatar + bio)
  • Custom visitor analytics — unique visitors, top countries, referrers
  • Public REST API with permission control
  • Production-ready deployment on Railway

🔌 API Design

GET    /api/posts/
GET    /api/posts/<slug>/
POST   /api/posts/
PUT    /api/posts/<slug>/
DELETE /api/posts/<slug>/
POST   /api/auth/token/
Enter fullscreen mode Exit fullscreen mode

Design decisions:

  • Public read access
  • Authenticated write access
  • Author-only updates/deletes
  • Slug-based lookups instead of IDs
  • Pagination enabled

🖼 Why Supabase Instead of S3?

Instead of AWS, I built a custom Django storage backend for Supabase.

This required:

  • Understanding Django's storage API
  • Handling server-side uploads securely
  • Generating public CDN URLs
  • Structuring bucket organization cleanly

It kept the stack simple while still being production-capable.


⚡ Why HTMX Instead of React?

I intentionally avoided a heavy frontend framework.

HTMX gave me:

  • Dynamic likes without reload
  • Cleaner backend focus
  • Simpler architecture
  • Faster development

Right tool for the project size.


🔐 Google OAuth — Beyond Basic Auth

After shipping the core platform I added Google OAuth using django-allauth.

This wasn't just dropping in a library. It required:

  • Configuring OAuth credentials in Google Cloud Console
  • Handling the redirect_uri_mismatch between local and production environments
  • Overriding allauth's default signup template to match the site's theme
  • Building a custom "Complete Your Profile" flow — after Google consent, new users pick a username, upload an avatar, and add a bio before landing on the site
  • Auto-connecting existing email accounts to Google via SOCIALACCOUNT_EMAIL_AUTHENTICATION_AUTO_CONNECT
  • Forcing the account picker on every login with prompt: select_account
  • Fixing the https vs http callback mismatch in production using ACCOUNT_DEFAULT_HTTP_PROTOCOL

The result is a smooth 3-step flow: click Google → consent screen → profile setup → home.


📊 Custom Visitor Analytics

I built a lightweight analytics system entirely in Django — no third-party tools.

How it works:

  • A custom middleware (VisitorTrackingMiddleware) intercepts every GET request
  • It records IP, path, referrer, and uses a free geolocation API to resolve country + city
  • Staff visits and excluded IPs are automatically filtered out
  • Data is stored in a Visitor model and surfaced in the admin + dashboard

What the superuser dashboard shows:

  • Total visits and unique visitors
  • Visits today
  • Top countries by traffic
  • Top referrers (how people find the site)
  • Most visited pages

This gave me real insight into traffic without handing data to Google Analytics.


🧠 Production Considerations

  • Environment-based configuration via python-decouple
  • SQLite locally, PostgreSQL in production
  • CSRF + trusted origins configured
  • DEBUG=False in production
  • Whitenoise for static files
  • collectstatic runs automatically on every Railway deploy
  • Sitemap + robots.txt for SEO
  • Site domain auto-configured on each deploy via Railway start command

I treated it like a real deployment — not just a localhost demo.


🚀 What I'd Add Next

  • Automated tests
  • CI/CD pipeline
  • Redis caching
  • Rate limiting
  • Structured logging
  • Email notifications for comments

🎯 Why This Project Matters

This wasn't about crochet.

It was about demonstrating:

  • Clean backend architecture
  • Thoughtful API design
  • External storage integration
  • Third-party OAuth integration in production
  • Custom middleware and analytics without external dependencies
  • Production deployment awareness
  • Full-stack decision-making under real constraints

If you're hiring for a backend or full-stack role, I'd love feedback.

— Sneha

Top comments (2)

Collapse
 
anmolbaranwal profile image
Anmol Baranwal

nice, it doesn't load by the way -- must be some issue with render

Collapse
 
sneh1117 profile image
sneh1117

yeah you are right !!you have to reload it multiple times as it sleeps after 15 minutes of inactivity!! previously i had it set up perfectly on railway but my one month trial got over and i wanted to make sure it remained completely free for me to host