My Personal Website
This is the website you are currently using!
April 18, 2021
Technology Used
Dependencies
Workflow (Developer Dependencies)
VS Code tasks
gulp / gulp-dart-sass / gulp-concat / gulp-postcss / gulp-sourcemaps / gulp-uglify / autoprefixer / cssnano
Agile Project Management
Trello (for User Stories, Ice Box, Current/MVP, Completed)
diagrams.net (for Sitemap)
Figma (for Wireframes)
Home page (desktop)
Home page (mobile)
Apps page (currently Projects)
Models
User Model
const UserSchema = new Schema(
{
username: { type: String, unique: true, required: true },
password: { type: String, required: true },
admin: { type: Boolean, required: true },
vip: { type: Boolean, default: false },
},
{ timestamps: true }
);
Nav Model (Navigation)
const NavSchema = new Schema(
{
name: { type: String, required: true, unique: true },
dir: { type: String, required: true, unique: true },
visible: { type: Boolean, default: true },
position: { type: Number, required: true },
},
{ timestamps: true }
);
Project Model
(same as Blog Model but with liveLink and codeLink properties added)
const ProjectSchema = new Schema(
{
title: { type: String, required: true },
liveLink: { type: String, required: true },
codeLink: { type: String, default: 'https://github.com/irackson' },
description: { type: String, required: true },
tags: { type: [String], required: true },
visible: { type: Boolean, default: false },
previouslySent: { type: Boolean, default: false },
markdown: { type: String, required: true },
featured: { type: Boolean, default: false },
thumbnail: {
type: String,
default: 'relevant-stock-icon.png',
},
slug: {
type: String,
required: true,
unique: true,
},
sanitizedHtml: {
type: String,
required: true,
},
},
{ timestamps: true }
);
ProjectSchema.pre('validate', function (next) {
if (this.title) {
this.slug = slugify(this.title, { lower: true, strict: true });
}
if (this.markdown) {
this.sanitizedHtml = dompurify.sanitize(marked(this.markdown));
}
next();
});
Sub Model (Subscription)
const SubSchema = new Schema(
{
contentType: {
type: Schema.Types.ObjectId,
ref: 'Nav',
required: true,
},
subscribers: {
type: [
{
first_name: { type: String },
email: { type: String, required: true },
confirmation: { type: Boolean, default: false },
account: { type: Schema.Types.ObjectId, ref: 'User' },
},
],
active: { type: Boolean, default: false },
default: [],
},
},
{ timestamps: true }
);
Route Maps
Users ("/users")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/create" | Render form for new User (users/create.ejs) |
POST | "/create" | Uses Form Submission to Create new User |
GET | "/login" | Display a Particular Post (projects/show.ejs) |
POST | "/login" | Render form to User login (projects/update.ejs) |
POST | "/subscribe" | Uses partials/footer.ejs Form Submission to Subscribe |
GET | "/unsubscribe/*" | Render form to Unsubscribe (users/unsubscribe.ejs) |
POST | "/unsubscribe/*" | Uses Form Submission to Unsubscribe |
GET | "/logout" | Logout a particular User |
GET | "/*" | Catch-all redirect to "/" (home page) |
Projects ("/projects")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | List all Posts (projects/index.ejs) |
GET | "/create" | Render form for New Post (projects/create.ejs) |
GET | "/:slug" | Display a Particular Post (projects/show.ejs) |
POST | "/" | Uses Form Submission to Create new Post |
GET | "/:slug/update" | Render form to edit Post (projects/update.ejs) |
PUT | "/:slug" | Uses Form Submission to edit Post |
DELETE | "/:slug" | Delete a particular Post |
GET | "/*" | Catch-all redirect to "/projects" |
Blog ("/blog")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | List all Posts (blog/index.ejs) |
GET | "/create" | Render form for New Post (blog/create.ejs) |
GET | "/:slug" | Display a Particular Post (blog/show.ejs) |
POST | "/" | Uses Form Submission to Create new Post |
GET | "/:slug/update" | Render form to edit Post (blog/update.ejs) |
PUT | "/:slug" | Uses Form Submission to edit Post |
DELETE | "/:slug" | Delete a particular Post |
GET | "/*" | Catch-all redirect to "/blog" |
Metrics ("/metrics")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | List all Metrics ("metrics/index.ejs") |
GET | "/*" | Catch-all redirect to "/metrics" |
About ("/about")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | List About content ("about/index.ejs") |
GET | "/*" | Catch-all redirect to "/about" |
Resume ("/resume")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | Render Resume page ("resume/index.ejs") |
GET | "/download" | Download Resume from public assets |
GET | "/*" | Catch-all redirect to "/resume" |
Webmaster ("/webmaster")
Method | Endpoint | Resource/View |
---|---|---|
GET | "/" | Render form for Sitewide Settings (webmaster/settings.ejs) |
POST | "/seed" | Reseed the Database |
PUT | "/" | Uses Form Submission to edit Sitewide Settings |
GET | "/*" | Catch-all redirect to "/webmaster" |