A common question I get asked is: "I know how to program but I don't know how to build websites. How do you learn this stuff?". Personally I believe that the best way to initially learn about building websites is to actually build one. In doing so you will begin to encounter certain problems, libraries, and concepts which will set the basis of further learning. Like most areas of programming, once you learn about a particular problem domain, it becomes easier to research the different solutions that exist, which can then lead to research to how these different solutions work, and in this way gain knowledge about how to build websites (or any other area of programming).
If you are asking me this question, then you likely haven't got a project that you are working on that is forcing you to learn how to build websites, and instead you want to learn how to build websites as a skill. In this case, I find it is best to copy an existing website so that you are only figuring how a feature works rather than designing features. However this approach is generally still too broad for those first starting off, so in this post I am going to layout the plans for a simple blog.
I am not going to be building this blog, this is an exercise for you to learn how to build a website by building a simple blog. To keep things focused, I will set the basic features that you must provide. I will also provide a starting point for software and libraries to use when building the blog - these will all be centered around Python. If you do not know Python, you are welcome to use a programming language of your own choice, and for the most part the libraries I mention will have equivalents in other languages.
If you get stuck on implementing something, then your own problem solving ability and your search engine of choice will be your friends. There will already exist many blogs and websites that will guide you step by step through the whole process if you wish, however be sure to actually research and implement it yourself as this is how you will learn the most about what makes websites work.
If you don't understand why I have chosen a particular software or library then feel free to research the alternatives. These are provided to reduce choice paralysis and are good starting points. If you eventually get to the point where you disagree with my choice, then awesome, the purpose of the exercise has been achieved.
As a security person, I would love for you to pay attention to website vulnerabilities whilst you build your blog. However, most modern libraries and frameworks (such as the ones below) will, by design, prevent common vulnerabilities; thus learning how to about these is not an immediate concern. The only exception to this is in regards to passwords being stored, but don't worry I will be explicit in providing the basics for safe password storage. I do strongly suggest that once you have a better understanding of how websites work, that you learn about common web vulnerabilities to avoid finding yourself in the news.
- All pages MUST have a common title bar / menu which should include links to the homepage and the about page.
- The about page MUST not be a blog post.
- The homepage MUST list the title, subtitle, and date of the 5 most recent blog posts.
- The homepage MAY use pagination, show more, or infinite scrolling to show more posts.
- Each blog post MUST have a title, subtitle, date posted, tags, and the actual post content.
- The post content MUST support 3 levels of headings, embedding links, and embedding images.
- Blog post tags MUST be clickable and take you to a page showing the 5 most recent posts with that tag.
- The tag page MUST display the same basic blog information and have the same pagination etc as the home page.
- There MUST be an admin section of the website which will include a stats and editor pages.
- The admin section MUST involve a process of login.
- The login MAY use OAuth or username / password.
- If username / passwords are used, passwords MUST NOT be stored in clear text - they MUST be checked and stored using using BCrypt with a minimum work factor of 12.
- Logged in sessions MUST expire after 12 hours.
- Logged in session MUST be able to be expired immediately through a logout button.
- The stats page MUST show the number of views for 24 hours, 7 days, 30 days, 365 days, and all time for each blog post and the total.
- The editor MUST use different input boxes for title and subtitle.
- The editor MUST provide a single input that can accept multiple tags.
- The editor MUST allow the use of markdown for writing the post content.
- The editor MUST allow saving draft blog posts (i.e. drafts do not appear on the non-admin pages)
Software and Libraries
Language. As previously stated we will use Python, specifically use Python 3. Whilst it is preferable to use as close to the most recent version of Python as possible, at the time of writing this is 3.7, you will likely find things easier if you use your system's version of Python 3 (e.g. Ubuntu 18.04 uses Python 3.6).
Framework. The Flask framework acts as the primary piece of plumbing for your application. It's most important task is to provide interfaces for you to receive HTTP requests and write responses.
HTML. Jinja2 is a templating library that comes bundled with Flask. You will primarily use it to write HTML templates. For those of you that do not want to learn writing HTML and CSS from scratch, I suggest grabbing a BootStrap theme and then moving it into your Jinja2 templates.
Login. For username / password login, passwords MUST be stored and checked using BCrypt with a work/cost factor of 12. For OAuth login I would suggest integrating with Google.
Sessions. Although there are many user and session management libraries in existence, it is preferred that you try implement this yourself. JWT's can be handy for this.
Once you are ready for a more "production ready" deployment, you should deploy your code to an Ubuntu server using Nginx and uWSGI to serve your application. DigitalOcean have some good guides for setting this up.
To level up your deployment you should use HTTPS and a domain name.
For HTTPS you can get free certificates using Let's Encrypt.
For domain names I use NameCheap.
For hosting I use DigitalOcean, although you can also use AWS free tier. If you wish to use DigitalOcean this link will give you $100 of credit (yes this is my referral link).
For more advanced DNS I use AWS Route53 (costs < $1 USD / month).
To level up your software development I suggest using Git for version control. Don't forget commit often!
Don't worry about making everything perfect the first time you write it. As you write and learn more, you will come up with better ways of implementing everything. For your first attempt try to implement everything once only modifying previous areas as needed. Once you've completed everything once, then you can begin to iterate and improve on features.