Introduction

Welcome amigo!

I created this wiki just for documenting some of the stuff that I have learnt. I use it as a quick reference to save time and kind of avoid relearning things. This whole wiki is specifically made for myself - so not everything in here is explained in detail and some of the pages may even contain mistakes.

Of course, if you have any questions or spot any mistakes, you are always free to contact me

What's on my Phone

Just some of the apps that I use my phone. I am not including every single one just the apps that I find useful.

Btw, I am an Android user and I use the OnePlus 7 as my daily driver.

  1. Raindrop

    In short, Raindrop is a cross-platform bookmanager with synchronisation so that I can access my bookmarks anywhere. I discovered Raindrop after watching MKBHD's What's on my Phone video and I really wanted to try it out. After using it for a couple of days, I thought to myself, how did I not use a bookmanager like Raindrop earlier.

    I use it to save articles,posts from reddit,memes, youtube video links and much more. Basically, anything I want to refer to later, I just save it to Raindrop.

  2. Seal

    Seal is a video/audio downloader based on yt-dlp. The app is really good. I love how quick and easy to use it is. The UI is pretty awesome too. You can download it from F-droid or directly from GitHub

  3. Paisa

    Paisa is a an expense and budget tracker. The app does a pretty good job but I think it is pretty overkill for an expense and budget tracker. I might switch from it to a more simple budget tracker. But until then, I am just going to keep using this app.

  4. Obsidian

    I use Obsidian for journalling. I love the offline approach of Obsidian and data doesn't leave my device.

  5. Notion

    I play the keyboard (Beginner) at my church and I needed something to keep track of the songs sung by our choir, so I found it really easy to set up a database in notion and also published it as a page on the web.

Push an existing local repository to GitHub

How to push an existing local repository to GitHub

Make sure the default branch name is 'main'.(main is the default branch name in my case.)

  1. Create a new repo on GitHub. The repository should be empty.

  2. Copy the URL of the repo on GitHub

  3. Add the copied URL as remote URL.

    git remote add origin REMOTE-URL

  4. Push the repo

    git push origin main

[!WARNING] This content is AI-generated. Verify before relying on it.

Useful Git Commands

A cheat sheet of commonly used Git commands organized by workflow.


Configuration & Identity

View User Name and Email

Check the user identity currently configured for commits:

ScopeCommand
Current Repositorygit config user.name
git config user.email
Global (System User)git config --global user.name
git config --global user.email
View All Configurationsgit config --list --show-origin

Set User Name and Email

# Set globally for all repositories
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

# Set locally for the current repository only
git config user.name "Your Name"
git config user.email "you@example.com"

View Remote URLs

# View remote repository names and fetch/push URLs
git remote -v

Inspecting History & Logs

git log --oneline -5

Shows the last 5 commits formatted on a single line each (abbreviated hash + commit message):

git log --oneline -5

Show Commits by a Specific Author

Filter the commit history to only show commits authored by a specific person (matches name or email substring):

# Filter by author name or email
git log --author="vachan"

# Combine with oneline and limit to 5 commits
git log --author="vachan" --oneline -5

Visual Commit Graph

# Visual ASCII graph of branching and merging
git log --oneline --graph --decorate -10

Viewing Differences (Diffs)

git diff vs git diff --staged

CommandComparesWhat it Shows
git diffWorking directory vs. Staging area (Index)Unstaged changes you haven't run git add on yet
git diff --staged
(or git diff --cached)
Staging area (Index) vs. Last commit (HEAD)Changes already staged with git add that will be included in the next commit
# View unstaged changes
git diff

# View unstaged changes for a specific file
git diff path/to/file.ext

# View staged changes waiting to be committed
git diff --staged

[!TIP] Always run git diff --staged before git commit to do a final self-review of what is about to be recorded.


Branch Management

Deleting a Branch

TargetCommandNotes
Local branch (Safe)git branch -d <branch-name>Prevents deletion if branch contains unmerged commits
Local branch (Force)git branch -D <branch-name>Forces deletion regardless of merge status
Remote branchgit push origin --delete <branch-name>Deletes branch from remote server (GitHub/GitLab)
# Delete a local merged feature branch
git branch -d feature-login

# Force-delete an abandoned local branch
git branch -D test-experiment

# Delete the branch from the remote repository
git push origin --delete feature-login

Sort Branches by Update Date

List branches ordered by the date of their latest commit (most recently updated branch first):

# Sort local branches by commit date (most recent first)
git branch --sort=-committerdate

# Include human-readable relative dates in the output
git branch --sort=-committerdate --format="%(committerdate:relative)%09%(refname:short)"

# Sort including remote tracking branches
git branch -a --sort=-committerdate

Moving a Commit from One Branch to Another

To move a commit (e.g. abc1234) committed to the wrong branch (branch-A) onto the correct branch (branch-B):

# 1. Switch to the target branch
git checkout branch-B

# 2. Cherry-pick the commit onto branch-B
git cherry-pick abc1234

# 3. Switch back to the original branch
git checkout branch-A

# 4. Remove the commit from branch-A (if it was the most recent commit)
git reset --hard HEAD~1

[!CAUTION] Only use git reset --hard if you have not pushed branch-A to a shared remote repository. If already pushed, use git revert abc1234 instead.


Stashing Changes

Use git stash to set aside uncommitted changes and return to a clean working directory.

# Stash tracked modified files
git stash

# Stash including untracked files with a descriptive message
git stash push -u -m "WIP: navbar redesign"

# List all saved stashes
git stash list

Difference Between git stash pop and git stash apply

Featuregit stash popgit stash apply
Applies changesYesYes
Removes from stash listYes (drops stash@{0})No (retains entry on the stack)
Best used whenYou are done with the stash and want it consumedYou want to apply the same stash to multiple branches
# Apply and delete the latest stash from the list
git stash pop

# Apply changes while keeping the stash intact
git stash apply

# Apply a specific stash from the list without deleting it
git stash apply stash@{2}

# Manually drop a stash entry
git stash drop stash@{0}

# Clear all stashes permanently
git stash clear

Cleaning & Resetting

git clean -fd

Removes untracked files and directories from your working tree.

# 1. Always run a dry run first to preview what would be deleted
git clean -nd

# 2. Force delete untracked files (-f) and untracked directories (-d)
git clean -fd

# Remove untracked files, directories, AND gitignored files
git clean -fdx

[!WARNING] git clean -fd permanently deletes untracked files from disk. They cannot be recovered from Git history. Always use git clean -nd first.

Resetting Commits (--soft vs --hard)

# Move HEAD back by 1 commit; all changes remain staged in the index
git reset --soft HEAD~1

# Move HEAD back by 1 commit; all staged and unstaged changes are destroyed
git reset --hard HEAD~1

Commit Shortcut: git commit -am

Stages all modified tracked files and commits them in a single step (does not add newly created untracked files):

git commit -am "Commit message"

Some Tips

  1. If you are a CS student, learn how to use git.

  2. Don't waste your money on pointless internships and certifications.

  3. Doing an internship where you have to pay money out of your pocket is a scam and best not to do it. (Speaking from experience.)

  4. First year of Engineering is difficult (But it depends on person to person), study well during this time. Work hard.

  5. If you find a subject difficult to understand and you think you are going to fail then ask for help from your friends or go to tuition (there is nothing embarrassing about it). Don't be lazy and fail the subject on purpose.

  6. YouTube,ChatGPT & the world wide web are your friends, use the resources available to learn stuff.

  7. If you do fail a paper, it is not the end of the world. Work hard and clear the paper in the next semester.

  8. Don't get into any stupid fights and don't do anything that might get you suspended from college.

  9. Does CGPA matter? Well, the answer can be Yes/No. But if you are looking to get placed, then having a CGPA above 7.5 is good. If you can get your CGPA above 8,even better.

  10. Perform well and get good marks on internals or just enough marks to pass internals.

  11. Regardless of your branch(CS,Mech,Civil...), It's always to good know a programming language such as Python, C, etc.

  12. If you are willing to put in the effort, you can pass sem exams even if you start studying a few days before the exam or during study leave.

  13. If you can, try to do an actual internship (like the one where you get paid) in the final year. (I couldn't do it but this is a great thing to do. You will learn a lot.)

  14. During placement drives, prepare for aptitude test and practice questions.

  15. Having a strong grip over the basics. If you know Python, you should know it's basics too. In technical interviews, you will be asked mostly about the basics.

  16. Have a boatload of fun with your friends.

  17. You should try using Linux instead of Windows.

Useful Stuff for KTU

A collection of playlists, youtube videos and channels and websites that I use for studying.

Subreddit

r/KTUKerala - unofficial subreddit for KTU Students. It's a decent place for asking questions and having discussions.

Previous Year Questions

S1 & S2

For first year, I mostly referred to the prescribed textbooks.

Engineering Mechanics

Engineering Physics

S3

DSA (Data Structures & Algorithms)

LSD (Logic System Design)

OOP (Object Oriented Programming) in Java

  • Head First Java: A Brain-Friendly Guide This is actually a really good book that I found helpful. All the important concepts are explained in simple language with plenty of examples. The book was pretty fun to read.

S5

FLAT (Finite Language and Automata)

S6

Computer Graphics

Linux

My Linux Journey

1. Debian

Debian is the first distro that I installed on my computer.

I got tired of Windows 10 and decided to switch to Debian 12 (bookworm) in the month of July of 2023. No dual-boot. Just only Debian.

I used a Dell Inspiron laptop at the time and the hardware worked really.

Not only that Debian is a rock solid distro and I didn't face any big issues while using, everything worked well.

alt text

2. Fedora

I think I used Debian Bookworm for a year and when I got my new laptop - A Lenovo Thinkpad E16, I decided to switch to a more up to date distro. So I chose Fedora.

Fedora is a solid distro and my thinkpad worked really well with it.

3. OpenSuse Tumbleweed (Current Distro)

Tumbleweed is what I am using right now.

After trying out Fedora for a while, I decided why not switch to a rolling release distribution. I could have gone with Arch but I thought why not try something different? Opensuse Tumbleweed was something that I had in my mind for a while and I really wanted to try it. So I went ahead and installed it.

Tumbleweed has been pretty good so far and I haven't faced any major issues so far. It's works pretty well considering it is a rolling release.

alt text

Desktop Environment

Gnome

Gnome is the desktop environment of my choice. I love how clean, minimal and polished it is. Gnome just looks so good and I love the MacOS style it has.

Yes, I know how a lot of people just hate Gnome and I totally understand you guys. But I love gnome and it's enough for me.

Yes, I have tried KDE Plasma but it's just full of way too many options and customizations that I really don't need. Whenever I installed Plasma, I always felt like going back and installing Gnome.

Yeah so Gnome is my favorite distro.

Using tar.gz

I decided to try out the jetbrains applications. This is how I use the tarball.

Once the file is downloaded, you have to extract the file. The application can be launched by executing the ./bin/ WebStorm.sh script.

But it is much easier to launch the application by adding the directory to the PATH

  1. Extract the file

  2. Add directory to PATH

    nano ~/.bashrc

    export PATH=$PATH:/path/to/directory/

  3. Reload the shell environment

    source ~/.bashrc

apt package manager

Search for a package

To search for a package from the command line, use: apt-cache search keyword

Show package details

To show package details, use apt show package-name.

Basics of Vim

I just put this here so I can for future reference. Of course, there are many cheatsheets and guides on how to use vim. This is just my personal cheatsheets. I am not planning on adding every command, only just some useful ones.

If you find any mistakes here, please let me know.

Additional Reference

Start

Vim has basically four modes:

  1. Normal Mode (Command Mode) - the default mode.
  2. Command Line Mode - Play around with commands
  3. Insert Mode - for editing the contents of the file
  4. Visual Mode - for selecting the text.

How to enter each modes?

  • Press Esc to enter normal mode.
  • Press i to enter insert mode.
  • Press v for visual mode.
  • Press : to enter command line mode.

Saving and Quitting

Enter command mode

  • Use :w to save the file
  • Use wq to save and quit
  • Use q! to exit the file without saving changes made to the file
  • Use q if no changes were made.

Cursor Movements

  • h - to move left
  • l - to move right
  • j - move cursor down
  • k- move cursor up
  • G - to move to the last line
  • $ - to move to the end of a line

More commands for insert mode

  • o - insert new line after the current line
  • O - insert line before the current line
  • a - insert after cursor
  • i - insert before cursor
  • A - insert at end of line
  • I - insert at beginning of line

Undo Redo

  • u - Undo
  • Ctrl + R - for redo

Set line numbers or relative line numbers

  • set number - to display line numbers
  • set relativenumber - to display relative line number

Debian Mirrors

The sources file is located at /etc/apt/sources.list. More info on the sources.list file can be found on the Debian Wiki.

Mirrors that I use:

More mirrors can be found on the Free Software Mirrors in India page.

Check if port is in use

To check which ports are in use and find which application is listening to which port. Use the following command:

sudo ss -tulpn | grep LISTEN

The command options are:

  • -t:TCP Ports
  • -u: UDP Ports
  • -l: listening sockets
  • -p: process using the port

Source

Thinkpad

I use a Lenovo ThinkPad E16 Gen 2 (AMD) with Fedora as my Operating System.

Operating System

  • Fedora 41 Workstation
  • GNOME Desktop

Specifications

  • Processor AMD Ryzen™ 5 7535U Processor (2.90 GHz up to 4.55 GHz)
  • Graphic Card Integrated AMD Radeon™ 660M
  • Memory 16 GB DDR5-4800MHz (SODIMM)
  • Storage 512 GB SSD M.2 2242 PCIe Gen4 TLC Opal
  • Display 40.64cms (16) WUXGA (1920 x 1200)
  • IPS, Anti-Glare, Non-Touch, 45%NTSC, 300 nits, 60Hz
  • Camera 720P HD RGB with Microphone and Privacy Shutter
  • Battery 3 Cell Li-Polymer 47Wh
  • WIFI Realtek 8852BE WIFI 6 2x2ax + BT5.x & Bluetooth® 5.1 or above

More information can be found in the PSREF

Charging Thresholds

To extend the lifespan of your battery, you can define charging thresholds.

A ThinkPad battery can be set for maximum runtime (hours), or for maximum lifespan (years).

More info

Setting the Charging Thresholds

Source: Reddit

  • You can set the charging start threshold in (At what value or below should charging start):

    /sys/class/power_supply/BAT0/charge_start_threshold

  • You can set the charging stop threshold in (At what value charging should stop):

    /sys/class/power_supply/BAT0/charge_stop_threshold

  • I have set the start threshold at 75 and stop threshold at 80 on my laptop

Optimizing for runtime (hours)

Source: Lenovo

The normal default Lenovo Power Manager Battery Maintenance setting keeps the battery fully charged. The setting starts charging when the battery drops below 96%, and stops at 100%. The battery runtime depends on the Power Plan settings.

Optimizing for lifespan (years)

Source: Lenovo

For maximum lifespan when rarely using the battery, set Custom charge thresholds to start charging at 40% capacity and stop at 50%, and keep the ThinkPad cool. The thresholds can be adjusted in the Battery Maintenance settings of Lenovo Power Manager.

If the battery is used somewhat frequently, set the start threshold at around 85% and stop at 90%. This will still give a good lifespan benefit over keeping the battery charged to 100%.

Swap Fn and Ctrl Key

On thinkpads for some reason, the function and control keys are in a different position. I have no clue why Lenovo does this.

Anyway, if you prefer, you can swap the keys by using the BIOS. Please refer this article by Lenovo to swap the function and control keys.

Linux Installation

You can install any distribution on your laptop. In my opinion, it is better to go with Fedora or Ubuntu to make sure the hardware works as intended.

Update System and BIOS

  • Before getting rid of Windows, update the BIOS using Lenovo Vantage software. For more information, visit Lenovo's website

Disable Bitlocker Encryption

Before installing Linux on your ThinkPad, you must check if Bitlocker encryption is enabled on your disk.

If BitLocker encryption is enabled, please disable it before following the below steps.

You must disable bitlocker encryption to install Linux and backup your keys

Secure Boot

What is Secure Boot?

UEFI Secure boot is a verification mechanism for ensuring that code launched by firmware is trusted. More info can be found in the Ubuntu Wiki

Enable Secure Boot

The Bitlocker recovery screen will appear on changing the BIOS settings. Make sure you have bitlocker encrpytion disabled and have a backup key of your recovery key. The screen appeared for me because I hadn't disabled Bitlocker.

Source of Instructions: Lenovo

  1. Reboot your PC
  2. Boot into the BIOS setup menu by pressing the F1 key when the Lenovo logo is displayed
  3. In the BIOS menu select the “Security” option and the “Secure Boot” sub-menu. Toggle the “Allow Microsoft 3rd party UEFI CA” to be “On” as shown below. BIOS of Lenovo
  4. Press F10 to save and reboot

Linux Install

  1. Flash the ISO on to a USB using Rufus, Balena Etcher or the software of your choice (Since I use Fedora, I used Fedora Media Writer)
  2. Take your freshly written USB key and insert it in the powered down installation platform.
  3. Power on the device and press F12 during early boot to enter the Boot Menu.
  4. Navigate down to the USB HDD device and press Enter.
  5. Select the appropriate option from the GRUB Menu (In my case it was Test this media & start Fedora-Workstation-Live.)

Updating the BIOS

Please also refer to the references used to write these instructions

You should always be careful when updating the BIOS. I will not be responsible for any damage caused to your system. Always take the necessary precautions and follow the instructions carefully.
If you are on Windows, you can easily update the BIOS with Lenovo Vantage.

But on Linux distributions, Lenovo Vantage is not supported and since Thinkpad 16 G2 (AMD) is not Linux certified, you cannot get udate the BIOS using fwupd.

You can manually update the BIOS by downloading the image and flashing it on to a USB Drive.

  1. Download the BIOS image from Lenovo Support. Make sure you choose the correct model. You should download the CD ISO image.

  2. Download geteltorito

  3. Change directory to geteltorito

  4. Set permissions by using the below command

    chmod +x ./geteltorito.pl

  5. Extract the bootable image from the ISO:

    ./geteltorito.pl -o bios.img iso_file.iso

The below command will delete everything in your USB Drive. Make sure you don't have any important files in it
When copying the image in your USB stick, make sure you have chosen the correct device
6. Copy the image into your USB stick by dd utility
sudo dd if=bios.img of=/dev/sdb

You now have a bootable USB drive.

Secure boot must be disabled it for the computer to boot the USB drive

ffmpeg

  1. Convert all the files in a particular directory to another format

    • For Linux and macOS this can be done in one line, using parameter expansion to change the filename extension of the output file
      for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
      

    Source

scrcpy

scrcpy (screen copy) is a tool used for mirroring and controlling your Android device via ADB. I found this tool particularly useful when I cracked the display on my phone and touch did not work properly.

To use scrcpy, you will need to enable USB Debugging on your device

You can download scrcpy from GitHub. To install it on Linux, see the following page.

  • To control the device using your keyboard and mouse (without Android Debugging). Use the following command.
scrcpy --otg
  • To mirror the device and control the device, simply run the following command
scrcpy
  • Use with the screen off
scrcpy --turn-screen-off --no-cleanup

source

Screenshot

alt text

ytdlp

  1. Download a video from YouTube as mp3

    yt-dlp --audio-format mp3 --add-metadata https://www.youtube.com/watch?v=r5PtlHs9igM
    
  2. Download video without audio

    yt-dlp youtube_link -F
    

pdftk

Merge Multiple PDFs into a single PDF

pdftk file1.pdf file2.pdf cat output output.pdf

Syncthing

I use syncthing to sync files between devices.

Note: On mobile, make sure syncthing is actually running. I was puzzled to find why syncthing wasn't running on my phone after I had installed it. Since battery saving mode was ON, the service hadn't actually started running. Just keep this in mind, if syncthing doesn't actually connect or sync properly.

Syncthing supports encryption for folders shared with devices. The data in the folder will be encrypted using a password and also can be decrypted using the same password.

For more info, refer to the syncthing docs

For decrypting the folder, use the command:

syncthing decrypt --to <plaintext-destination> --password <your-password> <encrypted-folder-path>

systemd

Start a service

systemctl start <service-name>

Stop a service

systemctl stop <service-name>

Restart a service

systemctl restart <service-name>

Reload a service

systemctl reload <service-name>

Enable service at boot

systemctl enable <service-name>

Disable service at boot

systemctl disable <service-name>

VS Code

VS Code is the text Editor of my choice.

Extensions I use

  1. Live Server

  2. SQLite Viewer

  3. Postman

CSS

Improving CSS Reset

How you can make your site a little bit more better by using the css below. Source

h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: balance;
}

p,
li,
figcaption {
  text-wrap: pretty;
  max-width:65ch;
}
 

Dark Theme

How to add dark theme to a website using only css.

@media (prefers-color-scheme: dark) {
  img {
    opacity: .75;
    transition: opacity .5s ease-in-out;
  }
  img:hover {
    opacity: 1;
  }
}

Source

Virtual Environment (venv)

Linux

I sometimes forget how to create a virtual environment when workinng on something.

To create a venv on Linux:

python3 -m venv venv

To activate the venv:

source venv/bin/activate

To deactivate the venv:

deactivate

Create a venv for a particular python version

Just specify the version number that's all.

python3.10 -m venv venv

Working with Coding Agents (Codex)

[!NOTE] Notes summarized from the OpenAI Getting Started with Codex crash course.

[!WARNING] This content was generated and structured using AI. Please review and verify commands against your project's environment.


Agent Collaboration Lifecycle

Working effectively with coding agents follows a disciplined five-phase loop:

  1. Prompt: Provide a clear goal, relevant context pointers, constraints, and completion criteria.
  2. Inspect: Explore how the repository works and establish a safe baseline check before editing.
  3. Act: Review the plan, implement a bounded change, and steer the agent when drift occurs.
  4. Validate: Run focused tests, execute quality checks, and manually verify the experience.
  5. Report: Review the diff and generate an evidence-based developer handoff.

1. Exploring Unfamiliar Codebases

When opening a new or unfamiliar repository, explore before modifying code.

6 Essential Exploration Questions

  1. How the application is structured.
  2. Which files manage state and controls.
  3. How to run the application (development commands).
  4. Which tests and validation commands are available.
  5. Which files need to change for the target feature.
  6. What assumptions, risks, or missing information exist.

Example: Codebase Exploration Prompt

Inspect this repository without making any changes.

Explain:
1. How the application is structured.
2. Which files manage the game’s state and controls.
3. How to run the application.
4. Which tests or validation commands are available.
5. Which files may need to change to add pause and resume controls.
6. Any assumptions, risks, or missing information.

Establishing a Safe Baseline

Before requesting code changes, run existing validation commands to establish an operational baseline:

  • Passing baseline: Confirms the environment is healthy before new code is introduced.
  • Failing baseline: Helps separate pre-existing bugs from regressions introduced by the agent.
  • Visual applications: Baseline feedback should include unit tests for state logic, the dev server command, and a brief manual interface check.
  • Libraries: Baseline feedback should include targeted tests, linter, type checks, and build commands.

2. Context Management & Scoping

  • Scope to one feature: Keep the agent focused on a single bounded problem per session.
  • Start fresh threads: When pivoting to another task or feature, start a new chat/thread to avoid context pollution and token bloat.
  • Supply only necessary context: Include only the files, errors, and constraints relevant to the immediate task.

3. Reusable Guidance with AGENTS.md

An AGENTS.md file captures recurring project instructions and expectations so you do not have to repeat them in every prompt. It keeps human-facing README.md files clean of agent-specific trivia.

Key Contents to Include

  • Important directories and application components.
  • Exact commands for running the app, linting, building, and running tests.
  • Coding conventions and architectural patterns.
  • Protected files and security requirements (files never to edit).
  • Verification steps required before completing a task.

Example: Repository AGENTS.md

# Project guidance
- Run the application with `pnpm dev`.
- Run automated tests with `pnpm test`.
- Follow existing patterns for game state, interface components, and user interactions.
- Keep changes focused on the requested feature and avoid unrelated modifications.
- Preserve existing scoring, reset behavior, and application styling.
- Add or update tests when changing application behavior.
- Run the relevant checks and report any issues before marking a task complete.

Layered Guidance Hierarchy

Guidance can be layered across scopes:

  1. Global Guidance (~/.codex/AGENTS.md): Applies across all projects on your machine.
  2. Repository Guidance (<root>/AGENTS.md): Applies to the entire codebase.
  3. Folder Guidance (<folder>/AGENTS.md): Applies when the agent works inside a specific subdirectory (e.g. frontend/AGENTS.md).

Precedence Rule: Guidance closer to the current working directory overrides broader guidance. An AGENTS.override.md file can completely replace the standard AGENTS.md at that level when an explicit override is required.


4. Making Workflows Executable

An agent can only self-correct if the repository provides executable feedback.

5 Steps to an Executable Development Path

  1. Document setup: Clear instructions to install dependencies and run the app.
  2. Provide focused tests: Fast, targeted tests for core state and logic.
  3. Expose quality tooling: Make linting, formatting, type-checking, and build commands readily available.
  4. Detail environment fixtures: Document environment variables, test services, and seed data without committing secrets.
  5. Define manual verification paths: Clear instructions for verifying UI and behaviors not covered by automated tests.

5. Defining Tasks (The 4-Part Task Brief)

Structure task requests into four distinct sections:

  1. Goal: State the behavior to add, change, or fix, and why it matters.
  2. Context pointers: Point to relevant files, errors, examples, or screenshots to inspect first.
  3. Constraints: Define what must remain unchanged, which patterns to follow, and scope boundaries.
  4. Done when: Specify observable behaviors and the exact checks that must pass.

Example: 4-Part Task Brief Prompt

Goal:
Add pause and resume controls to the game.

Context pointers:
Before making changes, inspect how the application manages game state and handles existing controls.

Constraints:
Follow the repository’s existing patterns. Do not change scoring, reset behavior, or unrelated styling.

Done when:
The task is complete when the game pauses and resumes correctly, repeated pause-and-resume cycles work, and the relevant tests pass.

6. Planning Mode (/plan) & Steering

When to Use Plan Mode

Use /plan before editing when the task:

  • Is ambiguous or underspecified.
  • Touches multiple components across the codebase.
  • Involves unfamiliar code or dependencies.
  • Carries meaningful security or regression risks.
  • Has more than one valid architectural approach.

Steering Active Work

If the agent begins drifting into unnecessary refactoring or unrelated styling changes, intervene early rather than restarting:

Keep the existing interface and add the pause and resume controls using the current component patterns. Avoid unrelated design changes and continue with the original plan.

7. The Validation Stack & Iteration

Validate changes using a multi-tiered stack, starting with checks closest to the modification:

The 3-Tier Validation Stack

  1. Focused Tests: Verify that unit and state transitions behave as intended (e.g., pausing transitions state correctly, resuming restores progress).
  2. Relevant Quality Checks: Run type checks, linters, and build commands to confirm no collateral syntax or type breakages.
  3. Manual Verification: Test interactive user flows, UI synchronization, and confirm nearby behaviors (e.g., reset, score counters) remain intact.

Investigating Failures as Evidence

When a test fails:

  1. Treat the failure as diagnostic evidence, not a prompt to blindly hack tests.
  2. Determine whether the cause is in the implementation, the test assertion, the environment, or an unclear requirement.
  3. Require the agent to identify the root cause before applying fixes.

8. Review & Evidence-Based Developer Handoff

Diff Review (/review)

Perform a second-pass review of the diff before accepting changes.

Review the pause-and-resume changes against the original task and implementation plan.

Check whether:
- The requested behavior works as intended.
- The changes remain within the agreed scope.
- Existing project patterns were followed.
- Relevant tests cover the new behavior.
- Scoring, reset behavior, and unrelated styling remain unchanged.
- Any security concerns or unresolved risks require attention.

Summarize the most important findings without making additional changes.

Evidence-Based Developer Handoff

Prepare a structured handoff summarizing concrete results:

Prepare an evidence-based developer handoff for this change.
Include:
- a concise summary of the PM request
- what changed and which files were affected
- exact automated commands and results
- browser and manual checks with results
- review findings and how each was handled
- anything unverified
- remaining risks or follow-up work
- the recommended next step

Separate observed evidence from assumptions or confidence statements.
Do not modify files.

9. Four Core Engineering Decisions

Retain engineering judgment by applying these four core principles:

  1. Start with repository evidence: Inspect existing files, patterns, and run baseline commands before choosing an implementation strategy.
  2. Define success before implementation: Formulate the 4-part brief (Goal → Context → Constraints → Done criteria) and identify what must be observed to accept the change.
  3. Guide the work within the boundary: Constrain the agent's working surface, review plans when uncertain, and steer specific drift promptly.
  4. Accept based on evidence: Evaluate using the 6-point checklist:
    • Correctness: Did the feature work as intended?
    • Scope: Did changes stay bounded?
    • Fit: Were existing patterns maintained?
    • Coverage: Are critical paths covered by tests?
    • Security: Are there any new vulnerabilities or exposed secrets?
    • Uncertainty: Are any unverified behaviors explicitly declared?

[!WARNING] This content is AI-generated. Verify before relying on it.

Laravel

Laravel is an expressive, elegant PHP web application framework utilizing the MVC (Model-View-Controller) architectural pattern.

Topic Index

TopicDescription
Artisan CommandsDaily CLI reference for generators, database, routing, and cache optimization
Migrations & SeedingDatabase schema version control, column modifiers, seeders, and factories
Form Requests & ValidationDedicated request validation classes, common rules, and controller integration
MailerMailables, envelopes, content, attachments, and email queueing
Task SchedulingManaging scheduled cron tasks in code, execution frequencies, and local workers
Authorization & PoliciesResource authorization, Gates vs Policies, and Blade/Controller checks

Standard Directory Structure

PathPurpose
app/Models/Eloquent ORM models
app/Http/Controllers/HTTP controllers handling incoming requests
app/Http/Requests/Form Request validation and authorization classes
app/Policies/Authorization policies mapped to models
app/Mail/Mailable classes for email generation
database/migrations/Schema definition files executed in order
database/seeders/Database seeders for test and initial data
database/factories/Model factories for generating fake test data
routes/web.phpStateful web routes (cookies, session, CSRF)
routes/api.phpStateless API routes with token/sanctum authentication
routes/console.phpArtisan console commands and scheduled tasks (Laravel 11+)
resources/views/Blade templates

[!WARNING] This content is AI-generated. Verify before relying on it.

Common Artisan Commands

Artisan is the command-line interface included with Laravel. It provides commands for generating boilerplate, running database migrations, managing caches, and inspecting application state.

Make / Generator Commands

Creating Models

CommandDescription
php artisan make:model PostCreates a basic Eloquent model
php artisan make:model Post -mModel + migration
php artisan make:model Post -cModel + controller
php artisan make:model Post -crModel + resource controller
php artisan make:model Post -mcrModel + migration + resource controller
php artisan make:model Post -sModel + seeder
php artisan make:model Post -fModel + factory
php artisan make:model Post -aModel + migration + factory + seeder + policy + resource controller + form requests (--all)
php artisan make:model RoleUser --pivotCreates a custom pivot model

Creating Controllers

CommandDescription
php artisan make:controller PostControllerBasic empty controller
php artisan make:controller PostController --resourceController with CRUD actions (index, create, store, show, edit, update, destroy)
php artisan make:controller PostController --resource --model=PostResource controller with typed model route-binding
php artisan make:controller Api/PostController --apiAPI resource controller (omits HTML create and edit methods)
php artisan make:controller ProvisionServer --invokableSingle action controller with __invoke()

Creating Other Core Classes

CommandDescription
php artisan make:migration create_posts_tableGenerates a new migration file
php artisan make:request StorePostRequestGenerates a Form Request validation class
php artisan make:policy PostPolicy --model=PostGenerates a Policy class mapped to a model
php artisan make:mail WelcomeUserGenerates a Mailable class
php artisan make:mail OrderShipped --markdown=emails.orders.shippedMailable with a Markdown Blade template
php artisan make:seeder PostSeederGenerates a database seeder
php artisan make:factory PostFactory --model=PostGenerates a model factory
php artisan make:middleware EnsureTokenIsValidGenerates custom HTTP middleware
php artisan make:job ProcessPodcastGenerates a queueable job

Database Migrations & Seeding

CommandDescription
php artisan migrateRun pending migrations
php artisan migrate:statusShow migration execution status and batches
php artisan migrate:rollbackRollback the last migration batch
php artisan migrate:rollback --step=2Rollback the last 2 migrations
php artisan migrate:resetRollback all database migrations
php artisan migrate:refreshRollback all migrations and run them again
php artisan migrate:refresh --seedRollback all, re-run, and seed database
php artisan migrate:freshDrop all tables and execute all migrations from scratch
php artisan migrate:fresh --seedDrop all tables, run all migrations, and run seeders
php artisan db:seedRun the root DatabaseSeeder
php artisan db:seed --class=UserSeederRun a specific seeder class

[!CAUTION] Never run migrate:fresh in production. It drops all tables and destroys data permanently.


Optimization & Caching

Use caching in production to boost performance by eliminating runtime file scanning and route parsing.

CommandDescription
php artisan optimizeCaches bootstrap files, configuration, and routes
php artisan optimize:clearClears all cached bootstrap files, config, routes, views, and events
php artisan route:cacheCompiles all routes into a single cached file
php artisan route:clearDeletes the compiled route cache
php artisan config:cacheMerges all config files into a single cached file
php artisan config:clearDeletes the compiled configuration cache
php artisan view:cachePre-compiles all Blade templates
php artisan view:clearClears compiled Blade view files
php artisan cache:clearFlushes the application data cache (Redis/Memcached/file)
php artisan event:cacheCaches discovered events and listeners
php artisan event:clearClears the event cache

[!TIP] During local development, run php artisan optimize:clear if route or configuration changes fail to reflect.


Routing & Inspection

CommandDescription
php artisan route:listLists all registered application routes
php artisan route:list --path=apiFilters routes by URI path
php artisan route:list --except-vendorExcludes vendor-registered routes
php artisan aboutDisplays environment, PHP version, cache drivers, and framework details

Development & Maintenance

CommandDescription
php artisan serveStarts local PHP development server (http://127.0.0.1:8000)
php artisan serve --port=8080Starts server on a specified port
php artisan tinkerInteractive REPL shell powered by PsySH
php artisan downPuts the application into maintenance mode
php artisan down --secret="bypass-token"Enables maintenance mode with a bypass cookie
php artisan upBrings the application out of maintenance mode
php artisan queue:workStarts processing queued jobs
php artisan schedule:workRuns the task scheduler locally (daemon mode for local dev)

[!WARNING] This content is AI-generated. Verify before relying on it.

Database Migrations & Seeding

Migrations are version control for database schemas. They allow a team to define, modify, and share database structure definitions across environments using PHP.

Generating Migrations

# Create a new table
php artisan make:migration create_posts_table

# Modify an existing table
php artisan make:migration add_status_to_posts_table --table=posts

Migration Structure

Migrations live in database/migrations/ and contain up() and down() methods:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('body');
            $table->boolean('is_published')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
            $table->softDeletes();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Common Column Types

Column DefinitionDatabase Equivalent
$table->id();BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY
$table->string('name', 255);VARCHAR(255)
$table->text('content');TEXT
$table->longText('payload');LONGTEXT
$table->integer('votes');INT
$table->unsignedBigInteger('account_id');BIGINT UNSIGNED
$table->decimal('price', 8, 2);DECIMAL(8, 2)
$table->boolean('is_active');TINYINT(1) / BOOLEAN
$table->json('metadata');JSON
$table->timestamp('activated_at');TIMESTAMP
$table->timestamps();Adds created_at and updated_at
$table->softDeletes();Adds deleted_at for soft delete support

Common Column Modifiers

$table->string('email')->nullable();           // Allows NULL values
$table->string('role')->default('subscriber'); // Default value
$table->string('username')->unique();          // Unique index
$table->string('category')->index();           // Standard index
$table->string('subtitle')->after('title');    // Place column after existing one (MySQL)

Foreign Key Constraints

Modern Laravel syntax uses concise foreign ID helpers:

// Shorthand for user_id referencing id on users table with cascade delete
$table->foreignId('user_id')->constrained()->cascadeOnDelete();

// Nullable foreign key that sets null on delete
$table->foreignId('category_id')->nullable()->constrained()->nullOnDelete();

// Manual foreign key definition
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');

Modifying Existing Tables

When modifying an existing table, specify changes in up() and reverse them in down():

public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->string('subtitle')->nullable()->after('title');
        $table->renameColumn('body', 'content');
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('subtitle');
        $table->renameColumn('content', 'body');
    });
}

Seeders & Model Factories

Seeders populate database tables with dummy or initial data (e.g. admin accounts, lookups).

1. Generating Seeders & Factories

php artisan make:seeder PostSeeder
php artisan make:factory PostFactory --model=Post

2. Defining a Factory (database/factories/PostFactory.php)

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'title' => fake()->sentence(),
            'slug' => fake()->unique()->slug(),
            'body' => fake()->paragraphs(3, true),
            'is_published' => fake()->boolean(80),
        ];
    }
}

3. Calling Seeders in database/seeders/DatabaseSeeder.php

namespace Database\Seeders;

use App\Models\User;
use App\Models\Post;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // Create an explicit admin user
        User::factory()->create([
            'name' => 'Admin User',
            'email' => 'admin@example.com',
        ]);

        // Generate 20 dummy posts with related users
        Post::factory(20)->create();

        // Or invoke specific seeder classes
        $this->call([
            RoleSeeder::class,
        ]);
    }
}

Running Migrations & Seeders

# Run pending migrations
php artisan migrate

# Run database seeders
php artisan db:seed

# Run a specific seeder class
php artisan db:seed --class=PostSeeder

# Roll back the last batch of migrations
php artisan migrate:rollback

# Drop all tables, re-run all migrations, and run seeders
php artisan migrate:fresh --seed

[!TIP] php artisan migrate:fresh --seed is the most common command during local development to reset the database to a clean, populated state.

[!CAUTION] Avoid migrate:fresh in production environments as it completely wipes existing tables and records.

[!WARNING] This content is AI-generated. Verify before relying on it.

Form Requests & Validation

Form Requests are dedicated HTTP request classes that encapsulate authorization and validation logic. They keep controllers lean and ensure input data is authorized and validated before controller methods execute.

Generating a Form Request

php artisan make:request StorePostRequest

Files are stored in app/Http/Requests/.


Form Request Anatomy

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;

class StorePostRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        // Return true to allow, or check policy / user permissions
        return $this->user() !== null;
    }

    /**
     * Modify input data before validation rules run.
     */
    protected function prepareForValidation(): void
    {
        $this->merge([
            'slug' => Str::slug($this->input('title')),
        ]);
    }

    /**
     * Get the validation rules that apply to the request.
     */
    public function rules(): array
    {
        return [
            'title'       => ['required', 'string', 'max:255'],
            'slug'        => ['required', 'string', 'unique:posts,slug'],
            'category_id' => ['required', 'integer', 'exists:categories,id'],
            'content'     => ['required', 'string', 'min:20'],
            'tags'        => ['nullable', 'array'],
            'tags.*'      => ['string', 'max:30'],
            'cover_image' => ['nullable', 'image', 'mimes:jpeg,png,webp', 'max:2048'],
        ];
    }

    /**
     * Custom validation error messages.
     */
    public function messages(): array
    {
        return [
            'category_id.exists' => 'The selected category does not exist.',
            'cover_image.max'    => 'Cover image size must not exceed 2MB.',
        ];
    }

    /**
     * Custom attribute names for validation errors.
     */
    public function attributes(): array
    {
        return [
            'category_id' => 'category',
        ];
    }
}

[!NOTE] If authorize() returns false, Laravel automatically halts execution and returns an HTTP 403 Forbidden response.


Controller Usage

Type-hint the Form Request in your controller action. Validation runs automatically before entering the method body:

namespace App\Http\Controllers;

use App\Http\Requests\StorePostRequest;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;

class PostController extends Controller
{
    public function store(StorePostRequest $request): RedirectResponse
    {
        // Retrieve all validated data (excludes unvalidated input fields)
        $validated = $request->validated();

        // Retrieve a specific subset of validated data
        $data = $request->safe()->only(['title', 'slug', 'content']);

        $post = Post::create($validated);

        return redirect()->route('posts.show', $post)
            ->with('success', 'Post created successfully!');
    }
}

Common Validation Rules

RuleDescriptionExample
requiredField must be present and not empty'title' => 'required'
nullableField can be null; validation rules only run if value exists'bio' => 'nullable\|string'
string / integer / boolean / arrayType checks'age' => 'integer'
emailValid email address format'email' => 'required\|email'
unique:table,columnValue must not exist in specified table/column'email' => 'unique:users,email'
exists:table,columnValue must exist in database table'role_id' => 'exists:roles,id'
min:value / max:valueMinimum / maximum length (strings) or numeric value'password' => 'min:8'
confirmedRequires matching field with _confirmation suffix'password' => 'confirmed' (checks password_confirmation)
date / after:date / before:dateValid date comparisons'end_date' => 'date\|after:start_date'
image / fileValid uploaded file'avatar' => 'file\|image\|max:1024'
mimes:foo,barValid MIME file extensions'resume' => 'mimes:pdf,docx\|max:5120'
in:foo,barValue must match one of the listed values'status' => 'in:draft,published,archived'
regex:/pattern/Custom regex validation'code' => 'regex:/^[A-Z]{3}-\d{4}$/'

Validation Behavior & Error Handling

  • Web Requests: On failure, Laravel redirects back to the previous form with input preserved (old('field')) and error messages stored in $errors.
  • API / JSON Requests: On failure, Laravel returns an HTTP 422 Unprocessable Content response containing a JSON payload with validation messages:
{
  "message": "The title field is required.",
  "errors": {
    "title": ["The title field is required."],
    "category_id": ["The selected category does not exist."]
  }
}

[!WARNING] This content is AI-generated. Verify before relying on it.

Mailer

Laravel provides a clean email API powered by Symfony Mailer. It supports drivers for SMTP, Amazon SES, Postmark, Resend, sendmail, and local development options like Mailpit and the application log.

Generating Mailables

# Standard view-based mailable
php artisan make:mail WelcomeUser

# Mailable with an auto-generated Markdown Blade template
php artisan make:mail OrderShipped --markdown=emails.orders.shipped

Mailable classes are placed in app/Mail/.


Mailable Structure

Modern Laravel mailables use Envelope, Content, and Attachment objects:

namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

    public function __construct(
        public Order $order
    ) {}

    /**
     * Define the email envelope (subject, sender, tags).
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Your Order #' . $this->order->id . ' Has Shipped',
        );
    }

    /**
     * Define the email message content / template.
     */
    public function content(): Content
    {
        return new Content(
            markdown: 'emails.orders.shipped',
            with: [
                'trackingUrl' => 'https://tracking.example.com/' . $this->order->tracking_code,
            ],
        );
    }

    /**
     * Attach files to the message.
     */
    public function attachments(): array
    {
        return [
            Attachment::fromStorage('invoices/' . $this->order->id . '.pdf')
                ->as('invoice.pdf')
                ->withMime('application/pdf'),
        ];
    }
}

Markdown Email Templates

Markdown mailables use pre-styled Blade components (resources/views/emails/orders/shipped.blade.php):

<x-mail::message>
# Order Shipped

Hi {{ $order->user->name }},

Good news! Your order **#{{ $order->id }}** has been handed over to the carrier.

<x-mail::button :url="$trackingUrl">
Track Your Shipment
</x-mail::button>

<x-mail::panel>
Estimated delivery: 2-4 business days.
</x-mail::panel>

Thanks,<br>
{{ config('app.name') }}
</x-mail::message>

Sending Mail

Use the Mail facade to send or queue messages:

use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Support\Facades\Mail;

$order = Order::find(1);

// Send synchronously
Mail::to($order->user->email)->send(new OrderShipped($order));

// Queue for asynchronous delivery (recommended for fast HTTP responses)
Mail::to($order->user->email)->queue(new OrderShipped($order));

// Add CC, BCC, and multiple recipients
Mail::to($order->user)
    ->cc('billing@example.com')
    ->bcc('audit@example.com')
    ->queue(new OrderShipped($order));

[!TIP] Implementing ShouldQueue on the Mailable class automatically queues the email when Mail::to()->send() is called, removing the need to remember ->queue().


Previewing Mailables in the Browser

You can return a Mailable directly from a route to preview its rendered HTML in the browser without sending test emails:

use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Support\Facades\Route;

Route::get('/mailable/preview', function () {
    $order = Order::first();

    return new OrderShipped($order);
});

Configuration & Local Testing

Configured in .env and config/mail.php:

# Production (SMTP example)
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

# Local development: Write all emails to storage/logs/laravel.log
# MAIL_MAILER=log

# Local development: Mailpit (localhost:1025 for SMTP, localhost:8025 for web UI)
# MAIL_MAILER=smtp
# MAIL_HOST=127.0.0.1
# MAIL_PORT=1025

[!WARNING] This content is AI-generated. Verify before relying on it.

Task Scheduling

Laravel's task scheduler eliminates the need to configure multiple cron entries on your production server. Instead, a single cron entry calls Artisan every minute, and all schedules are managed cleanly in application code.

Server Crontab Setup

Add this single cron job to your production server via crontab -e:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Defining Schedules

Laravel 11+ (routes/console.php)

use App\Jobs\GenerateWeeklyReport;
use Illuminate\Support\Facades\Schedule;

// Schedule an Artisan command
Schedule::command('backup:clean')->dailyAt('01:00');
Schedule::command('backup:run')->dailyAt('02:00');

// Schedule a queued job
Schedule::job(new GenerateWeeklyReport)->mondays()->at('06:00');

// Schedule a closure / PHP callback
Schedule::call(function () {
    \DB::table('temp_uploads')->where('created_at', '<', now()->subDay())->delete();
})->hourly();

// Schedule an OS shell command
Schedule::exec('node /scripts/metrics.js')->everyTenMinutes();

Laravel 10 and Earlier (app/Console/Kernel.php)

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule): void
    {
        $schedule->command('inspire')->hourly();
    }
}

Frequency Schedule Methods

Schedule MethodExecution Timing
->everyMinute();Runs once every minute
->everyFiveMinutes();Runs every 5 minutes (0, 5, 10, ...)
->everyTenMinutes();Runs every 10 minutes
->everyFifteenMinutes();Runs every 15 minutes
->everyThirtyMinutes();Runs every 30 minutes
->hourly();Runs at the beginning of every hour
->hourlyAt(15);Runs at 15 minutes past the hour
->daily();Runs daily at midnight (00:00)
->dailyAt('14:30');Runs daily at specified 24h time (14:30)
->twiceDaily(1, 13);Runs twice daily at specified hours (01:00 and 13:00)
->weekly();Runs weekly on Sunday at midnight
->weeklyOn(1, '08:00');Runs weekly on Monday (1) at 08:00
->monthly();Runs monthly on the 1st at midnight
->monthlyOn(15, '10:00');Runs on the 15th of every month at 10:00
->weekdays();Restricts execution to Monday through Friday
->weekends();Restricts execution to Saturday and Sunday
->timezone('UTC');Overrides the default timezone for the task
->cron('0 */4 * * *');Custom standard cron expression

Execution Modifiers & Constraints

// Prevent task overlap if the previous execution is still running
Schedule::command('emails:send')
    ->everyMinute()
    ->withoutOverlapping(); // Optional: ->withoutOverlapping(10) sets a 10 min lock expiry

// Run task in the background so it does not block subsequent tasks
Schedule::command('reports:compile')
    ->daily()
    ->runInBackground();

// Multi-server clustering: Ensure the task runs on only one server instance
Schedule::command('queue:prune-batches')
    ->daily()
    ->onOneServer();

// Run even when the app is in 'php artisan down' maintenance mode
Schedule::command('health:check')
    ->everyFiveMinutes()
    ->evenInMaintenanceMode();

// Conditional execution
Schedule::command('reminders:send')
    ->daily()
    ->when(fn () => config('features.reminders_enabled'));

Testing & Inspecting Schedules

CommandDescription
php artisan schedule:listDisplays a table of all scheduled tasks, intervals, and next run time
php artisan schedule:runEvaluates and triggers any tasks due at the current minute
php artisan schedule:workRuns a foreground daemon locally that fires schedule:run every minute

[!TIP] Use php artisan schedule:work during local development to test scheduled jobs without touching your local OS crontab.

[!WARNING] This content is AI-generated. Verify before relying on it.

Authorization & Policies

Laravel provides two primary mechanisms for authorizing user actions: Gates (closure-based) and Policies (class-based, organized around Eloquent models).

FeatureBest ForLocation
GatesGeneral actions not tied to a specific model (e.g. view admin panel)Registered in AppServiceProvider or AuthServiceProvider
PoliciesResource actions tied to a model (e.g. view, update, delete a Post)app/Policies/

Generating Policies

# Generate policy mapped to a specific model
php artisan make:policy PostPolicy --model=Post

# Generate a blank policy
php artisan make:policy AdminPolicy

Policies are saved to app/Policies/.


Policy Structure

namespace App\Policies;

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;

class PostPolicy
{
    /**
     * Perform pre-authorization checks (e.g. grant all permissions to Super Admin).
     */
    public function before(User $user, string $ability): ?bool
    {
        if ($user->is_super_admin) {
            return true;
        }

        return null; // Fall through to individual policy methods
    }

    /**
     * Determine if user can view the list of posts.
     */
    public function viewAny(User $user): bool
    {
        return true;
    }

    /**
     * Determine if user can view a specific post.
     */
    public function view(?User $user, Post $post): bool
    {
        // Type-hinting nullable ?User allows unauthenticated guests
        return $post->is_published || ($user && $user->id === $post->user_id);
    }

    /**
     * Determine if user can create posts.
     */
    public function create(User $user): bool
    {
        return $user->hasVerifiedEmail();
    }

    /**
     * Determine if user can update the post.
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }

    /**
     * Determine if user can delete the post.
     */
    public function delete(User $user, Post $post): Response
    {
        return $user->id === $post->user_id
            ? Response::allow()
            : Response::deny('You do not own this post.');
    }
}

[!NOTE] Laravel automatically discovers policies if the policy class is in app/Policies/ and matches the model name (e.g. App\Models\Post -> App\Policies\PostPolicy).


Authorizing Actions

1. In Controllers

Use $this->authorize() (or Gate::authorize()). If unauthorized, Laravel automatically throws an AuthorizationException resulting in an HTTP 403 Forbidden response:

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);

        // Update post...
    }

    public function destroy(Post $post)
    {
        $this->authorize('delete', $post);

        $post->delete();
    }
}

2. In Form Requests

Authorize directly inside the authorize() method of a Form Request:

public function authorize(): bool
{
    $post = $this->route('post');

    return $this->user()->can('update', $post);
}

3. In Blade Templates

Control UI visibility using @can and @cannot directives:

@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}">Edit Post</a>
@endcan

@can('delete', $post)
    <button type="submit">Delete Post</button>
@endcan

@cannot('update', $post)
    <p class="text-muted">You cannot edit this post.</p>
@endcannot

4. In Route Middleware

Protect routes directly at the routing level:

use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;

Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('can:update,post');

Route::delete('/posts/{post}', [PostController::class, 'destroy'])
    ->middleware('can:delete,post');

Defining & Using Gates

Gates are ideal for standalone actions not tied to a single model:

// Defined in AppServiceProvider.php (boot method)
use App\Models\User;
use Illuminate\Support\Facades\Gate;

Gate::define('access-admin-panel', function (User $user) {
    return $user->is_admin;
});

Using Gates in code:

// Check permission boolean
if (Gate::allows('access-admin-panel')) {
    // Proceed
}

// Check denial
if (Gate::denies('access-admin-panel')) {
    abort(403);
}

// Authorize or abort with 403
Gate::authorize('access-admin-panel');

Setting up a Printer with EG8145V5

How to set up a printer on Huawei EG8145V5 rotuter?

This guide focuses on Linux users but even if you are a windows user - you can follow this video

  1. First connect the printer to the USB port and turn on the printer.
  2. Access the router gateway (192.168.18.1) in your browser. You may have a different gateway address....see the back of your router.
  3. Enable printer and storage sharing. Note the name of the printer as you will need it. You need to press the icon of of USB port to access the below settings. See image below.

Screenshot of router gateway...choose the USB option on the router home page to access the settings of devices connected to the ISB port

  1. Open CUPS by going to http://localhost:631 in your browser.
  2. Go to the administration section and add the printer
  3. Choose Internet Printing Protocol (ipp)

alt text

  1. Enter the url as http://192.168.18.1:631/printers/name_of_printer. Replace name_of_printer with the name you noted down earlier from the router's gateway.
  2. Choose the manufacturer of your printer. On the next page choose the correct model and try printing a test page.
  3. Your printer should be working.