{"id":15978683,"url":"https://github.com/bluwy/penn-todo","last_synced_at":"2026-04-10T07:37:24.501Z","repository":{"id":114174378,"uuid":"201065261","full_name":"bluwy/penn-todo","owner":"bluwy","description":"A todo app built on the PENN stack","archived":false,"fork":false,"pushed_at":"2023-01-11T03:29:18.000Z","size":467,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-14T23:57:07.146Z","etag":null,"topics":["express","nodejs","nuxt","postgresql","todoapp","vue"],"latest_commit_sha":null,"homepage":"https://penn-todo.herokuapp.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bluwy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"bluwy"}},"created_at":"2019-08-07T14:19:30.000Z","updated_at":"2024-11-04T16:24:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"2c28ae3f-7078-4640-a979-6ba39370ae19","html_url":"https://github.com/bluwy/penn-todo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bluwy/penn-todo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluwy%2Fpenn-todo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluwy%2Fpenn-todo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluwy%2Fpenn-todo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluwy%2Fpenn-todo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bluwy","download_url":"https://codeload.github.com/bluwy/penn-todo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluwy%2Fpenn-todo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279014320,"owners_count":26085492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["express","nodejs","nuxt","postgresql","todoapp","vue"],"created_at":"2024-10-07T23:21:56.290Z","updated_at":"2025-10-13T08:38:42.019Z","avatar_url":"https://github.com/bluwy.png","language":"JavaScript","funding_links":["https://github.com/sponsors/bluwy"],"categories":[],"sub_categories":[],"readme":"# PENN Todo\n\n[![Build Status](https://travis-ci.org/BjornLuG/penn-todo.svg?branch=master)](https://travis-ci.org/BjornLuG/penn-todo)\n\nA todo app built on the PENN stack ([PostgreSQL](https://www.postgresql.org), [Express](https://expressjs.com/), [Nuxt](https://nuxtjs.org), [Node.js](https://nodejs.org)).\n\n## Demo\n\nA demo can be found at https://penn-todo.herokuapp.com. Currently, you can sign up a new account without a real email, since verification emails are being sent with [Ethereal](https://ethereal.email/). \n\nYou can log in with a demo account too:\n* Email: d@m.o\n* Password: demo\n\nFeel free to open an issue for any bugs and quirks :)\n\n## Table of contents\n* [Architecture](#architecture)\n* [Development state](#development-state)\n* [Installation](#installation)\n  * [Project setup](#project-setup)\n  * [Database setup](#database-setup)\n* [Deployment](#deployment)\n* [Roadmap](#roadmap)\n* [Contributing](#contributing)\n* [FAQ](#faq)\n* [License](#license)\n\n## Architecture\n\nThe todo app is a Nuxt-Express hybrid scaffolded with [create-nuxt-app](https://github.com/nuxt/create-nuxt-app) with Express for backend and Jest for unit testing. It is currently only built on a Windows machine, so Linux and MacOS are untested.\n\nExpress acts as the server middleware for Nuxt, so Nuxt will redirect api calls for Express to handle.\n\nExpress does CRUD operations on a PostgreSQL database. Authentication is needed to do so, and is based on JSON Web Token (JWT).\n\nJest is used for unit testing, **all** tests are located in `__tests__` folder.\n\n## Development state\n\nThe project is 90% done, only needs perfecting. Everything works, including todos database, user auth database, Express REST API, frontend interaction, etc... Currently, fake emails can be used for demos, but it still needs verification, which is sended as a link to [Ethereal](https://ethereal.email/).\n\n## Installation\n\nDependencies not included in repo:\n* [npm](https://www.npmjs.com) for managing packages.\n* [PostgreSQL](https://www.postgresql.org) for testing local database.\n\nMake sure to have them installed.\n\n### Project setup\n\nAfter cloning the repo, install the required dependencies:\n\n``` bash\n# Install dependencies\n$ npm run install\n```\n\nThe project uses [dotenv](https://github.com/motdotla/dotenv) to inject environment variables, a `.env` file is required before developing. Create one and place it in the root folder:\n``` ini\n; Prod/dev database url, e.g. postgres://john:12345678@localhost:5432/tododb\nDATABASE_URL=\n\n; Testing database url, e.g. postgres://john:12345678@localhost:5432/todotestdb\nDATABASE_URL_TEST=\n\n; Set 'true' without quotes to enable database SSL access, any other values will equal to false. (Default: false)\nDATABASE_SSL=false\n\n; Backend api url,  used by Nuxt for Axios' `baseUrl`. (Default: http://localhost:3000/api)\nAPI_URL_BROWSER=http://localhost:3000/api\n\n; Secret string used for JWT hashing\nJWT_SECRET=\n```\n\n\u003e Note: In the `.env` file, remove the comments as dotenv doesn't support it\n\nTo run dev server (This starts Nuxt and Express servers):\n``` bash\n# Serve with hot reload at localhost:3000\n$ npm run dev\n```\n\nTo lint files (Do either one):\n``` bash\n# Lint files with ESLint\n$ npm run lint\n# Lint and fix files with ESLint\n$ npm run lintfix\n```\n\nTo run tests:\n``` bash\n# Starts Jest unit testing\n$ npm run test\n```\n\nTo build for production and launch server:\n``` bash\n# Build for production and launch server\n$ npm run build\n$ npm run start\n```\n\u003e Note: Server can only be started after build\n\n### Database setup\n\nThe project uses two tables, `users` and `todos`.\n\nTable `users`:\n\n| Column       | Type                     | Collation | Nullable | Default                           |\n|--------------|--------------------------|-----------|----------|-----------------------------------|\n| id           | integer                  |           | not null | nextval('users_id_seq'::regclass) |\n| name         | text                     |           | not null |                                   |\n| email        | text                     |           | not null |                                   |\n| hash         | text                     |           | not null |                                   |\n| verified     | boolean                  |           | not null | false                             |\n| pwd_reset_ts | timestamp with time zone |           | not null | now()                             |\n\n| Extra         | Values                                                                           |\n|---------------|----------------------------------------------------------------------------------|\n| Indexes       | \"users_pkey\" PRIMARY KEY, btree (id)                                             |\n| Referenced by | TABLE \"todos\" CONSTRAINT \"fk_user_id\" FOREIGN KEY (user_id) REFERENCES users(id) |\n\nTable `todos`:\n\n| Column  | Type    | Collation | Nullable | Default                           |\n|---------|---------|-----------|----------|-----------------------------------|\n| id      | integer |           | not null | nextval('todos_id_seq'::regclass) |\n| title   | text    |           | not null |                                   |\n| done    | boolean |           | not null |                                   |\n| user_id | integer |           | not null |                                   |\n\n| Extra                   | Values                                                  |\n|-------------------------|---------------------------------------------------------|\n| Indexes                 | \"todos_pkey\" PRIMARY KEY, btree (id)                    |\n| Foreign-key constraints | \"fk_user_id\" FOREIGN KEY (user_id) REFERENCES users(id) |\n\nThe database is created with pgAdmin 4, but can be created manually with `psql` as follows:\n\nTable `users`:\n\n``` sql\nCREATE TABLE public.users\n(\n    id serial PRIMARY KEY,\n    name text NOT NULL,\n    email text NOT NULL,\n    hash text NOT NULL,\n    verified boolean NOT NULL DEFAULT false,\n    pwd_reset_ts timestamptz NOT NULL DEFAULT now()\n);\n```\n\nTable `todos`:\n\n``` sql\nCREATE TABLE public.todos\n(\n    id serial PRIMARY KEY,\n    title text NOT NULL,\n    done boolean NOT NULL,\n    user_id integer NOT NULL,\n    CONSTRAINT fk_user_id FOREIGN KEY (user_id)\n        REFERENCES public.users (id) MATCH SIMPLE\n);\n```\n\n\u003e Note: After creating the tables, you can run `\\d users` and `\\d todos` to each display the table properties. It should match the markdown tables above.\n\n## Deployment\n\n\u003cdetails\u003e\n\u003csummary\u003eDeployment tutorial\u003c/summary\u003e\n\nThe steps below will briefly describe how to integrate CI/CD with [Travis CI](https://travis-ci.org) and deploy with [Heroku](https://www.heroku.com). Make sure you have your repo ready on GitHub.\n\n### 1. Setup accounts\n\nCreate accounts for both [Travis CI](https://travis-ci.org) and [Heroku](https://www.heroku.com).\n\n### 2. Setup CLIs\n\nInstall the [Travis CLI](https://github.com/travis-ci/travis.rb#installation) and [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) (Optional). They are needed to encrypt your Heroku account's API key for Travis.\n\n\u003e Although you don't necessarily have to install the Heroku CLI, it is still recommended in cases where you need more control onto Heroku.\n\n### 3. Configure Travis CI\n\nAfter setting up your Travis CI account, in [your account dashboard](https://travis-ci.org/account/repositories), toggle on the repo you wish to have Travis CI connected.\n\nAfter that, navigate to your newly created repo dashboard, go to settings and configure the environment variables:\n\n| Key               | Value                                             | Comment                                                           |\n|-------------------|---------------------------------------------------|-------------------------------------------------------------------|\n| DATABASE_URL_TEST | postgres://postgres@localhost:5432/travis_ci_test | Value depends on how you setup your `.travis.yml` if you alter it |\n| JWT_SECRET        | \u0026lt;your-jwt-secret\u0026gt;                           | Used only in test (TODO: Mock it)                                 |\n\n\u003e Note: If your build automatically started, you can cancel it since it will fail on deploy.\n\n### 4. Configure Heroku\n\nAfter setting up your Heroku account, in [your account dashboard](https://dashboard.heroku.com), create a new app.\n\nAfter that, in your app's dashboard, go the *Resources* tab and add the *Heroku Postgres* add-on.\n\nNext, go to the *Deploy* tab, set *Deployment method* to GitHub and authorize Heroku. Below in the *Automatic deploys* section, check *Wait for CI to pass before deploy* and enable automatic deploys.\n\nThen, go to the *Settings* tab, edit your Config Vars:\n\n| Key                    | Value                                      | Comment                                                       |\n|------------------------|--------------------------------------------|---------------------------------------------------------------|\n| API_URL_BROWSER        | https://\u0026lt;app-name\u0026gt;.herokuapp.com/api | Your API endpoint used by Axios                               |\n| DATABASE_SSL           | true                                       | Heroku Postgres is only accessible with SSL                   |\n| JWT_SECRET             | \u0026lt;your-jwt-secret\u0026gt;                    | Your JWT secret key                                           |\n| HOST                   | 0.0.0.0                                    | [Required by Nuxt](https://nuxtjs.org/faq/heroku-deployment/) |\n| NODE_ENV               | production                                 | [Required by Nuxt](https://nuxtjs.org/faq/heroku-deployment/) |\n| NODE_CONFIG_PRODUCTION | false                                      | [Required by Nuxt](https://nuxtjs.org/faq/heroku-deployment/) |\n\n\u003e Note: The config var `DATABASE_URL` should be already set for you once you add the *Heroku Postgres* add-on.\n\n\u003e Note: At this point your project should not be built yet.\n\n### 5. Configure `.travis.yml`\n\nThe repo already includes all the configuration needed at `.travis.yml`. You only have to edit the `deploy` section, by [encrypting your Heroku api key](https://www.maniuk.net/2018/04/how-to-generate-secret-for-api-key-for-heroku-deployment-using-travis-ci.html) and replace the `secure: \u003cyour-encrypted-heroku-api-key\u003e` value, change `app: penn-todo` to `app: \u003cyour-heroku-app-name\u003e` and change `repo: BjornLuG/penn-todo` to `repo: \u003cgithub-user\u003e/\u003crepo-name\u003e`.\n\n\u003e Note: Although the [Travis CI docs](https://docs.travis-ci.com/user/deployment/heroku/) demonstrates another way to encrypt your Heroku API key, it does not work and will result in failing to decrpyt the API key when deploying. Use the method linked above to encrypt your Heroku API key instead.\n\n### 6. Trigger Travis CI Test\n\nOnce you have updated your `.travis.yml`, committed and pushed. Travis CI should automatically start the build. If it doesn't you can manually start it.\n\nAfter it runs the tests and passes, it will be deployed by Heroku and your site is now live.\n\n### 7. Further reading\n* https://devcenter.heroku.com/articles/getting-started-with-nodejs\n* https://nuxtjs.org/faq/heroku-deployment/\n* https://devcenter.heroku.com/articles/heroku-postgresql\n* https://docs.travis-ci.com/user/languages/javascript-with-nodejs/\n\n\u003e Note: If there's any mistakes in the steps listed above, feel free to open an issue.\n\u003c/details\u003e\n\n## Roadmap\n\n:heavy_check_mark: Done \n* Redesign interface \n* Clear done todos\n* Email authentication\n\n:blue_book: Todo\n* Real email authentication (Currently using Ethereal)\n* Refactor components\n* Refactor CSS\n* Refactor tests\n* Settings menu\n  * Edit profile\n  * Manage auth\n* Integrate payment system\n\n:x: Cancelled\n* Dockerize project (So much hassle for Windows 10 Home)\n* Grouping todos\n* Arrangable todos\n* Online and offline mode\n\n## Contributing\nFeel free to send a pull request for new features or fix. Open an issue for any issues or feature requests. Feedback is much appreciated.\n\n## FAQ\n\n\u003cdetails\u003e\n  \u003csummary\u003eWhat is PENN stack?\u003c/summary\u003e\n  The PENN stack is similar to the MEAN and MERN stacks. The only difference is that it uses PostgreSQL instead of MongoDB, and Nuxt (Vue) instead of React or Angular. It's an open-source stack too.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eIs this todo app any special than the others?\u003c/summary\u003e\n  Currently, no. It's just a simple todo app with only a custom design. It's only meant for me to learn backend, simple CRUD and auth, so it's not much of a production-ready app. A code review would be nice :)\n\u003c/details\u003e\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluwy%2Fpenn-todo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbluwy%2Fpenn-todo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluwy%2Fpenn-todo/lists"}