Help
RSS
API
Feed
Maltego
Contact
Domain > davidrowley.co.uk
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2025-06-20
3.5.245.131
(
ClassC
)
2025-07-06
3.5.246.51
(
ClassC
)
2025-11-16
3.169.173.64
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyServer: CloudFrontDate: Sun, 16 Nov 2025 03:39:11 GMTContent-Type: text/htmlContent-Length: 167Connection: keep-aliveLocation: https://davidrowley.co.uk/X-Cache: Redirect from cloudfrontVia: 1.1 8af7e76489ae9222af2304e63d2c0520.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: qoAEeo_7NoQcdSMKMJBNMo5uTo2GB2bI6WMNE5IStfTGXGetkvobzg html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>CloudFront/center>/body>/html>
Port 443
HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: 46660Connection: keep-aliveLast-Modified: Sat, 05 Jul 2025 14:50:54 GMTx-amz-server-side-encryption: AES256x-amz-version-id: 3qcO8aKxTlT8On3qexHsWhMzl_4RWWAGAccept-Ranges: bytesServer: AmazonS3Date: Sun, 16 Nov 2025 03:39:13 GMTETag: a95b20a3eff2fa6d2a2a34e8e3a10e19X-Cache: RefreshHit from cloudfrontVia: 1.1 c5e1a6561d8dc3977e11160718fc75e8.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: gDq_3rG0hNKJt4_Y5y3Al-nkumOhrcM2SXWzVgogtzu11JEkoRtOLw !DOCTYPE html>html langen>head> meta charsetUTF-8> meta nameviewport contentwidthdevice-width, initial-scale1.0> title>David Rowley - DevOps Engineer/title> link hrefhttps://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css relstylesheet> style> :root { --amber-primary: #f59e0b; --amber-dark: #d97706; --amber-light: #fbbf24; --bg-primary: #0a0a0a; --bg-secondary: #111111; --bg-tertiary: #1a1a1a; --text-primary: #ffffff; --text-secondary: #a1a1aa; --text-muted: #52525b; --border-color: #27272a; } body { font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif; background-color: var(--bg-primary); color: var(--text-primary); line-height: 1.6; } /* Override Bootstrap navbar */ .navbar { background-color: rgba(10, 10, 10, 0.95) !important; backdrop-filter: blur(10px); border-bottom: 1px solid var(--bg-tertiary); } .navbar-brand { font-size: 1.2rem; font-weight: 600; background: linear-gradient(45deg, var(--amber-primary), var(--amber-light)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .navbar-nav .nav-link { color: var(--text-secondary) !important; font-weight: 500; transition: color 0.2s ease; } .navbar-nav .nav-link:hover { color: var(--amber-primary) !important; } .navbar-toggler { border-color: var(--border-color); } .navbar-toggler-icon { background-image: url(data:image/svg+xml,%3csvg xmlnshttp://www.w3.org/2000/svg viewBox0 0 30 30%3e%3cpath strokergba%28161, 161, 170, 1%29 stroke-linecapround stroke-miterlimit10 stroke-width2 dM4 7h22M4 15h22M4 23h22/%3e%3c/svg%3e); } /* Custom hero section */ .hero { min-height: 100vh; display: flex; align-items: center; padding-top: 76px; } .hero h1 { font-size: clamp(2.5rem, 6vw, 4rem); font-weight: 700; color: var(--text-primary); } .hero .subtitle { font-size: clamp(1rem, 2.5vw, 1.3rem); color: var(--amber-primary); font-weight: 500; } .hero .description { height: auto; font-size: 1.1rem; color: var(--text-secondary); } .hero-image { width: 80%; height: auto; max-width: 350px; display: block; margin: 0 auto; } /* Custom buttons */ .btn-amber { background-color: var(--amber-primary); border-color: var(--amber-primary); color: #000000; font-weight: 500; } .btn-amber:hover { background-color: var(--amber-dark); border-color: var(--amber-dark); color: #000000; } .btn-outline-amber { color: var(--amber-primary); border-color: var(--amber-primary); background-color: transparent; } .btn-outline-amber:hover { background-color: rgba(245, 158, 11, 0.1); border-color: var(--amber-primary); color: var(--amber-primary); } /* Custom cards */ .custom-card { background-color: var(--bg-secondary); border: 1px solid var(--bg-tertiary); border-radius: 8px; transition: border-color 0.2s ease; } .custom-card:hover { border-color: var(--border-color); } .card-body { color: var(--text-primary); } /* Section styling */ .section { padding: 4rem 0; } .section-title { font-size: 2rem; font-weight: 600; color: var(--text-primary); margin-bottom: 2rem; } /* Skills styling */ .skill-category { background-color: var(--bg-secondary); border: 1px solid var(--bg-tertiary); border-radius: 8px; padding: 1.5rem; } .skill-category h5 { color: var(--amber-primary); font-weight: 600; font-size: 1rem; } .skill-tag { background-color: var(--bg-tertiary); color: var(--text-secondary); padding: 0.3rem 0.8rem; border-radius: 20px; font-size: 0.85rem; border: 1px solid var(--border-color); display: inline-block; margin: 0.2rem; } /* Project styling */ .project-card { background-color: var(--bg-secondary); border: 1px solid var(--bg-tertiary); border-radius: 8px; transition: border-color 0.2s ease; } .project-card:hover { border-color: var(--border-color); } .project-card .card-title { font-size: 1.1rem; font-weight: 600; color: var(--text-primary); } .project-card .card-text { color: var(--text-secondary); font-size: 0.95rem; } /* Project thumbnail styling */ .project-thumbnails { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-bottom: 1rem; } .project-thumbnail { height: 80px; background: linear-gradient(135deg, var(--bg-tertiary), var(--border-color)); border-radius: 6px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; overflow: hidden; position: relative; border: 1px solid transparent; } .project-thumbnail:hover { transform: scale(1.05); border-color: var(--amber-primary); } .project-thumbnail img { width: 100%; height: 100%; object-fit: cover; border-radius: 5px; } .project-thumbnail-placeholder { font-size: 1.5rem; color: var(--amber-primary); } .thumbnail-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s ease; border-radius: 5px; } .project-thumbnail:hover .thumbnail-overlay { opacity: 1; } .thumbnail-overlay span { color: var(--amber-primary); font-size: 0.9rem; font-weight: 500; } /* Modal styling */ .modal-content { background-color: var(--bg-secondary); border: 1px solid var(--border-color); } .modal-header { border-bottom: 1px solid var(--border-color); } .modal-title { color: var(--text-primary); } .btn-close { filter: invert(1); } .modal-body { position: relative; padding: 2rem; } .modal-body img { width: 100%; height: auto; max-height: 60vh; object-fit: contain; border-radius: 8px; } /* Gallery navigation */ .gallery-nav { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(0, 0, 0, 0.7); color: var(--amber-primary); border: 1px solid var(--amber-primary); border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; font-size: 1.2rem; font-weight: bold; } .gallery-nav:hover { background: var(--amber-primary); color: #000000; } .gallery-nav.prev { left: 10px; } .gallery-nav.next { right: 10px; } .gallery-nav:disabled { opacity: 0.3; cursor: not-allowed; } .gallery-nav:disabled:hover { background: rgba(0, 0, 0, 0.7); color: var(--amber-primary); } /* Gallery indicators */ .gallery-indicators { display: flex; justify-content: center; gap: 0.5rem; margin-top: 1rem; } .gallery-indicator { width: 10px; height: 10px; border-radius: 50%; background: var(--border-color); cursor: pointer; transition: all 0.2s ease; } .gallery-indicator.active { background: var(--amber-primary); } .gallery-indicator:hover { background: var(--amber-light); } /* Image counter */ .image-counter { position: absolute; top: 10px; right: 10px; background: rgba(0, 0, 0, 0.7); color: var(--text-secondary); padding: 0.3rem 0.8rem; border-radius: 15px; font-size: 0.85rem; } .tech-tag { background-color: rgba(245, 158, 11, 0.1); color: var(--amber-primary); padding: 0.2rem 0.6rem; border-radius: 12px; font-size: 0.8rem; border: 1px solid rgba(245, 158, 11, 0.2); display: inline-block; margin: 0.2rem; } .project-link { color: var(--text-secondary); text-decoration: none; font-size: 0.9rem; font-weight: 500; transition: color 0.2s ease; } .project-link:hover { color: var(--amber-primary); } /* Contact section */ .contact-section { background-color: var(--bg-secondary); border: 1px solid var(--bg-tertiary); border-radius: 8px; } .contact-link { color: var(--text-secondary); text-decoration: none; padding: 0.8rem 1.2rem; background-color: var(--bg-tertiary); border-radius: 4px; transition: all 0.2s ease; border: 1px solid var(--border-color); font-size: 0.9rem; display: inline-block; } .contact-link:hover { background-color: rgba(245, 158, 11, 0.1); border-color: var(--amber-primary); color: var(--amber-primary); } /* Footer */ .custom-footer { border-top: 1px solid var(--bg-tertiary); color: var(--text-muted); font-size: 0.9rem; } /* About text styling */ .about-text { color: var(--text-secondary); } /* Override Bootstrap text colors */ .text-muted { color: var(--text-secondary) !important; } /style>/head>body> !-- Navigation --> nav classnavbar navbar-expand-lg navbar-dark fixed-top> div classcontainer> a classnavbar-brand href#home>h4>strong>davidrowley.co.uk/strong>/h4>/a> button classnavbar-toggler typebutton data-bs-togglecollapse data-bs-target#navbarNav> span classnavbar-toggler-icon>/span> /button> div classcollapse navbar-collapse idnavbarNav> ul classnavbar-nav ms-auto> li classnav-item> a classnav-link href#home>Home/a> /li> li classnav-item> a classnav-link href#about>About/a> /li> li classnav-item> a classnav-link href#projects>Projects/a> /li> li classnav-item> a classnav-link href#contact>Contact/a> /li> /ul> /div> /div> /nav> !-- Hero Section --> section idhome classhero> div classcontainer> div classrow> div classcol-lg-5 d-flex align-items-center justify-content-center> img src/egg-bw-orangesgradient-vec.png altdavidrowley classhero-image> /div> div classcol-lg-7 align-items-center> h1 classmb-3>David Rowley/h1> p classsubtitle mb-3>?? DevOps Engineer → AI Developer/p> p classdescription mb-4> ?? Bridging infrastructure expertise with AI innovation. Building scalable, production-ready intelligent systems. /p> div classd-flex gap-3 flex-wrap> a href#projects classbtn btn-amber>View Work/a> a href#contact classbtn btn-outline-amber>Contact/a> /div> /div> /div> /div> /section> !-- About Section --> section idabout classsection> div classcontainer> h2 classsection-title>About Me/h2> div classrow g-4> div classcol-lg-6> p classabout-text mb-3> ?? X years in DevOps, now focused on AI development. I understand both the infrastructure that powers AI and the algorithms that drive intelligence. /p> p classabout-text> My unique background enables me to build AI systems that arent just innovative—theyre scalable, maintainable, and production-ready from day one. /p> /div> div classcol-lg-6> div classrow g-3> div classcol-md-12> div classskill-category h-100> h5 classmb-3>Technical Skills/h5> div classskill-tags> span classskill-tag>AWS/span> span classskill-tag>CI/CD/span> span classskill-tag>Django/span> span classskill-tag>Dcoker/span> span classskill-tag>FastAPI/span> span classskill-tag>Flutter/span> span classskill-tag>Kubernetes/span> span classskill-tag>Linux/span> span classskill-tag>Python/span> span classskill-tag>PyTorch/span> span classskill-tag>Terraform/span> /div> /div> /div>!-- div classcol-md-6> div classskill-category h-100> h5 classmb-3>AI & Development/h5> div classskill-tags> span classskill-tag>Python/span> span classskill-tag>TensorFlow/span> span classskill-tag>PyTorch/span> span classskill-tag>MLOps/span> span classskill-tag>FastAPI/span> /div> /div> /div> --> /div> /div> /div> /div> /section> !-- Projects Section --> section idprojects classsection> div classcontainer> h2 classsection-title>Projects/h2> div classrow g-4> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-imageshttps://via.placeholder.com/800x600/1a1a2e/f59e0b?textInfrastructure+Dashboard, https://via.placeholder.com/800x600/1a1a2e/fbbf24?textPredictive+Analytics, https://via.placeholder.com/800x600/1a1a2e/d97706?textAuto+Scaling+UI data-titleAI Fitness Assistant> div classproject-thumbnail data-index0> img src/book_rec/book_recommender1.png altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index1> img src/book_rec/book_recommender1.png altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> div classproject-thumbnail data-index2> img src/book_rec/book_recommender1.png altScreenshot3 loadinglazy> div classthumbnail-overlay> span>Screenshot3/span> /div> /div> /div> h5 classcard-title>AI Fitness Assistant/h5> p classcard-text>A personal AI fitness assistant that can track and record a users workouts just by using voice commands. Recognising intent from the users commands the assistant can also answer questions about the current workout./p> div classmb-3> span classtech-tag>PyTorch/span> span classtech-tag>HuggingFace/span> span classtech-tag>FastAPI/span> span classtech-tag>Flutter/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-imageshttps://via.placeholder.com/800x600/16213e/f59e0b?textLog+Classification, https://via.placeholder.com/800x600/16213e/fbbf24?textPriority+Matrix, https://via.placeholder.com/800x600/16213e/d97706?textAlert+System data-titleDevOps Chatbot> div classproject-thumbnail data-index0> img src/book_rec/book_recommender1.png altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index1> img src/book_rec/book_recommender1.png altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> div classproject-thumbnail data-index2> img src/book_rec/book_recommender1.png altScreenshot3 loadinglazy> div classthumbnail-overlay> span>Screenshot3/span> /div> /div> /div> h5 classcard-title>DevOps Chatbot/h5> p classcard-text>A chatbot that points at a series of DevOps related educational ebooks, which have been parsed, chunked and stored in a vector database. Using Ollama to connect to a WebUI frontend that uses RAG to access the data related to the user questions./p> div classmb-3> span classtech-tag>Llama/span> span classtech-tag>PyTorch/span> span classtech-tag>HuggingFace/span> span classtech-tag>FastAPI/span> span classtech-tag>ElasticSearch/span> span classtech-tag>Kubernetes/span> span classtech-tag>Ollama/span> span classtech-tag>Open WebUI/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/book_rec/book_recommender1.png, /book_rec/book_recommender2.png, /book_rec/book_recommender3.png data-titleBook Recommender> div classproject-thumbnail data-index0> img src/book_rec/book_recommender1.png altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index1> img src/book_rec/book_recommender2.png altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> div classproject-thumbnail data-index2> img src/book_rec/book_recommender3.png altScreenshot3 loadinglazy> div classthumbnail-overlay> span>Screenshot3/span> /div> /div> /div> h5 classcard-title>Book Recommender/h5> p classcard-text>A book recommender API using 2023 Amazon book dataset, which I cleaned and recuded to 3,000,000+ books. Through a mobile app this gives a user the top 10 results based on a search term or a list of genres./p> div classmb-3> span classtech-tag>PyTorch/span> span classtech-tag>Transformers/span> span classtech-tag>NLTK/span> span classtech-tag>Pandas/span> span classtech-tag>Numpy/span> span classtech-tag>FastAPI/span> span classtech-tag>ChromaDB/span> span classtech-tag>Flutter/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/recog/aws+image+recognition.png, /recog/recog-img3.jpg, /recog/recog-img5.jpg data-titleImage Recognition> div classproject-thumbnail data-index0> img src/recog/aws+image+recognition.png altArchitecture loadinglazy> div classthumbnail-overlay> span>Architecture/span> /div> /div> div classproject-thumbnail data-index1> img src/recog/recog-img3.jpg altExample1 loadinglazy> div classthumbnail-overlay> span>Example1/span> /div> /div> div classproject-thumbnail data-index2> img src/recog/recog-img5.jpg altExample2 loadinglazy> div classthumbnail-overlay> span>Example2/span> /div> /div> /div> h5 classcard-title>Image Recognition/h5> p classcard-text>A simple project to give me an introduction to AWS AI services. This allowed a user to upload an image and recive a list objects/attributes related to the image./p> div classmb-3> span classtech-tag>AWS Rekognition/span> span classtech-tag>AWS API Gateway/span> span classtech-tag>AWS Lambda/span> span classtech-tag>AWS DynamoDB/span> span classtech-tag>AWS SQS/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/dc-app/aws+app.png, /dc-app/dcapp-img4.jpg, /dc-app/dcapp-img8.jpg data-titleBookclub App> div classproject-thumbnail data-index0> img src/dc-app/aws+app.png altArchitecture loadinglazy> div classthumbnail-overlay> span>Architecture/span> /div> /div> div classproject-thumbnail data-index1> img src/dc-app/dcapp-img4.jpg altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index2> img src/dc-app/dcapp-img8.jpg altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> /div> h5 classcard-title>Bookclub App/h5> p classcard-text>A mobile bookclub app made in Flutter, hosted in AWS. This app allows the user to start or join specific book related group chats, browse and sign up to local events and suggest books for the bookclub sessions./p> div classmb-3> span classtech-tag>Flutter/span> span classtech-tag>AWS Amplify/span> span classtech-tag>AWS AppSync/span> span classtech-tag>AWS DynamoDB/span> span classtech-tag>AWS Lambda/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/game/aws+game+server.png, /game/game-img2.jpg, /game/game-img4.png data-titleGame Server> div classproject-thumbnail data-index0> img src/game/aws+game+server.png altArchitecture loadinglazy> div classthumbnail-overlay> span>Architecture/span> /div> /div> div classproject-thumbnail data-index1> img src/game/game-img2.jpg altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index2> img src/game/game-img4.png altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> /div> h5 classcard-title>Game Server/h5> p classcard-text>A game server hosted on AWS. This was a way for me to learn more about hosting and securing systems in AWS./p> div classmb-3> span classtech-tag>AWS EC2/span> span classtech-tag>Ubuntu/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/dc-web/azure+website.png, /dc-web/dcweb-img1.png, /dc-web/dcweb-img2.png data-titleBookclub Website> div classproject-thumbnail data-index0> img src/dc-web/azure+website.png altArchitecture loadinglazy> div classthumbnail-overlay> span>Architecture/span> /div> /div> div classproject-thumbnail data-index1> img src/dc-web/dcweb-img1.png altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index2> img src/dc-web/dcweb-img2.png altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> /div> h5 classcard-title>Bookclub Website/h5> p classcard-text>A bookclub website, hosted in Azure. A simple website to view all past and future books reviewed by the dookclub, with the option for members to leave reviews and ratings. I wanted to experience a different cloud provider/p> div classmb-3> span classtech-tag>Django/span> span classtech-tag>Azure Web App/span> span classtech-tag>Azure PostgresSQL DB/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> div classcol-lg-6> div classcard project-card h-100> div classcard-body> div classproject-thumbnails data-images/bmi-app/bmi-img1.jpg, /bmi-app/bmi-img2.jpg, /bmi-app/bmi-img4.jpg data-titleFitness Calculator> div classproject-thumbnail data-index0> img src/bmi-app/bmi-img1.jpg altScreenshot1 loadinglazy> div classthumbnail-overlay> span>Screenshot1/span> /div> /div> div classproject-thumbnail data-index1> img src/bmi-app/bmi-img2.jpg altScreenshot2 loadinglazy> div classthumbnail-overlay> span>Screenshot2/span> /div> /div> div classproject-thumbnail data-index2> img src/bmi-app/bmi-img4.jpg altScreenshot3 loadinglazy> div classthumbnail-overlay> span>Screenshot3/span> /div> /div> /div> h5 classcard-title>Fitness Calculator/h5> p classcard-text>A fitness calculator app containing a BMI, 1 rep max and a calorie calculators. My first attempt at app development/p> div classmb-3> span classtech-tag>Flutter/span> /div>!-- div classd-flex gap-3> a href# classproject-link>Demo/a> a href# classproject-link>Code/a> /div> --> /div> /div> /div> /div> /div> /section> !-- Contact Section --> section idcontact classsection> div classcontainer> div classcontact-section p-5 text-center> h3 classmb-3>Get In Touch/h3> div classd-flex justify-content-center gap-3 flex-wrap> a hrefmailto:david.srowley@gmail.com classcontact-link>Email/a> a hrefhttps://www.linkedin.com/in/david-rowley-1715b8237/ classcontact-link>LinkedIn/a> !-- a hrefhttps://github.com/yourusername classcontact-link>GitHub/a> --> a hrefyour-resume.pdf classcontact-link>Resume/a> /div> /div> /div> /section> !-- Footer --> footer classcustom-footer py-4> div classcontainer text-center> p classmb-0>© 2025 davidrowley.co.uk/p> /div> /footer> !-- Image Modal --> div classmodal fade idimageModal tabindex-1 aria-labelledbyimageModalLabel aria-hiddentrue> div classmodal-dialog modal-xl modal-dialog-centered> div classmodal-content> div classmodal-header> h5 classmodal-title idimageModalLabel>Project Gallery/h5> button typebutton classbtn-close data-bs-dismissmodal aria-labelClose>/button> /div> div classmodal-body> div classimage-counter> span idcurrentImage>1/span> / span idtotalImages>3/span> /div> button classgallery-nav prev idprevBtn>‹/button> button classgallery-nav next idnextBtn>›/button> img idmodalImage src altProject Screenshot classimg-fluid> div classgallery-indicators idgalleryIndicators> !-- Indicators will be dynamically generated --> /div> /div> /div> /div> /div> !-- Bootstrap JS --> script srchttps://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js>/script> script> // Smooth scrolling for navigation links document.querySelectorAll(ahref^#).forEach(anchor > { anchor.addEventListener(click, function (e) { e.preventDefault(); const target document.querySelector(this.getAttribute(href)); if (target) { target.scrollIntoView({ behavior: smooth, block: start }); // Close mobile menu if open const navbarCollapse document.getElementById(navbarNav); if (navbarCollapse.classList.contains(show)) { const bsCollapse new bootstrap.Collapse(navbarCollapse); bsCollapse.hide(); } } }); }); // Gallery functionality let currentProject null; let currentImageIndex 0; let projectImages ; const imageModal document.getElementById(imageModal); const modalImage document.getElementById(modalImage); const modalTitle document.getElementById(imageModalLabel); const currentImageSpan document.getElementById(currentImage); const totalImagesSpan document.getElementById(totalImages); const galleryIndicators document.getElementById(galleryIndicators); const prevBtn document.getElementById(prevBtn); const nextBtn document.getElementById(nextBtn); // Handle thumbnail clicks document.querySelectorAll(.project-thumbnail).forEach(thumbnail > { thumbnail.addEventListener(click, function() { const thumbnailsContainer this.closest(.project-thumbnails); const images JSON.parse(thumbnailsContainer.getAttribute(data-images)); const title thumbnailsContainer.getAttribute(data-title); const imageIndex parseInt(this.getAttribute(data-index)); openGallery(images, title, imageIndex); }); }); function openGallery(images, title, startIndex 0) { projectImages images; currentImageIndex startIndex; currentProject title; modalTitle.textContent `${title} - Gallery`; totalImagesSpan.textContent images.length; // Create indicators createIndicators(); // Show initial image updateImage(); // Show modal const modal new bootstrap.Modal(imageModal); modal.show(); } function createIndicators() { galleryIndicators.innerHTML ; projectImages.forEach((_, index) > { const indicator document.createElement(div); indicator.className gallery-indicator; if (index currentImageIndex) { indicator.classList.add(active); } indicator.addEventListener(click, () > goToImage(index)); galleryIndicators.appendChild(indicator); }); } function updateImage() { modalImage.src projectImagescurrentImageIndex; currentImageSpan.textContent currentImageIndex + 1; // Update indicators document.querySelectorAll(.gallery-indicator).forEach((indicator, index) > { indicator.classList.toggle(active, index currentImageIndex); }); // Update navigation buttons prevBtn.disabled currentImageIndex 0; nextBtn.disabled currentImageIndex projectImages.length - 1; } function goToImage(index) { if (index > 0 && index projectImages.length) { currentImageIndex index; updateImage(); } } function nextImage() { if (currentImageIndex projectImages.length - 1) { currentImageIndex++; updateImage(); } } function prevImage() { if (currentImageIndex > 0) { currentImageIndex--; updateImage(); } } // Navigation button events prevBtn.addEventListener(click, prevImage); nextBtn.addEventListener(click, nextImage); // Keyboard navigation document.addEventListener(keydown, function(e) { if (imageModal.classList.contains(show)) { if (e.key ArrowLeft) { prevImage(); } else if (e.key ArrowRight) { nextImage(); } else if (e.key Escape) { bootstrap.Modal.getInstance(imageModal).hide(); } } }); // Clear modal when closed imageModal.addEventListener(hidden.bs.modal, function () { modalImage.src ; projectImages ; currentImageIndex 0; currentProject null; }); /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]