{"id":26295549,"url":"https://github.com/seapagan/django-projects","last_synced_at":"2026-04-12T03:03:49.404Z","repository":{"id":282476177,"uuid":"948674587","full_name":"seapagan/django-projects","owner":"seapagan","description":"A developers profile web page to show off your favourite projects. Each project shows live GitHub stats. Uses Django, Tailwind, HTMX and Alpine.js","archived":false,"fork":false,"pushed_at":"2026-02-05T20:49:21.000Z","size":678,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-06T06:22:15.634Z","etag":null,"topics":["alpinejs","django","github-api","htmx","python","shadcn","tailwindcss"],"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/seapagan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"seapagan","ko_fi":"grantramsay","buy_me_a_coffee":"seapagan"}},"created_at":"2025-03-14T18:49:01.000Z","updated_at":"2026-02-05T20:48:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"a068d45a-757c-4ffc-97b7-75d9466aa8c3","html_url":"https://github.com/seapagan/django-projects","commit_stats":null,"previous_names":["seapagan/django-projects"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/seapagan/django-projects","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seapagan%2Fdjango-projects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seapagan%2Fdjango-projects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seapagan%2Fdjango-projects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seapagan%2Fdjango-projects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seapagan","download_url":"https://codeload.github.com/seapagan/django-projects/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seapagan%2Fdjango-projects/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31702582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"online","status_checked_at":"2026-04-12T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["alpinejs","django","github-api","htmx","python","shadcn","tailwindcss"],"created_at":"2025-03-15T04:14:22.435Z","updated_at":"2026-04-12T03:03:49.398Z","avatar_url":"https://github.com/seapagan.png","language":"Python","funding_links":["https://github.com/sponsors/seapagan","https://ko-fi.com/grantramsay","https://buymeacoffee.com/seapagan"],"categories":[],"sub_categories":[],"readme":"# Django Projects Portfolio \u003c!-- omit in toc --\u003e\n\n[![Tests](https://github.com/seapagan/django-projects/actions/workflows/tests.yml/badge.svg)](https://github.com/seapagan/django-projects/actions/workflows/tests.yml)\n[![Linting](https://github.com/seapagan/django-projects/actions/workflows/ruff.yml/badge.svg)](https://github.com/seapagan/django-projects/actions/workflows/ruff.yml)\n[![Type Checking](https://github.com/seapagan/django-projects/actions/workflows/mypy.yml/badge.svg)](https://github.com/seapagan/django-projects/actions/workflows/mypy.yml)\n\nA modern Django application for showcasing your development projects. Built with\nDjango 5.1 and styled with Tailwind CSS, this application provides a clean and\nresponsive interface to display your portfolio of projects.\n\nAll the `About`, `Skills`, `Social links` and `Projects` are **fully dynamic\nfrom the database**, no code editing should be needed to get your profile up and\nrunning.\n\nThere is a **live example of this portfolio app** at \u003chttps://www.gnramsay.com\u003e\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n  - [Using uv (Recommended)](#using-uv-recommended)\n  - [Using Traditional pip/venv](#using-traditional-pipvenv)\n- [Configuration](#configuration)\n  - [Environment Variables](#environment-variables)\n  - [PostgreSQL Database (Optional)](#postgresql-database-optional)\n  - [Email Settings (Optional)](#email-settings-optional)\n  - [`.env` File](#env-file)\n- [Usage](#usage)\n- [Add your Projects, Personal Details and skills](#add-your-projects-personal-details-and-skills)\n  - [Customizing the About Section](#customizing-the-about-section)\n  - [Adding Projects](#adding-projects)\n  - [App Settings](#app-settings)\n- [Contact Form](#contact-form)\n- [Caching](#caching)\n- [Production Deployment](#production-deployment)\n  - [Security Features](#security-features)\n- [Project Structure](#project-structure)\n- [Contributing](#contributing)\n- [Development](#development)\n- [License](#license)\n\n## Features\n\n- 🚀 Built with Django 5.1\n- 💅 Modern UI with Tailwind CSS. We use `django-tailwind-cli` to make the\n  integration easier. This uses the Tailwind CLI and does NOT require Node.js to\n  be installed\n- 🧩 Component-based templates using `django-cotton` and `django-shadcn`\n- 👤 Custom Models and Admin pages to customize the settings and text\n- 📝 Contact form with Google reCAPTCHA v2 integration for spam protection and\n  stored in the database as well as sent by email to the site owner\n- 🔒 Environment-based configuration with customization from the database\n- 🛠️ Modern development tools integration (`uv`, `pre-commit`, `ruff`, `mypy`)\n- 📱 Fully responsive design\n- 🌓 Light/Dark mode options, with a dropdown for user preference or system\n  setting.\n- 💾 Optional caching using memcached for improved performance\n- 🔄 Live browser reload during development\n- 🔐 Enhanced security features for production deployment\n- 🚀 Production-ready with gunicorn integration\n- 📄 Dynamic pagination of projects using HTMX for smooth, server-side loading\n- 🚫 Custom error pages (400, 403, 404, 500) for better user experience\n\n## Requirements\n\n- Python 3.10+\n\nOther package requirements will be automatically installed with the\ndependencies.\n\n## Installation\n\n### Using uv (Recommended)\n\n1. Clone the repository:\n\n```console\ngit clone https://github.com/seapagan/django-projects\ncd django-projects\n```\n\n2. Install dependencies using uv:\n\n```console\nuv venv\nuv sync --no-dev\nsource .venv/bin/activate # On Windows: .venv\\Scripts\\activate\n```\n\n### Using Traditional pip/venv\n\n1. Clone the repository:\n\n```console\ngit clone https://github.com/seapagan/django-projects\ncd django-projects\n```\n\n2. Create and activate a virtual environment:\n\n```console\npython -m venv venv\nsource venv/bin/activate  # On Windows: venv\\Scripts\\activate\n```\n\n3. Install Python dependencies:\n\n```console\npip install -r requirements.txt\n```\n\n## Configuration\n\n### Environment Variables\n\nThe application uses further environment variables for configuration and\nsecurity. Most of them **do** have a default setting that will be used if not\nspecified.\n\n Key settings:\n\n- `DJANGO_SECRET_KEY`: Your Django secret key. This MUST be set to a secure\n  string.\n- `DJANGO_DEBUG`: Set to 1 for development, 0 for production\n- `DJANGO_SECURE_MODE`: Set to 1 to enable enhanced security features for\n  production (see [Security Features](#security-features) section)\n- `DJANGO_CSRF_TRUSTED_ORIGINS`: JSON array of trusted origins for CSRF\n  protection, e.g. `[\"https://www.myserver.com\"]`\n- `DJANGO_ALLOWED_HOSTS`: JSON array of allowed hosts, e.g. `[\".myserver.com\"]`\n- `DJANGO_STATIC_ROOT`: Path where static files will be collected in production\n  mode\n- `DJANGO_USE_CACHE`: Set to 1 to enable caching for the whole application. This\n  uses `memcached` and that needs to be installed locally. Defaults to 0 (better\n  for development) See the [Caching](#caching) secton below.\n- `DJANGO_CACHE_TIMEOUT`: Cache expiry length, in seconds (Defaults to 600, 10\n  minutes)\n- `DJANGO_PROTECT_ADMIN`: Set to 1 to enable IP-based admin access restriction. If not set or set to 0, all IPs can access the admin panel\n- `DJANGO_ADMIN_IPS_ALLOWED`: JSON array of IP addresses allowed to access the\n  admin panel, e.g. `[\"127.0.0.1\", \"192.168.1.100\"]`. If not set, defaults to\n  `[\"127.0.0.1\", \"localhost\"]`. Only used when `DJANGO_PROTECT_ADMIN` is set to 1\n\n\u003e [!NOTE]\n\u003e\n\u003e If you do specify a value of `DJANGO_ADMIN_IPS_ALLOWED`, the defaults are\n\u003e REMOVED. Should you still want the defaults, they need to be manually added to\n\u003e the env var along with your custom addresses.\n\n- `DJANGO_SECURE_PROXY`: Set to 1 if you are using a secure reverse proxy (which\n  passes the `X_FORWARDED_FOR` header) to serve this app\n- `RECAPTCHA_SITE_KEY`: Your Google reCAPTCHA v2 site key\n- `RECAPTCHA_SECRET_KEY`: Your Google reCAPTCHA v2 secret key\n\n### PostgreSQL Database (Optional)\n\nBy default, the application uses SQLite for the database. However, you can\nconfigure it to use PostgreSQL instead by setting the following environment\nvariables:\n\n- `DJANGO_USE_POSTGRES`: Set to 1 to use PostgreSQL instead of SQLite\n- `DJANGO_POSTGRES_DB`: PostgreSQL database name\n- `DJANGO_POSTGRES_USER`: PostgreSQL username\n- `DJANGO_POSTGRES_PASSWORD`: PostgreSQL password\n- `DJANGO_POSTGRES_HOST`: PostgreSQL host (default: localhost)\n- `DJANGO_POSTGRES_PORT`: PostgreSQL port (default: 5432)\n\n\u003e [!NOTE]\n\u003e\n\u003e The PostgreSQL user and database **must already exist**, and the user needs to\n\u003e have **ownership** (or access) to that database.\n\u003e\n\u003e For SQLite, the local database file will be created when the migrations are\n\u003e run.\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e This project uses the binary version of `psycopg` which is not compatible with\n\u003e some older systems (primarily older Macs or if using PyPy Python). If you\n\u003e encounter compatibility issues, you should remove the `psycopg[binary]`\n\u003e package and use the plain `psycopg` package instead, or compile it locally.\n\u003e For more information, see the [psycopg documentation on supported\n\u003e systems](https://www.psycopg.org/psycopg3/docs/basic/install.html#supported-systems).\n\n### Email Settings (Optional)\n\nYou can configure the email (SMTP) server to send contact emails using the below\nenvironment variables:\n\n- `USE_LIVE_EMAIL`: Set to 1 to send actual emails, 0 or unset to output to\n  console\n- `EMAIL_HOST`: SMTP server host (required if USE_LIVE_EMAIL=1)\n- `EMAIL_PORT`: SMTP server port (required if USE_LIVE_EMAIL=1)\n- `EMAIL_HOST_USER`: SMTP username (required if USE_LIVE_EMAIL=1)\n- `EMAIL_HOST_PASSWORD`: SMTP password (required if USE_LIVE_EMAIL=1)\n- `EMAIL_USE_TLS`: Set to 1 to use TLS for SMTP (optional, defaults to 1)\n- `DEFAULT_FROM_EMAIL`: Default sender email address (required if\n  USE_LIVE_EMAIL=1)\n- `CONTACT_FORM_RECIPIENT`: Email address where contact form submissions will be\n  sent (required if USE_LIVE_EMAIL=1)\n\n### `.env` File\n\nCreate an `.env` file in the project root with the following content, or set the\nenvironment variables directly:\n\n```ini\nDJANGO_SECRET_KEY=your-secret-key\nDJANGO_DEBUG=1 # sets debug mode\nDJANGO_SECURE_MODE=0 # set to 1 for production security features\n\n# Database settings (optional - defaults to SQLite if not set)\nDJANGO_USE_POSTGRES=0 # set to 1 to use PostgreSQL\nDJANGO_POSTGRES_DB=mydatabase\nDJANGO_POSTGRES_USER=myuser\nDJANGO_POSTGRES_PASSWORD=your-postgres-password\nDJANGO_POSTGRES_HOST=localhost\nDJANGO_POSTGRES_PORT=5432\n\n# Production settings (required when DJANGO_DEBUG=0)\nDJANGO_CSRF_TRUSTED_ORIGINS=[\"https://www.myserver.com\"]\nDJANGO_ALLOWED_HOSTS=[\".myserver.com\"]\nDJANGO_STATIC_ROOT=\"/var/www/myproject/static/\"\n\n# cache settings\nDJANGO_USE_CACHE=0 # set to 0 for development, 1 for production when the database rarely changes\nDJANGO_CACHE_TIMEOUT=3600 # defaults to 600 (10 minutes) if not set\n\n# admin IP whitelist\nDJANGO_PROTECT_ADMIN=1 # set to 1 to enable IP-based admin access restriction\nDJANGO_ADMIN_IPS_ALLOWED=[\"127.0.0.1\", \"192.168.1.100\"] # IP addresses allowed to access admin panel\n\n# enable secure proxy forwarding. This ALSO needs 'DJANGO_SECURE_MODE=1'\nDJANGO_SECURE_PROXY=0 # set to 1 if you are serving behind a secure proxy (ie nginx etc)\n\n# recaptcha settings\nRECAPTCHA_SITE_KEY=your-recaptcha-site-key\nRECAPTCHA_SECRET_KEY=your-recaptcha-secret-key\n\n# Email settings (optional - if USE_LIVE_EMAIL=0, emails will output to console only)\nUSE_LIVE_EMAIL=1\nEMAIL_HOST=smtp.example.com\nEMAIL_PORT=587\nEMAIL_HOST_USER=your-email@example.com\nEMAIL_HOST_PASSWORD=your-smtp-password\nEMAIL_USE_TLS=1\nDEFAULT_FROM_EMAIL=your-email@example.com\nCONTACT_FORM_RECIPIENT=recipient@example.com\n```\n\n\u003e [!NOTE]\n\u003e\n\u003e There is an `.example.env` file in the project root you can rename and modify\n\u003e to your own settings\n\nTo get your reCAPTCHA keys (required for the contact form functionality):\n\n1. Visit the [Google reCAPTCHA Admin\n   Console](https://www.google.com/recaptcha/admin)\n2. Sign in with your Google account\n3. Click the \"+\" button to create a new site\n4. Choose \"reCAPTCHA v2\" and \"I'm not a robot\" Checkbox\n5. Add your domain(s) to the list (you can use '127.0.0.1' for local testing, be\n   sure to add the correct domain when you deploy)\n6. Copy the \"Site Key\" to `RECAPTCHA_SITE_KEY` and \"Secret Key\" to\n   `RECAPTCHA_SECRET_KEY`\n\n\u003e [!NOTE]\n\u003e\n\u003e For a Production or User-Facing project, **ALWAYS set `DJANGO_DEBUG=0`**\n\n## Usage\n\n1. Apply database migrations:\n\n```console\npython manage.py migrate\n```\n\n2. Create a superuser:\n\n```console\npython manage.py createsuperuser\n```\n\n3. Run the development server:\n\n```console\npython manage.py tailwind runserver\n```\n\n4. Visit \u003chttp://localhost:8000/admin\u003e to add your projects\n5. View your portfolio at \u003chttp://localhost:8000\u003e\n\n## Add your Projects, Personal Details and skills\n\nYou can customize the portfolio with your own skills and projects through the\nDjango Admin interface at \u003chttp://localhost:8000/admin\u003e\n\n### Customizing the About Section\n\nYou can add and manage about sections through the Django admin interface in the\n**Site Configuration** section. Each about section has the following field:\n\n- **Content**: The main text content for this section. This field supports\n  multiple paragraphs and can include limited HTML tags.\n\nAbout sections are linked to your site configuration and allow you to provide\ndetailed information about yourself, your background, skills, and experience.\nEach `about` record will be in a separate paragraph - you can use **limited**\nHTML tags in this field (`a`,`strong`,`em`,`ul`,`ol`,`li`,`sub`,`sup` - all\nothers will be stripped.)\n\nIf you have no about sections added, the About area will not be displayed.\n\n### Adding Projects\n\nYou can add projects by clicking on the **Projects** section in the admin pages.\nEach project has the following fields:\n\n- **Title**: The name of your project (maximum 100 characters)\n- **Details**: A detailed description of your project. This field supports\n  multiple paragraphs and can be left blank if needed\n- **Priority**: An optional integer value that determines the display order\n  (lower numbers appear first)\n- **Repository URL**: The URL to your project's source code repository\n  (optional)\n- **Website URL**: The URL to your project's live website or demo (optional)\n- **Tags**: Associate relevant tags with your project to categorize it\n  (optional). You first have to add the tags in the **Tags** section of the\n  Admin page.\n\nProjects are displayed on your portfolio page in the following order:\n\n1. Projects with a `priority` value are shown first, sorted by priority (lower\n   numbers appear first and duplicate priorities are sorted by their\n   `created_at` date.)\n2. Projects without a `priority` value are then displayed, sorted by creation\n   date (oldest to newest)\n\nYou can set a project's priority in the admin interface. This allows you to\nhighlight your most important projects by giving them lower priority numbers.\n\n### App Settings\n\nThe application provides additional configuration options through the Django\nadmin interface at the **Site Configuration** section . These settings allow you\nto customize various aspects of your portfolio:\n\n- **Site Content**\n  - `owner_name`: The Owner of the site. This will be the page title and the\n    text in the header of the page content (default: \"The Developer\")\n  - `hero_title`: The main title displayed on your portfolio (default: \"Full\n    Stack Developer\")\n  - `hero_info`: Primary text content for the hero section (up to 500\n    characters, no default)\n  - `hero_secondary`: Secondary text content for the hero section (up to 500\n    characters, no default)\n\n- **Social Media Links**\n  - `github_username`: Your GitHub username\n  - `twitter_username`: Your Twitter/X username\n  - `linkedin_username`: Your LinkedIn username\n  - `youtube_username`: Your YouTube channel username\n  - `medium_username`: Your Medium username\n\n  Any social media usernames left blank will not be displayed on your portfolio.\n\n- **About Section**\n\n  As mentioned [above](#customizing-the-about-section) you can add/edit your\n  'About' info here too.\n\n- **Languages and Frameworks**\n\n  You can manage your programming languages and frameworks through the Django\n  admin interface by editing the `Site Configuration` database.\n\n  - **Languages** : Add programming languages you work with\n    - `name`: Name of the programming language (e.g., \"Python\", \"JavaScript\")\n\n  - **Frameworks** (`/admin/app/framework/`): Add frameworks and libraries you\n    work with\n    - `name`: Name of the framework (e.g., \"Django\", \"React\")\n\n  Both languages and frameworks will be displayed on your portfolio to showcase\n  your technical stack. If you have none added, the whole **My SKills** section\n  will not be displayed.\n\nThese settings can be modified at any time through the admin interface and\nchanges will be reflected immediately on your portfolio (though, see the note\nbelow on **Caching**)\n\n## Contact Form\n\nThe contact form will save each contact into the database and you can view these\nin the Admin pages in the **Contact Submissions** section.\n\nOptionally, if you have set up the email, each contact will also be emailed to\nyou as it is submitted.\n\n## Caching\n\nThis Django application is set up for optional caching which is disabled by\ndefault. Generally it is not much use when you are setting up or customizing the\ndatabase since any changes will take 10 minutes to actually be visible in the\nfront-end. It is a bit overkill for this application but a good skill to learn.\n\n\u003e [!NOTE]\n\u003e\n\u003e Probably best **not** to enable this until your database is set up to your\n\u003e liking, as the default is a 10 minute cache time-out. See below how to change\n\u003e this.\n\nI have chosen to use [memcached](https://www.memcached.org/) for this, though\nyou can use **Redis**, **File Caching**, **Local Memory** or any other method\nthat Django supports. See the [Django docs on\nCaching](https://docs.djangoproject.com/en/5.1/topics/cache/) for more info.\n\nYou need to install [memcached](https://www.memcached.org/) for this to work. If\nthis is not installed and the cache enabled your application will crash.\n\nSee the link above for how to install for your server, under Debian/Ubuntu it is\navailable as a package:\n\n```console\nsudo apt install memcached\n```\n\nFinally, to enable the caching, set the below variable in your `.env` file or\nenvironment:\n\n```ini\nDJANGO_USE_CACHE=1\n```\n\nIf this variable is 0 or missing, caching will be disabled.\n\nYou can change the length of time that the database is cached by setting the\nbelow variable:\n\n```ini\nDJANGO_CACHE_TIMEOUT=1200 # Default is 600 (10 Minutes)\n```\n\n## Production Deployment\n\nFor production deployment, it's recommended to:\n\n1. Set `DJANGO_DEBUG=0` to disable debug mode\n2. Set `DJANGO_SECURE_MODE=1` to enable security features\n\n\u003e [!CAUTION]\n\u003e\n\u003e The Secure Mode settings may need tweaking for your exact use-case. As it\n\u003e stands, they work well for an application served behind an nginx reverse-proxy\n\u003e (which is a GREAT way to serve your Django App) but may cause issues in other\n\u003e cases. Checkout the `config/settings.py` file around the end to see what\n\u003e settings are set and add/adjust any that you need for your specific setup.\n\n3. Use PostgreSQL instead of SQLite by setting `DJANGO_USE_POSTGRES=1` and\n   configuring the related database settings\n4. Set `DJANGO_PROTECT_ADMIN=1` to enable IP-based admin access restriction and configure `DJANGO_ADMIN_IPS_ALLOWED` with trusted IP addresses\n5. Configure the production-specific environment variables:\n   - `DJANGO_CSRF_TRUSTED_ORIGINS`: Your domain(s) as a JSON array\n   - `DJANGO_ALLOWED_HOSTS`: Your domain(s) as a JSON array\n   - `DJANGO_STATIC_ROOT`: The path where static files will be collected\n\nYou should also run the collectstatic files before deployment:\n\n```console\npython manage.py collectstatic\n```\n\n\u003e [!TIP]\n\u003e\n\u003e This is a **customized** `collectstatic` command which, as well as the usual\n\u003e functionality will also:\n\u003e\n\u003e - **build** the Tailwind production file\n\u003e - **minimize** any Javascript files in the `assets/js` folder.\n\u003e\n\u003e You no longer need to run the `python manage.py tailwind build` command\n\u003e seperately.\n\nThe application includes gunicorn for production deployment. A typical command\nto run the application in production would be:\n\n```console\ngunicorn config.wsgi:application --bind 0.0.0.0:8000\n```\n\nFor a proper production setup, you should:\n\n1. Run gunicorn as a systemd service for automatic startup and monitoring\n2. Use Nginx as a reverse proxy in front of gunicorn to handle static files,\n   SSL, and more\n\nFor a detailed guide on setting up Django with Nginx and Gunicorn in production,\nsee: \u003chttps://realpython.com/django-nginx-gunicorn/\u003e\n\n### Security Features\n\nWhen `DJANGO_SECURE_MODE=1` (and `DJANGO_DEBUG=0`), the following security\nfeatures are enabled:\n\n- HTTP Strict Transport Security (HSTS) - Initially set to 30 seconds for\n  testing, with a commented option to increase to 15552000 seconds (180 days)\n  once you've verified everything works correctly\n\n\u003e [!CAUTION]\n\u003e\n\u003e Be very careful when setting the HSTS timeout to a longer value (like 180\n\u003e days). Once set, it can be almost impossible to change later as browsers\n\u003e will remember this setting for the specified duration. However, setting a\n\u003e longer timeout is highly recommended once you've verified that HSTS is\n\u003e working correctly for your site.\n\n- Secure cookies for CSRF and sessions\n- SSL redirection\n- Secure referrer policy\n- Permissions policy headers that restrict potentially dangerous browser\n  features\n- IP-based admin access restriction - When `DJANGO_PROTECT_ADMIN=1`, only allows specified IP addresses to\n  access the admin panel\n- Secure Proxy forwarding - When `DJANGO_SECURE_PROXY=1`, your proxy needs to\n  support this.\n\nThese features follow Django security best practices and help protect your\napplication against common web vulnerabilities.\n\n## Project Structure\n\n```pre\n├── app/               # Main application code\n├── assets/            # Static assets\n│   └── css/           # CSS files\n│   └── js/            # JavaScript files\n│   └── favicon.ico    # Put your favicon here or use the existing one\n├── config/            # Project configuration\n├── templates/         # HTML templates\n│   ├── app/           # Application templates\n│   └── cotton/        # Component templates\n└── manage.py          # Django management script\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## Development\n\nThis project uses several development tools to maintain code quality:\n\n- `pre-commit` hooks for code formatting and linting\n- `ruff` for Python linting\n- `mypy` for type-checking\n- `django-browser-reload` for live development\n- `django-stubs` for improved type checking\n\nInstall development dependencies and set up pre-commit:\n\nUsing uv (Recommended):\n\n```console\nuv sync\npre-commit install\n```\n\nUsing pip:\n\n```console\npip install -r requirements-dev.txt\npre-commit install\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for\ndetails.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseapagan%2Fdjango-projects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseapagan%2Fdjango-projects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseapagan%2Fdjango-projects/lists"}