Phronex is a project management and budgeting tool for small and medium sized companies with some AI features. It's been development as part of an assignment for a job interview. Also, it's been developed as a personal project out of interest to learn latest Next JS 15 and React 19. The development time for this assignment is 7 days.
The demo project is deployed under http://phronex.alienmind.eu (or at least will be for a few days).
The name is derived from the Greek word "Phronesis" (φρόνησις), which means practical wisdom or prudence—especially the kind used in decision-making, planning, and budgeting. The name Phronex captures the essence of thoughtful planning and managing resources, which fits perfectly for a project budgeting web application. Plus, it sounds modern and catchy 😉
The requirements were analyzed and the main use cases were identified:
-
Explicit use cases
- I as a user should be able to add project expenses.
- I as a user should be able to edit each expense (set category: consultancy, services, licenses, operations, ...)
- I as a user should be able to search expenses over time range
-
Underlying (implicit) use cases derived from the previous ones (that will be done at best effort)
- Being able to login / logout
- Create a new project or edit its metadata
- Edit individual cost details, not only the category (e.g. amount, date, description, etc.)
- Manage cost categories (add new categories, edit existing ones)
- Assign a budget for each cost category per project (being a budget application seems reasonable)
- Manage also the human resources (team members) which gives the application a more realistic and real-life scenario
Technical (non-functional) requirements:
- Clean and documented code.
- Maintainable code.
- Deployed & testable in local environment.
Will do at best effort:
- Scalable cloud deployment
- The code repository itself Github - you are there!
- This README.md which should include:
- Instructions on how to set the application up and running.
- All sources of information clearly stated and referenced (see the appendix down below)
- A presentation (in PDF)
- 10 mins max
- Overview: purpose and features
- Technical implementation: architecture, key components, challenges...
- Libraries/frameworks with a justification on why they were chosen
- Live demo, highlight key features and functionalities
-
SQL vs NoSQL The data model can be expressed naturally as a relational model compared to a NoSQL model. There's no realtime updates requirement nor something that could incline the solution to be based in DynamoDB or other key-value stores. Implementing it as a RDBMS makes room also for future data analytics over project expenditures with normal BI tools. The business problem can be easily expressed in SQL. Also there's no strong requirement of using an enterprise RBMS such as Oracle or DB2, therefore the natural choice is using PostgreSQL.
-
Implementation as a SPA or MPA with server components. It could be optionally be done mostly as a SPA (client side) but interacting with APIs in the backend. However there's no strong requirement to have such APIs and this adds additional complexity to the solution. There's clearly a need for BfF (Backend for Frontend) though, because of the filtering and searching functionalities. Therefore, we take a hybrid approach and decide to use:
- Server actions via direct call from the client component avoiding the need of APIs. This also benefits SSR where the page could be rendered fully server side before delivering.
- Some restful APIs for some dynamic operations (which also allows to test both integration methods)
-
Technology stack. As a consequence of point 2, we opt-in for latest React features (v19) and NextJS v15 which streamlines the application development with this novel approach. NextJS also provides very clear guardrails and opinionated folder structure which increases maintainability and favors SSR. It also keeps the (theoretical) application team simpler than, let's say, picking Python for a backend and React for the frontend. A single team of Javascript experts could be implementing both.
-
Cloud of choice. We decide for AWS because of being the most widely used cloud service provider and having all of the potentially required infrastructure services that ensure high availability and horizontal scalability in the future.
-
Deployment stack. Given the "project budget restrictions" (ehem, we just have one week) - we won't implement the fully scalable solution nor a CI/CD pipeline but anyway will use containers (Docker) as it can be easily ported from local to the cloud using for instance ECS / Fargate, trying to provide as much automation as possible.
-
Thorough testing (waiver). No comprehensive unit tests cases have been developed due to budget restrictions, but this would be completely unnacceptable in a real life application. Manual testing will be conducted over every major release with a test plan (see below).
-
Risk assessment - Confidentiality. We are going to store personal information (People names and surnames). This should be avoided in the production implementation, which should definitely rely in an external identity provider that provides also an API for enriching the identity information in the application tables. It is considered but accepted being a demo project with synthetic data.
- Linux (tested on Ubuntu v22.04 and Amazon Linux AMI) Could be prepared on Windows or Mac OS X but not tested nor .bat / .sh prepared for that.
- Docker v27 or up
- Node v20 / nvm / pnpm. Install with:
nvm install v20.11.1
npm install -g pnpm@latest- Clone the project
- Set up your .secrets file based on dot-secrets-example in the root of the project
Build process somehow requires the database to be up as SSR will require temporarily connect. It is necessary to bring up a partial docker-compose.yml with just the database up before building. This is tricky and will be investigated in the future.
All steps are automated in build.sh, just run:
./build.shAny subsequent run will just require the default docker-compose.yml file which can be run with:
./run.sh- Run
./rundev.sh- The application: http://localhost:3000/
- PostgreSQL web UI: http://localhost:8080/
- Access About screen -> Seed (or http://localhost:3000/seed ) Note: This is very insecure and has been done only for demo purposes. The test data can be reset at any point in time by clicking again in this button.
- Run:
./build.sh- Make sure that the image has been uploaded to docker hub or some other container registry. For reference, this one is under https://hub.docker.com/repository/docker/alienmind/phronex-web/general
- Upload prod-dist.tgz to EC2 via scp (follow along the instructions in the appendix II to properly set up the EC2 instance)
- Set up .secrets file in the EC2 instance
tar -xzvf prod-dist.tar.gz
./run.sh- Optionally, set up the DNS entry name to point to the public IP of the EC2 instance or the Elastic IP assigned.
- Set up project on Github
- High level solution architecture and navigation design
- Decide tech stack (with reasoned defaults)
- Scaffold basic app with the final stack and solve all required dependencies
- Containerized run at least of the dependencies (postgresql)
- V1 : local dev, login screen, basic prototype with static content
- Automate build process
- V2 : Basic application running in docker and in AWS
- V3 : Feature complete running in AWS
- V4 : do as many as the "best effort" extras as possible
- Finalize and adjust final solution architecture documentation
- Finish up presentation slides as code with revealJS
- .. Scaffold with nextJS (used my own follow up of the official NextJS tutorial + dockerized local postgresql, see references)
- .. Integrate tailwindcss, shadcn/ui, tanstack table and all other required libraries
- .. Visuals - basic screen layout inc. navbar and grid
- .. Landing page
- .. Login screen
- .. Form server action checks
- .. Create project modal & server action
- .. Create the actual data model DDLs and apply locally to postgresql
- .. Projects dashboard
- .. Stop using static data and use actual database for the dashboard
- .. Add a mandatory project manager
- .. Project detail screen inc. metadata, scope, reporting
- .. Implement update project details
- .. Dockerize the web app
- .. Search expenses over time range
- .. Generic feature to edit values in a data table
- .. Generic feature to add a new row to a data table
- .. Generic feature to delete a row from a data table
- .. Editing expenses values or descriptions live from the project detail screen
- .. Set up budget for the project
- .. Add expenses to projects
- .. Edit a expense detail in the project
- .. Delete an expense from the project
- .. Reassign / remove resources or costs to each project in the project detail screen
- .. Administration: manage roles
- .. Administration: manage persons
- .. Administration: manage categories
- .. Administration: manage budget per category per project
- .. Graph to show expenditures per category against budget
- .. Show expenses chart over time in the project expenses table
- .. Project dashboard: expenses vs budget grouped by category
- .. Colors when expenditures are above the estimate
- .. Colors the project cards based on their overexpend ratio
- .. Remove the Delete button from the project cards
- .. Search functionality in the main page
- .. Some of the server / client components had crossed interdependencies which resulted in depending on pg (postgres) for the client component. Fixed.
- .. Create project form have been intermitently broken due to some refactors. Fixed.
- .. Back button not working in About because of security constraints. Fixed.
- .. User auth is broken again - login somehow is a client side component needs to become a proper api or server action. It's been worked around but requires more work.
- .. Filtering by date range is not fully working
- .. Adding a new expense does not apply the right category ("Unknown")
- .. Not all the management tables have working the free text search feature (something afoot with the fake all_columns column)
- .. Filtering expenses over time range is not working - HTTP 400
- .. Calendar picker layout has gone crazy
- .. Fixed People tab since the big refactor of data-table.tsx
- .. Fixed Roles tab since the big refactor
- .. Fixed Expense Categories (... you know the drill)
- .. Select box does not preselect to 6 projects (visually) and it loses its focus.
- .. Adding a new expense does not work
- .. Adding a new resource to a project does not work
- .. Adding a new category does not work
- .. Creating a expense and assign it to the new category creates an exception
- .. Deleting an expense does not work
- .. Deleting a new category does not work
- .. Free search in the Roles table does not work
- .. (WORKED AROUND) Adding a new resource to the project does not work (worked around disabling this optional feature)
- .. (WORKED AROUND) When reassigning a resource to a project (changing the person), it works but there's a secondary toast with an unexpected error message. Needs to be investigated.
- .. (WORKED AROUND) If editing a budget through the chart, the slider does not get updated (F5 solves it)
- .. Adding a new category budget through the sliders does not work
- .. Changing the category over the expense list does not work
- .. Destroy buttons have lost their red style. There's some CSS mix-up
- .. Reset demo data shows the iframe at a wrong size
The extras:
- .. Dark theme
- .. Add easter egg
- .. AI features - integration with OpenAI for budget estimation
- .. Implement registration screen
- .. OAuth 2.0 authentication with Google or Github
- .. Create project form client validations (currently only in server)
- .. Graph resources assignment to projects
- .. Make more consistent the usage of server actions. Currently there's a mix between direct calls and calls from the API. It should be simplified and leave the APIs for whatever is really needed.
- .. Enhance server validation (error toast should iterate over all errors)
- .. Landing page: click on About, click on seed, click on presentation
- .. Login with demouser@gmail.com / 123456
- .. Mention the navbar to the left with the generic options. Mention also the feature of changing theme.
- .. See dashboard of project cards. Discuss the color scheme.
- .. Filter out to 3 projects or to any number.
- .. Search for a project by free text (Super Portal)
- .. Add a new project (TEST PROJECT).
- .. Delete the TEST PROEJCT
- .. Click on Super Portal to see the details. Explain the different sections on the page.
- .. Edit metadata of the project (Scope, Dates, etc)
- .. Adjust project budget for one category using the sliding bar
- .. Adjust the budget for one category clicking in the chart (exceed the current spent)
- .. Edit a expense amount or description. Change for instance the total amount of cloud consumption and see how the chart reacts.
- .. Filter expenses by date.
- .. Show the graph
- .. Sort the expenses table
- .. Create a new expense and categorize it (F5 to refresh)
- .. Add a new expense to the project
- .. Delete the new expense
- .. Reassign a resource to a different role in the same project
- .. Repeat basic checks over generic admin pages (Create a expense category, search for it, delete it, create a role, ...)
- .. Final words
This project from my Next JS demo project https://github.com/new?template_name=nextjs-postgresql-tutorial&template_owner=alienmind that I implemented from scratch following the tutorial in https://nextjs.org/learn
Plus some previous work where I started to work on reusable components, look here: https://github.com/alienmind/auditorium-web
This project has been scaffolded with: npx create-next-app@latest phronex --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example" --use-pnpm
I've been adding shadcn (https://ui.shadcn.com/) premade components to the project, together with tailwindcss (https://tailwindcss.com/) theming. These components are part of the code base althouth they have not been developed by me. It can be considered framework code, although what makes shadcn special is that the source code becomes part of the project, which allows you to customize it (other than adjusting paths, it's vanilla code from the shadcn project). Please note that this is exactly how shadcn intends to be used.
Install: npx shadcn@latest init
Successive UI components have been added under components/ui via:
npx shadcn@latest add sidebar
npx shadcn@latest add card
npx shadcn@latest add alert-dialog
npx shadcn@latest add dropdown-menu
npx shadcn@latest add table
npx shadcn@latest add scroll-area
npx shadcn@latest add drawer
npx shadcn@latest add dialog
npx shadcn@latest add form
...I had to adjust the shadcn components to use tailwindcss utility classes by setting tailwind.cssVariables = false in components.json
To add support for Docker to an existing project, I used the recommended Dockerfile available in Dockerfile and added the following to the next.config.js file:
// next.config.js
module.exports = {
// ... rest of the configuration.
output: "standalone",
};- Set up an ubuntu free tier EC2 instance
- Install docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -a -G docker ubuntu
newgrp docker
sudo systemctl enable docker.service
sudo systemctl start docker.service
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.32.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose- Set up .env
- Start posgresql with docker
docker compose up -dAdditional steps:
- Set up Elastic IP to the EC2 instance
- Set up Route 53 DNS entry
- Set up security group for the EC2 instance (port 80)
It would have been impossible to do this project without the following references, which are great for someone not fully expert in the latest frameworks or with a general interest in full stack javascript development.
- Theo T3GG Channel and livecoding sessions - https://www.youtube.com/@t3dotgg
- React Router 7 Tutorial - https://www.youtube.com/watch?v=pw8FAg07kdo
- NextJS Tutorial - https://nextjs.org/learn/dashboard-app/getting-started
- NextJS Tutorial with local PostgreSQL - https://medium.com/@dekadekadeka/next-js-tutorial-with-local-database-quick-start-guide-394d48a0aada
- ShadCN UI components - https://ui.shadcn.com/docs/components
- Lucide icons - https://lucide.dev/icons
- TailwindCSS cheat sheet - https://nerdcave.com/tailwind-cheat-sheet
- PostgreSQL locally with docker-compose https://medium.com/@agusmahari/docker-how-to-install-postgresql-using-docker-compose-d646c793f216
- PostgreSQL official docker image https://hub.docker.com/_/postgres
- Dockerize NextJS app https://nextjs.org/docs/app/building-your-application/deploying#docker-image
- NextJS tutorial with local database https://medium.com/@dekadekadeka/next-js-tutorial-with-local-database-quick-start-guide-394d48a0aada
- How to use Docker with Next.js based on the deployment documentation.
- Hybrid form validation client & server in Next : https://dev.to/bookercodes/nextjs-form-validation-on-the-client-and-server-with-zod-lbc
- Fix passing date with date picker to nextjs server action: https://www.youtube.com/watch?v=4d2g-yAD7xY
- Properly manage passwords with PostgreSQL: https://www.postgresql.org/docs/8.3/pgcrypto.html
- Fix signIn / signOut in next-auth https://medium.com/@youngjun625/next-js14-nextauth-v5-1-signin-signout-7e30cce52e7f
- Great article on next auth https://medium.com/@youngjun625/next-js14-nextauth-v5-1-signin-signout-7e30cce52e7f
- Adding OAuth authentication with nextauth.js: https://dev.to/ndom91/adding-authentication-to-an-existing-serverless-next-js-app-in-no-time-with-nextauth-js-192h
- Migrating to latest Next JS Auth https://authjs.dev/getting-started/migrating-to-v5#authenticating-server-side and https://authjs.dev/concepts/session-strategies
- Fix breaking changes on NextJS 15 URL params https://nextjs.org/docs/app/building-your-application/upgrading/version-15#async-request-apis-breaking-change
- Properly handle route params in NextJS https://nextjs.org/docs/app/api-reference/file-conventions/route
- Shadcn + Tanstack table https://ui.shadcn.com/docs/components/data-table
- Shadcn + Tanstack table - Filtering customization https://tanstack.com/table/v8/docs/guide/filters
- React Day Picker - how to fix upgrade to latest version - https://daypicker.dev/upgrading#7-update-your-custom-components
- RevealJS slides https://revealjs.com/installation/
- Shadcn + Tanstack table - Adding / editing rows shadcn-ui/ui#2639
- Shadcn Dashboard example https://ui.shadcn.com/examples/dashboard





