diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..9f66f13 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,58 @@ +# Copilot Instructions for Bind Mount Applications + +## Project Overview +This is a Docker learning project featuring a simple Todo app with Node.js/Express frontend and MongoDB backend. The codebase demonstrates containerized application development with Docker Compose. + +## Architecture Patterns + +### Service Architecture +- **App Service**: Node.js Express server (`app/server.js`) on port 3001 +- **Database Service**: MongoDB (`todo-database`) on custom port 27018 +- **Connection**: App connects to MongoDB via service name `todo-database:27018` + +### Key Files & Structure +``` +app/ +├── server.js # Main Express server, sets up EJS and routes +├── config/keys.js # Database connection config (uses service name) +├── models/Todo.js # Mongoose schema for todos +├── routes/front.js # All HTTP routes (GET /, POST /, POST /todo/destroy) +└── views/todos.ejs # Single EJS template with Bootstrap +``` + +## Development Workflows + +### Docker Development +- **Start**: `docker compose up -d` (app runs on http://localhost:3001) +- **Development Mode**: Container uses `npm run dev` with nodemon for live reload +- **Bind Mounts**: Commented out in `compose.yaml` - uncomment volumes for live code changes + +### Key Conventions +- **Database Config**: Always use Docker service names (`todo-database:27018`), not localhost +- **Port Mapping**: App runs on 3001 internally and externally +- **MongoDB Port**: Uses non-standard 27018 to avoid conflicts +- **EJS Templates**: Moment.js available globally via `app.locals.moment` + +### Model Patterns +- Single Mongoose model exports as `module.exports = Todo = mongoose.model('todos', TodoSchema)` +- Schema uses `created_at` with `Date.now()` default +- Routes use async/await for database operations + +### Route Structure +- All routes in single file (`routes/front.js`) +- GET `/` - fetches todos and renders EJS template +- POST `/` - creates new todo and redirects +- POST `/todo/destroy` - deletes todo by `_key` field + +## Docker Specifics +- **Dockerfile**: Uses Node 19.5.0 Alpine with multi-stage build optimizations +- **Dependencies**: Installed via bind mounts for caching efficiency +- **Runtime User**: Runs as non-root `node` user +- **Links**: Uses legacy Docker `links` for service discovery + +## Quick Start for AI Agents +1. Database operations always go through Mongoose models +2. All HTML rendering uses EJS with Bootstrap 4.3.1 and Font Awesome +3. Form submissions are POST requests with `body-parser` URL-encoded parsing +4. Error handling is minimal - check `server.js` and route files for patterns +5. No authentication, testing, or API endpoints - pure server-rendered CRUD app \ No newline at end of file diff --git a/app/package-lock.json b/app/package-lock.json index ca4b813..180e090 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "body-parser": "^1.20.2", "ejs": "^3.1.9", - "express": "^4.18.2", + "express": "^4.19.2", "moment": "^2.29.4", "mongoose": "^7.1.0", "nodemon": "^3.0.1" @@ -268,9 +268,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -359,16 +359,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -399,29 +399,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -435,20 +412,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", diff --git a/app/package.json b/app/package.json index e015236..0950c49 100644 --- a/app/package.json +++ b/app/package.json @@ -12,7 +12,7 @@ "dependencies": { "body-parser": "^1.20.2", "ejs": "^3.1.9", - "express": "^4.18.2", + "express": "^4.19.2", "moment": "^2.29.4", "mongoose": "^7.1.0", "nodemon": "^3.0.1"