{"id":27885967,"url":"https://github.com/1999azzar/exposeur","last_synced_at":"2026-01-23T00:30:59.652Z","repository":{"id":290610102,"uuid":"936508332","full_name":"1999AZZAR/exposeur","owner":"1999AZZAR","description":"Flask-based content and team management platform that allows administrators to manage news articles, categories, users, team members, and more through a unified web interface with toast notifications for user feedback.","archived":false,"fork":false,"pushed_at":"2025-05-02T15:31:27.000Z","size":136356,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"beast","last_synced_at":"2025-05-05T07:54:02.308Z","etag":null,"topics":["content-management-system","website"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/1999AZZAR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-02-21T07:55:43.000Z","updated_at":"2025-05-02T15:31:31.000Z","dependencies_parsed_at":"2025-04-29T18:38:33.419Z","dependency_job_id":null,"html_url":"https://github.com/1999AZZAR/exposeur","commit_stats":null,"previous_names":["1999azzar/exposeur"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/1999AZZAR/exposeur","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1999AZZAR%2Fexposeur","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1999AZZAR%2Fexposeur/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1999AZZAR%2Fexposeur/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1999AZZAR%2Fexposeur/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/1999AZZAR","download_url":"https://codeload.github.com/1999AZZAR/exposeur/tar.gz/refs/heads/beast","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1999AZZAR%2Fexposeur/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28676145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T20:48:19.482Z","status":"ssl_error","status_checked_at":"2026-01-22T20:48:14.968Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["content-management-system","website"],"created_at":"2025-05-05T07:50:30.443Z","updated_at":"2026-01-23T00:30:59.631Z","avatar_url":"https://github.com/1999AZZAR.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exposeur\n\nExposeur is a Flask-based content and team management platform that allows administrators to manage news articles, categories, users, team members, and more through a unified web interface with toast notifications for user feedback.\n\n## Table of Contents\n1. [Features](#features)\n2. [Tech Stack](#tech-stack)\n3. [Prerequisites](#prerequisites)\n4. [Installation](#installation)\n5. [Configuration](#configuration)\n6. [Running the Application](#running-the-application)\n7. [Project Structure](#project-structure)\n8. [Key Components](#key-components)\n9. [API Endpoints](#api-endpoints)\n10. [Authentication \u0026 Authorization](#authentication--authorization)\n11. [Styling \u0026 UI](#styling--ui)\n12. [Toast Notifications](#toast-notifications)\n13. [Database \u0026 Migrations](#database--migrations)\n14. [Utility Scripts](#utility-scripts)\n15. [Deployment](#deployment)\n16. [Contributing](#contributing)\n17. [License](#license)\n\n## Features\n- Comprehensive news management: create, edit, delete articles; toggle visibility; advanced search and filtering by category and tags\n- Dynamic category management with drag-and-drop ordering\n- Robust user management with role-based access control (SUPERUSER, ADMIN, GENERAL)\n- Team member management for editorial and operational staff\n- Account management with password change and account deletion capabilities\n- YouTube video integration with video management features\n- Contact details management system\n- Comprehensive policy management (Privacy Policy, Media Guidelines, Vision/Mission)\n- Real-time user feedback via toast notifications\n- Secure file uploads with image validation\n- RESTful API with JSON responses and CSRF protection\n- Dynamic sidebar navigation based on user role\n- Consistent white-card UI design across all settings pages\n\n## Tech Stack\n- Python 3.x\n- Flask (Web Framework)\n- Flask-Login (Authentication)\n- Flask-Migrate (Database migrations)\n- Flask-WTF (Form handling)\n- Flask-SQLAlchemy (ORM)\n- Flask-CORS (Cross-origin resource sharing)\n- Jinja2 (Template engine)\n- Tailwind CSS (Styling)\n- JavaScript (ES6+)\n- Alembic (Database migrations)\n- Gunicorn (Production WSGI server)\n\n## Prerequisites\n- Python 3.8+\n- pip\n- SQLite (default) or configure another database via `DATABASE_URI`\n\n## Installation\n1. Create and activate virtual environment:\n```bash\npython -m venv .venv\nsource .venv/bin/activate  # On Windows: .venv\\Scripts\\activate\n```\n\n2. Install dependencies:\n```bash\npip install -r requirements.txt\n```\n\n## Configuration\n1. Copy `.env.example` to `.env` (or create `.env`).\n2. Set environment variables:\n```env\nSECRET_KEY=your_secret_key\nDATABASE_URI=sqlite:///exposeur.db\nFLASK_ENV=development\n```\n\n## Running the Application\n```bash\npython main.py\n```\nOpen `http://127.0.0.1:5000` in your browser.\n\n## Project Structure\n```\nexposure/\n├── main.py              # Application entrypoint\n├── models.py            # SQLAlchemy models\n├── routes/              # Flask route blueprints\n│   ├── __init__.py      # Blueprint initialization\n│   ├── routes_auth.py   # Authentication routes\n│   ├── routes_news.py   # News routes\n│   ├── routes_public.py # Public routes\n│   └── ...              # Other routes\n├── requirements.txt     # Python dependencies\n├── passenger_wsgi.py    # Passenger WSGI entrypoint\n├── static/              # Static assets\n│   ├── css/             # Stylesheets\n│   ├── js/              # JavaScript files (toast.js, sidebar-toggle.js, etc.)\n│   ├── pic/             # Static images\n│   └── uploads/         # Uploaded assets\n├── templates/           # Jinja2 templates\n│   ├── public/          # Public-facing templates\n│   ├── admin_base.html  # Dynamic sidebar template (role-based navigation)\n│   ├── base.html        # Base template\n│   └── settings/        # Admin/settings templates\n│       ├── account_management.html\n│       ├── categories_management.html\n│       ├── users_management.html\n│       ├── team_members_management.html\n│       ├── youtube_management.html\n│       └── ...         # Other settings pages\n├── instance/           # Instance folder (created by Flask)\n├── helper/             # Data seeding scripts\n│   ├── generate_user.py    # Create test users\n│   ├── add_fake_news.py    # Seed news items\n│   ├── add_fake_images.py  # Download placeholder images\n│   ├── add_videos.py       # Seed YouTube videos\n│   ├── add_categories.py   # Create default categories\n│   └── init_footer_data.py # Populate policy data\n├── .env                # Environment variables\n└── .env.example        # Example environment variables\n```\n\n## Key Components\n- `main.py`: initializes Flask app, extensions, context processors, and registers blueprints.\n- `models.py`: defines database models (User, News, Category, TeamMember, etc.).\n- `routes/`: blueprint `main_blueprint` handles public routes and `/settings/*` CRUD operations.\n- `templates/`: Jinja2 templates using Tailwind utility classes for consistent white-card UI.\n- `static/js/toast.js`: global `showToast()` function for toast notifications.\n\n## API Endpoints\n- `GET /api/news`             : List all news articles (supports query params: `search`, `category`, `tag`, `status`, etc.)\n- `POST /api/news`            : Create a new article (JSON: `title`, `content`, `category_id`, `tags`).\n- `PATCH /api/news/\u003cid\u003e`      : Update article fields or toggle visibility via `/visibility` endpoint.\n- `DELETE /api/news/\u003cid\u003e`     : Remove an article permanently.\n- `GET /api/categories`       : List all categories.\n- `POST /api/categories`      : Add a new category.\n- `PATCH /api/categories/\u003cid\u003e`: Update category name or order.\n- `DELETE /api/categories/\u003cid\u003e`: Delete a category.\n- `GET /api/users`            : List all users.\n- `POST /api/users`           : Create a new user (JSON: `username`, `password`, `role`).\n- `PATCH /api/users/\u003cid\u003e/status`: Toggle user active/inactive.\n- `PATCH /api/users/\u003cid\u003e/verify`: Toggle user verified status.\n- `PATCH /api/users/\u003cid\u003e`     : Update user details.\n- `DELETE /api/users/\u003cid\u003e`    : Delete a user account.\n- `GET /api/team_members`     : List all team members.\n- `POST /api/team_members`    : Add a new team member.\n- `PATCH /api/team_members/\u003cid\u003e`: Update member fields (name, title, order, active).\n- `DELETE /api/team_members/\u003cid\u003e`: Remove a team member.\n\n## Authentication \u0026 Authorization\n- Flask-Login for session management.\n- Roles: `SUPERUSER`, `ADMIN`, `GENERAL` via `UserRole` enum.\n- `login_required` decorator on protected views.\n- `current_user.is_owner()` guard for owner-only sections like team members.\n\n## Styling \u0026 UI\n- Consistent white-card design with subtle shadows and rounded corners.\n- Headings: `text-xl font-semibold text-gray-900`.\n- Inputs: `w-full bg-white border-gray-300 p-2 rounded-lg focus:ring-2 focus:ring-blue-400`.\n- Buttons: `w-full bg-yellow-500 text-gray-900 py-3 rounded-lg font-semibold hover:bg-yellow-400 focus:outline-none focus:ring-2 focus:ring-yellow-300`.\n\n## Toast Notifications\n- Unified notifications for all CRUD actions; uses `showToast(type, message)`.\n- Flash messages from Flask are passed via `get_flashed_messages` in templates.\n- **Customization**: adjust duration and position in `static/js/toast.js`:\n  ```js\n  // default: duration 5000ms, position top-right\n  showToast('success', 'Message', { duration: 3000, position: 'bottom-left' });\n  ```\n- CSS classes available: `.toast-success`, `.toast-error`, `.toast-info`, `.toast-warning`.\n\n## Database \u0026 Migrations\n- Managed with Flask-Migrate and Alembic under the `migrations/` folder.\n- Initialize/revision/upgrade:\n  ```bash\n  # Set up environment\n  export FLASK_APP=main.py\n  export FLASK_ENV=development\n\n  # Initialize migrations (only once)\n  flask db init\n\n  # Create and apply migrations\n  flask db migrate -m \"\u003cmessage\u003e\"\n  flask db upgrade\n  ```\n- Connection URI configured via `DATABASE_URI` in `.env` (defaults to SQLite).\n\n## Utility Scripts\nThe `helper/` directory provides data-seeding scripts:\n- `generate_user.py`    : Create test users with various roles.\n- `add_fake_news.py`    : Seed news items using Faker library.\n- `add_fake_images.py`  : Download and attach placeholder images.\n- `add_videos.py`       : Seed YouTubeVideo entries.\n- `add_categories.py`   : Create default category set.\n- `init_footer_data.py` : Populate PrivacyPolicy, MediaGuideline, VisiMisi, Penyangkalan, PedomanHak default data.\n\n## Deployment\n- For production, serve with Gunicorn behind a reverse proxy:\n  ```bash\n  gunicorn --bind 0.0.0.0:8000 main:app\n  ```\n- Configure environment variables (`SECRET_KEY`, `DATABASE_URI`, `FLASK_ENV=production`).\n- Use a process manager (systemd or Docker) to ensure uptime.\n\n## Contributing\n1. Fork the repository.\n2. Create a feature branch (`git checkout -b feature/name`).\n3. Commit your changes (`git commit -m \"feat: description\"`).\n4. Push to branch (`git push origin feature/name`).\n5. Create a Pull Request.\n\n## License\nThis project is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1999azzar%2Fexposeur","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F1999azzar%2Fexposeur","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1999azzar%2Fexposeur/lists"}