A community platform for documenting, caring for, and rehoming stray cats in Metro Manila's public markets.
Live Demo | Features | Get Started | Documentation
Behind every fish stall, beside every vegetable crate in a Metro Manila public market, there are cats. Vendors feed them. Neighbors watch over colonies. Security guards build cardboard shelters during typhoon season. Communities form around these animals — invisible to anyone who doesn't walk through that market every day.
This kindness is real, but it's fragmented. There's no way to track which cats need help, no coordination between volunteers across markets, no channel to report injured strays to someone who can respond, and no friction-free way to donate (most Filipinos rely on mobile wallets, not credit cards).
Palengkatts makes the invisible visible — the cats, the caretakers, and the communities formed around them. It connects the informal care networks already in place with structured support: adoption pathways, volunteer coordination, stray reporting, and direct donations via GCash and Maya QR.
| Feature | Description |
|---|---|
| Market Profiles | Browse cat communities across Metro Manila markets with authentic vendor stories |
| Interactive Map | Leaflet map with market pins — discover colonies near you |
| Cat Adoption | Browse available cats with backstories, filter by age and personality, submit inquiries |
| Report a Stray | Zero-friction form with photo upload — no account needed |
| Volunteer Sign-up | Calendar-based scheduling for feeding, transport, and fostering |
| QR Donations | GCash and Maya QR codes — scan and donate in seconds, zero fees |
| Admin Dashboard | CRUD panel for managing cats, reports, volunteers, and markets |
| Accessibility | WCAG 2.1 AA — works on budget phones, screen readers, and 3G connections |
| Layer | Technology | Rationale |
|---|---|---|
| Frontend | React 18, Vite 5, React Router v7 | Fast builds, modern SPA routing |
| Styling | Tailwind CSS v4, shadcn/ui | Utility-first CSS, accessible component primitives |
| State Management | Zustand | Minimal boilerplate, built-in selectors, clean async |
| Forms & Validation | React Hook Form + Zod | Performant, schema-driven, type-safe |
| Map | Leaflet + react-leaflet | Free, no API key, OpenStreetMap tiles |
| Animations | Framer Motion | Respects prefers-reduced-motion automatically |
| Notifications | Sonner | Lightweight toast system |
| Backend | Supabase (PostgreSQL, Storage, RLS) | Free tier, instant REST API, relational data |
| Hosting | Vercel | Auto-deploy on push, global CDN, SPA rewrites |
| CI/CD | GitHub Actions | Build and test on every push and PR |
palengkatts/
├── public/
│ └── images/
│ ├── cats/ Cat profile photos
│ ├── markets/ Market hero images
│ └── qr/ GCash/Maya QR codes
├── src/
│ ├── components/ Shared UI components
│ │ └── ui/ shadcn/ui primitives (9 components)
│ ├── layouts/ PublicLayout, AdminLayout
│ ├── lib/
│ │ ├── stores/ Zustand stores (market, cat, report, volunteer, adoption)
│ │ ├── motion.js Framer Motion design tokens and reusable variants
│ │ ├── rateLimit.js Client-side form submission rate limiting
│ │ ├── schemas.js Zod validation schemas
│ │ ├── supabase.js Supabase client initialization
│ │ └── utils.js Tailwind merge utility
│ ├── pages/ Route pages (10 public, 6 admin)
│ │ └── admin/ Admin dashboard pages
│ ├── test/ Test suite (Vitest + RTL)
│ ├── App.jsx Route definitions
│ └── main.jsx Application entry point
├── supabase/
│ ├── migrations/
│ │ └── 001_initial_schema.sql Database schema (tables, indexes, RLS)
│ └── seed.sql Demo data (4 markets, 8 cats, sample reports)
├── docs/ Extended documentation
├── documentation/ Project report (hackathon submission)
├── .github/workflows/ci.yml CI pipeline
├── vercel.json Deployment configuration
└── package.json
- Node.js 22 or later
- npm 9 or later
- A Supabase account (free tier)
# Clone the repository
git clone https://github.com/your-team/palengkatts.git
cd palengkatts
# Install dependencies
npm install
# Copy environment template
cp .env.example .envEdit .env with your Supabase credentials (found in Settings > API):
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...In your Supabase project's SQL Editor, run these files in order:
supabase/migrations/001_initial_schema.sql— creates tables, indexes, and RLS policiessupabase/seed.sql— populates demo data (4 markets, 8 cats with backstories, sample reports and volunteers)
npm run dev # Development server at http://localhost:5173
npm run build # Production build to dist/
npm run preview # Preview production build
npm test # Run test suiteFor detailed setup instructions including troubleshooting, see docs/SETUP.md.
┌──────────────────┐ ┌──────────────────┐
│ markets │ │ cats │
├──────────────────┤ ├──────────────────┤
│ id (PK) │◄────────│ market_id (FK) │
│ name │ 1:N │ id (PK) │
│ city │ │ name │
│ description │ │ age_category │
│ latitude │ │ personality │
│ longitude │ │ description │
│ cat_count │ │ traits[] │
│ gradient │ │ status │
│ created_at │ │ image_url │
└──────────────────┘ │ created_at │
└────────┬─────────┘
│ 1:N
┌────────┴─────────┐
│ adoptions │
├──────────────────┤
│ id (PK) │
│ cat_id (FK) │
│ applicant_name │
│ applicant_contact│
│ message │
│ status │
│ created_at │
└──────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ reports │ │ volunteers │
├──────────────────┤ ├──────────────────┤
│ id (PK) │ │ id (PK) │
│ market_name │ │ name │
│ location_detail │ │ contact │
│ color, size │ │ city │
│ conditions[] │ │ roles[] │
│ behavior, notes │ │ available_dates[]│
│ photo_url │ │ note │
│ urgency │ │ status │
│ status │ │ created_at │
│ created_at │ └──────────────────┘
└──────────────────┘
Five tables, all with Row-Level Security enabled. Public read/write policies for the hackathon demo (no authentication). Full schema reference: docs/DATABASE.md.
- Push the repository to GitHub
- Import the project at vercel.com/new
- Add environment variables:
VITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEY - Deploy — Vercel auto-detects Vite and applies the
vercel.jsonconfiguration
Every subsequent push to main triggers automatic redeployment. Pull requests get preview deployments with unique URLs.
GitHub Actions runs on every push to main and on pull requests:
- Node.js 22 environment
npm installfor dependency installationnpm run buildto verify compilation- 10-minute timeout per job
Full deployment guide: docs/DEPLOYMENT.md
| Path | Page | Description |
|---|---|---|
/ |
Home | Market listings, interactive map, hero |
/adopt |
Adoption | Browse and filter cats, submit inquiries |
/report |
Report Stray | Form with photo upload for sightings |
/market/:id |
Market Profile | Individual market with its cat colony |
/donate |
Donate | GCash and Maya QR codes |
/volunteer |
Volunteer | Sign-up form with calendar scheduling |
/about |
About | Mission and community story |
/contact |
Contact | Contact information |
/faq |
FAQ | Frequently asked questions |
/admin |
Overview | Summary statistics |
/admin/reports |
Reports | Manage stray reports |
/admin/cats |
Cats | Add and edit cat profiles |
/admin/volunteers |
Volunteers | Manage volunteer roster |
/admin/adoptions |
Adoptions | Manage adoption inquiries |
/admin/markets |
Markets | Manage market data |
Palengkatts targets WCAG 2.1 AA compliance:
- Touch targets — 44x44px minimum on all interactive elements
- Color contrast — 4.5:1 for normal text, 3:1 for large text
- Form accessibility — All inputs have labels; errors linked via
aria-describedby - Motion sensitivity —
prefers-reduced-motion: reducedisables all animations - Image alt text — Descriptive text for content images, empty
altfor decorative - Keyboard navigation — Visible 2px focus indicators, logical tab order
- Skip link — First focusable element on every page
- Error announcements —
aria-live="assertive"for validation messages
Palengkatts addresses a real problem in Metro Manila's urban communities:
- Emergency response — Injured stray reports reach volunteers in hours, not days
- Adoption pipeline — Connects willing adopters directly to market caretakers
- TNR visibility — Tracks neutered cats, preventing duplicate veterinary work
- Community dignity — Celebrates vendors already doing this work (bayanihan, not charity)
- Scalable model — Market-by-market approach mirrors how informal cat care naturally spreads
- Zero friction — No sign-ups, no auth walls. Every action is one tap away.
- Community first — Vendors, cats, and stories are the hero. The UI gets out of the way.
- Low bandwidth — Images under 200KB, works on 3G, budget phone friendly.
- Empathy over polish — A genuine story beats a slick animation.
- Filipino context — GCash over Stripe, palengke over marketplace, bayanihan over charity.
| Document | Contents |
|---|---|
| Architecture | System design, data flows, design decisions |
| Setup Guide | Complete local development walkthrough |
| Features | User flows, validation rules, technical details |
| Database | Full schema reference with constraints and indexes |
| Deployment | Vercel configuration, CI/CD, production checklist |
| API Reference | Stores, queries, validation schemas, error handling |
| Project Report | Hackathon submission report and testing matrix |
npm testRuns Vitest in single-execution mode. Test coverage includes:
- Zod schema validation (valid and invalid inputs for all three form schemas)
- Zustand store fetch logic with mocked Supabase responses
- Client-side rate limiting logic
- CI pipeline executes tests on every push and pull request
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m 'feat: add your feature' - Push to the branch:
git push origin feature/your-feature - Open a Pull Request
Follow the existing conventions: Tailwind for styling, Zustand for state, Zod for validation, Sonner for notifications.
Palengkatts — Built for the cats of Metro Manila's public markets.
| Name | Role | GitHub |
|---|---|---|
| gtapp1 | Developer | @gtapp1 |
This project is open source under the MIT License.