{"id":20689443,"url":"https://github.com/paulshpilsher/instalike","last_synced_at":"2026-04-08T21:31:43.722Z","repository":{"id":203108203,"uuid":"707238597","full_name":"PaulShpilsher/instalike","owner":"PaulShpilsher","description":"Instagram-like Go-based REST API backend webservice. ","archived":false,"fork":false,"pushed_at":"2025-08-06T01:42:53.000Z","size":618,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-05T21:42:26.794Z","etag":null,"topics":["cors","docker","docker-compose","go","gofiber","golang","jwt","jwt-authentication","postgres","postgresql","rest","rest-api","restapi","rsa","sqlx","swagger"],"latest_commit_sha":null,"homepage":"","language":"Go","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/PaulShpilsher.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}},"created_at":"2023-10-19T13:49:31.000Z","updated_at":"2025-08-06T01:42:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"99edd7a4-71d2-4630-ab7b-0e40b88d9778","html_url":"https://github.com/PaulShpilsher/instalike","commit_stats":null,"previous_names":["paulshpilsher/instalike"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PaulShpilsher/instalike","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulShpilsher%2Finstalike","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulShpilsher%2Finstalike/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulShpilsher%2Finstalike/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulShpilsher%2Finstalike/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaulShpilsher","download_url":"https://codeload.github.com/PaulShpilsher/instalike/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaulShpilsher%2Finstalike/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31575445,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"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":["cors","docker","docker-compose","go","gofiber","golang","jwt","jwt-authentication","postgres","postgresql","rest","rest-api","restapi","rsa","sqlx","swagger"],"created_at":"2024-11-16T23:09:40.814Z","updated_at":"2026-04-08T21:31:43.705Z","avatar_url":"https://github.com/PaulShpilsher.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InstaLike\n\n\u003cp\u003e\nGo-based REST API webservice for an Instagram-like app, thus InstaLike :-)\n\u003c/p\u003e\n\n## 📝 Table of Contents\n\n- [About](#about)\n- [Quick start](#quickstart)\n- [Features](#features)\n- [Design](#design)\n- [Development](#development)\n- [Configuration](#config)\n- [API](#api)\n\n## About \u003ca name = \"about\"\u003e\u003c/a\u003e\n\nThis is a simple web service provides a simple way managing user posts.\nIs is Go web service written in Go that uses Postgres for data storage.\n\n\n## Quick start \u003ca name = \"quickstart\"\u003e\u003c/a\u003e\n\nRun fully functioning service with the database in docker containers using docker compose (assuming docker and docker compose are installed):\n```\ngit clone https://github.com/PaulShpilsher/instalike.git\ncd instalike\ndocker-compose up --build\n```\nIn your browser go to http://localhost:3000/swagger/index.html\n\n\n## Features \u003ca name = \"features\"\u003e\u003c/a\u003e\n\n- REST standard (followed as much as possible)\n- CORS\n- New users registration and logging them in uses a simple username/password pattern.\n- Accessing posts and other resources are protected by JWT.  RSA public key scheme used in token creation and verification.\n- For simplicity and given time constraints post’s multimedia attachments (image and video content) are stored in the database.  TODO: This needs to be changed to store the binary data in the file system.\n- Smallest possible docker image using fromscratch base image.\n\n\n## Design\n\n### Tech\n- go …duh!\n- go fiber - very fast API framework build on top Fasthttp\n- go playground validator - structure validation\n- go playgroud jwt - for token creation and validation\n- brcypt - for password hashing\n- swag - swagger\n- pgx - a postgres driver\n- sqlx - is a library which provides a set of extensions on go's standard database/sql library.\n\n### Code\nProject’s structure if fairly simple.  Here is run down of top level subdirectories:\n- db: contains database initialization sql script files\n- docs: contains swagger generated documentation files (to create them run command “make swag”\n- keys: contains RSA public and private keys for token authentication (to create then run command “make cert”)\n- pkg: contains all of the application logic\n\nThe application uses Domain Driven Design (DDD). ‘pkg/domain’ contains code for 3 domain bounded contexts. They are:\n- users - contains everything related to user related use cases\n- posts - contains  everything related to user posts related use cases.\n- media - contains multimedia related code, such as downloading post images and videos\n\nEach of the bounded contexts uses layered separation of responsibilities design pattern.  It uses dependency injection for layer interaction.  The layers are:\n- repository - provides \\database / store access\n- service - provides domain’s business logic\n- endpoint - provides API functionality, i.e. API handlers\n- router - defines API routes\n\nAlso domain may contain definitions for domain’s data model, API DTO, and layer interface declarations\n\n\n### Database\n\nThe model:\n\n![diagram](https://github.com/PaulShpilsher/instalike/assets/20777554/cca01ccf-7c0c-41e7-a5b3-f21193c1d594)\n\n\nAn architectural decision was made not to delete any data.  Delete entity business use case is approached by having a deleted BOOLEAN column on “posts” and “post_comments” tables.  This allows to retain for historical and auditing purposes all the data.\n\nSince the data returned to the user is filtered WHERE deleted IS FALSE we use filtered indexes to efficiently get the relevant data.\n\nAnother performance improvement is use of the VIEWS.  This allows us to save database access calls when for example we need to return post data with filled in author’s email (or in future username).  Without this we would have to query posts and users tables, and in code match user information to each of the posts read from the database.  \n\nImportant notes:  \n- posts likes are stored in an array column containing ids of users who liked the post.  This is done in order to prevent user liking more than once provide the “unlike” functionality (not implement). And counting likes is provided for our pleasure by Postgres’s cardinality method (see posts_view)\n- in future storing multimedia files needs to be removed from post_attachmens table.  This table will store only attachment’s metadata information and a reference (probably file id) to the file storage.\n\n\n## Development \u003ca name = \"development\"\u003e\u003c/a\u003e\nAssuming Go, docker, git and make installed, here are simple instructions to get you up and running in no time\n\nGet the code from github\n```\n  git clone https://github.com/PaulShpilsher/instalike.git\n  cd instalike\n```\n\nStart Postgres server instance in a docker container (*Docker must be installed*)\n```\n  make postgres\n```\n\nTODO: instructions on how to apply db/init.sql.  But for now just execute db/init.sql script in the database using you favorite Postgres client. (look .env file for database connection information)\n\nGenerate RSA keys (they will be stored in ./keys directory):\n```\n  make cert\n```\n\nGenerate Swagger documents ( they will be stored in ./doc/instalike directory):\n```\n  make swag\n```\n\nStart web service:\n```\n  make start\n```\n\nBuild:\n```\n  make build\n```\nThis will build the code and put it in ./bin directory along with required supporting files (configuration and RSA keys for JWT)\n\n\n## Configuration \u003ca name = \"config\"\u003e\u003c/a\u003e\n\nThis web service uses .env file for configuration.\n\nexample:\n```\n# ./.env\n\n# Server configuration\nHOST=\"0.0.0.0\"\nPORT=3000\nDOMAIN=\"localhost\"\n\nCORS_ALLOWED_ORIGINS=\"*\"\n\nTOKEN_EXPIRATION_MINUTES=720\nTOKEN_PRIVATE_KEY_FILE=\"keys/rsa\"\nTOKEN_PUBLIC_KEY_FILE=\"keys/rsa.pub\"\n\n\n# Database configuration\nDB_URL=\"postgresql://pusr:pusr_secret@localhost:5432/instalike-data?sslmode=disable\"\nDB_MAX_CONNECTIONS=100\nDB_MAX_IDLE_CONNECTIONS=10\nDB_MAX_LIFETIME_CONNECTIONS=2\n```\n\n## API \u003ca name=\"api\"\u003e\u003c/a\u003e\n\nThe APIs definitions are available with swagger.  Just start the server using docker compose and navigate to at http://localhost:3000/swagger/index.html\n\nSummary of APIs:\n\nUsers:\n  - POST /api/users/register\n  - POST /api/users/login\n\n Posts:\n  - GET /api/posts - get all posts\n  - GET /api/posts/:postId - get a post by id\n  - POST /api/posts - creates a post\n  - PUT /api/posts/:postId - updates a post by id (only authors are allowed to update)\n  - DELETE /api/posts/:postId - deletes a post by id (only authors are allowed to delete)\n  - POST /api/posts/:postId/attachment - attaches a multimedia file to post (only authors are allowed to update)\n  - POST /api/posts/:postId/like - likes a post (likes are limited to 1 per user)\n\nPost comments:\n  - POST/api/posts/{postId}/comments - creates a new post comment\n  - GET /api/posts/{postId}/comments - gets a list of post's comments by id\n\nMultimedia:\n  - GET /media/attachments/{attachmentId} - downloads a attached multimedia file by id.  \n\n\n## TODO \u003ca name = \"todo\"\u003e\u003c/a\u003e\n- Tests\n- File storage\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulshpilsher%2Finstalike","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaulshpilsher%2Finstalike","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulshpilsher%2Finstalike/lists"}