{"id":31782480,"url":"https://github.com/andrewohnsland/andrewohnsland.github.io","last_synced_at":"2026-04-28T12:03:31.124Z","repository":{"id":51572343,"uuid":"290522589","full_name":"AndreWohnsland/andrewohnsland.github.io","owner":"AndreWohnsland","description":"React Web App with node.js API for my homepage, hosted by GitHub pages","archived":false,"fork":false,"pushed_at":"2025-08-21T13:41:27.000Z","size":28099,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-10T09:23:04.497Z","etag":null,"topics":["backend","frontend","mongodb","nodejs","react","typescript"],"latest_commit_sha":null,"homepage":"https://andrewohnsland.github.io/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AndreWohnsland.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-08-26T14:41:52.000Z","updated_at":"2025-08-21T13:40:09.000Z","dependencies_parsed_at":"2025-10-10T09:22:49.759Z","dependency_job_id":"15dee6d1-35aa-4709-9a96-03cd29272de7","html_url":"https://github.com/AndreWohnsland/andrewohnsland.github.io","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AndreWohnsland/andrewohnsland.github.io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndreWohnsland%2Fandrewohnsland.github.io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndreWohnsland%2Fandrewohnsland.github.io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndreWohnsland%2Fandrewohnsland.github.io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndreWohnsland%2Fandrewohnsland.github.io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AndreWohnsland","download_url":"https://codeload.github.com/AndreWohnsland/andrewohnsland.github.io/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndreWohnsland%2Fandrewohnsland.github.io/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32379629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T11:25:28.583Z","status":"ssl_error","status_checked_at":"2026-04-28T11:25:05.435Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["backend","frontend","mongodb","nodejs","react","typescript"],"created_at":"2025-10-10T09:22:15.725Z","updated_at":"2026-04-28T12:03:31.073Z","avatar_url":"https://github.com/AndreWohnsland.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Web App with Node.js Backend\n\nThis is a React web app with the corresponding backend made with node.js, TypeScript, express, cors and MongoDB.\n\n\u003c!-- TOC --\u003e\n\n- [React Web App with Node.js Backend](#react-web-app-with-nodejs-backend)\n  - [Features](#features)\n  - [Markdown Support](#markdown-support)\n  - [Architecture](#architecture)\n  - [Installation](#installation)\n  - [Start the Application](#start-the-application)\n  - [Access the Application](#access-the-application)\n  - [Generate an Admin User](#generate-an-admin-user)\n  - [Use Dropbox to Store and Access Pictures](#use-dropbox-to-store-and-access-pictures)\n  - [ToDo's](#todos)\n  - [Known Issues](#known-issues)\n\n\u003c!-- /TOC --\u003e\n\n## Features\n\nThis project consists of the frontend (`client` folder) and the API (main / `src` folder). The exact architecture is explained in the section below. The site divides between project and blog post. Basically they are quite similar. Project posts are aimed to be more compact and have a link to the referred project, while blog posts go more into the depth and may not be specific to any project. The viewers can filter by category to limit the cards to only show relevant topics. The card will show the title, the description, the categories in alphabetical order and the creation date, or the update date, if updated. In addition, there is also the possibility to upload and display pictures for artworks or similar topics, grouped by defined categories.\n\n![User View](docs/pictures/blog_project_view.PNG)\n\nThe Admin user can (while authenticated) edit and add everything over the admin UI. Besides defining the title, the description and the link (only for project posts), there is also the option to define categories. You can either select existing categories or add new ones into your pool. In addition there is the possibility to flag your post as a draft. That will save the posts into the database for later editing but the post will not be available to the user (neither over the website nor over the API, except for authenticated user).\n\n![Admin Edit](docs/pictures/admin_edit.PNG)\n\n## Markdown Support\n\nThe blog text is written in Markdown and is parsed into HTML with help of the [remark](https://github.com/remarkjs/remark) parser. In addition, some plugins and custom renders were defined to have even more possibilities.\n\nFeatures supported in Markdown:\n\n- All native (\"vanilla\") Markdown features\n- Strike through, tables, task lists and direct URLs\n- Code syntax highlighting and custom language header\n- Latex math expressions (inline and block math)\n- Custom colored container (blocks for informative / warning text)\n\nYou can use custom blocks, rendered by `remark-directive-rehype`. The classes are currently:\n\n- `danger`: Red themed block element\n- `warning`: Yellow themed block element\n- `info`: Grey themed block element\n- `helpful`: Green themed block element\n\nYou simply generate them using the code syntax with the language defined as the class and the type as a div:\n\n```md\n:::div{.danger}\nThis will be rendered into a div of the class danger. It has a red-ish background with dark red text color and a red left border. It is used to inform the user of any critical things to consider.\n:::\n```\n\nThe body within will also be translated from Markdown to HTML code, all supported features can be used. The example above will be translated into the following element:\n\n![Custom Block](docs/pictures/custom_danger.PNG)\n\nOne critical aspect is to check the right spelling, otherwise the element will rendered into a code block of the misspelled tag.\n\n## Architecture\n\nThe following schema shows the architecture of the Web App, API and corresponding services. React is used to build the frontend and gets hosted on github pages. The node.js with express is used for the API and is hosted on deta. The data is stored in a MongoDB. The blog pages either get the pictures from dropbox or from github. The user and the Admin interacts with the Web App to update data or just view the content:\n\n![Architecture](docs/diagrams/out/Architecture.svg)\n\n## Installation\n\nOver npm the server and the client can be installed separately:\n\n```bash\nnpm install\ncd ./client\nnpm install\n```\n\n## Start the Application\n\nTo start the application some variables need to be set fist. This concludes the variables `ATLAS_URI` and `JWT_SECRET` in the `.env` file. Also if you are running everything locally, be sure to set the `ENVIRONMENT_TYPE` to 'dev'. The first is the connection string to the database, the second is the 'password' for your token encryption. To get the mongodb running either create an instance at [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) or create a local instance with [docker](https://hub.docker.com/_/mongo). The fastest way is to create a volume and image locally with docker (required docker installed):\n\n```bash\ndocker volume create --name=yourVolumeName\ndocker run --name yourMongoDbName -v yourVolumeName:/data/db -p 27017:27017 -d mongo\n```\n\nThis will run mongodb on your local port 27017 in docker. In this case (if no credentials are set) the `.env` file would look similar to:\n\n```bash\nATLAS_URI=mongodb://127.0.0.1:27017\nJWT_SECRET=YourSecretForJWT\nENVIRONMENT_TYPE=dev\nWHITELIST=yourwebdomainadress\n```\n\nYou can use the `.env.default` as starting point for your .env file. Create a copy and rename it to `.env`. The whitelist can also be a list of domains, separated by a single whitespace (\" \").\n\nThe same applies to your `.env` files for the frontend / client. The default `.env.development` file contains the address of the api, this will probably be different in your `.env.production` file, later when running on different servers.\n\nAfter that you can run both (be sure to be in the main folder), server and backend with:\n\n```bash\nnpm run dev\n```\n\nThis will run both the backend api, and the frontend on local port 5000 and 3000 by default.\n\n## Access the Application\n\nThe front end should be opened automatically when running it. Otherwise you can always access it on http://localhost:3000/ when the app is running. The backend API runs on port 5000 by default. You can use the `PORT` variable to change the default port. To make requests to the API, other tools like [Postman](https://www.postman.com/) or [Insomnia](https://insomnia.rest/) can be used. To make a call use the http://localhost:5000/api/ endpoint. Since cors will most probably block the call by default, use `\"Origin\": \"http://localhost:3000\"` as header.\n\n## Generate an Admin User\n\nBy default, at first boot up, the backend will look if any user is found. If there is no existing user, it will create a default user with the name `admin` and the password `adminadmin`. It is strongly recommended to change the password directly after your first login over the admin interface. There is a graphical option for that. You could also use the environment variables `ADMIN_USER` and `ADMIN_PASSWORD` for other initial values than the default ones. Also, you can create additional user over the _/api/user/add_ post endpoint. You will need to be authenticated for that and pass the `username` and `password` in the body.\n\n## Use Dropbox to Store and Access Pictures\n\nI am using [dropbox-v2-api](https://github.com/adasq/dropbox-v2-api) for easy interaction with the dropbox API. You need an dropbox account and a project with an according access token. The token is stored at the `.env` file under `DROPBOX_ACCESS_TOKEN`.\nSteps to create a project and get the access token:\n\n1. Go to [dropbox developer](https://www.dropbox.com/developers/apps) and create your app.\n2. Set the Permissions settings before generating the token as it remembers the settings.\n3. Go to the Permissions tab.\n4. Check `sharing.write` and `file_requests.write` as well as `files.content.read` and `files.content.write`.\n5. Generate and copy your token from the Settings tab. Change expiration to \"No expiration\". You can also re-generate for a new token here if it has been compromised.\n6. Paste the token into your `.env` file.\n\n## ToDo's\n\n- Create a more established style for the whole app\n- User Swagger or similar tool for API documentation\n- Implementing delete functionality for the API\n\n## Known Issues\n\n- iOS based browsers do not respect the code cell formatting and break long code lines into multiple ones even if it's defined not to do so.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewohnsland%2Fandrewohnsland.github.io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewohnsland%2Fandrewohnsland.github.io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewohnsland%2Fandrewohnsland.github.io/lists"}