Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Skuul Laravel Package

yungifez/skuul

Skuul is an open-source Laravel school management system for handling students, staff, classes, attendance, exams, and fees. It provides a clean admin dashboard and practical tools to streamline daily school operations, with a flexible, self-hosted setup for schools.

View on GitHub
Deep Wiki
Context7

Getting Started

Skuul is a full Laravel application, not a composer require-able library. You adopt it by forking/cloning the repo and running it as your base, so “getting started” means standing up the app and learning its domain model.

Minimal path:

  1. Clone the repo and install dependencies:
    git clone https://github.com/yungifez/skuul.git
    cd skuul
    composer install
    npm install && npm run build
    cp .env.example .env
    php artisan key:generate
    
  2. Configure .env for your database (MySQL/Postgres), mail, and filesystem, then:
    php artisan migrate --seed
    php artisan storage:link
    php artisan serve
    
  3. Check the README/seeder for the seeded admin credentials, then log in and create a school, an academic session, classes/sections, and a few students.

Where to look first (in rough order of value):

  • routes/ — reveals the actual module surface (students, teachers, classes, attendance, exams, fees, reports).
  • app/Models/ — the domain core: School, Session/AcademicYear, Class, Section, Student, Guardian, Teacher, Exam, Attendance, Fee.
  • database/migrations/ and database/seeders/ — how multi-school scoping (school_id) and roles are modeled.
  • app/Http/Middleware/ — how the “current school” context is resolved per request.
  • resources/views/ (and any Livewire components) — the UI layer you’ll be customizing.

First real use case: run it locally as a single-school install, seed demo data, then walk one student through the full lifecycle — enroll → mark attendance → create an exam → enter marks → generate a report card → record a fee payment. That exercise touches every subsystem you’ll be extending and exposes the session/school scoping rules early.

Implementation Patterns

Treat it as a fork, not a dependency. Keep your customizations in your own namespaces (App\Modules\..., App\Services\...) and prefer new migrations/views over editing upstream files, so you can still pull security fixes from the repo.

Multi-school scoping is the central pattern. Most domain tables carry a school_id (and often session_id). Follow the existing convention religiously:

  • New tables that belong to a school get a school_id foreign key and an index.
  • Apply the app’s existing global scope / query scoping so a request never leaks another school’s rows.
  • Resolve the current school once (middleware or a context service) and inject it — don’t read auth()->user()->school_id ad hoc in every controller.
// Illustrative shape of a school-scoped model
class Hostel extends Model
{
    protected $fillable = ['school_id', 'name'];

    protected static function booted(): void
    {
        static::addGlobalScope('school', fn ($q) =>
            $q->where('school_id', app(SchoolContext::class)->id())
        );
    }
}

Adding a module (e.g., library, hostel, transport):

  1. Migration with school_id (+ session_id if it’s year-bound).
  2. Model with the school scope and relationships.
  3. Policy/ability registered against the existing roles-permissions setup.
  4. Controller or Livewire component + routes inside the authenticated/school group.
  5. Blade views matching the existing layout so navigation and theming stay consistent.

Extending existing entities: add columns via a new migration with a later timestamp; never edit the original migration once it’s shipped to other schools. Use model events (StudentCreated, fee-paid, attendance-marked) as the hook for notifications, SMS/email, and audit logs rather than stuffing logic into controllers.

Bulk onboarding: the highest-leverage day-to-day tool is a CSV import artisan command (php artisan school:import-students {file}) that wraps the same services the UI uses, so validation and school scoping are identical.

Year rollover: many queries implicitly depend on the “current session.” When you add features, be explicit about whether you query the active session or accept a session parameter — this is where most custom modules silently break.

Gotchas and Tips

  • No semantic versioning for internals. The “release” is an application release. Upstream class names, routes, and schema can change between pulls. Pin to a commit, keep a diff of your changes, and rebase deliberately.
  • Data-leak risk is the #1 pitfall. Any raw query, DB::table(), report export, or API endpoint you add bypasses global scopes. Test every new listing endpoint with two schools in the database and assert isolation.
  • Don’t run seeders in production. Seeders assume demo schools/users; they can create duplicate or insecure accounts.
  • Permission cache: if roles/permissions are seeded or changed via code, run php artisan permission:cache-reset (or the app’s equivalent) or users will see stale access.
  • Migration collisions when pulling upstream: keep your migrations timestamped after the latest upstream one; if upstream adds a column you also added, resolve by dropping your duplicate rather than renaming.
  • Session edge cases: enrollment, exams, and fees tied to a session behave oddly at rollover — verify promotions/closures before the new session starts, and back up first.
  • Performance: student and attendance listings get heavy fast. Eager-load student, class, section; ensure indexes on school_id, session_id, and foreign keys; paginate everything.
  • Storage: file uploads (photos, documents, report cards) need php artisan storage:link and the correct FILESYSTEM_DISK; a missing link is a common “broken image” report.
  • Debugging: add Laravel Telescope in local only; log the resolved school/session context in middleware to diagnose “wrong data shown” bugs. Check storage/logs/laravel.log before assuming a scoping bug.
  • Extension points to favor: model events, policies, service bindings in a service provider, and Blade component overrides. Avoid editing core controllers — patch surface area is what makes future upgrades painful.
  • Testing: factories must create a school and set context; write isolation tests per model. Any test that passes with a single school but fails with two is a scoping bug waiting for production.
  • Evaluate fit up front: with ~400 stars and a single-maintainer profile, budget for self-support. It’s a strong starting point for a school SaaS or an internal deployment, but a weak choice if you need a stable, documented library API to build on top of.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo