100 Node.js practice problems with solutions

Want to get comfortable with Node.js by writing real code? This post is exactly what you need. We’ve put together 100 Node.js practice problems with clear, step-by-step solutions. You’ll work on everything from basic JavaScript on the server, reading files, and handling events to building APIs with Express, working with databases, and managing async tasks.

Each problem is written in plain language so you can understand the goal, try it on your own, and then check the answer. Perfect for beginners who just started with Node as well as developers brushing up before an interview. Pick a challenge, write some code, and watch your skills grow.

Here are 100 Node.js practice problems with solutions, covering core modules, Express, databases, authentication, streams, and more.

Try it: 100 Javascript practice problems with solutions

1. Hello World Server

Create an HTTP server that responds with “Hello, World!”.

js

const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello, World!');
});
server.listen(3000, () => console.log('Server running on port 3000'));

2. Read a File

Read data.txt and log its content.

js

const fs = require('fs');
fs.readFile('data.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

3. Write to a File

Write “Hello, Node.js” to output.txt.

js

const fs = require('fs');
fs.writeFile('output.txt', 'Hello, Node.js', (err) => {
  if (err) throw err;
  console.log('File written');
});

4. Append to a File

Append a line to log.txt.

js

const fs = require('fs');
fs.appendFile('log.txt', 'New log entry\n', (err) => {
  if (err) throw err;
});

5. Read a JSON File

Parse and log the contents of config.json.

js

const fs = require('fs');
fs.readFile('config.json', 'utf8', (err, data) => {
  if (err) throw err;
  const config = JSON.parse(data);
  console.log(config);
});

6. Watch a File for Changes

Log a message when data.txt changes.

js

const fs = require('fs');
fs.watch('data.txt', (eventType, filename) => {
  console.log(`File ${filename} changed: ${eventType}`);
});

7. Create a Directory

Create a directory named uploads if it doesn’t exist.

js

const fs = require('fs');
if (!fs.existsSync('uploads')) {
  fs.mkdirSync('uploads');
}

8. Read a Directory

List all files and folders in the current directory.

js

const fs = require('fs');
fs.readdir('.', (err, files) => {
  if (err) throw err;
  console.log(files);
});

9. Delete a File

Remove temp.txt.

js

const fs = require('fs');
fs.unlink('temp.txt', (err) => {
  if (err) throw err;
  console.log('Deleted');
});

10. Delete a Directory (Recursively)

Remove a directory old_data and all its contents.

js

const fs = require('fs');
fs.rm('old_data', { recursive: true }, (err) => {
  if (err) throw err;
});

11. Join Path Segments

Create a full path to a file in the user’s home directory.

js

const path = require('path');
const filePath = path.join(process.env.HOME || process.env.USERPROFILE, 'app', 'config.json');
console.log(filePath);

12. Get OS Information

Log total memory, free memory, and CPU architecture.

js

const os = require('os');
console.log('Total Memory:', os.totalmem());
console.log('Free Memory:', os.freemem());
console.log('Architecture:', os.arch());

13. Read Environment Variables

Log the value of the NODE_ENV variable.

js

console.log(process.env.NODE_ENV || 'development');

14. Parse Command Line Arguments

Print all command line arguments passed to the script.

js

process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`);
});

15. Exit a Process

Exit the process with a specific exit code.

js

process.exit(1); // failure

16. Event Emitter Basics

Create a custom event emitter that emits a greet event.

js

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('greet', (name) => {
  console.log(`Hello, ${name}`);
});
myEmitter.emit('greet', 'Alice');

17. Readable Stream from File

Stream bigfile.txt and log chunks.

js

const fs = require('fs');
const readable = fs.createReadStream('bigfile.txt', { encoding: 'utf8' });
readable.on('data', (chunk) => {
  console.log('Received chunk:', chunk.length);
});
readable.on('end', () => console.log('Finished reading'));

18. Writable Stream

Write data to a file using a writable stream.

js

const fs = require('fs');
const writable = fs.createWriteStream('output.txt');
writable.write('Line 1\n');
writable.write('Line 2\n');
writable.end();

19. Pipe a Readable to Writable

Stream copy a file using pipe.

js

const fs = require('fs');
const readable = fs.createReadStream('source.txt');
const writable = fs.createWriteStream('destination.txt');
readable.pipe(writable);

20. Transform Stream (Uppercase)

Create a transform stream that converts input to uppercase.

js

const { Transform } = require('stream');
const upperCaseTransform = new Transform({
  transform(chunk, encoding, callback) {
    callback(null, chunk.toString().toUpperCase());
  }
});
process.stdin.pipe(upperCaseTransform).pipe(process.stdout);

21. HTTP GET Request (Client)

Make a GET request to a URL and log the response body.

js

const http = require('http');
http.get('http://jsonplaceholder.typicode.com/posts/1', (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => console.log(data));
});

22. HTTP POST Request

Send a POST request with JSON payload.

js

const https = require('https');
const data = JSON.stringify({ name: 'Node' });
const options = {
  hostname: 'httpbin.org',
  path: '/post',
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Content-Length': data.length }
};
const req = https.request(options, res => {
  res.pipe(process.stdout);
});
req.write(data);
req.end();

23. Basic Express App

Create an Express server listening on port 3000.

js

const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello Express'));
app.listen(3000, () => console.log('Server started'));

24. Express Route with Parameter

Define a route that greets a user by name: /hello/:name.

js

app.get('/hello/:name', (req, res) => {
  res.send(`Hello, ${req.params.name}`);
});

25. Serve Static Files with Express

Serve files from a public directory.

js

app.use(express.static('public'));

26. Express Middleware

Log every incoming request method and URL.

js

app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

27. Error Handling Middleware

Catch all errors and send a generic message.

js

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

28. Parse JSON Request Body

Enable JSON body parser in Express.

js

app.use(express.json());

29. Parse URL-Encoded Data

Handle form submissions.

js

app.use(express.urlencoded({ extended: true }));

30. CORS Handling

Enable CORS for all routes using cors package.

js

const cors = require('cors');
app.use(cors());

31. File Upload with Multer

Receive a single file upload under photo field.

js

const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('photo'), (req, res) => {
  res.send('File uploaded');
});

32. Basic Authentication Middleware

Protect a route with basic authentication.

js

app.use('/admin', (req, res, next) => {
  const auth = req.headers.authorization;
  if (!auth || auth !== 'Basic ' + Buffer.from('admin:secret').toString('base64')) {
    res.status(401).send('Unauthorized');
  } else {
    next();
  }
});

33. JWT Authentication

Generate a JWT token on login and verify middleware.

js

const jwt = require('jsonwebtoken');
// Login
app.post('/login', (req, res) => {
  const user = { id: 1, name: 'Alice' };
  const token = jwt.sign({ user }, 'secretkey', { expiresIn: '1h' });
  res.json({ token });
});
// Middleware
function verifyToken(req, res, next) {
  const token = req.headers['authorization'];
  if (!token) return res.sendStatus(403);
  jwt.verify(token.split(' ')[1], 'secretkey', (err, decoded) => {
    if (err) return res.sendStatus(403);
    req.user = decoded.user;
    next();
  });
}
app.get('/protected', verifyToken, (req, res) => res.json(req.user));

34. Hashing Passwords with bcrypt

Hash a password and compare.

js

const bcrypt = require('bcrypt');
async function hashPassword(plain) {
  const salt = await bcrypt.genSalt(10);
  return await bcrypt.hash(plain, salt);
}
async function checkPassword(plain, hashed) {
  return await bcrypt.compare(plain, hashed);
}

35. Session Management (express-session)

Use sessions to store a counter.

js

const session = require('express-session');
app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true }));
app.get('/counter', (req, res) => {
  req.session.views = (req.session.views || 0) + 1;
  res.send(`Views: ${req.session.views}`);
});

36. Cookies

Set and read cookies with cookie-parser.

js

const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.get('/set-cookie', (req, res) => {
  res.cookie('name', 'Alice').send('Cookie set');
});
app.get('/get-cookie', (req, res) => {
  res.send(`Cookie: ${req.cookies.name}`);
});

37. Mongoose Connection

Connect to a MongoDB database.

js

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true })
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.error(err));

38. Mongoose Model

Define a User model with name and email.

js

const userSchema = new mongoose.Schema({
  name: String,
  email: { type: String, unique: true }
});
const User = mongoose.model('User', userSchema);

39. Mongoose Create

Insert a new user.

js

const newUser = new User({ name: 'Alice', email: 'alice@example.com' });
newUser.save().then(user => console.log(user));

40. Mongoose Find

Retrieve all users.

js

User.find().then(users => console.log(users));

41. Mongoose Update

Update a user’s email.

js

User.updateOne({ name: 'Alice' }, { email: 'newalice@example.com' }).then(console.log);

42. Mongoose Delete

Remove a user by ID.

js

User.findByIdAndDelete('user-id').then(console.log);

43. Async/Await with Mongoose

Use async/await to create a user.

js

async function createUser(name, email) {
  const user = new User({ name, email });
  return await user.save();
}

44. Read File with Promise (fs/promises)

Read a file using the promise-based API.

js

const fsp = require('fs/promises');
fsp.readFile('data.txt', 'utf8')
  .then(console.log)
  .catch(console.error);

45. Promisify a Callback Function

Convert fs.readFile to a promise using util.promisify.

js

const util = require('util');
const readFileProm = util.promisify(fs.readFile);
readFileProm('data.txt', 'utf8').then(console.log);

46. Environment Variables with dotenv

Load .env file at the top of the script.

js

require('dotenv').config();
console.log(process.env.DATABASE_URL);

47. Child Process exec

Execute a shell command and log output.

js

const { exec } = require('child_process');
exec('ls -la', (err, stdout, stderr) => {
  if (err) throw err;
  console.log(stdout);
});

48. Child Process spawn

Run a command with streaming output.

js

const { spawn } = require('child_process');
const ls = spawn('ls', ['-la']);
ls.stdout.on('data', data => console.log(`Output: ${data}`));
ls.stderr.on('data', data => console.error(`Error: ${data}`));

49. Cluster Module

Fork a worker for each CPU core.

js

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
  http.createServer((req, res) => res.end('Hello from worker')).listen(8000);
}

Try it: 100 TypeScript practice problems with solutions

50. Process Signals

Gracefully exit on SIGINT.

js

process.on('SIGINT', () => {
  console.log('Shutting down');
  process.exit(0);
});

51. setTimeout and setInterval

Run a function every second.

js

const id = setInterval(() => console.log('Tick'), 1000);
// clearInterval(id);

52. nextTick vs setImmediate

js

console.log('Start');
process.nextTick(() => console.log('nextTick'));
setImmediate(() => console.log('setImmediate'));

53. Stream Backpressure

Handle backpressure in a writable stream.

js

const readable = fs.createReadStream('large');
const writable = fs.createWriteStream('copy');
readable.on('data', chunk => {
  const canContinue = writable.write(chunk);
  if (!canContinue) { readable.pause(); }
});
writable.on('drain', () => readable.resume());

54. Readline Interface

Ask a question in the terminal.

js

const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.question('What is your name? ', name => {
  console.log(`Hello, ${name}`);
  rl.close();
});

55. Crypto Hash

Create a SHA-256 hash of a string.

js

const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('Hello').digest('hex');
console.log(hash);

56. Random Bytes

Generate a random hex string.

js

crypto.randomBytes(16, (err, buf) => {
  if (err) throw err;
  console.log(buf.toString('hex'));
});

57. URL Parsing

Extract query string from a URL.

js

const url = require('url');
const myUrl = new URL('http://example.com/path?name=Alice');
console.log(myUrl.searchParams.get('name'));

58. Query String Parse

Parse a query string into an object.

js

const qs = require('querystring');
const parsed = qs.parse('name=Alice&age=30');
console.log(parsed);

59. Buffer Basics

Create a buffer from a string and convert back.

js

const buf = Buffer.from('Hello', 'utf8');
console.log(buf.toString('hex'));

60. Buffer Concatenation

Concatenate two buffers.

js

const buf1 = Buffer.from('Hello ');
const buf2 = Buffer.from('World');
const combined = Buffer.concat([buf1, buf2]);
console.log(combined.toString());

61. Readable Stream from String

Create a readable stream from a large string.

js

const { Readable } = require('stream');
const readable = Readable.from(['Hello ', 'World']);
readable.on('data', chunk => console.log(chunk.toString()));

62. Writable Stream to Array

Collect stream data into an array.

js

const chunks = [];
const writable = new Writable({
  write(chunk, encoding, callback) {
    chunks.push(chunk);
    callback();
  }
});
writable.on('finish', () => console.log(Buffer.concat(chunks).toString()));

63. Duplex Stream

A basic duplex stream (echo).

js

const { Duplex } = require('stream');
const echo = new Duplex({
  read(size) {},
  write(chunk, encoding, callback) {
    this.push(chunk);
    callback();
  }
});
process.stdin.pipe(echo).pipe(process.stdout);

Try it: 100 jquery practice problems with solutions

64. Pipeline

Use stream.pipeline to safely pipe with error handling.

js

const { pipeline } = require('stream');
pipeline(
  fs.createReadStream('source.txt'),
  fs.createWriteStream('dest.txt'),
  (err) => { if (err) console.error(err); }
);

65. Zlib Compress

Compress a file using gzip.

js

const zlib = require('zlib');
const gzip = zlib.createGzip();
const source = fs.createReadStream('input.txt');
const dest = fs.createWriteStream('input.gz');
source.pipe(gzip).pipe(dest);

66. Zlib Decompress

js

const gunzip = zlib.createGunzip();
fs.createReadStream('input.gz').pipe(gunzip).pipe(fs.createWriteStream('output.txt'));

67. HTTP/2 Server

Create a secure HTTP/2 server (with self-signed cert).

js

const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
});
server.on('stream', (stream, headers) => {
  stream.respond({ 'content-type': 'text/html', ':status': 200 });
  stream.end('<h1>Hello HTTP/2</h1>');
});
server.listen(8443);

68. WebSocket Server with ws

Broadcast messages to all connected clients.

js

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
  ws.on('message', (message) => {
    wss.clients.forEach(client => client.send(message));
  });
});

69. Graceful Shutdown

Close server and database connections on SIGTERM.

js

process.on('SIGTERM', () => {
  server.close(() => {
    console.log('HTTP server closed');
    mongoose.disconnect().then(() => process.exit(0));
  });
});

70. Logger with Winston

Set up a logger that writes to file and console.

js

const winston = require('winston');
const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});
logger.info('Hello, Winston');

71. Rate Limiting in Express

Limit each IP to 100 requests per 15 minutes.

js

const rateLimit = require('express-rate-limit');
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100 });
app.use(limiter);

72. Helmet Security Headers

Apply security headers.

js

const helmet = require('helmet');
app.use(helmet());

73. Response Compression

Compress responses with gzip.

js

const compression = require('compression');
app.use(compression());

74. Rendering with EJS

Set EJS as view engine and render a template.

js

app.set('view engine', 'ejs');
app.get('/home', (req, res) => {
  res.render('home', { title: 'My App' });
});

75. API Documentation with Swagger (via swagger-jsdoc)

Set up Swagger UI Express.

js

const swaggerUi = require('swagger-ui-express');
const swaggerJsDoc = require('swagger-jsdoc');
const options = { definition: { openapi: '3.0.0', info: { title: 'API', version: '1.0.0' } }, apis: ['./routes/*.js'] };
const specs = swaggerJsDoc(options);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

76. Testing with Jest (Simple Unit)

js

// sum.js
function sum(a, b) { return a + b; }
module.exports = sum;
// sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => expect(sum(1,2)).toBe(3));

77. Supertest for Express

Test an endpoint response.

js

const request = require('supertest');
const app = require('./app');
test('GET /', async () => {
  const res = await request(app).get('/');
  expect(res.statusCode).toBe(200);
});

78. Debugging with the Inspector

bash

node --inspect-brk app.js

79. Performance Measurement with perf_hooks

js

const { performance, PerformanceObserver } = require('perf_hooks');
const obs = new PerformanceObserver((list) => { console.log(list.getEntries()); });
obs.observe({ entryTypes: ['function'] });

80. Worker Threads

Offload CPU-heavy work to a worker.

js

const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
  const worker = new Worker(__filename);
  worker.on('message', msg => console.log(msg));
  worker.postMessage('start');
} else {
  parentPort.on('message', (msg) => {
    let sum = 0;
    for (let i = 0; i < 1e9; i++) sum += i;
    parentPort.postMessage(sum);
  });
}

81. DNS Lookup

Resolve a domain name to IP address.

js

const dns = require('dns');
dns.lookup('google.com', (err, address) => {
  if (err) throw err;
  console.log('IP:', address);
});

82. Network Interfaces

List all network interfaces and their IPs.

js

const { networkInterfaces } = require('os');
console.log(networkInterfaces());

83. Proxy Server

Simple proxy that forwards requests to another server.

js

const http = require('http');
const proxy = http.createServer((req, res) => {
  const options = { hostname: 'example.com', port: 80, path: req.url, method: req.method };
  const proxyReq = http.request(options, proxyRes => proxyRes.pipe(res));
  req.pipe(proxyReq);
});
proxy.listen(9000);

84. Environment-Driven Configuration

js

const config = {
  port: process.env.PORT || 3000,
  db: process.env.DATABASE_URL || 'mongodb://localhost:27017/myapp'
};
module.exports = config;

85. OAuth2 Flow (Simple with Passport)

This is conceptual; using passport-google strategy.

js

const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
  clientID: 'CLIENT_ID',
  clientSecret: 'SECRET',
  callbackURL: '/auth/google/callback'
}, (accessToken, refreshToken, profile, done) => done(null, profile)));
app.get('/auth/google', passport.authenticate('google', { scope: ['profile'] }));
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/' }), (req, res) => res.redirect('/'));

86. JWT Refresh Token

Endpoint that returns a new token if provided token is valid.

js

app.post('/refresh', (req, res) => {
  const token = req.body.token;
  jwt.verify(token, 'secretkey', (err, decoded) => {
    if (err) return res.sendStatus(403);
    const newToken = jwt.sign({ user: decoded.user }, 'secretkey', { expiresIn: '1h' });
    res.json({ token: newToken });
  });
});

87. Sending Email with Nodemailer

js

const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: { user: 'you@gmail.com', pass: 'password' }
});
transporter.sendMail({
  from: 'you@gmail.com',
  to: 'friend@example.com',
  subject: 'Test',
  text: 'Hello'
}).then(console.log);

88. Scheduling a Cron Job

Run a function every minute.

js

const cron = require('node-cron');
cron.schedule('* * * * *', () => {
  console.log('Running every minute');
});

89. Building a CLI with Commander

js

const { program } = require('commander');
program
  .version('1.0.0')
  .description('A simple CLI')
  .option('-n, --name <type>', 'Your name')
  .action((options) => console.log(`Hello, ${options.name}`));
program.parse(process.argv);

90. Readline Prompts

js

const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (question) => new Promise(resolve => rl.question(question, resolve));
(async () => {
  const name = await ask('Name: ');
  console.log(`Hello ${name}`);
  rl.close();
})();

91. Markdown to HTML

Use marked to convert Markdown string.

js

const marked = require('marked');
console.log(marked.parse('# Hello\n**bold**'));

92. CSV Parser

Parse CSV data and output JSON.

js

const csv = require('csv-parser');
fs.createReadStream('data.csv')
  .pipe(csv())
  .on('data', (row) => console.log(row))
  .on('end', () => console.log('Done'));

93. JSON to CSV

Convert an array of objects to CSV string.

js

const { Parser } = require('json2csv');
const json = [{ name: 'Alice', age: 30 }];
const parser = new Parser();
const csv = parser.parse(json);
fs.writeFileSync('output.csv', csv);

94. Image Resizing with Sharp

Resize an image to 300×200.

js

const sharp = require('sharp');
sharp('input.jpg')
  .resize(300, 200)
  .toFile('output.jpg');

Try it: 100 C++ practice problems with solutions

95. Generate PDF with PDFKit

Create a simple PDF file.

js

const PDFDocument = require('pdfkit');
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream('output.pdf'));
doc.fontSize(25).text('Hello, PDF!');
doc.end();

96. Serving a Single Page Application

Serve an SPA with fallback to index.html.

js

app.use(express.static('client/build'));
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html')));

97. Environment‑based Config Loading

js

const env = process.env.NODE_ENV || 'development';
const config = require(`./config/${env}.json`);
console.log(config);

98. Global Uncaught Exception Handler

js

process.on('uncaughtException', (err) => {
  console.error('Unhandled Exception:', err);
  process.exit(1);
});

99. Unhandled Promise Rejection

js

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  process.exit(1);
});

100. Custom Error Class

Create a custom error with status code.

js

class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }
}
throw new AppError('Not Found', 404);

Final Thought

One hundred Node.js problems — and you didn’t just solve them, you explored them!

Think back to the first problem. It was a quiet trailhead. Now look at the mental landscape you’ve crossed: streams, buffers, event loops, APIs, file systems, databases, and invisible async currents that only the bravest developers learn to navigate. This wasn’t a tutorial marathon — it was an expedition. And you, fearless coder, led the way.

Every error was a cliff you climbed. Every solution was a hidden waterfall shimmering at the end of a long debugging hike. You’re no longer tethered to the browser — you’re a full-stack explorer who can spin servers out of thin air and harness the raw power of V8 with nothing but JavaScript and grit.

Now that you’ve tasted adventure, don’t settle for comfortable. Build that real-time chat app. Deploy that API to a cheap VPS just for the thrill. Hike into a new npm package without a map. The Node.js world is massive, wild, and deeply rewarding — and you’ve already proven you have the spirit to roam it.

Bookmark this page like an old compass. Return when the path feels foggy. And always remember: the greatest code you’ll ever write lies just beyond the next challenge. Adventure on!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top