We cheesed webdev.
My friend and I just finished making a free portfolio generation and hosting website — https://portosaurus.com/
Looks pretty legit right? Bet you think we have a nice Node backend on AWS and stuck to good, modern practices for something like this…
You may recall my medium article roasting the LinkedIn API, which we used for our initial attempt to harvest data to build your portfolio https://ethansk.medium.com/do-not-use-the-linkedin-api-e4cea9649115
You may recall my medium article about Portosaurus, the website in question today https://ethansk.medium.com/i-made-a-portfolio-generator-website-its-amazing-c0b21d2bcbe7
Well now get ready to feast your eyes on the painfully cringe but mouth-wateringly beautiful ($0 cost!!) architecture of Portosaurus. I cbf to make an architecture diagram but if any of you had the balls to I would suck em.
So the frontend is decently standard stuff: React, Typescript, hosted on Firebase Hosting.
The backend may also seem pretty standard at first: Express, Typescript, Firebase Functions. We share typings between the two.
Our deployment strategy is pretty standard; everything pushed to master gets deployed via Github Actions.
Now the interesting part. Let’s walk through the process of you, an end user, using Portosaurus, and what happens behind the scenes.
Lê Portfolio Templates
So assume you have filled in all your profile data: name, description, experience, projects, education, skills, images etc. You now go to your dashboard, and can see a preview of the full final portfolio. This preview is actually an iframe that loads up a prebuilt (was built during our deployment GitHub Action), minified portfolio template.
What exactly is a portfolio template? It is the actual portfolio website that’s written in React that uses Infima components to look thicc . To show user-specific information (which you kinda need for a per-user portfolio website…), the template will either read from local storage if being shown in preview mode on portosaurus.com, or will read from a json file if it is the final production build that is being hosted (either for you or by you, we let you do both :D).
And so the way we get the preview of your portfolio to update instantly on your Portosaurus dashboard is by writing your profile data and your portfolio settings to the aforementioned local storage, which the iframe can read because it’s the same domain! (Took us a while to figure this out…)
Juicy Portfolio Generation
After you’re happy with your portfolio preview, you may be tempted by that succulent “Generate” button to start building your portfolio. When you click it, a request is sent to Firebase Functions telling it of the sin you just committed.
After doing some verification, authentication, and whatnot, the Function will do something miracular — it will send an HTTP request to trigger a ‘build_portfolio’ GitHub Action. This Action will load up the cached portfolio template’s compiled static files, as well as restore node_modules. After setting up the environment correctly, the Action will invoke a script in our backend’s src dir that actually builds your portfolio! And hosts it!
Take a second to appreciate what we’ve done. We are using GitHub Actions as part of our production backend to run a job to build your portfolio, simply because it is free! (or cheaper [assuming we ran out of minutes] than alternatives like a worker process in Heroku, which is what we had before 😖). Not only that, but appreciate that we’ve had to make a large portion of our backend code run in both Firebase Functions, AND in Github Action’s Ubuntu server under Node (we use ts-node-script). If you’ve ever properly worked with Firebase, you’d know the vast array of micro-annoyances you experience when trying to anything like a normal web developer.
Anyway, during this job, we are constantly updating your document in Firestore with updates on the build/host status, which the client (the dashboard page you are staring at) listens to realtime updates on so it can show the correct loading info, or buttons to go to, download, or delete your generated portfolio if it’s done.
Question, why not just do the portfolio building on Functions directly? Well, it would take way too long and would timeout, and eat up our Blaze plan, and other problems…but basically it’s not possible.
Now let’s talk about our hosting strategy. Fun fun. Again, we are leaching off of Microsoft’s generosity. We take the minified portfolio template files, and write your profile data and settings to that json described earlier. We then create a new private repo under our Portosaurus GitHub organisation just for you (we actually pay a couple dollars a month so it can be private ❤), and upload all the files to that repo. Using some GitHub API magic, we enable GitHub Pages for that repo, and Bob’s your daddy, your portfolio is now hosted on a world class CDN, completely for free.
So we now have leveraged GitHub as a hosting service for our service 🤪🤪. A fine Camembert, maybe even Manchego. Once hosted, all the metadata is written to Firestore so you can view, delete, or download your portfolio, which is done by generating a download URL from the repo created for you.
So yeah…we gamed the system. Are you not entertained. Essentially 0 cost to run a full on portfolio generation website, always up and running (even if none of you actually use it…like now 😔). This architecture is a lot to take in, and is very unconventional…maybe one day i’ll get someone to draw a nice diagram of it just for ol’ times sake.
Who knows how long this architecture will remain feasible? Will Microsoft have a spaz attack like they did with the LinkedIn API, or will they remain kind and generous for us to abuse?