Full Stack Development Lab File | 12 Copyable Practicals
Full Stack Development lab file: 12 standalone front-end and Node.js exercises. Each has an aim, copyable code, expected result and viva question. HTML/CSS examples were parsed and checked structurally; JavaScript examples were run with Node.js 22. This is a general practical set, not an official college manual or deployable production app. Read Full Stack Exam Notes and the Semester 5 lab guide.
Lab Files index | Online Compiler: choose JavaScript, paste copied code, then run. Browser UI examples need an HTML browser preview; Node HTTP examples need a local Node runtime with loopback access.
1. Semantic HTML form
Aim: Create an accessible task form with labels. How to run: Open this HTML in a browser.
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><title>Task form</title></head>
<body><form id="taskForm"><label for="title">Task title</label>
<input id="title" name="title" required maxlength="80">
<button type="submit">Add task</button></form></body></html>Sample input: fixed values in the code. Expected result: The page has a labeled Task title input and an Add task button.
Viva: Why pair label for with an input id? It gives the input an accessible name.
2. Responsive CSS
Aim: Use a grid that stacks on narrow screens. How to run: Open this HTML in a browser.
<!doctype html><html lang="en"><head><meta name="viewport" content="width=device-width,initial-scale=1"><style>
.cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}
.card{border:1px solid #aaa;padding:1rem}
@media(max-width:600px){.cards{grid-template-columns:1fr}}
</style></head><body><main class="cards"><article class="card">A</article><article class="card">B</article></main></body></html>Sample input: fixed values in the code. Expected result: Two columns on wide screens and one on screens at most 600px wide.
Viva: Why use minmax(0,1fr)? It helps prevent grid content from forcing overflow.
3. DOM event listener
Aim: Add a task to a list after form submission. How to run: Open this HTML in a browser.
<!doctype html><html lang="en"><body><form id="f"><label for="task">Task</label><input id="task" required><button>Add</button></form><ul id="tasks"></ul><script>
document.querySelector('#f').addEventListener('submit', event => {
event.preventDefault();
const value = document.querySelector('#task').value.trim();
if (!value) return;
const item = document.createElement('li'); item.textContent = value;
document.querySelector('#tasks').append(item);
event.target.reset();
});
</script></body></html>Sample input: fixed values in the code. Expected result: Submitting a nonempty task adds one text-only list item.
Viva: Why use textContent? It avoids interpreting typed HTML as markup.
4. JSON response shape
Aim: Serialize a task record to JSON. How to run: Run with Node.js 22.
const task = { id: 1, title: 'Read notes', done: false };
console.log(JSON.stringify(task));Sample input: fixed values in the code. Expected result: {"id":1,"title":"Read notes","done":false}
Viva: Why use JSON? It is a common structured interchange format for APIs.
5. HTTP GET route
Aim: Serve a JSON task list using Node built-ins. How to run: Run with Node.js 22.
const http = require('node:http');
const server = http.createServer((req, res) => {
if (req.method !== 'GET' || req.url !== '/tasks') {
res.writeHead(404); return res.end('Not found');
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify([{ id: 1, title: 'Read notes' }]));
});
server.listen(0, '127.0.0.1', () => {
const port = server.address().port;
http.get(`http://127.0.0.1:${port}/tasks`, res => {
let text = ''; res.on('data', chunk => text += chunk);
res.on('end', () => { console.log(res.statusCode + ' ' + text); server.close(); });
});
});Sample input: fixed values in the code. Expected result: 200 [{"id":1,"title":"Read notes"}]
Viva: Why bind to 127.0.0.1? This test stays on the local machine.
6. HTTP POST validation
Aim: Reject invalid JSON task requests. How to run: Run with Node.js 22.
const http = require('node:http');
const server = http.createServer((req, res) => {
if (req.method !== 'POST' || req.url !== '/tasks') { res.writeHead(404); return res.end(); }
let body = '';
req.on('data', chunk => { body += chunk; if (body.length > 1024) req.destroy(); });
req.on('end', () => {
let input; try { input = JSON.parse(body); } catch { res.writeHead(400); return res.end('Invalid JSON'); }
if (typeof input.title !== 'string' || !input.title.trim()) { res.writeHead(400); return res.end('Invalid title'); }
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ id: 1, title: input.title.trim() }));
});
});
server.listen(0, '127.0.0.1', () => {
const req = http.request({ hostname: '127.0.0.1', port: server.address().port, path: '/tasks', method: 'POST' }, res => {
let text = ''; res.on('data', chunk => text += chunk);
res.on('end', () => { console.log(res.statusCode + ' ' + text); server.close(); });
});
req.end(JSON.stringify({ title: 'Write code' }));
});Sample input: fixed values in the code. Expected result: 201 {"id":1,"title":"Write code"}
Viva: Why validate on the server? Browser checks can be bypassed.
7. URL query parameters
Aim: Read and validate a page-size parameter. How to run: Run with Node.js 22.
const url = new URL('https://example.test/tasks?limit=5');
const raw = Number(url.searchParams.get('limit'));
const limit = Number.isInteger(raw) && raw >= 1 && raw <= 50 ? raw : 10;
console.log(`Limit=${limit}`);Sample input: fixed values in the code. Expected result: Limit=5
Viva: Why cap pagination size? To protect memory and response time.
8. Password hashing demo
Aim: Hash a test password using a salt and scrypt. How to run: Run with Node.js 22.
const { scryptSync } = require('node:crypto');
const password = 'demo-only-password';
const salt = Buffer.from('0123456789abcdef0123456789abcdef', 'hex');
const hash = scryptSync(password, salt, 32);
console.log('Hash bytes=' + hash.length);
console.log('Different input differs=' + !hash.equals(scryptSync(password + 'x', salt, 32)));Sample input: fixed values in the code. Expected result: Hash bytes=32 Different input differs=true
Viva: Should a real service use this fixed demo salt? No, use a random per-user salt and secure storage.
9. SQL parameter concept
Aim: Show safe positional binding syntax for a task query. How to run: Run with Node.js 22.
const sql = 'SELECT id, title FROM tasks WHERE owner_id = ?';
const params = [42];
console.log(sql);
console.log(JSON.stringify(params));Sample input: fixed values in the code. Expected result: SELECT id, title FROM tasks WHERE owner_id = ? [42]
Viva: Why bind values rather than concatenate? It avoids SQL injection when a DB driver executes the query.
10. Unit test
Aim: Test a pure title-normalizing function. How to run: Run with Node.js 22.
const assert = require('node:assert/strict');
function normalizeTitle(value) {
if (typeof value !== 'string') throw new TypeError('title');
const title = value.trim();
if (!title || title.length > 80) throw new RangeError('title length');
return title;
}
assert.equal(normalizeTitle(' Read notes '), 'Read notes');
assert.throws(() => normalizeTitle(''), RangeError);
console.log('2 checks passed');Sample input: fixed values in the code. Expected result: 2 checks passed
Viva: What makes a pure function easy to test? Same input gives the same output without external state.
11. Environment configuration
Aim: Read a port from environment with fallback. How to run: Run with Node.js 22.
const raw = Number(process.env.PORT);
const port = Number.isInteger(raw) && raw >= 1 && raw <= 65535 ? raw : 3000;
console.log(`Port=${port}`);Sample input: fixed values in the code. Expected result: Port=3000
Viva: Why avoid secrets in source files? Code can be shared or committed.
12. Task app in memory
Aim: Add, finish and list tasks without persistence. How to run: Run with Node.js 22.
const tasks = [];
let nextId = 1;
function add(title) { const task = { id: nextId++, title, done: false }; tasks.push(task); return task; }
function finish(id) { const task = tasks.find(item => item.id === id); if (task) task.done = true; }
add('Read notes'); add('Write code'); finish(1);
console.log(tasks.map(item => `${item.id}:${item.done}`).join(' '));Sample input: fixed values in the code. Expected result: 1:true 2:false
Viva: What is missing from an in-memory app? Data is lost when the process exits.
Verification: Nine JavaScript programs (4-12) ran under Node 22 with stated results; HTML/CSS examples (1-3) passed parser and structural checks but require a browser for visual behavior. These are teaching examples. Semester hub.
Comments
Post a Comment