Outdoorsy is a full‑stack web application where users discover, review, and share campsites worldwide.
Live: joshlehman.ca/outdoorsy · API Docs: joshlehman.ca/outdoorsy/api-docs
Recent improvements mapped to the public roadmap:
-
Architecture & Code Quality
- Modular
config/(db, session, passport, security, swagger). - Centralized middleware exports (
middleware/index.js). - Joi validation and Passport auth middleware.
app.jsrefactored to minimal bootstrap.
- Modular
-
Error Handling & Developer Experience
- Unified error classes (
AppError,ValidationError, etc.). - Centralized error handler with dev stack traces.
- Modernized flash messages (Bootstrap 5, aria-live).
- Unified error classes (
-
Frontend Accessibility & Semantics
- Correct heading hierarchy in views.
- Landmarks, keyboard navigation, labelled SVG icons.
- Forms with
<fieldset>/<legend>, properly associated labels. - Focus styles, skip links, staggered reveal animations respecting reduced motion.
-
UI/UX & Styling
- Responsive homepage with features, stats, CTA.
- Organized
public/stylesheets/(home, navbar, footer, etc.). - Removed inline styles; consistent button/input styling.
-
Performance
- MongoDB indexes on key models.
- Pagination for campgrounds and reviews.
- Lazy-loaded images and responsive layout improvements.
-
Security
- Rate limiting for auth and API routes.
- CSRF protection on forms (
csurf). - Hardened CSP via Helmet; request size limits and env validation.
-
Documentation
- README overhauled, roadmap published, Swagger UI hosted.
See the full roadmap for in‑progress and upcoming items.
- Browse campgrounds and reviews without logging in
- Create, edit, delete campgrounds and reviews (auth required)
- Secure authentication & authorization with PassportJS
- Image handling and storage on AWS/Cloudinary
- Nearby discovery, gallery, and review system
- Swagger-powered API documentation
| Layer | Technologies |
|---|---|
| Frontend | HTML5, CSS3, Bootstrap 5 |
| Backend | Node.js, Express.js |
| Database | MongoDB (Mongoose) |
| Auth | PassportJS |
| Security | Helmet, Joi, csurf, express-rate-limit |
| Docs | Swagger‑UI / JSDoc |
| Deploy | Render.com, AWS |
| Architecture | REST + MVC, SSR with EJS |
- Website: joshlehman.ca/outdoorsy
- API Docs (Swagger): joshlehman.ca/outdoorsy/api-docs
| Home | All Campgrounds | Campground Details | Login/Register |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
API & UMLs:
Outdoorsy/
├─ app.js
├─ server.js
├─ config/
│ ├─ db.js
│ ├─ session.js
│ ├─ passport.js
│ ├─ security.js
│ └─ swagger.js
├─ routes/
│ ├─ campgrounds.js
│ ├─ reviews.js
│ ├─ users.js
│ └─ api/v1/
├─ controllers/
│ ├─ campgrounds.controller.js
│ ├─ reviews.controller.js
│ └─ users.controller.js
├─ models/
│ ├─ Campground.js
│ ├─ Review.js
│ └─ User.js
├─ middleware/
│ ├─ index.js
│ ├─ auth.js
│ ├─ validation.js
│ └─ errors.js
├─ public/
│ ├─ javascripts/home.js
│ └─ stylesheets/
│ ├─ main.css
│ ├─ home.css
│ ├─ navbar.css
│ └─ ...
└─ views/
├─ layouts/boilerplate.ejs
├─ partials/{navbar,footer,flash}.ejs
├─ campgrounds/{index,show,new,edit,nearby}.ejs
└─ users/{login,register,success}.ejs
Create a .env file (example):
# App
NODE_ENV=development
PORT=3000
BASE_URL=http://localhost:3000
# Database
MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/outdoorsy
# Storage / CDN (Cloudinary example)
CLOUDINARY_CLOUD_NAME=your-cloud
CLOUDINARY_KEY=your-key
CLOUDINARY_SECRET=your-secret
# Sessions & Auth
SESSION_SECRET=supersecretkey
GOOGLE_CLIENT_ID=your-id
GOOGLE_CLIENT_SECRET=your-secret
GOOGLE_CALLBACK_URL=/auth/google/callbackInstall and run:
npm install
npm startRun tests:
npm test- Rate limiting on auth & API
- CSRF tokens on forms
- Strict CSP and Helmet headers
- Joi validation for critical paths
- Request size limits and env var validation
- Incident response & security documentation
- Designed to WCAG 2.1 AA standards
- Proper heading hierarchy and landmarks
- Keyboard-accessible navigation and controls
- Focus states, skip links, and
aria-livefor dynamic messages
- Done: foundation, security controls, accessibility overhaul, documentation refresh
- In Progress: image optimization pipeline, caching/CDN, SEO metadata
- Planned: user profiles, bookmarks/favorites, advanced search, API v1 (JWT), monitoring & CI observability
See ROADMAP.md for full details.
Joshua Lehman
- Portfolio: joshlehman.ca
- GitHub: joshl26
- LinkedIn: Joshua Lehman
Issues and PRs welcome.
- Issues: github.com/joshl26/Outdoorsy/issues
- Contributing Guide: CONTRIBUTING.md
MIT © 2023–2025 Joshua Lehman — see LICENSE






