{"id":28154603,"url":"https://github.com/timonrieger/blog-boiler-pro","last_synced_at":"2026-02-19T16:33:58.658Z","repository":{"id":287865420,"uuid":"913995607","full_name":"timonrieger/blog-boiler-pro","owner":"timonrieger","description":"Flask boilerplate for creating an advanced database-based blog.","archived":false,"fork":false,"pushed_at":"2025-04-14T10:18:04.000Z","size":19353,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-12T12:14:24.036Z","etag":null,"topics":["blog","boilerplate","database","flask","template"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timonrieger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-01-08T18:41:14.000Z","updated_at":"2025-04-14T10:18:08.000Z","dependencies_parsed_at":"2025-04-14T11:39:54.803Z","dependency_job_id":null,"html_url":"https://github.com/timonrieger/blog-boiler-pro","commit_stats":null,"previous_names":["timonrieger/blog-boiler-pro"],"tags_count":10,"template":true,"template_full_name":null,"purl":"pkg:github/timonrieger/blog-boiler-pro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timonrieger%2Fblog-boiler-pro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timonrieger%2Fblog-boiler-pro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timonrieger%2Fblog-boiler-pro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timonrieger%2Fblog-boiler-pro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timonrieger","download_url":"https://codeload.github.com/timonrieger/blog-boiler-pro/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timonrieger%2Fblog-boiler-pro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29622019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T13:04:20.082Z","status":"ssl_error","status_checked_at":"2026-02-19T13:03:33.775Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blog","boilerplate","database","flask","template"],"created_at":"2025-05-15T06:14:03.954Z","updated_at":"2026-02-19T16:33:58.624Z","avatar_url":"https://github.com/timonrieger.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch2 align=\"center\"\u003eBlog Boiler Pro\u003c/h2\u003e\n\u003cp align=\"center\"\u003eA lightweight Flask-based boilerplate for creating an advanced blog with database storage.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/status-no%20further%20development-blue\"/\u003e\n\u003cimg src=\"https://img.shields.io/github/license/timonrieger/blog-boiler-pro\n\"\u003e\n\u003cimg src=\"https://img.shields.io/github/last-commit/timonrieger/blog-boiler-pro\n\"\u003e\n\u003cimg src=\"https://img.shields.io/github/languages/top/timonrieger/blog-boiler-pro\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/code_style-black-black\"/\u003e\n\u003c/p\u003e\n\n\u003ctable\u003e\n\t\u003ctbody\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd width=\"14.3%\"\u003e\n\t\t\t\tHome\n\t\t\t\t\u003cimg src=\".github/demo/home.png\"\u003e\n\t\t\t\u003c/td\u003e\n         \u003ctd width=\"14.3%\"\u003e\n\t\t\t\tLogin\n\t\t\t\t\u003cimg src=\".github/demo/login.png\"\u003e\n\t\t\t\u003c/td\u003e\n         \u003ctd width=\"14.3%\"\u003e\n\t\t\t\tRegister\n\t\t\t\t\u003cimg src=\".github/demo/register.png\"\u003e\n\t\t\t\u003c/td\u003e\n         \u003ctd width=\"14.3%\"\u003e\n\t\t\t\tPost Page\n\t\t\t\t\u003cimg src=\".github/demo/post.png\"\u003e\n\t\t\t\u003c/td\u003e\n\t\t\t\u003ctd width=\"14.3%\"\u003e\n\t\t\t\tComment View\n\t\t\t\t\u003cimg src=\".github/demo/comments.png\"\u003e\n\t\t\t\u003c/td\u003e\n         \u003ctd width=\"14.3%\"\u003e\n\t\t\t\tPost Panel\n\t\t\t\t\u003cimg src=\".github/demo/panel.png\"\u003e\n\t\t\t\u003c/td\u003e\n         \u003ctd width=\"14.3%\"\u003e\n\t\t\t\tAuthor Page\n\t\t\t\t\u003cimg src=\".github/demo/author.png\"\u003e\n\t\t\t\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\n\n## Intention\n\nThis project is a advanced blog implementation, designed for users who prefer a more complete solution. If you don't require features like user management, an admin interface, or database storage, consider checking out [the lite version](https://github.com/timonrieger/blog-boiler-lite).\n\n## Demo\n\nI [extended and customised](https://github.com/timonrieger/blog) this template myself for [my personal blog](https://blog.timonrieger.de/). Check it out, to see it in action!\n\n## Features\n\n- **Create, Edit, Draft, Preview and Delete Blog Posts:** Easily manage blog content with intuitive CRUD operations with database storage.\n- **Pagination:** View posts with pagination for better navigation and user experience.\n- **User-Friendly Text Editor:** A simple and intuitive editor for creating and editing blog posts provided by CKEditor 4.\n- **Responsive Design with Bootstrap:** The site automatically adjusts to various screen sizes and devices for seamless usability.\n- **Collaboration Support:** Give admin access to co-authors to collaborate on the blog.\n- **Secure, SEO Optimized, and Fast:** Optimized for performance and search engine visibility according to [Checkbot](https://checkbot.io/).\n- **Customizable About Page:** Personalize an \"About\" page for each author to share their story or expertise.\n- **User Management:** Basic functionality to manage users: registration, login, anonymous users, and admin management.\n- **Admin Privileges:** Assign co-authors the admin role to write, edit, delete their blog posts and all comments. You remain the Super Admin.\n- **Multi Language Support:** Use the language your are writing in for the whole application (\u003ca href=\"#multi-language-support\"\u003eRead on\u003c/a\u003e)\n- **Commenting System:** Users can publish and edit comments on posts, with moderation capabilities for the comment author and admins.\n- **Soft deletion with undo option**: Deleting posts and comments does not erase them entirely, but rather flag and hide them. \n- **Filter by tag, author and year**: Posts can be filtered by tag, author and year to narrow down the results.\n- **RSS Support**: Auto-generated RSS feed, which users can subscribe to with their RSS-Reader to receive new posts comfortably.\n- **HTTP/Browser Caching Strategy**: Invalidates the browser cache for changed content, else uses the cached version.\n\n## Limitations\n\n- No extension or plugin system\n- No analytics by default (which I regard as positive)\n- No file upload\n- No account settings for users, like confirmation email or password reset ([add an authentication microservice](https://github.com/timonrieger/auth-service))\n\n## Setup\n\n1. **Clone the repository**\n   ```\n   git clone https://github.com/timonrieger/blog-boiler-pro.git\n   ```\n\n2. **Navigate to the project directory**\n   ```\n   cd blog-boiler-pro\n   ```\n\n3. **Create a virtual environment**\n   ```\n   python -m venv venv\n   ```\n\n4. **Activate the virtual environment**\n   - On Windows:\n     ```\n     venv\\Scripts\\activate\n     ```\n   - On macOS/Linux:\n     ```\n     source venv/bin/activate\n     ```\n\n5. **Install the required dependencies**\n   ```\n   pip install -r requirements.txt\n   ```\n\n6. Set the required **environment variables** in a `.env` at the root directory. \n   ```\n   SECRET_KEY=yoursecretkey\n   DB_URI=postgresql://username:password@host:port/db\n   ANONYMOUS_ID=1 # register the first user with username \"anonymous\" or similar for letting users comment anonymously\n   SUPER_ID=2 # register yourself, set as admin in the database and define your ID in the `.env`\n   ```\n\n7. **Run the application**\n   ```\n   python -m main\n   ```\n   Now go to http://127.0.0.1:5000/ and register the first two users (anonymous and yourself) as mentioned in step 6\n\n## Your First Blog Post\n1. **Create a New Blog Post**\n   - Go to http://127.0.0.1:5000/new after logging in with your account. This will open the form to write a new blog post.\n   - Fill the form with your content.\n\n2. **Add Images to Your Blog Post**\n   - Upload your image to the `static/uploads/` directory.\n   - To display the image in the blog post, use the following HTML code in your post content or add the URL in CKEditors image interface:\n     ```\n     \u003cp\u003e\u003cimg alt=\"\" src=\"/static/uploads/2.png\" style=\"height:100%; width:100%\" /\u003e\u003c/p\u003e\n     ```\n   \n3. **Set Blog Image URL**\n    - For the field `Blog Image URL` field, use the path of the uploaded image, e.g., `/static/uploads/3.png`.\n\n\n4. **Submit the form**\n\n\u003e **Warning**: Before submitting the form, copy the source HTML code to avoid data loss in case application fails. You can usually go back in the browser to load the filled form again, though.\n\n\n## Configuration\n\n1. **Add Images**  \n   Add the images you want to use in the `static/uploads/` directory with your image files (I personally name the files with [autoincrementing numbers](https://github.com/timonrieger/blog/tree/main/static/uploads)).\n\n2. **Modify Static Assets**  \n   Feel free to modify the following directories and files:\n   - `static/assets/img/` (for images)\n   - `static/assets/favicon.ico` (for the site favicon)\n\n3. **Modify SEO contents**  \n   Replace the contents at the top of each file in the `templates/`\n   directory to reflect your content.\n\n4. **Edit author pages**  \n   Edit the contents in the author files in `templates/authors/`. Change the name of the file to the username you registered as well as the profile picture in `static/assets/img/`, e.g. John Doe \u003e `john-doe.html` and `john-doe.jpg`\n\n5. **Update the `src/config.py` configuration file**\n   - `LANGUAGE`: Your blog should be in a different language than English? \u003ca href=\"#multi-language-support\"\u003estart here\u003c/a\u003e\n   - `DISPLAY_READING_TIME`: Show the approximate reading time on each post (True/False).\n   - `DISPLAY_EDIT_DATE`: Show the edit date if you edited the post body (True/False).\n   - `DRAFT_ON_DEFAULT`: Sets the checkbox to publish as draft in the post form on default (True/False).\n   - `LEVEL_ADMINS`: Whether all admins have should have all right. Useful if you work together and trust each other. (True/False)\n   - `TIMEZONE_OFFSET`: Set the offset to UTC (e.g. for New York -5) (± number)\n   - `DATE_FORMAT`: The format for dates (used everywhere except comments) (valid datetime format).\n\n      =\u003e [Datetime Format Guide](https://www.pythonmorsels.com/strptime/) and [Date Format Patterns](https://unicode.org/reports/tr35/tr35-dates.html#date-format-patterns)\n   - `CHECK_EMAIL`: Whether to check if the email is valid/delivarable (True/False)\n   - `IMAGES_FOLDER`: The path to your images folder (path).\n   - `POSTS_PER_PAGE`: Number of posts on the home route before displaying pagination buttons (integer).\n   - `NR_RELATED_POSTS`: Number of related (same tags) posts at the end of a post\n   - `COMMENT_RICH_EDITOR`: \n      - `True`: Uses a rich text editor (Ckeditor) for comments, making it easy for users to format content, but may increase the risk of misuse.  \n      - `False`: Uses a plain text area. HTML is still allowed, but the user experience is simpler.\n   - `SHOW_COMMENT_TUTORIAL` : \n      Controls whether the `How to comment` tutorial link is shown.  \n      - Links to: [Tutorial Image](/.github/demo/comments.png)  \n      - `True`: Displays the tutorial link.\n      - `False`: Hides the tutorial link.\n   - `BLOG_NAME`: The name of your blog (string).\n   - `BLOG_TITLE`: The title that shows up on search machines for the home page (string).\n   - `BLOG_DESCRIPTION`: The description that shows up on search machines for the home page (string).\n\n\n\n## Multi-Language Support\n\nThe blog currently supports **English** (`en`) and **German** (`de`).\n\nWhen setting up your blog, you can define the default language for your application. The intent is not for users to switch between languages dynamically but to ensure that application texts align with the language you are writing in.\n\n### Contribute a New Language\nIf you'd like to contribute a new language you're fluent in, feel free to submit a Pull Request (PR) containing the translated `message.po` file for that language. Your contribution is highly appreciated! Note that there are approximately **75 phrases/sentences** to translate, making it a manageable task.\n\n### Using a Different Language Without Translating\n\nIf you'd rather use a different language without contributing translations, start by following the instructions in the section [Compile the Language](#compile-the-language).\n\n### Translating a Language\n\nIf you'd like to help translate, follow these steps:\n\n1. Navigate to the project root.\n\n   ```bash\n   cd /path/to/project\n\n### Get all languages available\n```bash\nfind translations -mindepth 1 -maxdepth 1 -type d\n```\n\n### Get all strings for translation\nExtracts all translateable strings from the `.html` and `.py` files into `message.pot`.\n```bash\npybabel extract -F babel.cfg -k lazy_gettext -o translations/messages.pot .\n```\n\n### a) Initialize a language (ONLY ONCE)\n```bash\npybabel init -i translations/messages.pot -d translations -l LANG_LOCAL\n```\n\n### b) Update a language\n```bash\npybabel update -i translations/messages.pot -d translations\n```\n\n### Translate \nWe have to translate manually, but you can start out with [Deepl in VSCode](https://marketplace.visualstudio.com/items?itemName=soerenuhrbach.vscode-deepl). We use common not highly formal language.\n\nFill the `msgstr \"\"` in the `LANG_LOCAL/LC_MESSAGES/messages.po` with the translation. Check existing languages if you're lost.\n`⌘F` and search for the term `fuzzy` and delete it ([docs](https://python-babel.github.io/flask-babel/#translating-applications)).\n\n### Compile the language\nCompiles all languages for usage.\n```bash\npybabel compile -f -d translations\n```\n\n### Apply and reload\nIn `src/config.py` change `LANGUAGE` to the language locale you want, then run:\n```bash\npython -m main\n```\n\n## Roles\nThere are five types of users:\n- Non logged in users: `read` access\n- Anonymous user: as above + `write:comment`\n- Logged in users: as above + `delete:own_comment`\n- Admin user: as above + `write:post`, `edit:own_post`, `delete:own_post`\n- Super admin (only one, YOU): full access (can delete, edit, write anything)\n   \n   =\u003e you can level all admins to the super admin role (see \u003ca href=\"#configuration\"\u003econfiguration section\u003c/a\u003e)\n\n## Endpoints\n\n- **Home**: `/` - View all blog posts.\n- **Show Post**: `/\u003cpost_title\u003e` - View a single blog post. Add comment logic here as well.\n- **New Post**: `/new` - Create a new blog post.\n- **Edit Post**: `/\u003cpost_title\u003e/edit` - Edit an existing blog post.\n- **Delete Post**: `/\u003cpost_title\u003e/delete` - Soft deletes a single blog post.\n- **Restore Post**: `/\u003cpost_title\u003e/restore` - Restores/Unhides a single blog post. \n- **Delete Comment**: `/\u003cpost_title\u003e/delete/comment/\u003cint:comment_id\u003e` - Soft deletes a single comment.\n- **Restore Comment**: `/\u003cpost_title\u003e/restore/comment/\u003cint:comment_id\u003e` - Restores/Unhides a single comment. \n- **Show Author** - `/author/\u003cauthor\u003e` - View an author's page.\n- **Login**: `/login` - Login as a user or anonymously.\n- **Register**: `/register` - Register a user.\n- **Logout**: `/logout` - Logout a user.\n- **RSS**: `/feed`, `/rss` and `/rss.xml` - Load blog feed users can subscribe to.\n\n## Requirements\n\n- Python 3.x\n- The following Python packages (as listed in `requirements.txt`)\n- A hosting service to deploy your blog to ([Vercel](https://vercel.com/), [Render](https://render.com/) etc.)\n- A database ([Supabase](https://supabase.com/) is free)\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimonrieger%2Fblog-boiler-pro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimonrieger%2Fblog-boiler-pro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimonrieger%2Fblog-boiler-pro/lists"}