diff --git a/.gitignore b/.gitignore index c6bba59..9572469 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,6 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# Mac specific files +.DS_Store diff --git a/package.json b/package.json new file mode 100644 index 0000000..7e75bb9 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "my-express-app", + "version": "1.0.0", + "description": "A simple Express app", + "main": "server.js", + "scripts": { + "start": "node dist/server.js", + "compile": "tsc && cp -R src/views dist/views", + "dev": "nodemon src/server.ts" + }, + "dependencies": { + "ejs": "^3.1.6", + "express": "^4.17.1", + "mime": "^3.0.0" + }, + "devDependencies": { + "@types/express": "^4.17.13", + "@types/node": "20.3.1", + "nodemon": "^2.0.13", + "ts-node": "^10.2.1", + "typescript": "^4.4.3" + } +} diff --git a/src/public/css/about.css b/src/public/css/about.css new file mode 100644 index 0000000..0ff75e7 --- /dev/null +++ b/src/public/css/about.css @@ -0,0 +1,5 @@ +.about-team ul { + list-style: none; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/src/public/css/accessibility.css b/src/public/css/accessibility.css new file mode 100644 index 0000000..7e28a22 --- /dev/null +++ b/src/public/css/accessibility.css @@ -0,0 +1,13 @@ +.skip-link { + position: absolute; + top: -40px; + left: 0; + background-color: #fff; + color: #000; + padding: 10px; + z-index: 999; +} + +.skip-link:focus { + top: 0; +} \ No newline at end of file diff --git a/src/public/css/nav.css b/src/public/css/nav.css new file mode 100644 index 0000000..cb85d5d --- /dev/null +++ b/src/public/css/nav.css @@ -0,0 +1,102 @@ +nav { + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 20px; + background-color: #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.hamburger-menu { + display: block; + width: 30px; + height: 30px; + background-color: transparent; + border: none; + cursor: pointer; +} + +.hamburger-menu__line { + display: block; + width: 100%; + height: 2px; + background-color: #333; + margin: 5px 0; + transition: transform 0.2s ease-in-out; +} + +.hamburger-menu[aria-expanded="true"] .hamburger-menu__line:nth-child(1) { + transform: rotate(45deg) translate(5px, 5px); +} + +.hamburger-menu[aria-expanded="true"] .hamburger-menu__line:nth-child(2) { + opacity: 0; +} + +.hamburger-menu[aria-expanded="true"] .hamburger-menu__line:nth-child(3) { + transform: rotate(-45deg) translate(5px, -5px); +} + +.nav-links { + display: none; + list-style: none; + margin: 0; + padding: 0; +} + +.nav-links.show { + display: flex; + flex-direction: column; +} + +.nav-links li { + margin: 10px 0; +} + +.nav-link { + font-family: 'Montserrat', sans-serif; + font-size: 18px; + font-weight: 700; + color: #333; + text-decoration: none; + transition: color 0.2s ease-in-out; +} + +.nav-link.active { + color: #0077c2; +} + +.nav-link:hover, .nav-link:focus { + color: #0077c2; +} + +.nav-links li:last-child a { + background-color: #333; + color: #fff; + padding: 10px 15px; + border-radius: 10%; +} + +.nav-links li:last-child a:hover, .nav-links li:last-child a:focus { + background-color: #fff; + color: #333; +} + +@media screen and (min-width: 768px) { + nav { + align-items: center; + justify-content: center; + } + + .nav-links li { + margin: 0 15px; + } + + .hamburger-menu { + display: none; + } + + .nav-links { + display: flex; + } +} \ No newline at end of file diff --git a/src/public/css/style.css b/src/public/css/style.css new file mode 100644 index 0000000..cc6e285 --- /dev/null +++ b/src/public/css/style.css @@ -0,0 +1,81 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; +} + +.content { + position: relative; + min-height: 100%; + padding-bottom: 100px; +} + +main { + width: 80%; + height: 100%; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: center; +} + +section { + width: 100%; + display: flex; + flex-direction: column; + margin: 0.5rem 0; +} + +.homepage-banner { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.homepage-banner__content { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.homepage-banner__title { + font-size: 3rem; + font-weight: 700; + color: #000; + margin-bottom: 1rem; +} + +.homepage-banner__text { + font-size: 1.5rem; + font-weight: 400; + color: #000; + margin-bottom: 1rem; +} + +.homepage-banner__content img { + width: 100%; + height: 100%; + object-fit: cover; +} + +img { + width: 100%; +} + +footer { + display: flex; + position: absolute; + bottom: 0; + width: 100%; + height: 100px; + margin-top: auto; + padding: 0; + background-color: #333; + color: #fff; + flex-direction: column; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/src/public/img/alan.jpeg b/src/public/img/alan.jpeg new file mode 100755 index 0000000..c806a4b Binary files /dev/null and b/src/public/img/alan.jpeg differ diff --git a/src/public/img/logo_with_black_background.png b/src/public/img/logo_with_black_background.png new file mode 100644 index 0000000..cfa36a7 Binary files /dev/null and b/src/public/img/logo_with_black_background.png differ diff --git a/src/public/js/hamburger.js b/src/public/js/hamburger.js new file mode 100644 index 0000000..dc65a32 --- /dev/null +++ b/src/public/js/hamburger.js @@ -0,0 +1,9 @@ +document.addEventListener('DOMContentLoaded', () => { + const hamburgerMenu = document.querySelector('.hamburger-menu'); + const navLinks = document.querySelector('.nav-links'); + + hamburgerMenu.addEventListener('click', () => { + hamburgerMenu.setAttribute('aria-expanded', hamburgerMenu.getAttribute('aria-expanded') === 'false' ? 'true' : 'false'); + navLinks.classList.toggle('show'); + }); +}); \ No newline at end of file diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..1aea152 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,81 @@ +import path from 'path'; +import express from 'express'; +import mime from 'mime'; + +const app = express(); + +app.get('/', (req, res) => { + res.render('index.ejs', { + title: 'Home', + business: { + location: 'Winnipeg, MB' + } + }); +}); + +app.get('/about', (req, res) => { + res.render('about.ejs', { + title: 'About', + people: [ + { + fname: 'Alan', + lname: 'Bridgeman', + position: 'Proprietor, CEO & Lead Developer', + bio: '' + + 'Alan has been an avid disability advocate for over a decade including being a part of or involved with a variety of civic, provincial, national and international organizations around disability or accessibility. ' + + 'Alan has held numerous certifications including but not limited to: Mental Health First Aid, Certified Professional in Accessibility Core Competinies (CPACC) with the International Association of Accessibility Professionals (IAAP), among others. ' + + 'In additioan to his involvment in the disability community Alan is a dedicated and passionate software developer with a significant amount of experience in the industry. ' + + 'He has worked on a wide variety of projects, from small websites for research teams and non-profits to large enterprise applications at fourtune 500 companites like Microsoft. ' + + 'He has a strong background in web and cloud development, but has also worked on desktop and mobile applications. He has worked with many different technologies, including C#, Python, JavaScript, TypeScript, React, Node.js, Java, and many more. ' + + 'Alan startecd Bridgeman Accessible because he saw over and over again companies that were lead by non-disabled people and non-developers trying to solve digital accessibility problems. ' + + 'Moreover, they would only every consult or give advice but never build or innovate in ways that would help the community and the industry in a meaningful and impactful way.', + image: 'alan.jpeg', + website: 'https://alanbridgeman.ca/', + email: 'alan@alanbridgeman.ca' + }, + //{ + // fname: 'John', + // lname: 'Oberton', + // position: 'Infrastructure Developer (Project by Project basis/Contract)' + //}, + //{ + // fname: 'Trevor', + // lname: 'Xie', + // position: 'Designer (Project by Project basis/Contract)' + //} + ] + }); +}); + +app.get('/services', (req, res) => { + res.render('services.ejs', { + title: 'Services' + }); +}); + +app.get('/products', (req, res) => { + res.render('products.ejs', { + title: 'Products' + }); +}); + +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, 'views')); + +app.use(express.static(path.join(__dirname, 'public'), { + setHeaders: (res, path) => { + if (mime.getType(path) === 'text/html') { + res.setHeader('Content-Type', 'text/html'); + } + else if (mime.getType(path) === 'text/css') { + res.setHeader('Content-Type', 'text/css'); + } + else if (mime.getType(path) === 'application/javascript') { + res.setHeader('Content-Type', 'application/javascript'); + } + } +})); + +app.listen(3000, () => { + console.log('Server is running on port 3000'); +}); diff --git a/src/views/about.ejs b/src/views/about.ejs new file mode 100644 index 0000000..9510382 --- /dev/null +++ b/src/views/about.ejs @@ -0,0 +1,104 @@ +<%- include('header.ejs', { + extra_css: [ 'about.css' ], + active_page: 'about' +}) %> + +
At Bridgeman Accessible, our mission is to create or help others create digital products and services that promote sustainable, iterative and meaningful improvement to the accessibility of the world we live in.
++ What that means is, we believe in making our world more accessible to everyone, regardless of ability particularly as our world becomes increasingly digital. + And we further believe that everyone should have equal access to information and resources online, in-person or in whatever format that they can engage with best or can be most productive with and we're committed to making that a reality. +
++ At Bridgeman Accessible, we recognize that the current state of digital accessibility often means doing more work and spending dedicated time to do the right thing. + But as a result it often gets put off or treated as an afterthought. We want to change that culture so that digital accessibility isn't something people dread doing but rather something people just do as part of “regular” tasks. + We feel that this is the only way that we'll ever start to achieve real accessibilty where it's not about chasing people but having it be a natural part of the process. +
++ At Bridgeman Accessible, we've had the pleasure of working with a diverse group of organizations on a wide variety of projects. Here are a few examples of organizations that have choosen to partner with us:
+ +Our team is made up of experienced professionals who are passionate about digital accessibility. Here are a few of our key team members:
+<%= person.position %>
+ <% + if (typeof(person.bio) !== 'undefined') { + %> +<%= person.bio %>
+ <% + } + %> + <% + if (typeof(person.website) !== 'undefined') { + %> + Website + <% + } + %> + <% + if (typeof(person.email) !== 'undefined') { + %> + Contact + <% + } + %> +