├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── accounts ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── management │ └── commands │ │ └── rename.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── static │ └── accounts │ │ └── css │ │ └── auth.css ├── templates │ └── accounts │ │ ├── base.html │ │ ├── login.html │ │ └── register.html ├── tests.py ├── urls.py └── views.py ├── dashboard ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── static │ └── dashboard │ │ └── css │ │ └── dashboard.css ├── templates │ └── dashboard │ │ ├── base.html │ │ └── index.html ├── tests.py ├── urls.py └── views.py ├── djangotemplate ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── landing_page ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── requirements.txt ├── static │ └── landing_page │ │ ├── css │ │ ├── index.css │ │ └── reset.css │ │ └── images │ │ └── favicon.png ├── templates │ └── landing_page │ │ ├── base.html │ │ └── index.html ├── tests.py ├── urls.py └── views.py ├── manage.py ├── package-lock.json ├── renovate.json ├── requirements.txt ├── setup.sh └── theme ├── __init__.py ├── apps.py ├── static_src ├── .gitignore ├── package-lock.json ├── package.json ├── postcss.config.js ├── src │ └── styles.css └── tailwind.config.js └── templates └── base.html /.env.example: -------------------------------------------------------------------------------- 1 | DEBUG="True" 2 | SECRET_KEY="k=1opvz^^jopszbbzspxy(x45d_v0%ylhzbsr!05)!=_lihxz7" 3 | 4 | DB_NAME="djangotemplate" 5 | DB_USER="postgres" 6 | DB_PASSWORD="postgres" 7 | DB_HOST="localhost" 8 | DB_PORT="5432" 9 | 10 | AWS_ACCESS_KEY_ID="AWS_ACCESS_KEY_ID" 11 | AWS_SECRET_ACCESS_KEY="AWS_SECRET_ACCESS_KEY" 12 | AWS_STORAGE_BUCKET_NAME="AWS_STORAGE_BUCKET_NAME" 13 | AWS_S3_SIGNATURE_VERSION="s3v4" 14 | AWS_S3_REGION_NAME="eu-north-1" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/django,visualstudiocode,visualstudio,windows,macos,linux 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=django,visualstudiocode,visualstudio,windows,macos,linux 3 | 4 | ### Django ### 5 | *.log 6 | *.pot 7 | *.pyc 8 | __pycache__/ 9 | local_settings.py 10 | db.sqlite3 11 | db.sqlite3-journal 12 | media 13 | 14 | # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ 15 | # in your Git repository. Update and uncomment the following line accordingly. 16 | # /staticfiles/ 17 | 18 | ### Django.Python Stack ### 19 | # Byte-compiled / optimized / DLL files 20 | *.py[cod] 21 | *$py.class 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | lib/ 35 | lib64/ 36 | parts/ 37 | sdist/ 38 | var/ 39 | wheels/ 40 | share/python-wheels/ 41 | *.egg-info/ 42 | .installed.cfg 43 | *.egg 44 | MANIFEST 45 | 46 | # PyInstaller 47 | # Usually these files are written by a python script from a template 48 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 49 | *.manifest 50 | *.spec 51 | 52 | # Installer logs 53 | pip-log.txt 54 | pip-delete-this-directory.txt 55 | 56 | # Unit test / coverage reports 57 | htmlcov/ 58 | .tox/ 59 | .nox/ 60 | .coverage 61 | .coverage.* 62 | .cache 63 | nosetests.xml 64 | coverage.xml 65 | *.cover 66 | *.py,cover 67 | .hypothesis/ 68 | .pytest_cache/ 69 | cover/ 70 | 71 | # Translations 72 | *.mo 73 | 74 | # Django stuff: 75 | 76 | # Flask stuff: 77 | instance/ 78 | .webassets-cache 79 | 80 | # Scrapy stuff: 81 | .scrapy 82 | 83 | # Sphinx documentation 84 | docs/_build/ 85 | 86 | # PyBuilder 87 | .pybuilder/ 88 | target/ 89 | 90 | # Jupyter Notebook 91 | .ipynb_checkpoints 92 | 93 | # IPython 94 | profile_default/ 95 | ipython_config.py 96 | 97 | # pyenv 98 | # For a library or package, you might want to ignore these files since the code is 99 | # intended to run in multiple environments; otherwise, check them in: 100 | # .python-version 101 | 102 | # pipenv 103 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 104 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 105 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 106 | # install all needed dependencies. 107 | #Pipfile.lock 108 | 109 | # poetry 110 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 111 | # This is especially recommended for binary packages to ensure reproducibility, and is more 112 | # commonly ignored for libraries. 113 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 114 | #poetry.lock 115 | 116 | # pdm 117 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 118 | #pdm.lock 119 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 120 | # in version control. 121 | # https://pdm.fming.dev/#use-with-ide 122 | .pdm.toml 123 | 124 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 125 | __pypackages__/ 126 | 127 | # Celery stuff 128 | celerybeat-schedule 129 | celerybeat.pid 130 | 131 | # SageMath parsed files 132 | *.sage.py 133 | 134 | # Environments 135 | .env 136 | .venv 137 | env/ 138 | venv/ 139 | ENV/ 140 | env.bak/ 141 | venv.bak/ 142 | 143 | # Spyder project settings 144 | .spyderproject 145 | .spyproject 146 | 147 | # Rope project settings 148 | .ropeproject 149 | 150 | # mkdocs documentation 151 | /site 152 | 153 | # mypy 154 | .mypy_cache/ 155 | .dmypy.json 156 | dmypy.json 157 | 158 | # Pyre type checker 159 | .pyre/ 160 | 161 | # pytype static type analyzer 162 | .pytype/ 163 | 164 | # Cython debug symbols 165 | cython_debug/ 166 | 167 | # PyCharm 168 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 169 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 170 | # and can be added to the global gitignore or merged into this file. For a more nuclear 171 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 172 | #.idea/ 173 | 174 | ### Linux ### 175 | *~ 176 | 177 | # temporary files which can be created if a process still has a handle open of a deleted file 178 | .fuse_hidden* 179 | 180 | # KDE directory preferences 181 | .directory 182 | 183 | # Linux trash folder which might appear on any partition or disk 184 | .Trash-* 185 | 186 | # .nfs files are created when an open file is removed but is still being accessed 187 | .nfs* 188 | 189 | ### macOS ### 190 | # General 191 | .DS_Store 192 | .AppleDouble 193 | .LSOverride 194 | 195 | # Icon must end with two \r 196 | Icon 197 | 198 | 199 | # Thumbnails 200 | ._* 201 | 202 | # Files that might appear in the root of a volume 203 | .DocumentRevisions-V100 204 | .fseventsd 205 | .Spotlight-V100 206 | .TemporaryItems 207 | .Trashes 208 | .VolumeIcon.icns 209 | .com.apple.timemachine.donotpresent 210 | 211 | # Directories potentially created on remote AFP share 212 | .AppleDB 213 | .AppleDesktop 214 | Network Trash Folder 215 | Temporary Items 216 | .apdisk 217 | 218 | ### macOS Patch ### 219 | # iCloud generated files 220 | *.icloud 221 | 222 | ### VisualStudioCode ### 223 | .vscode/* 224 | !.vscode/settings.json 225 | !.vscode/tasks.json 226 | !.vscode/launch.json 227 | !.vscode/extensions.json 228 | !.vscode/*.code-snippets 229 | 230 | # Local History for Visual Studio Code 231 | .history/ 232 | 233 | # Built Visual Studio Code Extensions 234 | *.vsix 235 | 236 | ### VisualStudioCode Patch ### 237 | # Ignore all local history of files 238 | .history 239 | .ionide 240 | 241 | ### Windows ### 242 | # Windows thumbnail cache files 243 | Thumbs.db 244 | Thumbs.db:encryptable 245 | ehthumbs.db 246 | ehthumbs_vista.db 247 | 248 | # Dump file 249 | *.stackdump 250 | 251 | # Folder config file 252 | [Dd]esktop.ini 253 | 254 | # Recycle Bin used on file shares 255 | $RECYCLE.BIN/ 256 | 257 | # Windows Installer files 258 | *.cab 259 | *.msi 260 | *.msix 261 | *.msm 262 | *.msp 263 | 264 | # Windows shortcuts 265 | *.lnk 266 | 267 | ### VisualStudio ### 268 | ## Ignore Visual Studio temporary files, build results, and 269 | ## files generated by popular Visual Studio add-ons. 270 | ## 271 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 272 | 273 | # User-specific files 274 | *.rsuser 275 | *.suo 276 | *.user 277 | *.userosscache 278 | *.sln.docstates 279 | 280 | # User-specific files (MonoDevelop/Xamarin Studio) 281 | *.userprefs 282 | 283 | # Mono auto generated files 284 | mono_crash.* 285 | 286 | # Build results 287 | [Dd]ebug/ 288 | [Dd]ebugPublic/ 289 | [Rr]elease/ 290 | [Rr]eleases/ 291 | x64/ 292 | x86/ 293 | [Ww][Ii][Nn]32/ 294 | [Aa][Rr][Mm]/ 295 | [Aa][Rr][Mm]64/ 296 | bld/ 297 | [Bb]in/ 298 | [Oo]bj/ 299 | [Ll]og/ 300 | [Ll]ogs/ 301 | 302 | # Visual Studio 2015/2017 cache/options directory 303 | .vs/ 304 | # Uncomment if you have tasks that create the project's static files in wwwroot 305 | #wwwroot/ 306 | 307 | # Visual Studio 2017 auto generated files 308 | Generated\ Files/ 309 | 310 | # MSTest test Results 311 | [Tt]est[Rr]esult*/ 312 | [Bb]uild[Ll]og.* 313 | 314 | # NUnit 315 | *.VisualState.xml 316 | TestResult.xml 317 | nunit-*.xml 318 | 319 | # Build Results of an ATL Project 320 | [Dd]ebugPS/ 321 | [Rr]eleasePS/ 322 | dlldata.c 323 | 324 | # Benchmark Results 325 | BenchmarkDotNet.Artifacts/ 326 | 327 | # .NET Core 328 | project.lock.json 329 | project.fragment.lock.json 330 | artifacts/ 331 | 332 | # ASP.NET Scaffolding 333 | ScaffoldingReadMe.txt 334 | 335 | # StyleCop 336 | StyleCopReport.xml 337 | 338 | # Files built by Visual Studio 339 | *_i.c 340 | *_p.c 341 | *_h.h 342 | *.ilk 343 | *.meta 344 | *.obj 345 | *.iobj 346 | *.pch 347 | *.pdb 348 | *.ipdb 349 | *.pgc 350 | *.pgd 351 | *.rsp 352 | *.sbr 353 | *.tlb 354 | *.tli 355 | *.tlh 356 | *.tmp 357 | *.tmp_proj 358 | *_wpftmp.csproj 359 | *.tlog 360 | *.vspscc 361 | *.vssscc 362 | .builds 363 | *.pidb 364 | *.svclog 365 | *.scc 366 | 367 | # Chutzpah Test files 368 | _Chutzpah* 369 | 370 | # Visual C++ cache files 371 | ipch/ 372 | *.aps 373 | *.ncb 374 | *.opendb 375 | *.opensdf 376 | *.sdf 377 | *.cachefile 378 | *.VC.db 379 | *.VC.VC.opendb 380 | 381 | # Visual Studio profiler 382 | *.psess 383 | *.vsp 384 | *.vspx 385 | *.sap 386 | 387 | # Visual Studio Trace Files 388 | *.e2e 389 | 390 | # TFS 2012 Local Workspace 391 | $tf/ 392 | 393 | # Guidance Automation Toolkit 394 | *.gpState 395 | 396 | # ReSharper is a .NET coding add-in 397 | _ReSharper*/ 398 | *.[Rr]e[Ss]harper 399 | *.DotSettings.user 400 | 401 | # TeamCity is a build add-in 402 | _TeamCity* 403 | 404 | # DotCover is a Code Coverage Tool 405 | *.dotCover 406 | 407 | # AxoCover is a Code Coverage Tool 408 | .axoCover/* 409 | !.axoCover/settings.json 410 | 411 | # Coverlet is a free, cross platform Code Coverage Tool 412 | coverage*.json 413 | coverage*.xml 414 | coverage*.info 415 | 416 | # Visual Studio code coverage results 417 | *.coverage 418 | *.coveragexml 419 | 420 | # NCrunch 421 | _NCrunch_* 422 | .*crunch*.local.xml 423 | nCrunchTemp_* 424 | 425 | # MightyMoose 426 | *.mm.* 427 | AutoTest.Net/ 428 | 429 | # Web workbench (sass) 430 | .sass-cache/ 431 | 432 | # Installshield output folder 433 | [Ee]xpress/ 434 | 435 | # DocProject is a documentation generator add-in 436 | DocProject/buildhelp/ 437 | DocProject/Help/*.HxT 438 | DocProject/Help/*.HxC 439 | DocProject/Help/*.hhc 440 | DocProject/Help/*.hhk 441 | DocProject/Help/*.hhp 442 | DocProject/Help/Html2 443 | DocProject/Help/html 444 | 445 | # Click-Once directory 446 | publish/ 447 | 448 | # Publish Web Output 449 | *.[Pp]ublish.xml 450 | *.azurePubxml 451 | # Note: Comment the next line if you want to checkin your web deploy settings, 452 | # but database connection strings (with potential passwords) will be unencrypted 453 | *.pubxml 454 | *.publishproj 455 | 456 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 457 | # checkin your Azure Web App publish settings, but sensitive information contained 458 | # in these scripts will be unencrypted 459 | PublishScripts/ 460 | 461 | # NuGet Packages 462 | *.nupkg 463 | # NuGet Symbol Packages 464 | *.snupkg 465 | # The packages folder can be ignored because of Package Restore 466 | **/[Pp]ackages/* 467 | # except build/, which is used as an MSBuild target. 468 | !**/[Pp]ackages/build/ 469 | # Uncomment if necessary however generally it will be regenerated when needed 470 | #!**/[Pp]ackages/repositories.config 471 | # NuGet v3's project.json files produces more ignorable files 472 | *.nuget.props 473 | *.nuget.targets 474 | 475 | # Microsoft Azure Build Output 476 | csx/ 477 | *.build.csdef 478 | 479 | # Microsoft Azure Emulator 480 | ecf/ 481 | rcf/ 482 | 483 | # Windows Store app package directories and files 484 | AppPackages/ 485 | BundleArtifacts/ 486 | Package.StoreAssociation.xml 487 | _pkginfo.txt 488 | *.appx 489 | *.appxbundle 490 | *.appxupload 491 | 492 | # Visual Studio cache files 493 | # files ending in .cache can be ignored 494 | *.[Cc]ache 495 | # but keep track of directories ending in .cache 496 | !?*.[Cc]ache/ 497 | 498 | # Others 499 | ClientBin/ 500 | ~$* 501 | *.dbmdl 502 | *.dbproj.schemaview 503 | *.jfm 504 | *.pfx 505 | *.publishsettings 506 | orleans.codegen.cs 507 | 508 | # Including strong name files can present a security risk 509 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 510 | #*.snk 511 | 512 | # Since there are multiple workflows, uncomment next line to ignore bower_components 513 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 514 | #bower_components/ 515 | 516 | # RIA/Silverlight projects 517 | Generated_Code/ 518 | 519 | # Backup & report files from converting an old project file 520 | # to a newer Visual Studio version. Backup files are not needed, 521 | # because we have git ;-) 522 | _UpgradeReport_Files/ 523 | Backup*/ 524 | UpgradeLog*.XML 525 | UpgradeLog*.htm 526 | ServiceFabricBackup/ 527 | *.rptproj.bak 528 | 529 | # SQL Server files 530 | *.mdf 531 | *.ldf 532 | *.ndf 533 | 534 | # Business Intelligence projects 535 | *.rdl.data 536 | *.bim.layout 537 | *.bim_*.settings 538 | *.rptproj.rsuser 539 | *- [Bb]ackup.rdl 540 | *- [Bb]ackup ([0-9]).rdl 541 | *- [Bb]ackup ([0-9][0-9]).rdl 542 | 543 | # Microsoft Fakes 544 | FakesAssemblies/ 545 | 546 | # GhostDoc plugin setting file 547 | *.GhostDoc.xml 548 | 549 | # Node.js Tools for Visual Studio 550 | .ntvs_analysis.dat 551 | node_modules/ 552 | 553 | # Visual Studio 6 build log 554 | *.plg 555 | 556 | # Visual Studio 6 workspace options file 557 | *.opt 558 | 559 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 560 | *.vbw 561 | 562 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 563 | *.vbp 564 | 565 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 566 | *.dsw 567 | *.dsp 568 | 569 | # Visual Studio 6 technical files 570 | 571 | # Visual Studio LightSwitch build output 572 | **/*.HTMLClient/GeneratedArtifacts 573 | **/*.DesktopClient/GeneratedArtifacts 574 | **/*.DesktopClient/ModelManifest.xml 575 | **/*.Server/GeneratedArtifacts 576 | **/*.Server/ModelManifest.xml 577 | _Pvt_Extensions 578 | 579 | # Paket dependency manager 580 | .paket/paket.exe 581 | paket-files/ 582 | 583 | # FAKE - F# Make 584 | .fake/ 585 | 586 | # CodeRush personal settings 587 | .cr/personal 588 | 589 | # Python Tools for Visual Studio (PTVS) 590 | 591 | # Cake - Uncomment if you are using it 592 | # tools/** 593 | # !tools/packages.config 594 | 595 | # Tabs Studio 596 | *.tss 597 | 598 | # Telerik's JustMock configuration file 599 | *.jmconfig 600 | 601 | # BizTalk build output 602 | *.btp.cs 603 | *.btm.cs 604 | *.odx.cs 605 | *.xsd.cs 606 | 607 | # OpenCover UI analysis results 608 | OpenCover/ 609 | 610 | # Azure Stream Analytics local run output 611 | ASALocalRun/ 612 | 613 | # MSBuild Binary and Structured Log 614 | *.binlog 615 | 616 | # NVidia Nsight GPU debugger configuration file 617 | *.nvuser 618 | 619 | # MFractors (Xamarin productivity tool) working folder 620 | .mfractor/ 621 | 622 | # Local History for Visual Studio 623 | .localhistory/ 624 | 625 | # Visual Studio History (VSHistory) files 626 | .vshistory/ 627 | 628 | # BeatPulse healthcheck temp database 629 | healthchecksdb 630 | 631 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 632 | MigrationBackup/ 633 | 634 | # Ionide (cross platform F# VS Code tools) working folder 635 | .ionide/ 636 | 637 | # Fody - auto-generated XML schema 638 | FodyWeavers.xsd 639 | 640 | # VS Code files for those working on multiple tools 641 | *.code-workspace 642 | 643 | # Local History for Visual Studio Code 644 | 645 | # Windows Installer files from build outputs 646 | 647 | # JetBrains Rider 648 | *.sln.iml 649 | 650 | ### VisualStudio Patch ### 651 | # Additional files built by Visual Studio 652 | 653 | # End of https://www.toptal.com/developers/gitignore/api/django,visualstudiocode,visualstudio,windows,macos,linux -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Michael 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # ⚡django-quickstart 3 | 4 | django-quickstart is a simple Django application designed to simplify your development process. It provides a ready-to-use **landing page**, built-in **authentication**, and a **dashboard**. For a smoother development experience, it includes **django-auto-reload** to enable hot reloading and **django-tailwind** for immediate use of TailwindCSS. 5 | 6 | The app is equipped with **Postgres** support, which allows for easy transition to a production-ready database as you prepare for deployment. Additionally, **AWS S3** configuration is available for serving static files in production environments. 7 | 8 | django-quickstart aims to streamline the setup process for new Django projects by providing a ready-made foundation with essential features, saving developers time and effort. 9 | 10 | 11 | 12 | ## Features 13 | 14 | This Django template is intentionally minimalistic, containing three pre-configured apps: **landing_page**, **accounts**, and **dashboard**. 15 | 16 | 1. **landing_page**: Acts as the homepage for your application, and can be further customized to meet your requirements. 17 | 18 | 2. **accounts**: Provides user registration, login, and logout capabilities to your application. 19 | 20 | 3. **dashboard**: Directs users to this app post-login/registration, where you can expand on your application’s functionality. 21 | 22 | Key production-ready features include: 23 | 24 | 1. **Postgres support**: Allows for easy transition to a PostgreSQL database for production environments. 25 | 26 | 2. **AWS S3 support**: Facilitates configuring S3-compatible storage for serving static files in production. 27 | 28 | The template is also equipped with the following pre-installed Python packages: 29 | 30 | 1. [**django-auto-reload**](https://github.com/adamchainz/django-browser-reload): Offers hot reload functionality to streamline your development process. 31 | 32 | 2. [**django-tailwind**](https://django-tailwind.readthedocs.io/en/latest/installation.html): Provides built-in support for using TailwindCSS. 33 | 34 | ## Requirements 35 | 36 | To use this template you'll need to have the following installed: 37 | 38 | 1. Python 3 39 | 2. Latest version of NodeJS (https://nodejs.org/en) 40 | 41 | ## Setup 42 | 43 | To begin using this template, start by creating a directory for your project: 44 | 45 | mkdir 46 | cd 47 | 48 | Clone the repository into the current directory: 49 | 50 | git clone git@github.com:michael-awe/django-template.git . 51 | 52 | Next, create and activate a virtual environment 53 | 54 | python3 -m venv env 55 | source env/bin/activate 56 | 57 | Now install the dependencies from requirements.txt 58 | 59 | pip install -r requirements.txt 60 | 61 | After installing the requirements, run setup.sh. You will then be prompted to enter a new project name. **Please ensure that the project name you enter is unique to ensure no clashes with Django or other Python modules**: 62 | 63 | sh setup.sh 64 | 65 | Next, install tailwind by running the following command: 66 | 67 | python manage.py tailwind install 68 | 69 | Next, create a `.env` file in the root directory of your project(same level as manage.py) and add the following secrets. It should look just like `.env.example` : 70 | 71 | DEBUG="True" 72 | SECRET_KEY="k=1opvz^^jopszbbzspxy(x45d_v0%ylhzbsr!05)!=_lihxz7" 73 | 74 | 75 | ## Usage 76 | 77 | In order to use Tailwind, you'll have to create two terminal tabs, one to start tailwind and the other to start your Django server 78 | 79 | 80 | In the first terminal enter the following command to get tailwind running: 81 | 82 | python manage.py tailwind start 83 | 84 | You can then start your Django server in a separate tab with this command: 85 | 86 | python manage.py runserver 87 | 88 | You're now all set and ready to start developing! 89 | 90 | 91 | ### Adding Tailwind to additional templates 92 | 93 | By default, the landing_page, accounts and dashboard apps all have Tailwind integrated in their respective base.html files. 94 | 95 | However, if you'd like to create a new app and add Tailwind support, either inherit from the base.html files of the other apps or add the following tags to your new HTML templates: 96 | 97 | ``` 98 | 99 | {% load static tailwind_tags %} 100 | 101 | ... 102 | 103 | 104 | 105 | ... 106 | 107 | {% tailwind_css %} 108 | 109 | ... 110 | 111 | 112 | 113 | ``` 114 | 115 | 116 | ### Configuring Postgres 117 | 118 | This template is pre-configured for Postgres functionality. While the application operates with SQLite in DEBUG mode, switching DEBUG to False enables Postgres. To ensure it functions correctly, the following environment variables need to be defined in your .env file: 119 | 120 | ```plaintext 121 | 122 | DB_NAME="" 123 | 124 | DB_USER="" 125 | 126 | DB_PASSWORD="" 127 | 128 | DB_HOST="" 129 | 130 | DB_PORT="" 131 | 132 | ``` 133 | 134 | ### Configuring AWS S3 135 | 136 | The template is also pre-configured for S3 storage to host static files. Like with Postgres, setting DEBUG to False in your environment variables activates S3 storage. To use this feature, ensure these environment variables are in your .env file: 137 | 138 | ```plaintext 139 | 140 | AWS_ACCESS_KEY_ID="AWS_ACCESS_KEY_ID" 141 | 142 | AWS_SECRET_ACCESS_KEY="AWS_SECRET_ACCESS_KEY" 143 | 144 | AWS_STORAGE_BUCKET_NAME="AWS_STORAGE_BUCKET_NAME" 145 | 146 | AWS_S3_SIGNATURE_VERSION="s3v4" 147 | 148 | AWS_S3_REGION_NAME="eu-north-1" 149 | 150 | ``` 151 | 152 | This setup is optimized for AWS S3, though minor adjustments can allow compatibility with other S3-like storage solutions such as Cloudflare R2 and DigitalOcean Spaces. For further details, refer to the documentation at [django-storages](https://django-storages.readthedocs.io/). 153 | 154 | ## Contributing 155 | 156 | If you would like to contribute to this repository or notice any issues with the code, please feel free to fork this repository and submit your changes in a pull request. Any contributions that improve the functionality or usability of the project are welcome. 157 | 158 | 159 | ## License 160 | 161 | Django Template is licensed under the MIT License, which means that you are free to use, modify, and distribute the project as you see fit. See the LICENSE file for more information. 162 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import User 3 | from django.contrib.auth.admin import UserAdmin 4 | 5 | # Register your models here. 6 | admin.site.register(User, UserAdmin) -------------------------------------------------------------------------------- /accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'accounts' 7 | -------------------------------------------------------------------------------- /accounts/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.forms import UserCreationForm 2 | from .models import User 3 | 4 | class CustomUserCreationForm(UserCreationForm): 5 | class Meta: 6 | model = User 7 | fields = ['username', 'email', 'password1', 'password2'] -------------------------------------------------------------------------------- /accounts/management/commands/rename.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | import os 3 | import sys 4 | 5 | class Command(BaseCommand): 6 | help = "Renames your Django project. Note this method was not intended for use after initial project setup." 7 | 8 | def add_arguments(self, parser): 9 | parser.add_argument('old_project_name', type=str, help='The current project name') 10 | parser.add_argument('new_project_name', type=str, help='The new project name') 11 | 12 | def handle(self, *args, **kwargs): 13 | 14 | # Get the old and new project names from the command line arguments 15 | old_project_name = kwargs['old_project_name'] 16 | new_project_name = kwargs['new_project_name'] 17 | 18 | print(f"Renaming {old_project_name} to {new_project_name}...") 19 | 20 | #Rename the project directory 21 | os.rename(old_project_name, new_project_name) 22 | 23 | # Iterate through all files in the project directory and its subdirectories 24 | for root, dirs, files in os.walk(new_project_name): 25 | for file in files: 26 | file_path = os.path.join(root, file) 27 | 28 | try: 29 | # Open the file for reading 30 | with open(file_path, 'r') as f: 31 | file_contents = f.read() 32 | 33 | # Replace all occurrences of the old project name with the new project name 34 | file_contents = file_contents.replace(old_project_name, new_project_name) 35 | 36 | # Open the file for writing and write the modified contents 37 | with open(file_path, 'w') as f: 38 | f.write(file_contents) 39 | except: 40 | pass 41 | 42 | #renames the project name in the manage.py file 43 | with open(f"./manage.py", 'r') as f: 44 | file_contents = f.read() 45 | 46 | # Replace all occurrences of the old project name with the new project name 47 | file_contents = file_contents.replace(f'{old_project_name}', f'{new_project_name}') 48 | 49 | # Open the file for writing and write the modified contents 50 | with open(f"./manage.py", 'w') as f: 51 | print("writing to file") 52 | f.write(file_contents) 53 | 54 | # Print a message indicating that the project has been renamed 55 | print(f"{old_project_name} has been renamed to {new_project_name}.") -------------------------------------------------------------------------------- /accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-02-16 11:56 2 | 3 | import django.contrib.auth.models 4 | import django.contrib.auth.validators 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ('auth', '0012_alter_user_first_name_max_length'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='User', 20 | fields=[ 21 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('password', models.CharField(max_length=128, verbose_name='password')), 23 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 24 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 25 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 26 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), 27 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), 28 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), 29 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 30 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 31 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 32 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), 33 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), 34 | ], 35 | options={ 36 | 'verbose_name': 'user', 37 | 'verbose_name_plural': 'users', 38 | 'abstract': False, 39 | }, 40 | managers=[ 41 | ('objects', django.contrib.auth.models.UserManager()), 42 | ], 43 | ), 44 | ] 45 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | # Create your models here. 5 | class User(AbstractUser): 6 | pass 7 | -------------------------------------------------------------------------------- /accounts/static/accounts/css/auth.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); 2 | 3 | :root{ 4 | --primary-font: 'Inter', sans-serif; 5 | } 6 | 7 | body{ 8 | background-color: rgb(224, 224, 224); 9 | font-family: var(--primary-font); 10 | } -------------------------------------------------------------------------------- /accounts/templates/accounts/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | {% load static tailwind_tags %} 3 | 4 | 5 | 6 | {% tailwind_css %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | django auth - {% block title%} {% endblock %} 14 | 15 | 16 | {% block form %} 17 | {% endblock form %} 18 | 19 | -------------------------------------------------------------------------------- /accounts/templates/accounts/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'accounts/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Login{% endblock title %} 5 | 6 | {% block form %} 7 |
8 | {% csrf_token %} 9 | 10 |

Log In

11 | 12 | {% if message %} 13 |

{{ message }}

14 | {% endif %} 15 |
16 |

17 | Username 18 |

19 | 20 |
21 | 22 |
23 |

24 | Password 25 |

26 | 27 |
28 | 29 | 30 | 31 |

32 | Don't have an account? Register here. 33 |

34 |
35 | 36 | 37 | {% endblock %} -------------------------------------------------------------------------------- /accounts/templates/accounts/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'accounts/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Register{% endblock title %} 5 | 6 | {% block form %} 7 |
8 | {% csrf_token %} 9 | 10 |

Register

11 | 12 | {% if message %} 13 |

{{ message }}

14 | {% endif %} 15 | 16 | {% for field in form %} 17 |
18 |

19 | {{ field.label }} 20 |

21 | {{ field }} 22 |
23 | {% endfor %} 24 | 25 | 26 | 27 |

28 | Already have an account? Login here. 29 |

30 | 31 |
32 | 33 | 34 | {% endblock %} -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | app_name = 'accounts' 5 | 6 | urlpatterns = [ 7 | path('login/', views.login_view, name='login'), 8 | path('logout/', views.logout_view, name='logout'), 9 | path('register/', views.register_view, name='register'), 10 | ] 11 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.contrib.auth import authenticate, login, logout 3 | from django.http import HttpResponse 4 | 5 | from .forms import CustomUserCreationForm 6 | from .models import User 7 | 8 | # Create your views here. 9 | def login_view(request): 10 | 11 | #prevents access by logged in users 12 | if request.user.is_authenticated: 13 | return redirect('dashboard:index') 14 | 15 | if request.method == 'POST': 16 | username = request.POST['username'] 17 | password = request.POST['password'] 18 | user = authenticate(request, username=username, password=password) 19 | 20 | if user is not None: 21 | login(request, user) 22 | return redirect('dashboard:index') 23 | else: 24 | return render(request, 'accounts/login.html', { 25 | 'message': 'Invalid username and/or password' 26 | }) 27 | elif request.method == 'GET': 28 | return render(request, 'accounts/login.html') 29 | 30 | def logout_view(request): 31 | logout(request) 32 | return redirect('accounts:login') 33 | 34 | def register_view(request): 35 | 36 | #prevents access by logged in users 37 | if request.user.is_authenticated: 38 | return redirect('dashboard:index') 39 | 40 | if request.method == 'POST': 41 | form = CustomUserCreationForm(request.POST) 42 | if form.is_valid(): 43 | user = form.save() 44 | login(request, user) 45 | return redirect('dashboard:index') 46 | else: 47 | #checks if username is taken 48 | username = request.POST['username'] 49 | if User.objects.filter(username=username).exists(): 50 | return render(request, 'accounts/register.html', { 51 | 'form': form, 52 | 'message': 'Username has already been taken' 53 | }) 54 | #checks if email is taken 55 | email = request.POST['email'] 56 | if User.objects.filter(email=email).exists(): 57 | return render(request, 'accounts/register.html', { 58 | 'form': form, 59 | 'message': 'Email address is already in use' 60 | }) 61 | password1 = request.POST['password1'] 62 | confirm = request.POST['password2'] 63 | if password1 != confirm: 64 | return render(request, 'accounts/register.html', { 65 | 'form': form, 66 | 'message': 'Passwords do not match' 67 | }) 68 | 69 | return render(request, 'accounts/register.html', { 70 | 'form': form, 71 | 'message': 'An unknown error occured.' 72 | }) 73 | elif request.method == 'GET': 74 | form = CustomUserCreationForm() 75 | return render(request, 'accounts/register.html', {'form': form}) 76 | -------------------------------------------------------------------------------- /dashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/dashboard/__init__.py -------------------------------------------------------------------------------- /dashboard/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /dashboard/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DashboardConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'dashboard' 7 | -------------------------------------------------------------------------------- /dashboard/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/dashboard/migrations/__init__.py -------------------------------------------------------------------------------- /dashboard/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /dashboard/static/dashboard/css/dashboard.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); 2 | 3 | :root{ 4 | --primary-font: 'Inter', sans-serif; 5 | --heading-color: #19a26d; 6 | } 7 | 8 | strong{ 9 | font-weight: 600; 10 | color: var(--heading-color); 11 | } 12 | 13 | body{ 14 | font-family: var(--primary-font); 15 | background-color: rgb(255, 255, 255); 16 | display: flex; 17 | flex-direction: column; 18 | gap: 20px; 19 | padding: 20px 20px; 20 | } 21 | 22 | li{ 23 | margin: 5px 0px; 24 | } 25 | 26 | h1{ 27 | font-weight: 600; 28 | font-size: 32px; 29 | color: var(--heading-color); 30 | } 31 | 32 | h2{ 33 | font-weight: 600; 34 | font-size: 28px; 35 | color: var(--heading-color); 36 | } -------------------------------------------------------------------------------- /dashboard/templates/dashboard/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | {% load static tailwind_tags %} 3 | 4 | 5 | 6 | {% tailwind_css %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | dashboard 14 | 15 | 16 | {% block content %} 17 | {% endblock content %} 18 | 19 | -------------------------------------------------------------------------------- /dashboard/templates/dashboard/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'dashboard/base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |

Hi there, {{request.user}}. Welcome to the dashboard

8 | 9 | This is a blank dashboard page which inherits from dashboard/base.html. It has seperate CSS from the landing page and is located at dashboard/static/dashboard/css/dashboard.css 10 | 11 |

Note: this page is login restricted and can only be accessed by logged in users.

12 | 13 |

Instructions

14 | 15 |
    16 |
  1. 17 | There is one CSS file in this app - dashboard.css. Feel free to replace this CSS with your own custom CSS 18 |
  2. 19 |
20 | 21 |

To log out, click here

22 | 23 | 24 | {% endblock content %} 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /dashboard/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /dashboard/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from . import views 3 | 4 | app_name = 'dashboard' 5 | 6 | urlpatterns = [ 7 | path('', views.index, name='index') 8 | ] 9 | -------------------------------------------------------------------------------- /dashboard/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.contrib.auth.decorators import login_required 3 | 4 | # Create your views here. 5 | def index(request): 6 | 7 | #if user is not logged in, redirect to home page 8 | if not request.user.is_authenticated: 9 | return redirect('accounts:login') 10 | 11 | return render(request, 'dashboard/index.html') -------------------------------------------------------------------------------- /djangotemplate/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/djangotemplate/__init__.py -------------------------------------------------------------------------------- /djangotemplate/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for djangotemplate project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangotemplate.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /djangotemplate/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for djangotemplate project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.1.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.1/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | from pathlib import Path 16 | from dotenv import load_dotenv 17 | from shutil import which 18 | 19 | 20 | load_dotenv() 21 | 22 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 23 | BASE_DIR = Path(__file__).resolve().parent.parent 24 | 25 | NPM_BIN_PATH = which('npm') 26 | 27 | 28 | # Quick-start development settings - unsuitable for production 29 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 30 | 31 | # SECURITY WARNING: keep the secret key used in production secret! 32 | SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-25(@rn#gehs9i^-a9(v2m2$%bio6&r%%mx@2&=9m9r-wixk)6$') 33 | 34 | # SECURITY WARNING: don't run with debug turned on in production! 35 | DEBUG = os.getenv('DEBUG', 'True').lower() != 'false' 36 | 37 | ALLOWED_HOSTS = [] 38 | 39 | 40 | # Application definition 41 | 42 | INSTALLED_APPS = [ 43 | 'django_browser_reload', 44 | 'theme', 45 | 'tailwind', 46 | 'accounts', 47 | 'landing_page', 48 | 'dashboard', 49 | 'django.contrib.admin', 50 | 'django.contrib.auth', 51 | 'django.contrib.contenttypes', 52 | 'django.contrib.sessions', 53 | 'django.contrib.messages', 54 | 'django.contrib.staticfiles', 55 | 'storages', 56 | ] 57 | 58 | MIDDLEWARE = [ 59 | 'django_browser_reload.middleware.BrowserReloadMiddleware', 60 | 'django.middleware.security.SecurityMiddleware', 61 | 'django.contrib.sessions.middleware.SessionMiddleware', 62 | 'django.middleware.common.CommonMiddleware', 63 | 'django.middleware.csrf.CsrfViewMiddleware', 64 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 65 | 'django.contrib.messages.middleware.MessageMiddleware', 66 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 67 | ] 68 | 69 | ROOT_URLCONF = 'djangotemplate.urls' 70 | 71 | TEMPLATES = [ 72 | { 73 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 74 | 'DIRS': [], 75 | 'APP_DIRS': True, 76 | 'OPTIONS': { 77 | 'context_processors': [ 78 | 'django.template.context_processors.debug', 79 | 'django.template.context_processors.request', 80 | 'django.contrib.auth.context_processors.auth', 81 | 'django.contrib.messages.context_processors.messages', 82 | ], 83 | }, 84 | }, 85 | ] 86 | 87 | WSGI_APPLICATION = 'djangotemplate.wsgi.application' 88 | 89 | 90 | # Database 91 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 92 | 93 | 94 | if DEBUG: 95 | DATABASES = { 96 | 'default': { 97 | 'ENGINE': 'django.db.backends.sqlite3', 98 | 'NAME': BASE_DIR / 'db.sqlite3', 99 | } 100 | } 101 | else: 102 | DATABASES = { 103 | 104 | 'default': { 105 | 106 | 'ENGINE': 'django.db.backends.postgresql', 107 | 'NAME': os.getenv('DB_NAME'), 108 | 'USER': os.getenv('DB_USER'), 109 | 'PASSWORD': os.getenv('DB_PASSWORD'), 110 | 'HOST': os.getenv('DB_HOST'), 111 | 'PORT': os.getenv('DB_PORT'), 112 | 113 | } 114 | 115 | } 116 | 117 | # Password validation 118 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 119 | 120 | AUTH_PASSWORD_VALIDATORS = [ 121 | { 122 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 123 | }, 124 | { 125 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 126 | }, 127 | { 128 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 129 | }, 130 | { 131 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 132 | }, 133 | ] 134 | 135 | 136 | # Internationalization 137 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 138 | 139 | LANGUAGE_CODE = 'en-us' 140 | 141 | TIME_ZONE = 'UTC' 142 | 143 | USE_I18N = True 144 | 145 | USE_TZ = True 146 | 147 | 148 | # Static files (CSS, JavaScript, Images) 149 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 150 | 151 | STATIC_URL = 'static/' 152 | 153 | # Default primary key field type 154 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 155 | 156 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 157 | 158 | AUTH_USER_MODEL = 'accounts.User' 159 | 160 | #Tailwind configuration 161 | TAILWIND_APP_NAME = 'theme' 162 | INTERNAL_IPS = [ 163 | '127.0.0.1', 164 | ] 165 | 166 | #AWS S3 configuration 167 | if not DEBUG: 168 | AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID') 169 | AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY') 170 | AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME') 171 | AWS_S3_SIGNATURE_VERSION = 's3v4' 172 | AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME') 173 | 174 | AWS_S3_FILE_OVERWRITE = False 175 | AWS_DEFAULT_ACL = None 176 | 177 | STORAGES = { 178 | "default": { 179 | "BACKEND": "storages.backends.s3.S3Storage", 180 | }, 181 | "staticfiles": { 182 | "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", 183 | }, 184 | } -------------------------------------------------------------------------------- /djangotemplate/urls.py: -------------------------------------------------------------------------------- 1 | """djangotemplate URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('', include('landing_page.urls', namespace='landing_page')), 22 | path('dashboard/', include('dashboard.urls', namespace='dashboard')), 23 | path('accounts/', include('accounts.urls', namespace='accounts')), 24 | path("__reload__/", include("django_browser_reload.urls")), 25 | ] 26 | -------------------------------------------------------------------------------- /djangotemplate/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djangotemplate project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangotemplate.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /landing_page/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/landing_page/__init__.py -------------------------------------------------------------------------------- /landing_page/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /landing_page/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class LandingPageConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'landing_page' 7 | -------------------------------------------------------------------------------- /landing_page/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/landing_page/migrations/__init__.py -------------------------------------------------------------------------------- /landing_page/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /landing_page/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/landing_page/requirements.txt -------------------------------------------------------------------------------- /landing_page/static/landing_page/css/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); 2 | 3 | :root{ 4 | --primary-font: 'Inter', sans-serif; 5 | --heading-color: #092e20; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /landing_page/static/landing_page/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | blockquote, q { 35 | quotes: none; 36 | } 37 | blockquote:before, blockquote:after, 38 | q:before, q:after { 39 | content: ''; 40 | content: none; 41 | } 42 | table { 43 | border-collapse: collapse; 44 | border-spacing: 0; 45 | } -------------------------------------------------------------------------------- /landing_page/static/landing_page/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/landing_page/static/landing_page/images/favicon.png -------------------------------------------------------------------------------- /landing_page/templates/landing_page/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | {% load static tailwind_tags %} 3 | 4 | 5 | 6 | {% tailwind_css %} 7 | 8 | 9 | 10 | 13 | 14 | 15 | django template 16 | 17 | 18 | {% block content %} 19 | {% endblock content %} 20 | 21 | 22 | -------------------------------------------------------------------------------- /landing_page/templates/landing_page/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'landing_page/base.html' %} 2 | {% load static %} 3 | {% block content %} 4 |

Welcome to the landing page

5 | This is a blank landing page which inherits from landing_page/base.html. Feel free to add more routes to this app and edit the base.html file to add more content to the landing page. 6 |

Editing Instructions

7 |
    8 |
  1. 9 | The default favicon can be found in static/landing_page/images/favicon.png. To use your own logo, simply replace favicon.png with your own image (use the same image name or edit base.html to reflect the new name). 10 |
  2. 11 |
  3. 12 | There are two CSS files in this app - reset.css and index.css. 13 |
      14 |
    • 15 | reset.css is used to reset the default CSS of the browser. I used this CSS reset from Meyerweb but feel free to replace it with Normalize CSS or any other CSS reset. 18 |
    • 19 |
    • index.css is used to style this page. Feel free to delete this CSS file and replace it with your own.
    • 20 |
    21 |
  4. 22 |
23 |

24 | To log in, click here 25 |

26 |

27 | To register, click here 28 |

29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /landing_page/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /landing_page/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from . import views 3 | 4 | app_name = 'landing_page' 5 | 6 | urlpatterns = [ 7 | path('', views.index, name='index') 8 | ] 9 | -------------------------------------------------------------------------------- /landing_page/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Initial landing page view. 4 | def index(request): 5 | return render(request, 'landing_page/index.html') 6 | 7 | 8 | #Add other views here -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangotemplate.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "django-template", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "django-template" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | arrow==1.3.0 2 | asgiref==3.8.1 3 | binaryornot==0.4.4 4 | boto3==1.35.74 5 | botocore==1.35.74 6 | certifi>=2024.7.4 7 | chardet==5.2.0 8 | charset-normalizer==3.3.2 9 | click==8.1.7 10 | colorama==0.4.6 11 | cookiecutter==2.6.0 12 | cssbeautifier==1.15.1 13 | Django>=5.0.14 14 | django-browser-reload==1.12.1 15 | django-storages==1.14.4 16 | django-tailwind==3.8.0 17 | djlint==1.36.3 18 | EditorConfig==0.12.4 19 | idna==3.7 20 | Jinja2==3.1.4 21 | jmespath==1.0.1 22 | jsbeautifier==1.15.1 23 | json5==0.10.0 24 | markdown-it-py==3.0.0 25 | MarkupSafe==2.1.3 26 | mdurl==0.1.2 27 | pathspec==0.12.1 28 | psycopg2-binary==2.9.10 29 | Pygments==2.16.1 30 | python-dateutil==2.8.2 31 | python-dotenv==1.0.1 32 | python-slugify==8.0.4 33 | PyYAML==6.0.1 34 | regex==2024.11.6 35 | requests==2.32.0 36 | rich==13.6.0 37 | s3transfer==0.10.4 38 | six==1.16.0 39 | sqlparse==0.5.0 40 | text-unidecode==1.3 41 | tqdm==4.67.1 42 | types-python-dateutil==2.8.19.14 43 | tzdata==2024.2 44 | urllib3==2.2.1 45 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #Make database migrations 2 | python manage.py makemigrations && python manage.py migrate 3 | 4 | #Renames project 5 | echo "Enter a new project name: (ensure name is allowed by Django before pressing enter)" 6 | read project_name 7 | python manage.py rename 'djangotemplate' $project_name 8 | 9 | #Run server 10 | python manage.py runserver 11 | 12 | #Install tailwind dependencies 13 | python manage.py tailwind install 14 | 15 | echo "Project setup complete." -------------------------------------------------------------------------------- /theme/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-awe/django-quickstart/cf84666446071ea1dd98ce0284dfa623b04188c7/theme/__init__.py -------------------------------------------------------------------------------- /theme/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ThemeConfig(AppConfig): 5 | name = 'theme' 6 | -------------------------------------------------------------------------------- /theme/static_src/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /theme/static_src/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theme", 3 | "version": "3.6.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "theme", 9 | "version": "3.6.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@tailwindcss/aspect-ratio": "^0.4.2", 13 | "@tailwindcss/forms": "^0.5.3", 14 | "@tailwindcss/line-clamp": "^0.4.4", 15 | "@tailwindcss/typography": "^0.5.9", 16 | "cross-env": "^7.0.3", 17 | "postcss": "^8.4.24", 18 | "postcss-import": "^15.1.0", 19 | "postcss-nested": "^6.0.1", 20 | "postcss-simple-vars": "^7.0.1", 21 | "rimraf": "^5.0.1", 22 | "tailwindcss": "^3.3.2" 23 | } 24 | }, 25 | "node_modules/@alloc/quick-lru": { 26 | "version": "5.2.0", 27 | "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 28 | "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 29 | "dev": true, 30 | "engines": { 31 | "node": ">=10" 32 | }, 33 | "funding": { 34 | "url": "https://github.com/sponsors/sindresorhus" 35 | } 36 | }, 37 | "node_modules/@isaacs/cliui": { 38 | "version": "8.0.2", 39 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 40 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 41 | "dev": true, 42 | "dependencies": { 43 | "string-width": "^5.1.2", 44 | "string-width-cjs": "npm:string-width@^4.2.0", 45 | "strip-ansi": "^7.0.1", 46 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 47 | "wrap-ansi": "^8.1.0", 48 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 49 | }, 50 | "engines": { 51 | "node": ">=12" 52 | } 53 | }, 54 | "node_modules/@jridgewell/gen-mapping": { 55 | "version": "0.3.3", 56 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 57 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 58 | "dev": true, 59 | "dependencies": { 60 | "@jridgewell/set-array": "^1.0.1", 61 | "@jridgewell/sourcemap-codec": "^1.4.10", 62 | "@jridgewell/trace-mapping": "^0.3.9" 63 | }, 64 | "engines": { 65 | "node": ">=6.0.0" 66 | } 67 | }, 68 | "node_modules/@jridgewell/resolve-uri": { 69 | "version": "3.1.1", 70 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", 71 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", 72 | "dev": true, 73 | "engines": { 74 | "node": ">=6.0.0" 75 | } 76 | }, 77 | "node_modules/@jridgewell/set-array": { 78 | "version": "1.1.2", 79 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 80 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 81 | "dev": true, 82 | "engines": { 83 | "node": ">=6.0.0" 84 | } 85 | }, 86 | "node_modules/@jridgewell/sourcemap-codec": { 87 | "version": "1.4.15", 88 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 89 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 90 | "dev": true 91 | }, 92 | "node_modules/@jridgewell/trace-mapping": { 93 | "version": "0.3.20", 94 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", 95 | "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", 96 | "dev": true, 97 | "dependencies": { 98 | "@jridgewell/resolve-uri": "^3.1.0", 99 | "@jridgewell/sourcemap-codec": "^1.4.14" 100 | } 101 | }, 102 | "node_modules/@nodelib/fs.scandir": { 103 | "version": "2.1.5", 104 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 105 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 106 | "dev": true, 107 | "dependencies": { 108 | "@nodelib/fs.stat": "2.0.5", 109 | "run-parallel": "^1.1.9" 110 | }, 111 | "engines": { 112 | "node": ">= 8" 113 | } 114 | }, 115 | "node_modules/@nodelib/fs.stat": { 116 | "version": "2.0.5", 117 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 118 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 119 | "dev": true, 120 | "engines": { 121 | "node": ">= 8" 122 | } 123 | }, 124 | "node_modules/@nodelib/fs.walk": { 125 | "version": "1.2.8", 126 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 127 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 128 | "dev": true, 129 | "dependencies": { 130 | "@nodelib/fs.scandir": "2.1.5", 131 | "fastq": "^1.6.0" 132 | }, 133 | "engines": { 134 | "node": ">= 8" 135 | } 136 | }, 137 | "node_modules/@pkgjs/parseargs": { 138 | "version": "0.11.0", 139 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 140 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 141 | "dev": true, 142 | "optional": true, 143 | "engines": { 144 | "node": ">=14" 145 | } 146 | }, 147 | "node_modules/@tailwindcss/aspect-ratio": { 148 | "version": "0.4.2", 149 | "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", 150 | "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", 151 | "dev": true, 152 | "peerDependencies": { 153 | "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" 154 | } 155 | }, 156 | "node_modules/@tailwindcss/forms": { 157 | "version": "0.5.6", 158 | "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.6.tgz", 159 | "integrity": "sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==", 160 | "dev": true, 161 | "dependencies": { 162 | "mini-svg-data-uri": "^1.2.3" 163 | }, 164 | "peerDependencies": { 165 | "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" 166 | } 167 | }, 168 | "node_modules/@tailwindcss/line-clamp": { 169 | "version": "0.4.4", 170 | "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz", 171 | "integrity": "sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==", 172 | "dev": true, 173 | "peerDependencies": { 174 | "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" 175 | } 176 | }, 177 | "node_modules/@tailwindcss/typography": { 178 | "version": "0.5.10", 179 | "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.10.tgz", 180 | "integrity": "sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==", 181 | "dev": true, 182 | "dependencies": { 183 | "lodash.castarray": "^4.4.0", 184 | "lodash.isplainobject": "^4.0.6", 185 | "lodash.merge": "^4.6.2", 186 | "postcss-selector-parser": "6.0.10" 187 | }, 188 | "peerDependencies": { 189 | "tailwindcss": ">=3.0.0 || insiders" 190 | } 191 | }, 192 | "node_modules/ansi-regex": { 193 | "version": "6.0.1", 194 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 195 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 196 | "dev": true, 197 | "engines": { 198 | "node": ">=12" 199 | }, 200 | "funding": { 201 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 202 | } 203 | }, 204 | "node_modules/ansi-styles": { 205 | "version": "6.2.1", 206 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 207 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 208 | "dev": true, 209 | "engines": { 210 | "node": ">=12" 211 | }, 212 | "funding": { 213 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 214 | } 215 | }, 216 | "node_modules/any-promise": { 217 | "version": "1.3.0", 218 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 219 | "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", 220 | "dev": true 221 | }, 222 | "node_modules/anymatch": { 223 | "version": "3.1.3", 224 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 225 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 226 | "dev": true, 227 | "dependencies": { 228 | "normalize-path": "^3.0.0", 229 | "picomatch": "^2.0.4" 230 | }, 231 | "engines": { 232 | "node": ">= 8" 233 | } 234 | }, 235 | "node_modules/arg": { 236 | "version": "5.0.2", 237 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", 238 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", 239 | "dev": true 240 | }, 241 | "node_modules/balanced-match": { 242 | "version": "1.0.2", 243 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 244 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 245 | "dev": true 246 | }, 247 | "node_modules/binary-extensions": { 248 | "version": "2.2.0", 249 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 250 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 251 | "dev": true, 252 | "engines": { 253 | "node": ">=8" 254 | } 255 | }, 256 | "node_modules/brace-expansion": { 257 | "version": "2.0.1", 258 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 259 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 260 | "dev": true, 261 | "dependencies": { 262 | "balanced-match": "^1.0.0" 263 | } 264 | }, 265 | "node_modules/braces": { 266 | "version": "3.0.2", 267 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 268 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 269 | "dev": true, 270 | "dependencies": { 271 | "fill-range": "^7.0.1" 272 | }, 273 | "engines": { 274 | "node": ">=8" 275 | } 276 | }, 277 | "node_modules/camelcase-css": { 278 | "version": "2.0.1", 279 | "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", 280 | "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", 281 | "dev": true, 282 | "engines": { 283 | "node": ">= 6" 284 | } 285 | }, 286 | "node_modules/chokidar": { 287 | "version": "3.5.3", 288 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 289 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 290 | "dev": true, 291 | "funding": [ 292 | { 293 | "type": "individual", 294 | "url": "https://paulmillr.com/funding/" 295 | } 296 | ], 297 | "dependencies": { 298 | "anymatch": "~3.1.2", 299 | "braces": ">=3.0.3", 300 | "glob-parent": "~5.1.2", 301 | "is-binary-path": "~2.1.0", 302 | "is-glob": "~4.0.1", 303 | "normalize-path": "~3.0.0", 304 | "readdirp": "~3.6.0" 305 | }, 306 | "engines": { 307 | "node": ">= 8.10.0" 308 | }, 309 | "optionalDependencies": { 310 | "fsevents": "~2.3.2" 311 | } 312 | }, 313 | "node_modules/chokidar/node_modules/glob-parent": { 314 | "version": "5.1.2", 315 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 316 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 317 | "dev": true, 318 | "dependencies": { 319 | "is-glob": "^4.0.1" 320 | }, 321 | "engines": { 322 | "node": ">= 6" 323 | } 324 | }, 325 | "node_modules/color-convert": { 326 | "version": "2.0.1", 327 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 328 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 329 | "dev": true, 330 | "dependencies": { 331 | "color-name": "~1.1.4" 332 | }, 333 | "engines": { 334 | "node": ">=7.0.0" 335 | } 336 | }, 337 | "node_modules/color-name": { 338 | "version": "1.1.4", 339 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 340 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 341 | "dev": true 342 | }, 343 | "node_modules/commander": { 344 | "version": "4.1.1", 345 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 346 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 347 | "dev": true, 348 | "engines": { 349 | "node": ">= 6" 350 | } 351 | }, 352 | "node_modules/concat-map": { 353 | "version": "0.0.1", 354 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 355 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 356 | "dev": true 357 | }, 358 | "node_modules/cross-env": { 359 | "version": "7.0.3", 360 | "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", 361 | "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", 362 | "dev": true, 363 | "dependencies": { 364 | "cross-spawn": "^7.0.1" 365 | }, 366 | "bin": { 367 | "cross-env": "src/bin/cross-env.js", 368 | "cross-env-shell": "src/bin/cross-env-shell.js" 369 | }, 370 | "engines": { 371 | "node": ">=10.14", 372 | "npm": ">=6", 373 | "yarn": ">=1" 374 | } 375 | }, 376 | "node_modules/cross-spawn": { 377 | "version": "7.0.3", 378 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 379 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 380 | "dev": true, 381 | "dependencies": { 382 | "path-key": "^3.1.0", 383 | "shebang-command": "^2.0.0", 384 | "which": "^2.0.1" 385 | }, 386 | "engines": { 387 | "node": ">= 8" 388 | } 389 | }, 390 | "node_modules/cssesc": { 391 | "version": "3.0.0", 392 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 393 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 394 | "dev": true, 395 | "bin": { 396 | "cssesc": "bin/cssesc" 397 | }, 398 | "engines": { 399 | "node": ">=4" 400 | } 401 | }, 402 | "node_modules/didyoumean": { 403 | "version": "1.2.2", 404 | "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", 405 | "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", 406 | "dev": true 407 | }, 408 | "node_modules/dlv": { 409 | "version": "1.1.3", 410 | "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 411 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 412 | "dev": true 413 | }, 414 | "node_modules/eastasianwidth": { 415 | "version": "0.2.0", 416 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 417 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 418 | "dev": true 419 | }, 420 | "node_modules/emoji-regex": { 421 | "version": "9.2.2", 422 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 423 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 424 | "dev": true 425 | }, 426 | "node_modules/fast-glob": { 427 | "version": "3.3.1", 428 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", 429 | "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", 430 | "dev": true, 431 | "dependencies": { 432 | "@nodelib/fs.stat": "^2.0.2", 433 | "@nodelib/fs.walk": "^1.2.3", 434 | "glob-parent": "^5.1.2", 435 | "merge2": "^1.3.0", 436 | "micromatch": "^4.0.4" 437 | }, 438 | "engines": { 439 | "node": ">=8.6.0" 440 | } 441 | }, 442 | "node_modules/fast-glob/node_modules/glob-parent": { 443 | "version": "5.1.2", 444 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 445 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 446 | "dev": true, 447 | "dependencies": { 448 | "is-glob": "^4.0.1" 449 | }, 450 | "engines": { 451 | "node": ">= 6" 452 | } 453 | }, 454 | "node_modules/fastq": { 455 | "version": "1.15.0", 456 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", 457 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 458 | "dev": true, 459 | "dependencies": { 460 | "reusify": "^1.0.4" 461 | } 462 | }, 463 | "node_modules/fill-range": { 464 | "version": "7.0.1", 465 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 466 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 467 | "dev": true, 468 | "dependencies": { 469 | "to-regex-range": "^5.0.1" 470 | }, 471 | "engines": { 472 | "node": ">=8" 473 | } 474 | }, 475 | "node_modules/foreground-child": { 476 | "version": "3.1.1", 477 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 478 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 479 | "dev": true, 480 | "dependencies": { 481 | "cross-spawn": "^7.0.0", 482 | "signal-exit": "^4.0.1" 483 | }, 484 | "engines": { 485 | "node": ">=14" 486 | }, 487 | "funding": { 488 | "url": "https://github.com/sponsors/isaacs" 489 | } 490 | }, 491 | "node_modules/fs.realpath": { 492 | "version": "1.0.0", 493 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 494 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 495 | "dev": true 496 | }, 497 | "node_modules/fsevents": { 498 | "version": "2.3.3", 499 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 500 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 501 | "dev": true, 502 | "hasInstallScript": true, 503 | "optional": true, 504 | "os": [ 505 | "darwin" 506 | ], 507 | "engines": { 508 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 509 | } 510 | }, 511 | "node_modules/function-bind": { 512 | "version": "1.1.2", 513 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 514 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 515 | "dev": true, 516 | "funding": { 517 | "url": "https://github.com/sponsors/ljharb" 518 | } 519 | }, 520 | "node_modules/glob": { 521 | "version": "10.3.10", 522 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", 523 | "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", 524 | "dev": true, 525 | "dependencies": { 526 | "foreground-child": "^3.1.0", 527 | "jackspeak": "^2.3.5", 528 | "minimatch": "^9.0.1", 529 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", 530 | "path-scurry": "^1.10.1" 531 | }, 532 | "bin": { 533 | "glob": "dist/esm/bin.mjs" 534 | }, 535 | "engines": { 536 | "node": ">=16 || 14 >=14.17" 537 | }, 538 | "funding": { 539 | "url": "https://github.com/sponsors/isaacs" 540 | } 541 | }, 542 | "node_modules/glob-parent": { 543 | "version": "6.0.2", 544 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 545 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 546 | "dev": true, 547 | "dependencies": { 548 | "is-glob": "^4.0.3" 549 | }, 550 | "engines": { 551 | "node": ">=10.13.0" 552 | } 553 | }, 554 | "node_modules/hasown": { 555 | "version": "2.0.0", 556 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", 557 | "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", 558 | "dev": true, 559 | "dependencies": { 560 | "function-bind": "^1.1.2" 561 | }, 562 | "engines": { 563 | "node": ">= 0.4" 564 | } 565 | }, 566 | "node_modules/inflight": { 567 | "version": "1.0.6", 568 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 569 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 570 | "dev": true, 571 | "dependencies": { 572 | "once": "^1.3.0", 573 | "wrappy": "1" 574 | } 575 | }, 576 | "node_modules/inherits": { 577 | "version": "2.0.4", 578 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 579 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 580 | "dev": true 581 | }, 582 | "node_modules/is-binary-path": { 583 | "version": "2.1.0", 584 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 585 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 586 | "dev": true, 587 | "dependencies": { 588 | "binary-extensions": "^2.0.0" 589 | }, 590 | "engines": { 591 | "node": ">=8" 592 | } 593 | }, 594 | "node_modules/is-core-module": { 595 | "version": "2.13.1", 596 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", 597 | "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", 598 | "dev": true, 599 | "dependencies": { 600 | "hasown": "^2.0.0" 601 | }, 602 | "funding": { 603 | "url": "https://github.com/sponsors/ljharb" 604 | } 605 | }, 606 | "node_modules/is-extglob": { 607 | "version": "2.1.1", 608 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 609 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 610 | "dev": true, 611 | "engines": { 612 | "node": ">=0.10.0" 613 | } 614 | }, 615 | "node_modules/is-fullwidth-code-point": { 616 | "version": "3.0.0", 617 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 618 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 619 | "dev": true, 620 | "engines": { 621 | "node": ">=8" 622 | } 623 | }, 624 | "node_modules/is-glob": { 625 | "version": "4.0.3", 626 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 627 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 628 | "dev": true, 629 | "dependencies": { 630 | "is-extglob": "^2.1.1" 631 | }, 632 | "engines": { 633 | "node": ">=0.10.0" 634 | } 635 | }, 636 | "node_modules/is-number": { 637 | "version": "7.0.0", 638 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 639 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 640 | "dev": true, 641 | "engines": { 642 | "node": ">=0.12.0" 643 | } 644 | }, 645 | "node_modules/isexe": { 646 | "version": "2.0.0", 647 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 648 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 649 | "dev": true 650 | }, 651 | "node_modules/jackspeak": { 652 | "version": "2.3.6", 653 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", 654 | "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", 655 | "dev": true, 656 | "dependencies": { 657 | "@isaacs/cliui": "^8.0.2" 658 | }, 659 | "engines": { 660 | "node": ">=14" 661 | }, 662 | "funding": { 663 | "url": "https://github.com/sponsors/isaacs" 664 | }, 665 | "optionalDependencies": { 666 | "@pkgjs/parseargs": "^0.11.0" 667 | } 668 | }, 669 | "node_modules/jiti": { 670 | "version": "1.20.0", 671 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", 672 | "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", 673 | "dev": true, 674 | "bin": { 675 | "jiti": "bin/jiti.js" 676 | } 677 | }, 678 | "node_modules/lilconfig": { 679 | "version": "2.1.0", 680 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", 681 | "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", 682 | "dev": true, 683 | "engines": { 684 | "node": ">=10" 685 | } 686 | }, 687 | "node_modules/lines-and-columns": { 688 | "version": "1.2.4", 689 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 690 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 691 | "dev": true 692 | }, 693 | "node_modules/lodash.castarray": { 694 | "version": "4.4.0", 695 | "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", 696 | "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", 697 | "dev": true 698 | }, 699 | "node_modules/lodash.isplainobject": { 700 | "version": "4.0.6", 701 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 702 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", 703 | "dev": true 704 | }, 705 | "node_modules/lodash.merge": { 706 | "version": "4.6.2", 707 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 708 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 709 | "dev": true 710 | }, 711 | "node_modules/lru-cache": { 712 | "version": "10.0.1", 713 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", 714 | "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", 715 | "dev": true, 716 | "engines": { 717 | "node": "14 || >=16.14" 718 | } 719 | }, 720 | "node_modules/merge2": { 721 | "version": "1.4.1", 722 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 723 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 724 | "dev": true, 725 | "engines": { 726 | "node": ">= 8" 727 | } 728 | }, 729 | "node_modules/micromatch": { 730 | "version": "4.0.5", 731 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 732 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 733 | "dev": true, 734 | "dependencies": { 735 | "braces": "^3.0.2", 736 | "picomatch": "^2.3.1" 737 | }, 738 | "engines": { 739 | "node": ">=8.6" 740 | } 741 | }, 742 | "node_modules/mini-svg-data-uri": { 743 | "version": "1.4.4", 744 | "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", 745 | "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", 746 | "dev": true, 747 | "bin": { 748 | "mini-svg-data-uri": "cli.js" 749 | } 750 | }, 751 | "node_modules/minimatch": { 752 | "version": "9.0.3", 753 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", 754 | "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", 755 | "dev": true, 756 | "dependencies": { 757 | "brace-expansion": "^2.0.1" 758 | }, 759 | "engines": { 760 | "node": ">=16 || 14 >=14.17" 761 | }, 762 | "funding": { 763 | "url": "https://github.com/sponsors/isaacs" 764 | } 765 | }, 766 | "node_modules/minipass": { 767 | "version": "7.0.4", 768 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", 769 | "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", 770 | "dev": true, 771 | "engines": { 772 | "node": ">=16 || 14 >=14.17" 773 | } 774 | }, 775 | "node_modules/mz": { 776 | "version": "2.7.0", 777 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 778 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 779 | "dev": true, 780 | "dependencies": { 781 | "any-promise": "^1.0.0", 782 | "object-assign": "^4.0.1", 783 | "thenify-all": "^1.0.0" 784 | } 785 | }, 786 | "node_modules/nanoid": { 787 | "version": "3.3.6", 788 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 789 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 790 | "dev": true, 791 | "funding": [ 792 | { 793 | "type": "github", 794 | "url": "https://github.com/sponsors/ai" 795 | } 796 | ], 797 | "bin": { 798 | "nanoid": "bin/nanoid.cjs" 799 | }, 800 | "engines": { 801 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 802 | } 803 | }, 804 | "node_modules/normalize-path": { 805 | "version": "3.0.0", 806 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 807 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 808 | "dev": true, 809 | "engines": { 810 | "node": ">=0.10.0" 811 | } 812 | }, 813 | "node_modules/object-assign": { 814 | "version": "4.1.1", 815 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 816 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 817 | "dev": true, 818 | "engines": { 819 | "node": ">=0.10.0" 820 | } 821 | }, 822 | "node_modules/object-hash": { 823 | "version": "3.0.0", 824 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", 825 | "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", 826 | "dev": true, 827 | "engines": { 828 | "node": ">= 6" 829 | } 830 | }, 831 | "node_modules/once": { 832 | "version": "1.4.0", 833 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 834 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 835 | "dev": true, 836 | "dependencies": { 837 | "wrappy": "1" 838 | } 839 | }, 840 | "node_modules/path-is-absolute": { 841 | "version": "1.0.1", 842 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 843 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 844 | "dev": true, 845 | "engines": { 846 | "node": ">=0.10.0" 847 | } 848 | }, 849 | "node_modules/path-key": { 850 | "version": "3.1.1", 851 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 852 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 853 | "dev": true, 854 | "engines": { 855 | "node": ">=8" 856 | } 857 | }, 858 | "node_modules/path-parse": { 859 | "version": "1.0.7", 860 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 861 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 862 | "dev": true 863 | }, 864 | "node_modules/path-scurry": { 865 | "version": "1.10.1", 866 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", 867 | "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", 868 | "dev": true, 869 | "dependencies": { 870 | "lru-cache": "^9.1.1 || ^10.0.0", 871 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 872 | }, 873 | "engines": { 874 | "node": ">=16 || 14 >=14.17" 875 | }, 876 | "funding": { 877 | "url": "https://github.com/sponsors/isaacs" 878 | } 879 | }, 880 | "node_modules/picocolors": { 881 | "version": "1.0.0", 882 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 883 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 884 | "dev": true 885 | }, 886 | "node_modules/picomatch": { 887 | "version": "2.3.1", 888 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 889 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 890 | "dev": true, 891 | "engines": { 892 | "node": ">=8.6" 893 | }, 894 | "funding": { 895 | "url": "https://github.com/sponsors/jonschlinkert" 896 | } 897 | }, 898 | "node_modules/pify": { 899 | "version": "2.3.0", 900 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 901 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 902 | "dev": true, 903 | "engines": { 904 | "node": ">=0.10.0" 905 | } 906 | }, 907 | "node_modules/pirates": { 908 | "version": "4.0.6", 909 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", 910 | "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", 911 | "dev": true, 912 | "engines": { 913 | "node": ">= 6" 914 | } 915 | }, 916 | "node_modules/postcss": { 917 | "version": "8.4.31", 918 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", 919 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", 920 | "dev": true, 921 | "funding": [ 922 | { 923 | "type": "opencollective", 924 | "url": "https://opencollective.com/postcss/" 925 | }, 926 | { 927 | "type": "tidelift", 928 | "url": "https://tidelift.com/funding/github/npm/postcss" 929 | }, 930 | { 931 | "type": "github", 932 | "url": "https://github.com/sponsors/ai" 933 | } 934 | ], 935 | "dependencies": { 936 | "nanoid": "^3.3.6", 937 | "picocolors": "^1.0.0", 938 | "source-map-js": "^1.0.2" 939 | }, 940 | "engines": { 941 | "node": "^10 || ^12 || >=14" 942 | } 943 | }, 944 | "node_modules/postcss-import": { 945 | "version": "15.1.0", 946 | "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", 947 | "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", 948 | "dev": true, 949 | "dependencies": { 950 | "postcss-value-parser": "^4.0.0", 951 | "read-cache": "^1.0.0", 952 | "resolve": "^1.1.7" 953 | }, 954 | "engines": { 955 | "node": ">=14.0.0" 956 | }, 957 | "peerDependencies": { 958 | "postcss": "^8.0.0" 959 | } 960 | }, 961 | "node_modules/postcss-js": { 962 | "version": "4.0.1", 963 | "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", 964 | "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", 965 | "dev": true, 966 | "dependencies": { 967 | "camelcase-css": "^2.0.1" 968 | }, 969 | "engines": { 970 | "node": "^12 || ^14 || >= 16" 971 | }, 972 | "funding": { 973 | "type": "opencollective", 974 | "url": "https://opencollective.com/postcss/" 975 | }, 976 | "peerDependencies": { 977 | "postcss": "^8.4.21" 978 | } 979 | }, 980 | "node_modules/postcss-load-config": { 981 | "version": "4.0.1", 982 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", 983 | "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", 984 | "dev": true, 985 | "dependencies": { 986 | "lilconfig": "^2.0.5", 987 | "yaml": "^2.1.1" 988 | }, 989 | "engines": { 990 | "node": ">= 14" 991 | }, 992 | "funding": { 993 | "type": "opencollective", 994 | "url": "https://opencollective.com/postcss/" 995 | }, 996 | "peerDependencies": { 997 | "postcss": ">=8.0.9", 998 | "ts-node": ">=9.0.0" 999 | }, 1000 | "peerDependenciesMeta": { 1001 | "postcss": { 1002 | "optional": true 1003 | }, 1004 | "ts-node": { 1005 | "optional": true 1006 | } 1007 | } 1008 | }, 1009 | "node_modules/postcss-nested": { 1010 | "version": "6.0.1", 1011 | "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", 1012 | "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", 1013 | "dev": true, 1014 | "dependencies": { 1015 | "postcss-selector-parser": "^6.0.11" 1016 | }, 1017 | "engines": { 1018 | "node": ">=12.0" 1019 | }, 1020 | "funding": { 1021 | "type": "opencollective", 1022 | "url": "https://opencollective.com/postcss/" 1023 | }, 1024 | "peerDependencies": { 1025 | "postcss": "^8.2.14" 1026 | } 1027 | }, 1028 | "node_modules/postcss-nested/node_modules/postcss-selector-parser": { 1029 | "version": "6.0.13", 1030 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", 1031 | "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", 1032 | "dev": true, 1033 | "dependencies": { 1034 | "cssesc": "^3.0.0", 1035 | "util-deprecate": "^1.0.2" 1036 | }, 1037 | "engines": { 1038 | "node": ">=4" 1039 | } 1040 | }, 1041 | "node_modules/postcss-selector-parser": { 1042 | "version": "6.0.10", 1043 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", 1044 | "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", 1045 | "dev": true, 1046 | "dependencies": { 1047 | "cssesc": "^3.0.0", 1048 | "util-deprecate": "^1.0.2" 1049 | }, 1050 | "engines": { 1051 | "node": ">=4" 1052 | } 1053 | }, 1054 | "node_modules/postcss-simple-vars": { 1055 | "version": "7.0.1", 1056 | "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", 1057 | "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", 1058 | "dev": true, 1059 | "engines": { 1060 | "node": ">=14.0" 1061 | }, 1062 | "funding": { 1063 | "type": "opencollective", 1064 | "url": "https://opencollective.com/postcss/" 1065 | }, 1066 | "peerDependencies": { 1067 | "postcss": "^8.2.1" 1068 | } 1069 | }, 1070 | "node_modules/postcss-value-parser": { 1071 | "version": "4.2.0", 1072 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 1073 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 1074 | "dev": true 1075 | }, 1076 | "node_modules/queue-microtask": { 1077 | "version": "1.2.3", 1078 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1079 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1080 | "dev": true, 1081 | "funding": [ 1082 | { 1083 | "type": "github", 1084 | "url": "https://github.com/sponsors/feross" 1085 | }, 1086 | { 1087 | "type": "patreon", 1088 | "url": "https://www.patreon.com/feross" 1089 | }, 1090 | { 1091 | "type": "consulting", 1092 | "url": "https://feross.org/support" 1093 | } 1094 | ] 1095 | }, 1096 | "node_modules/read-cache": { 1097 | "version": "1.0.0", 1098 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 1099 | "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", 1100 | "dev": true, 1101 | "dependencies": { 1102 | "pify": "^2.3.0" 1103 | } 1104 | }, 1105 | "node_modules/readdirp": { 1106 | "version": "3.6.0", 1107 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1108 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1109 | "dev": true, 1110 | "dependencies": { 1111 | "picomatch": "^2.2.1" 1112 | }, 1113 | "engines": { 1114 | "node": ">=8.10.0" 1115 | } 1116 | }, 1117 | "node_modules/resolve": { 1118 | "version": "1.22.8", 1119 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", 1120 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", 1121 | "dev": true, 1122 | "dependencies": { 1123 | "is-core-module": "^2.13.0", 1124 | "path-parse": "^1.0.7", 1125 | "supports-preserve-symlinks-flag": "^1.0.0" 1126 | }, 1127 | "bin": { 1128 | "resolve": "bin/resolve" 1129 | }, 1130 | "funding": { 1131 | "url": "https://github.com/sponsors/ljharb" 1132 | } 1133 | }, 1134 | "node_modules/reusify": { 1135 | "version": "1.0.4", 1136 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1137 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1138 | "dev": true, 1139 | "engines": { 1140 | "iojs": ">=1.0.0", 1141 | "node": ">=0.10.0" 1142 | } 1143 | }, 1144 | "node_modules/rimraf": { 1145 | "version": "5.0.5", 1146 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", 1147 | "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", 1148 | "dev": true, 1149 | "dependencies": { 1150 | "glob": "^10.3.7" 1151 | }, 1152 | "bin": { 1153 | "rimraf": "dist/esm/bin.mjs" 1154 | }, 1155 | "engines": { 1156 | "node": ">=14" 1157 | }, 1158 | "funding": { 1159 | "url": "https://github.com/sponsors/isaacs" 1160 | } 1161 | }, 1162 | "node_modules/run-parallel": { 1163 | "version": "1.2.0", 1164 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1165 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1166 | "dev": true, 1167 | "funding": [ 1168 | { 1169 | "type": "github", 1170 | "url": "https://github.com/sponsors/feross" 1171 | }, 1172 | { 1173 | "type": "patreon", 1174 | "url": "https://www.patreon.com/feross" 1175 | }, 1176 | { 1177 | "type": "consulting", 1178 | "url": "https://feross.org/support" 1179 | } 1180 | ], 1181 | "dependencies": { 1182 | "queue-microtask": "^1.2.2" 1183 | } 1184 | }, 1185 | "node_modules/shebang-command": { 1186 | "version": "2.0.0", 1187 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1188 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1189 | "dev": true, 1190 | "dependencies": { 1191 | "shebang-regex": "^3.0.0" 1192 | }, 1193 | "engines": { 1194 | "node": ">=8" 1195 | } 1196 | }, 1197 | "node_modules/shebang-regex": { 1198 | "version": "3.0.0", 1199 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1200 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1201 | "dev": true, 1202 | "engines": { 1203 | "node": ">=8" 1204 | } 1205 | }, 1206 | "node_modules/signal-exit": { 1207 | "version": "4.1.0", 1208 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1209 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1210 | "dev": true, 1211 | "engines": { 1212 | "node": ">=14" 1213 | }, 1214 | "funding": { 1215 | "url": "https://github.com/sponsors/isaacs" 1216 | } 1217 | }, 1218 | "node_modules/source-map-js": { 1219 | "version": "1.0.2", 1220 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1221 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1222 | "dev": true, 1223 | "engines": { 1224 | "node": ">=0.10.0" 1225 | } 1226 | }, 1227 | "node_modules/string-width": { 1228 | "version": "5.1.2", 1229 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 1230 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 1231 | "dev": true, 1232 | "dependencies": { 1233 | "eastasianwidth": "^0.2.0", 1234 | "emoji-regex": "^9.2.2", 1235 | "strip-ansi": "^7.0.1" 1236 | }, 1237 | "engines": { 1238 | "node": ">=12" 1239 | }, 1240 | "funding": { 1241 | "url": "https://github.com/sponsors/sindresorhus" 1242 | } 1243 | }, 1244 | "node_modules/string-width-cjs": { 1245 | "name": "string-width", 1246 | "version": "4.2.3", 1247 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1248 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1249 | "dev": true, 1250 | "dependencies": { 1251 | "emoji-regex": "^8.0.0", 1252 | "is-fullwidth-code-point": "^3.0.0", 1253 | "strip-ansi": "^6.0.1" 1254 | }, 1255 | "engines": { 1256 | "node": ">=8" 1257 | } 1258 | }, 1259 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 1260 | "version": "5.0.1", 1261 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1262 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1263 | "dev": true, 1264 | "engines": { 1265 | "node": ">=8" 1266 | } 1267 | }, 1268 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 1269 | "version": "8.0.0", 1270 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1271 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1272 | "dev": true 1273 | }, 1274 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 1275 | "version": "6.0.1", 1276 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1277 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1278 | "dev": true, 1279 | "dependencies": { 1280 | "ansi-regex": "^5.0.1" 1281 | }, 1282 | "engines": { 1283 | "node": ">=8" 1284 | } 1285 | }, 1286 | "node_modules/strip-ansi": { 1287 | "version": "7.1.0", 1288 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 1289 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 1290 | "dev": true, 1291 | "dependencies": { 1292 | "ansi-regex": "^6.0.1" 1293 | }, 1294 | "engines": { 1295 | "node": ">=12" 1296 | }, 1297 | "funding": { 1298 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1299 | } 1300 | }, 1301 | "node_modules/strip-ansi-cjs": { 1302 | "name": "strip-ansi", 1303 | "version": "6.0.1", 1304 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1305 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1306 | "dev": true, 1307 | "dependencies": { 1308 | "ansi-regex": "^5.0.1" 1309 | }, 1310 | "engines": { 1311 | "node": ">=8" 1312 | } 1313 | }, 1314 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 1315 | "version": "5.0.1", 1316 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1317 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1318 | "dev": true, 1319 | "engines": { 1320 | "node": ">=8" 1321 | } 1322 | }, 1323 | "node_modules/sucrase": { 1324 | "version": "3.34.0", 1325 | "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", 1326 | "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", 1327 | "dev": true, 1328 | "dependencies": { 1329 | "@jridgewell/gen-mapping": "^0.3.2", 1330 | "commander": "^4.0.0", 1331 | "glob": "7.1.6", 1332 | "lines-and-columns": "^1.1.6", 1333 | "mz": "^2.7.0", 1334 | "pirates": "^4.0.1", 1335 | "ts-interface-checker": "^0.1.9" 1336 | }, 1337 | "bin": { 1338 | "sucrase": "bin/sucrase", 1339 | "sucrase-node": "bin/sucrase-node" 1340 | }, 1341 | "engines": { 1342 | "node": ">=8" 1343 | } 1344 | }, 1345 | "node_modules/sucrase/node_modules/brace-expansion": { 1346 | "version": "1.1.11", 1347 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1348 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1349 | "dev": true, 1350 | "dependencies": { 1351 | "balanced-match": "^1.0.0", 1352 | "concat-map": "0.0.1" 1353 | } 1354 | }, 1355 | "node_modules/sucrase/node_modules/glob": { 1356 | "version": "7.1.6", 1357 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 1358 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 1359 | "dev": true, 1360 | "dependencies": { 1361 | "fs.realpath": "^1.0.0", 1362 | "inflight": "^1.0.4", 1363 | "inherits": "2", 1364 | "minimatch": "^3.0.4", 1365 | "once": "^1.3.0", 1366 | "path-is-absolute": "^1.0.0" 1367 | }, 1368 | "engines": { 1369 | "node": "*" 1370 | }, 1371 | "funding": { 1372 | "url": "https://github.com/sponsors/isaacs" 1373 | } 1374 | }, 1375 | "node_modules/sucrase/node_modules/minimatch": { 1376 | "version": "3.1.2", 1377 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1378 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1379 | "dev": true, 1380 | "dependencies": { 1381 | "brace-expansion": "^1.1.7" 1382 | }, 1383 | "engines": { 1384 | "node": "*" 1385 | } 1386 | }, 1387 | "node_modules/supports-preserve-symlinks-flag": { 1388 | "version": "1.0.0", 1389 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1390 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1391 | "dev": true, 1392 | "engines": { 1393 | "node": ">= 0.4" 1394 | }, 1395 | "funding": { 1396 | "url": "https://github.com/sponsors/ljharb" 1397 | } 1398 | }, 1399 | "node_modules/tailwindcss": { 1400 | "version": "3.3.5", 1401 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", 1402 | "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", 1403 | "dev": true, 1404 | "dependencies": { 1405 | "@alloc/quick-lru": "^5.2.0", 1406 | "arg": "^5.0.2", 1407 | "chokidar": "^3.5.3", 1408 | "didyoumean": "^1.2.2", 1409 | "dlv": "^1.1.3", 1410 | "fast-glob": "^3.3.0", 1411 | "glob-parent": "^6.0.2", 1412 | "is-glob": "^4.0.3", 1413 | "jiti": "^1.19.1", 1414 | "lilconfig": "^2.1.0", 1415 | "micromatch": "^4.0.5", 1416 | "normalize-path": "^3.0.0", 1417 | "object-hash": "^3.0.0", 1418 | "picocolors": "^1.0.0", 1419 | "postcss": "^8.4.23", 1420 | "postcss-import": "^15.1.0", 1421 | "postcss-js": "^4.0.1", 1422 | "postcss-load-config": "^4.0.1", 1423 | "postcss-nested": "^6.0.1", 1424 | "postcss-selector-parser": "^6.0.11", 1425 | "resolve": "^1.22.2", 1426 | "sucrase": "^3.32.0" 1427 | }, 1428 | "bin": { 1429 | "tailwind": "lib/cli.js", 1430 | "tailwindcss": "lib/cli.js" 1431 | }, 1432 | "engines": { 1433 | "node": ">=14.0.0" 1434 | } 1435 | }, 1436 | "node_modules/tailwindcss/node_modules/postcss-selector-parser": { 1437 | "version": "6.0.13", 1438 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", 1439 | "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", 1440 | "dev": true, 1441 | "dependencies": { 1442 | "cssesc": "^3.0.0", 1443 | "util-deprecate": "^1.0.2" 1444 | }, 1445 | "engines": { 1446 | "node": ">=4" 1447 | } 1448 | }, 1449 | "node_modules/thenify": { 1450 | "version": "3.3.1", 1451 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 1452 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 1453 | "dev": true, 1454 | "dependencies": { 1455 | "any-promise": "^1.0.0" 1456 | } 1457 | }, 1458 | "node_modules/thenify-all": { 1459 | "version": "1.6.0", 1460 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 1461 | "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", 1462 | "dev": true, 1463 | "dependencies": { 1464 | "thenify": ">= 3.1.0 < 4" 1465 | }, 1466 | "engines": { 1467 | "node": ">=0.8" 1468 | } 1469 | }, 1470 | "node_modules/to-regex-range": { 1471 | "version": "5.0.1", 1472 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1473 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1474 | "dev": true, 1475 | "dependencies": { 1476 | "is-number": "^7.0.0" 1477 | }, 1478 | "engines": { 1479 | "node": ">=8.0" 1480 | } 1481 | }, 1482 | "node_modules/ts-interface-checker": { 1483 | "version": "0.1.13", 1484 | "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", 1485 | "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", 1486 | "dev": true 1487 | }, 1488 | "node_modules/util-deprecate": { 1489 | "version": "1.0.2", 1490 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1491 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1492 | "dev": true 1493 | }, 1494 | "node_modules/which": { 1495 | "version": "2.0.2", 1496 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1497 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1498 | "dev": true, 1499 | "dependencies": { 1500 | "isexe": "^2.0.0" 1501 | }, 1502 | "bin": { 1503 | "node-which": "bin/node-which" 1504 | }, 1505 | "engines": { 1506 | "node": ">= 8" 1507 | } 1508 | }, 1509 | "node_modules/wrap-ansi": { 1510 | "version": "8.1.0", 1511 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 1512 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 1513 | "dev": true, 1514 | "dependencies": { 1515 | "ansi-styles": "^6.1.0", 1516 | "string-width": "^5.0.1", 1517 | "strip-ansi": "^7.0.1" 1518 | }, 1519 | "engines": { 1520 | "node": ">=12" 1521 | }, 1522 | "funding": { 1523 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1524 | } 1525 | }, 1526 | "node_modules/wrap-ansi-cjs": { 1527 | "name": "wrap-ansi", 1528 | "version": "7.0.0", 1529 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1530 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1531 | "dev": true, 1532 | "dependencies": { 1533 | "ansi-styles": "^4.0.0", 1534 | "string-width": "^4.1.0", 1535 | "strip-ansi": "^6.0.0" 1536 | }, 1537 | "engines": { 1538 | "node": ">=10" 1539 | }, 1540 | "funding": { 1541 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1542 | } 1543 | }, 1544 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 1545 | "version": "5.0.1", 1546 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1547 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1548 | "dev": true, 1549 | "engines": { 1550 | "node": ">=8" 1551 | } 1552 | }, 1553 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 1554 | "version": "4.3.0", 1555 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1556 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1557 | "dev": true, 1558 | "dependencies": { 1559 | "color-convert": "^2.0.1" 1560 | }, 1561 | "engines": { 1562 | "node": ">=8" 1563 | }, 1564 | "funding": { 1565 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1566 | } 1567 | }, 1568 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 1569 | "version": "8.0.0", 1570 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1571 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1572 | "dev": true 1573 | }, 1574 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 1575 | "version": "4.2.3", 1576 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1577 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1578 | "dev": true, 1579 | "dependencies": { 1580 | "emoji-regex": "^8.0.0", 1581 | "is-fullwidth-code-point": "^3.0.0", 1582 | "strip-ansi": "^6.0.1" 1583 | }, 1584 | "engines": { 1585 | "node": ">=8" 1586 | } 1587 | }, 1588 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 1589 | "version": "6.0.1", 1590 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1591 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1592 | "dev": true, 1593 | "dependencies": { 1594 | "ansi-regex": "^5.0.1" 1595 | }, 1596 | "engines": { 1597 | "node": ">=8" 1598 | } 1599 | }, 1600 | "node_modules/wrappy": { 1601 | "version": "1.0.2", 1602 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1603 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1604 | "dev": true 1605 | }, 1606 | "node_modules/yaml": { 1607 | "version": "2.3.3", 1608 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", 1609 | "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", 1610 | "dev": true, 1611 | "engines": { 1612 | "node": ">= 14" 1613 | } 1614 | } 1615 | } 1616 | } 1617 | -------------------------------------------------------------------------------- /theme/static_src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theme", 3 | "version": "3.6.0", 4 | "description": "", 5 | "scripts": { 6 | "start": "npm run dev", 7 | "build": "npm run build:clean && npm run build:tailwind", 8 | "build:clean": "rimraf ../static/css/dist", 9 | "build:tailwind": "cross-env NODE_ENV=production tailwindcss --postcss -i ./src/styles.css -o ../static/css/dist/styles.css --minify", 10 | "dev": "cross-env NODE_ENV=development tailwindcss --postcss -i ./src/styles.css -o ../static/css/dist/styles.css -w", 11 | "tailwindcss": "node ./node_modules/tailwindcss/lib/cli.js" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "MIT", 16 | "devDependencies": { 17 | "@tailwindcss/aspect-ratio": "^0.4.2", 18 | "@tailwindcss/forms": "^0.5.3", 19 | "@tailwindcss/line-clamp": "^0.4.4", 20 | "@tailwindcss/typography": "^0.5.9", 21 | "cross-env": "^7.0.3", 22 | "postcss": "^8.4.24", 23 | "postcss-import": "^15.1.0", 24 | "postcss-nested": "^6.0.1", 25 | "postcss-simple-vars": "^7.0.1", 26 | "rimraf": "^5.0.1", 27 | "tailwindcss": "^3.3.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /theme/static_src/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | "postcss-import": {}, 4 | "postcss-simple-vars": {}, 5 | "postcss-nested": {} 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /theme/static_src/src/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /theme/static_src/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a minimal config. 3 | * 4 | * If you need the full config, get it from here: 5 | * https://unpkg.com/browse/tailwindcss@latest/stubs/defaultConfig.stub.js 6 | */ 7 | 8 | module.exports = { 9 | content: [ 10 | /** 11 | * HTML. Paths to Django template files that will contain Tailwind CSS classes. 12 | */ 13 | 14 | /* Templates within theme app (/templates), e.g. base.html. */ 15 | '../templates/**/*.html', 16 | 17 | /* 18 | * Main templates directory of the project (BASE_DIR/templates). 19 | * Adjust the following line to match your project structure. 20 | */ 21 | '../../templates/**/*.html', 22 | 23 | /* 24 | * Templates in other django apps (BASE_DIR//templates). 25 | * Adjust the following line to match your project structure. 26 | */ 27 | '../../**/templates/**/*.html', 28 | 29 | /** 30 | * JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure 31 | * patterns match your project structure. 32 | */ 33 | /* JS 1: Ignore any JavaScript in node_modules folder. */ 34 | // '!../../**/node_modules', 35 | /* JS 2: Process all JavaScript files in the project. */ 36 | // '../../**/*.js', 37 | 38 | /** 39 | * Python: If you use Tailwind CSS classes in Python, uncomment the following line 40 | * and make sure the pattern below matches your project structure. 41 | */ 42 | // '../../**/*.py' 43 | ], 44 | theme: { 45 | extend: {}, 46 | }, 47 | plugins: [ 48 | /** 49 | * '@tailwindcss/forms' is the forms plugin that provides a minimal styling 50 | * for forms. If you don't like it or have own styling for forms, 51 | * comment the line below to disable '@tailwindcss/forms'. 52 | */ 53 | require('@tailwindcss/forms'), 54 | require('@tailwindcss/typography'), 55 | require('@tailwindcss/line-clamp'), 56 | require('@tailwindcss/aspect-ratio'), 57 | ], 58 | } 59 | -------------------------------------------------------------------------------- /theme/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static tailwind_tags %} 2 | 3 | 4 | 5 | Django Tailwind 6 | 7 | 8 | 9 | {% tailwind_css %} 10 | 11 | 12 | 13 |
14 |
15 |

Django + Tailwind = ❤️

16 |
17 |
18 | 19 | 20 | --------------------------------------------------------------------------------