Introduction • Features • Technical Details • Development and Deployment • Future Improvements • Acknowledgements & Version History • Using This Project • License • Contributing • Contact
This repository houses my product design portfolio, showcasing various projects and designs I've worked on.
About me: product-focused designer with 10+ years of experience, based in Tokyo, Japan (prev in San Francisco)
Why all this for a website?
- It's a personal website, so why not? It's one of the few times you can build what you want without compromises. For example, I was able to incorporate features like a custom optically-aligned typographic "engine" that might be less practical in large-team settings or with less technical designers.
- I heard all of my eng friends saying how fast you can build features in elixir/phoenix, and I wanted to build something with a lot more infra and a better DX (e.g. admin interface, metrics, gitops)
- It'll be reusable for future app development
- This is also a homelab project
Offers tools to ensure code quality and consistency:
- Automated code formatting and linting
- Comprehensive test suite with coverage reporting
- Security checks with Sobelow
- Static code analysis with Dialyzer
- Git hooks for pre-commit and pre-push checks
You can read more in Development and Deployment
The portfolio supports both English (/en) and Japanese (/ja) languages. It determines the locale, by in order:
- Locale in URL
- Accept-Language header to detect the user's preferred language.
For application and landing page content, we use Gettext for translations. Case studies and other long form content have separate markdown files for each language.
You can also add a new language in /gettext/
for UI and /priv/content/schema/
for whichever schema you want to translate.
An admin interface with a Markdown-based system allows for creating case studies with live reloading. This feature is only accessible in the development environment and is not exposed in production.
A custom optically-aligned typographic "engine" takes into account line-height box and typeface characteristics. It optically subtracts space so that typography aligns to a baseline, ensuring any two objects are equally spaced optically.
The backend is built with Elixir and Phoenix. PostgreSQL is used as the database for storing project data and user interactions. Obviously overkill for what's basically a website, but I hope to use the infra for other projects.
On the frontend, we use:
- esbuild: An extremely fast JavaScript bundler and minifier
- TailwindCSS: A utility-first CSS framework
- Heroicons: For SVG icons
PostgreSQL is used for data storage. A file watcher looks for markdown files with the correct frontmatter key-value pairs to update records in the database.
To set up the project locally:
- Clone the repository
- Ensure you have Docker installed
- Run
docker-compose up -d
to start the application - Run
./run mix ecto.setup
to initially set up the db - Visit
localhost:8000
in your browser
This project uses Lefthook for managing Git hooks to ensure code quality and consistency. The configuration can be found in .lefthook.yml
. Here's a brief overview of what's included:
- Pre-commit hooks: Format Elixir files and ensure containers are running.
- Pre-push hooks: Run format checks, linting (Credo), and tests for Elixir code.
To use these hooks, install Lefthook by following the instructions at Lefthook's GitHub repository.
These hooks help maintain code quality, but you bypass the checks easily if you want to do it all in CI workflows.
Deployment details are still being finalized. The project uses GitHub Actions for CI/CD, as indicated by the workflow status badge at the top of this README. Below is a WIP:
You'll need to make sure the env variables are set to production, namely:
export DOCKER_WEB_VOLUME=./priv/static:/app/priv/static # Use this for production
#export DOCKER_WEB_VOLUME=.:/app # use this for dev
If you encounter issues running mix ecto.drop
while the app is running, try stopping the web app first:
docker compose stop web
If that doesn't work:
docker exec -it YOURAPP-postgres-1 psql -U YOURUSER -d YOURDATABASE -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'YOURDATABASE' AND pid <> pg_backend_pid();"
Then drop your database:
docker exec -it YOURAPP-postgres-1 psql -U YOURAPP -d postgres -c "DROP DATABASE YOURDATABASE;"
and the test database as well (otherwise they'll be out of sync)
docker exec -it YOURAPP-postgres-1 psql -U YOURAPP -d postgres -c "DROP DATABASE YOURDATABASE_test;"
After that, run your app again with docker compose up -d
and then do ./run mix ecto.setup
.
Planned enhancements include:
- Image optimization and minification
- OG graph image generation
- Performance optimizations
- Full implementation of telemetry
A special thanks to Nick Janetakis for creating the docker-phoenix-example, which served as the foundation for this portfolio.
Previous portfolio versions:
- 2016 – 2024: Built using React, NextJS, and Styled-Components. Code available here.
- 2014 – 2016: Built using Vanilla JS. View on Wayback Machine.
- 2010: Built using Flash.
This project is licensed under AGPL-3.0. See the LICENSE file for details.
If you're using this project as a base for your own portfolio website, I ask that you provide credit for the original work. Here's how you can do that:
- Include a comment in your main layout file (e.g.,
root.html.heex
) that says:
<!-- Based on Zane Riley's Portfolio: https://github.com/zaneriley/personal-site -->
- Add a line to your README.md file:
This project is based on [Zane Riley's Portfolio](https://github.com/zaneriley/personal-site).
By providing credit, you help support open-source projects and allow others to discover and learn from the original work. Thank you for your consideration!
Contributions are welcome, but obviously since this is my personal site I'd be amazed if anyone would want to.
Project Link: https://github.com/zaneriley/personal-site