4.2 KiB
GitHub Copilot Instructions
This is an electronic component inventory management system built with Phoenix LiveView. Follow these project-specific patterns for effective contributions.
Project Architecture
Core Structure: Phoenix 1.8 with LiveView-first architecture for real-time inventory management
lib/components_elixir/- Business logic contexts (Inventory, AprilTag, Auth)lib/components_elixir_web/live/- LiveView modules for real-time UI- Key contexts:
Inventory(components/categories/locations),DatasheetDownloader,AprilTag
Hierarchical Data Pattern: Both categories and storage locations use unlimited nesting
# Use Hierarchical module for tree operations
alias ComponentsElixir.Inventory.Hierarchical
Hierarchical.build_tree(categories) # Converts flat list to nested structure
Authentication: Simple session-based auth using ComponentsElixir.Auth
- All LiveViews must check
Auth.authenticated?(session)in mount/3 - Default password: "changeme" (configurable via
AUTH_PASSWORDenv var)
Key Development Workflows
Development Setup:
mix deps.get
mix ecto.setup # Creates DB, runs migrations, seeds data
mix phx.server # Starts dev server with hot reload
Code Quality (Critical): Always run before committing
mix precommit # Compiles with warnings-as-errors, formats, runs tests
Database Operations:
mix ecto.reset # Drop/recreate/migrate/seed database
mix ecto.gen.migration # Generate new migration
LiveView Patterns
Stream-Based Components: Use LiveView streams for component lists to prevent memory issues:
# In LiveView
stream(socket, :components, components)
# In template
<div id="components" phx-update="stream">
<div :for={{id, component} <- @streams.components} id={id}>
<!-- component content -->
</div>
</div>
File Upload Handling: Uses Phoenix.LiveView.Upload with custom validators
- Datasheets: PDF only, 10MB max, stored in
uploads/datasheets/ - Images: JPEG/PNG only, 5MB max, stored in
uploads/images/
Database Conventions
Hierarchical Relationships: Self-referential parent_id foreign keys
# Schema pattern for categories/locations
field :parent_id, :id
belongs_to :parent, __MODULE__
has_many :children, __MODULE__, foreign_key: :parent_id
Component Search: Full-text search across name, description, keywords
# Use ilike for case-insensitive search
from c in Component, where: ilike(c.name, ^"%#{search}%")
Asset Management
DaisyUI Components: Prefer DaisyUI classes for consistent styling:
btn btn-primaryfor buttonscard card-compactfor component cardsbadgefor category/location tags
External Dependencies
AprilTag Generation: SVG-based tags for physical location labeling
ComponentsElixir.AprilTag.generate_svg(tag_id) # Returns SVG string
Testing Guidelines
Factory Pattern: Use explicit test data setup, not factories
- Seed realistic test data in
test/support/modules - Test both hierarchical and flat data structures
Production Deployment
Docker-First: Primary deployment method via docker-compose.yml
- Environment:
SECRET_KEY_BASE,AUTH_PASSWORD,PHX_HOST - File uploads mounted as volumes:
./uploads:/app/uploads
Release Commands: Database migrations via release tasks
# In production container
./bin/components_elixir eval "ComponentsElixir.Release.migrate"
CI/CD with Gitea Actions
Gitea Actions Limitations (important differences from GitHub Actions):
- No
concurrency,run-name,permissions,timeout-minutes,continue-on-errorsupport - Limited expression support (only
always()function) - No package repository authorization - use Personal Access Token for OCI publishing
- Problem matchers and error annotations are ignored
- Simple
runs-onsyntax only (runs-on: ubuntu-latest, not complex selectors)
CI Pipeline Will Include:
- Code quality checks (
mix precommit) - Test execution across Elixir/OTP versions
- Docker image building and publishing (requires PAT for package registry)
- Database migration testing
Ensure all code passes mix precommit before pushing, as this will be enforced in CI.