diff --git a/Job_postings_feature_plan.md b/Job_postings_feature_plan.md
new file mode 100644
index 0000000..dc00cae
--- /dev/null
+++ b/Job_postings_feature_plan.md
@@ -0,0 +1,296 @@
+# Job Postings Feature — Implementation Plan
+
+## 1. Overview
+
+This feature has two sides:
+
+- **Admin side** — create/manage job position templates, publish open positions, review applicant submissions.
+- **Client side** — browse open positions, view details, and submit an application (with resume upload) that triggers a confirmation email.
+
+---
+
+## 2. Data Model
+
+### JobTemplate
+| Field | Type | Notes |
+|---|---|---|
+| `template_id` | UUID | Primary key |
+| `title` | string | |
+| `description` | text | |
+| `department` | string | |
+| `location` | string | |
+| `employment_type` | string | e.g. full-time, part-time, contract |
+| `requirements` | text | |
+| `salary_range` | string | optional |
+| `version` | int | increments on each edit |
+| `is_active` | bool | soft-archive instead of delete |
+| `created_by` | user ref | |
+| `created_at` / `updated_at` | timestamp | |
+
+### JobPosition
+| Field | Type | Notes |
+|---|---|---|
+| `position_id` | UUID | **Unique ID per job, required** |
+| `template_id` | UUID (nullable) | set if created from a template |
+| `title`, `description`, `department`, `location`, `employment_type`, `requirements`, `salary_range` | — | copied from template at creation time (not a live reference) |
+| `status` | enum | draft / open / closed / filled |
+| `created_at` / `updated_at` | timestamp | |
+| `posted_by` | user ref | |
+
+### Application
+| Field | Type | Notes |
+|---|---|---|
+| `application_id` | UUID | |
+| `position_id` | FK | which job they applied to |
+| `first_name`, `last_name` | string | required |
+| `email` | string | required, validated |
+| `phone` | string | required |
+| `resume_file_url` | string | pointer to stored file |
+| `submitted_at` | timestamp | |
+| `status` | enum | new / reviewed / contacted / rejected / hired |
+| `admin_notes` | text | for admin follow-up tracking |
+
+---
+
+## 3. Admin Side
+
+### 3.1 Create Open Position
+- Form fields: title, description, department, location, employment type, requirements, salary range.
+- Option to start **blank** or **from a template**.
+- On save: generate unique `position_id`, default status `draft` → publish sets `open`.
+
+### 3.2 Job Templates (CRUD)
+- List / create / edit / archive templates.
+- **Editing behavior**: support both
+ - **Overwrite** current version, or
+ - **Save as new version** (keeps history)
+- Version history viewable/revertible.
+- Archiving a template never affects positions already created from it (fields are copied, not linked live).
+
+### 3.3 Create Position from Template
+- Admin selects a template → fields pre-fill a new position form → admin edits as needed → save generates a new `position_id`.
+
+### 3.4 Review Applications
+- Dashboard listing all submissions, filterable by position, status, or date.
+- Detail view: applicant info, resume preview/download, position applied to.
+- Status + notes fields so admin can track follow-up (contacted, rejected, hired).
+- Nice-to-have: CSV export, direct email link to applicant.
+
+---
+
+## 4. Client Side
+
+### 4.1 Open Positions Listing
+- Public page listing all positions where `status = open`.
+- Card/list view: title, department, location, short summary.
+
+### 4.2 Position Detail Page
+- Full description, requirements, etc.
+- "Apply" call-to-action.
+
+### 4.3 Application Form
+- Fields: First Name, Last Name, Email, Phone, Resume upload (PDF/DOC).
+- Client-side validation: required fields, email format, file type/size limits.
+- Submits to create an `Application` tied to `position_id`.
+
+### 4.4 Confirmation Email
+- Sent automatically to the applicant's email on successful submission.
+- References the position title and sets expectation of review/follow-up.
+- Optional: parallel notification email to admin/HR inbox.
+
+---
+
+## 5. API Endpoints (suggested)
+
+**Admin**
+```
+POST /admin/templates
+PUT /admin/templates/:id
+GET /admin/templates
+
+POST /admin/positions (optional template_id)
+PUT /admin/positions/:id
+GET /admin/positions
+
+GET /admin/applications (filter by position, status)
+PATCH /admin/applications/:id (update status/notes)
+```
+
+**Client (public)**
+```
+GET /positions (open only)
+GET /positions/:id
+POST /positions/:id/apply (multipart form, includes resume)
+```
+
+---
+
+## 6. Infrastructure Notes
+
+- **File storage**: resumes go to object storage (S3 or equivalent); store the file URL/key on the Application record, not the binary in the database.
+- **Email**: use a transactional email provider (SendGrid, SES, Postmark) for confirmation + admin notification emails, driven by templates.
+- **Auth**: admin routes require authenticated/role-gated access; client routes remain public.
+
+---
+
+## 7. Database Migrations
+
+Assumes PostgreSQL syntax (adjust types for MySQL/SQLite as needed). Each migration is additive and ordered so foreign keys resolve correctly.
+
+### Migration 001 — create `job_templates`
+```sql
+-- up
+CREATE TABLE job_templates (
+ template_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ department VARCHAR(255),
+ location VARCHAR(255),
+ employment_type VARCHAR(50),
+ requirements TEXT,
+ salary_range VARCHAR(100),
+ version INT NOT NULL DEFAULT 1,
+ is_active BOOLEAN NOT NULL DEFAULT TRUE,
+ created_by UUID REFERENCES users(id),
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE INDEX idx_job_templates_active ON job_templates (is_active);
+
+-- down
+DROP TABLE IF EXISTS job_templates;
+```
+
+### Migration 002 — create `job_template_versions` (version history)
+```sql
+-- up
+CREATE TABLE job_template_versions (
+ version_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ template_id UUID NOT NULL REFERENCES job_templates(template_id) ON DELETE CASCADE,
+ version INT NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ department VARCHAR(255),
+ location VARCHAR(255),
+ employment_type VARCHAR(50),
+ requirements TEXT,
+ salary_range VARCHAR(100),
+ saved_by UUID REFERENCES users(id),
+ saved_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE INDEX idx_template_versions_template_id ON job_template_versions (template_id);
+
+-- down
+DROP TABLE IF EXISTS job_template_versions;
+```
+
+### Migration 003 — create `job_positions`
+```sql
+-- up
+CREATE TYPE position_status AS ENUM ('draft', 'open', 'closed', 'filled');
+
+CREATE TABLE job_positions (
+ position_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ template_id UUID REFERENCES job_templates(template_id) ON DELETE SET NULL,
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ department VARCHAR(255),
+ location VARCHAR(255),
+ employment_type VARCHAR(50),
+ requirements TEXT,
+ salary_range VARCHAR(100),
+ status position_status NOT NULL DEFAULT 'draft',
+ posted_by UUID REFERENCES users(id),
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE INDEX idx_job_positions_status ON job_positions (status);
+
+-- down
+DROP TABLE IF EXISTS job_positions;
+DROP TYPE IF EXISTS position_status;
+```
+
+### Migration 004 — create `applications`
+```sql
+-- up
+CREATE TYPE application_status AS ENUM ('new', 'reviewed', 'contacted', 'rejected', 'hired');
+
+CREATE TABLE applications (
+ application_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ position_id UUID NOT NULL REFERENCES job_positions(position_id) ON DELETE CASCADE,
+ first_name VARCHAR(100) NOT NULL,
+ last_name VARCHAR(100) NOT NULL,
+ email VARCHAR(255) NOT NULL,
+ phone VARCHAR(30) NOT NULL,
+ resume_file_url TEXT NOT NULL,
+ status application_status NOT NULL DEFAULT 'new',
+ admin_notes TEXT,
+ submitted_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE INDEX idx_applications_position_id ON applications (position_id);
+CREATE INDEX idx_applications_status ON applications (status);
+CREATE INDEX idx_applications_email ON applications (email);
+
+-- down
+DROP TABLE IF EXISTS applications;
+DROP TYPE IF EXISTS application_status;
+```
+
+### Migration 005 — updated_at auto-touch triggers (optional, Postgres)
+```sql
+-- up
+CREATE OR REPLACE FUNCTION set_updated_at()
+RETURNS TRIGGER AS $$
+BEGIN
+ NEW.updated_at = now();
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER trg_job_templates_updated_at
+BEFORE UPDATE ON job_templates
+FOR EACH ROW EXECUTE FUNCTION set_updated_at();
+
+CREATE TRIGGER trg_job_positions_updated_at
+BEFORE UPDATE ON job_positions
+FOR EACH ROW EXECUTE FUNCTION set_updated_at();
+
+-- down
+DROP TRIGGER IF EXISTS trg_job_templates_updated_at ON job_templates;
+DROP TRIGGER IF EXISTS trg_job_positions_updated_at ON job_positions;
+DROP FUNCTION IF EXISTS set_updated_at();
+```
+
+### Migration order & notes
+1. `job_templates` → 2. `job_template_versions` → 3. `job_positions` → 4. `applications` → 5. triggers.
+2. `users` table is assumed to already exist (for `created_by` / `posted_by`); drop those FK constraints if no auth/user table exists yet.
+3. Run each migration's `up` in order; `down` scripts reverse in the opposite order for rollback.
+4. If using a migration tool (Knex, Prisma, Sequelize, Alembic, Rails ActiveRecord, etc.), split each numbered migration above into that tool's file format/naming convention — the SQL logic stays the same.
+
+---
+
+## 8. Build Phases
+
+| Phase | Scope |
+|---|---|
+| 1 | Data models + admin CRUD for Positions (no templates yet) |
+| 2 | Template CRUD + versioning + "create position from template" |
+| 3 | Client-facing listing + detail pages |
+| 4 | Application form + file upload + submission handling |
+| 5 | Confirmation email + admin notification email |
+| 6 | Admin review dashboard (applications list, status, notes) |
+| 7 | Polish: validation, admin auth/permissions, testing |
+
+---
+
+## 9. Open Questions
+
+- How is admin access authenticated/restricted (login system, roles)?
+- Should duplicate applications (same email + position) be blocked or allowed?
+- What resume file types/size limits are acceptable?
+- Should closed positions remain visible (marked "closed") or disappear from the client list entirely?
\ No newline at end of file
diff --git a/agent_instructions.md b/agent_instructions.md
new file mode 100644
index 0000000..a77f898
--- /dev/null
+++ b/agent_instructions.md
@@ -0,0 +1,52 @@
+# Scope Discipline Rules
+
+These rules override any general instinct to "improve while I'm in there." Follow them on every task, no exceptions.
+
+## Before touching any code
+
+1. Restate the task in one sentence: what behavior must change, and what the expected outcome is.
+2. Identify the smallest set of files/functions responsible for that behavior. This is your **allowed scope**. Everything else is **protected**.
+3. Read the relevant code before editing it. Do not edit based on assumptions about how it probably works.
+
+## The hard rule: ask before expanding scope
+
+If, while working, you find that:
+- a file outside your allowed scope needs to change,
+- a dependency needs to be added/updated,
+- a test needs modification,
+- an unrelated bug is blocking you,
+- or a "cleaner" implementation would touch more than the minimum,
+
+**stop and ask me before making that change.** Explain:
+- what you were trying to do,
+- why the fix requires going outside the original scope,
+- exactly what you want to change and where.
+
+Wait for my answer. Do not proceed on your own judgment, even if you're confident it's correct or trivial.
+
+This applies even to small things (renaming a variable for clarity, fixing a typo in an unrelated comment, reformatting a block you had to scroll past). If it's not required to satisfy the request, ask first.
+
+## While editing
+
+- Make the fewest-line, fewest-file change that correctly satisfies the request.
+- Preserve existing naming, structure, patterns, and formatting. Match the codebase's existing style, don't impose your own.
+- Never run project-wide formatters/linters-with-autofix/import-organizers as a side effect of a small change.
+- Never touch tests except to add new ones that validate the requested behavior — and only after confirming that's in scope.
+- Treat any uncommitted/staged changes already in the working tree as off-limits. Don't revert, reset, or absorb them into your edit.
+
+## Before reporting done
+
+Review your own diff, file by file, line by line. For anything you can't justify with "this was required by the explicit request," revert it.
+
+Then report:
+- **Files changed** — list, with a one-line reason each tied directly to the request.
+- **Scope confirmation** — explicitly state: "No files, dependencies, tests, or config outside this list were modified."
+- **Anything you noticed but didn't touch** — unrelated bugs, tech debt, cleanup opportunities. Mention them, don't fix them.
+
+## If the task genuinely can't be done without expanding scope
+
+Say so plainly, explain what would need to change and why, and wait for confirmation. Don't silently do the bigger version, and don't pretend a partial/incorrect fix is complete.
+
+---
+
+**Default when uncertain: don't make the change, ask instead.**
\ No newline at end of file
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index c32358f..1175842 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -222,6 +222,7 @@ $routes->post('/user/store', 'View\UserController::store');
$routes->get('/thankyou', 'View\UserController::thankyou'); // Thank you page route
$routes->get('/', 'View\UserController::home'); // Home page route
$routes->get('/about', 'View\UserController::about'); // About page route
+$routes->get('/careers', 'View\UserController::careers'); // Careers page route
$routes->get('/classes', 'View\UserController::classes'); // Classes page route
$routes->get('/contact', 'View\UserController::contact'); // Contact Us page route
$routes->post('/user/login', 'AuthController::login');
diff --git a/app/Controllers/View/UserController.php b/app/Controllers/View/UserController.php
index 5234daf..24c9460 100644
--- a/app/Controllers/View/UserController.php
+++ b/app/Controllers/View/UserController.php
@@ -117,6 +117,12 @@ class UserController extends BaseController
return view('/about');
}
+ // Method to show the careers page
+ public function careers()
+ {
+ return view('/careers');
+ }
+
// Method to show the classes page
public function classes()
{
diff --git a/app/Views/careers.php b/app/Views/careers.php
new file mode 100644
index 0000000..338c2fa
--- /dev/null
+++ b/app/Views/careers.php
@@ -0,0 +1,382 @@
+
+
+
+