No description
- PHP 57.3%
- Twig 32.1%
- JavaScript 7.4%
- Dockerfile 2%
- SCSS 1.2%
| .github | ||
| .vscode | ||
| assets | ||
| bin | ||
| config | ||
| docker | ||
| migrations | ||
| public | ||
| src | ||
| templates | ||
| tests | ||
| translations | ||
| .dockerignore | ||
| .editorconfig | ||
| .env.dev | ||
| .env.sample | ||
| .gitignore | ||
| .nvmrc | ||
| compose.override.yaml | ||
| compose.yaml | ||
| composer.json | ||
| composer.lock | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| phpunit.dist.xml | ||
| README.md | ||
| symfony.lock | ||
| webpack.config.js | ||
cyrleb.dev
Overview
This Symfony 7 blog publishes long-form posts and short tips about privacy-friendly tools, ad-blocking and anti-advertisement tools, self-hosting and homelabbing, development, and adjacent topics (security, open-source, digital minimalism, and indie web). The site is meant to be privacy-first and lightweight.
Audience
- Self-hosters, homelabbers, privacy-conscious users
- Developers interested in tooling, automation, and self-hosted alternatives
- People looking to reduce advertising and tracking in their online life
Content categories
- Reviews (tools, services)
- Tutorials / How-tos (setup, deployment)
- Tips & Tricks (short actionable items)
- News & Updates (project announcements, upstream changes)
- Showcases (config repos, dotfiles, homelab layouts)
- Opinion & Essays (deep dives into privacy philosophy)
- Comparisons (self-hosted vs SaaS, tool comparisons)
Core Requirements
Functional features
- Posts: rich content with title, short summary, body (Markdown support), categories, tags, featured image, publish date
- Pages: static pages (About, Contact, Privacy Policy)
- Taxonomy: categories (primary) and tags (many-to-many)
- Drafts and scheduled publishing
- Auto-saving drafts
- Editor: WYSIWYG editor provided by EasyAdminBundle with Markdown support, preview, syntax highlighting for code blocks
- Search: full-text search of posts (title, summary, body) with filters by tag/category/date
- RSS/Atom feeds for posts and categories
- Sitemap generation for SEO
- Email newsletter integration (subscribe/unsubscribe flows) with double opt-in support (integration points, optional)
- Related posts recommendations (tags/categories similarity)
- Tags & category listing pages (with pagination)
- Pagination on index and archive pages
- Admin area with authentication to create/edit/publish posts (provided by EasyAdminBundle)
- Analytics: optional, privacy-friendly analytics (Plausible/Simple Analytics/Matomo self-hosted or server-side logs); ability to opt out entirely
- Rate limiting and protections for forms (contact, comments)
- Canonical URLs and redirects management
Non-functional features
- Privacy-first by default: no third-party trackers enabled, clear privacy policy, minimal cookies, respect Do Not Track when reasonable
- Accessibility (WCAG AA) and responsive design
- Performance: fast initial load, caching (HTTP cache + Redis/memcached optional), critical CSS, asset minification
- Low infrastructure costs: support for self-hosting on modest hardware (Raspberry Pi, VPS)
- Internationalization (i18n) ready (content primary language English but translatable strings)
- Security: strong password policies, rate-limiting, CSRF protection, XSS prevention, input sanitization, content Security Policy (CSP)
- Backups and migrations for data and media
Data model (high-level)
- User
- id, username, email (optional public), role(s), passwordHash, avatarPath, socialLinks, createdAt
- Post
- id, slug, title, summary, body (Markdown / HTML), status (draft/published/scheduled/archived), featuredImage, publishedAt, updatedAt
- Category
- id, name, slug, description
- Tag
- id, name, slug
- Comment (optional)
- id, postId, authorName, authorEmail (optional), body, status (pending/approved/spam), createdAt
- Media
- id, path, originalFilename, mimeType, width, height, uploadedAt
API and Endpoints (suggested)
Public routes
- GET / - recent posts (paginated)
- GET /posts/{slug} - single post
- GET /category/{slug} - posts in category
- GET /tag/{slug} - posts with tag
- GET /author/{username} - author page
- GET /feed.xml - RSS/Atom
- GET /sitemap.xml - sitemap
Security & Privacy Specs
- Default: no analytics, no third-party embeds that track users
- For embeds (YouTube, Twitter): either use privacy-enhanced placeholders or a consent gate to load them
- Strict CSP with ability to relax for certain pages where the author intentionally embeds content
- Email addresses should not be stored in public-facing fields unless consented; consider hashing or obfuscation
- Use secure cookies, HTTPS only in production, and HSTS
Deployment and Operations
- Docker Compose example (optional) for self-hosting stacks (app, database, redis)
- Optional small VPS / Raspberry Pi deployment guide
- Backups: database dumps and media sync to remote storage (SFTP/rsync or object store)
- Monitoring: basic health checks, error reporting (Sentry optional)
Prioritized feature roadmap (MVP → v1 → v2)
MVP
- Static pages, posts (Markdown), categories/tags, basic admin editor, publish/draft, RSS feed, sitemap, privacy policy page, responsive theme, simple search (SQL LIKE)
v1
- Full-text search (Elasticsearch/Meilisearch), image optimization and responsive images, scheduled publishing, roles, comments (privacy-first), export/import Markdown, newsletter integration
v2
- Social features (bookmarks, likes), multi-author workflows, advanced recommendations, native mobile PWA, multi-language content
Integrations and third-party options
- Admin UI: EasyAdminBundle for rapid admin backend scaffolding and management (users, posts, categories, tags, media)
- Search: Meilisearch, ElasticSearch
- Analytics: Plausible, Simple Analytics, Matomo self-hosted
- Comments: Staticman, Gödel, Isso, Remark42, Disqus (not recommended by default)
- Newsletter: Mailgun, Postmark, listmonk self-hosted
- Media: imgproxy, Thumbor, Cloudflare Images (optional)
Developer notes
- Use Symfony 7, Doctrine ORM, Twig templates, Vite for assets, and PHPUnit for tests
- Write end-to-end tests for publishing flow and public post rendering
- Keep code modular: Content domain isolated from presentation
- Provide CLI commands to create posts and rebuild indexes
Next steps
- Review this specification and mark must-have vs nice-to-have features
- Sketch the data model and seed with example content
- Implement MVP: post model, editor (Markdown), admin, public views, RSS