{"id":14991065,"url":"https://github.com/amamenko/inky-doodle","last_synced_at":"2025-04-12T03:30:22.348Z","repository":{"id":46876065,"uuid":"333978554","full_name":"amamenko/inky-doodle","owner":"amamenko","description":"Interactive application with pedigree chart, paginated search features, and automated Instagram posts for Inky Doodle characters","archived":false,"fork":false,"pushed_at":"2022-11-30T22:14:22.000Z","size":30368,"stargazers_count":21,"open_issues_count":3,"forks_count":18,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T23:05:31.246Z","etag":null,"topics":["cms","contentful","doodle","heredity","inky","nes","nescss","pedigree"],"latest_commit_sha":null,"homepage":"https://inky-doodle.vercel.app","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/amamenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-28T22:59:59.000Z","updated_at":"2025-01-17T13:48:41.000Z","dependencies_parsed_at":"2023-01-23T12:16:16.298Z","dependency_job_id":null,"html_url":"https://github.com/amamenko/inky-doodle","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amamenko%2Finky-doodle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amamenko%2Finky-doodle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amamenko%2Finky-doodle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amamenko%2Finky-doodle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amamenko","download_url":"https://codeload.github.com/amamenko/inky-doodle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248512418,"owners_count":21116598,"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","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":["cms","contentful","doodle","heredity","inky","nes","nescss","pedigree"],"created_at":"2024-09-24T14:21:24.344Z","updated_at":"2025-04-12T03:30:22.328Z","avatar_url":"https://github.com/amamenko.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![MIT License][license-shield]][license-url]\n[![LinkedIn][linkedin-shield]][linkedin-url]\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/amamenko/inky-doodle\"\u003e\n    \u003cimg src=\"client/src/images/InkyDoodleLogo.png\" alt=\"Logo\" width=\"350\"  /\u003e\n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003eInky Doodle\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    Single-Page Application (SPA) Integrated with Contentful\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://inkydoodle.ml\"\u003eView Demo\u003c/a\u003e\n    ·\n    \u003ca href=\"https://www.youtube.com/watch?v=VPKyCoFkgS0\"\u003eWatch Video Demo\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/amamenko/inky-doodle/issues\"\u003eReport Issue\u003c/a\u003e \n    ·\n    \u003ca href=\"https://www.instagram.com/inkydoodle.ml\"\u003eFollow @inkydoodle.ml\u003c/a\u003e \n  \u003c/p\u003e\n\u003c/p\u003e\n\n## Overview\n\nInky Doodle is a single-page application (SPA) that illustrates and explores the biological concepts of hybridization and heredity with the use of imaginary species of \"Inky Doodles.\" The website also has a [Pokédex](https://www.pokemon.com/us/pokedex/)-like search functionality. The website includes a landing page that allows the user to navigate to a Frequently Asked Questions (FAQ) page, a Search Inky Doodle page, a Pedigree Chart page, and a Contact Us page.\n\n### Search Functionality\n\nThe search functionality gives users the ability to look up Inky Doodles by name or ID number. This search input queries the Inky Doodle Contentful database and shows all the matching Inky Doodles in a paginated result page format. Users can then click on a desired Inky Doodle preview thumbnail to open up that specific Inky Doodle's full profile. This profile includes their picture, name, number, parents, children, and Instagram history. If the Inky Doodle has already been posted to the [@inkydoodle.ml](https://www.instagram.com/inkydoodle.ml) Instagram page, then users can see when it was posted and also click a link that leads to that specific post. Otherwise, the scheduled date for that Inky Doodle's post will be shown.\n\nIn the Inky Doodle profile, any parent (if not the same as the Inky Doodle itself) or child can be clicked to view the associated parent or child's profile. Users can traverse back and forth through nested profiles easily since the profile states are stored and manipulated through a stack data structure (last in, first out).\n\n### Contact Page\n\nThe contact page includes a form (consisting of a name, email, and any questions/comments) that is connected to a [Getform.io](https://getform.io) endpoint. This endpoint is, in turn, connected to an email associated with Inky Doodle that receives the form when it is submitted. The form inputs then reset after submission.\n\n### Pedigree Chart\n\nAn additional feature of the application is a tree-structured pedigree chart with three generations. The first generation has a left tree and a right tree with spaces for two\nsets of parents. These parents can then be bred to form second generation offspring, which can, in turn, be bred to potentialy create third generation offspring.\nSecond-generation Inky Doodle mates can only produce viable offpspring if either one or both mates are purebreds or, in the case of both second-generation mates being F1 (filial 1) hybrids, if at least one of each mate's parents is of the same species.\nThe seven possible combinations of the three generations are as follows, where capital letters (e.g. A, B) designate purebred parents, mixed letters (e.g. Ab, Bc) designate hybrids, and\narrows designate breeding to create a new generation:\n\n\u003cp align=\"center\"\u003eA, A, A, A \u0026rarr; A, A \u0026rarr; A\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, A, A, B \u0026rarr; A, Ab \u0026rarr; A\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, A, B, B \u0026rarr; A, B \u0026rarr; Ab\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, A, B, C \u0026rarr; A, Bc \u0026rarr; Abac\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, B, A, B \u0026rarr; Ab, Ab \u0026rarr; Ab\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, B, A, C \u0026rarr; Ab, Ac \u0026rarr; Abac\u003c/p\u003e\n\u003cp align=\"center\"\u003eA, B, C, D \u0026rarr; Ab, Cd \u0026rarr; No Match\u003c/p\u003e\n\n### Circle Mode\n\nThis feature is similar to the pedigree tree except it includes an additional generation 1 parent.\n\nGeneration 2 Inky Doodles can only breed with other generation 2 Inky Doodles that share a parent with them. This means that any two generation 2 Inky Doodles will have a natural third partner that is the child of the two parents they don't share.\n\nThis results in 3 triangular-shaped relationships that make up a pedigree \"circle\": the three generation 1 parents, the three generation 2s that the generation 1 parents create, and the three generation 3 cousins that result from the pairing of the generation 2 offspring.\n\n### Deployment\n\nThe project was deployed to [Vercel](https://vercel.com). The custom domain was acquired from [Freenom](https://www.freenom.com/en/index.html?lang=en). DNS routing provided by [Cloudflare](https://www.cloudflare.com).\n\n\u003cbr /\u003e\n\n## UX / UI\n\n\u003cbr /\u003e \n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://inkydoodle.ml\"\u003e\n    \u003cimg  src=\"client/src/images/ResponsiveDesignImage.png\" alt=\"Inky Doodle Responsiveness Demo Screenshots\" width=\"700\" /\u003e\n\u003c/a\u003e\n\u003c/span\u003e\n\u003cbr/ \u003e\n\u003cbr /\u003e\n\nThe application was built by using React, [Styled Components](https://github.com/styled-components/styled-components), and [NES.css](https://github.com/nostalgic-css/NES.css).\nAll Inky Doodle information including names, parent information, images, and order number are stored in a [Contentful](https://www.contentful.com/) space and queried as needed by using Contentful's [Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api).\n\nInky Doodles are the intellectual property of Alex Jaloza. Inky Doodle assets, info, and initial design mockups courtesy of Alex Jaloza.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"client/src/images/PreliminarySketch.PNG\" alt=\"Inky Doodle Preliminary Sketch\" width=\"300\" /\u003e\n  \u003cimg src=\"client/src/images/ProductionScreenshot.png\" alt=\"Inky Doodle Production Screenshot\" width=\"400\" /\u003e \n\u003c/p\u003e\n\n\u003cbr /\u003e\n\nAs opposed to the initial design mock-ups for the Pedigree Tree, which just included the Inky Doodle's name underneath each individual parent's tree node, the production application added generational title indicators underneath each node. These allow for the dynamic setting of the Inky Doodle tree structure.\n\nFirst generation parent dropdowns in the Pedigree Tree also highlight names (with appropriate associated Inky Doodle colors) of parent species selected on the opposite side of the tree\nto suggest a next selection that will produce a successful generation 3 offspring.\n\nA randomizer button was also added to the Pedigree Tree in production that automatically selects first generation parents according to one of the seven breeding combinations mentioned in the introduction.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg  src=\"client/src/images/CircleModeSketch.png\" alt=\"Inky Doodle Circle Mode Preliminary Sketch\" width=\"300\" /\u003e\n  \u003cimg src=\"client/src/images/CircleModeProd.png\" alt=\"Inky Doodle Circle Mode Production Screenshot\" width=\"450\" /\u003e \n\u003c/p\u003e\n\n\u003cbr /\u003e\n\nSimilarly, as opposed to the preliminary sketch, the production feature of Circle Mode includes generational title indicators and each Inky Doodle's name under each Inky Doodle's associated image. Arrows are also included to better illustrate the relationship that each generation 2 and generation 3 Inky Doodles have to their parents.\n\nRed arrows indicate generation 1 pairings that form generation 2 offspring. Blue arrows indicate generation 2 pairings that form generation 3 offspring.\n\n## Automated Server-side Instagram Posting\n\nThe project also incudes an [Express](https://expressjs.com) server that posts a new Inky Doodle from [Contentful](https://www.contentful.com/) with a custom caption (including the Inky Doodle's name, ID number, parents, if any, and its generation) to the [@inkydoodle.ml](https://www.instagram.com/inkydoodle.ml) Instagram page every day at 4PM Eastern Time via [node-cron](https://www.npmjs.com/package/node-cron) and [instagram-web-api](https://www.npmjs.com/package/instagram-web-api).\n\nThe server logs in to Instagram initially with a username and password. It then persists the authenticated cookies in a cookie store via [tough-cookie-filestore2](https://www.npmjs.com/package/tough-cookie-filestore2) for future use. The Instagram link and date of posting for that particular Inky Doodle are then automatically stored via [the JavaScript SDK for Contentful's Content Management API](https://www.npmjs.com/package/contentful-management).\n\nThe server was initially deployed to [Heroku](https://www.heroku.com) and the Heroku dyno kept awake with [Kaffeine](https://kaffeine.herokuapp.com), but is now deployed on [AWS](https://aws.amazon.com). A video walkthrough of the code for this server can be found on [YouTube](https://www.youtube.com/watch?v=XzyYi_yv86A).\n\nI have also created a [shorter tutorial on YouTube](https://www.youtube.com/watch?v=E46vCLlJ2Dw) going over the basics of automating daily Instagram posts with one static photo. This shorter tutorial centers around my other project called [Daily Pixel Mike](https://github.com/amamenko/daily-pixel-mike). This video also includes how to set up a cookie store via [tough-cookie-filestore2](https://www.npmjs.com/package/tough-cookie-filestore2), which the previous tutorial did not mention. It also includes random words generated daily using the [wordpos](https://www.npmjs.com/package/wordpos) library. The source code also shows how I implemented daily definitions for the randomly generated adjectives.\n\n## Local Development\n\nTo set up this project locally, you can follow the steps below.\n\n### Prerequisites\n\nYou will need to have the following software installed:\n\n- npm\n- Git\n- Node.js\n\n### Installation\n\n1. Get a free Contentful space at [https://www.contentful.com](https://www.contentful.com) and create a model and associated content.\n2. Clone the Github repository.\n   ```sh\n   git clone https://github.com/amamenko/inky-doodle.git\n   ```\n3. Install all server-side NPM packages.\n   ```sh\n   npm install\n   ```\n4. Add your server-side environment variables.\n   ```JS\n   INSTAGRAM_USERNAME=YOUR INSTAGRAM USERNAME\n   INSTAGRAM_PASSWORD=YOUR INSTAGRAM PASSWORD\n   CONTENTFUL_SPACE_ID=YOUR CONTENTFUL SPACE ID\n   CONTENTFUL_ACCESS_TOKEN=YOUR CONTENTFUL ACCESS TOKEN\n   CONTENTFUL_MANAGEMENT_TOKEN=YOUR CONTENTFUL MANAGEMENT TOKEN\n   YOUR_EMAIL=YOUR EMAIL ADDRESS\n   YOUR_EMAIL_PASSWORD=YOUR EMAIL PASSWORD\n   ```\n5. `cd` into the client-side directory.\n   ```sh\n   cd client\n   ```\n6. Install all client-side NPM packages.\n   ```sh\n   npm install\n   ```\n7. Enter your Contentful Content Delivery API credentials as client-side environment variables.\n   ```JS\n   REACT_APP_SPACE_ID=YOUR CONTENTFUL SPACE ID\n   REACT_APP_ACCESS_TOKEN=YOUR CONTENTFUL ACCESS TOKEN\n   REACT_APP_GETFORM_CONTACT_ENDPOINT=YOUR GETFORM URL ENDPOINT\n   ```\n8. Start the local server.\n   ```JS\n   npm start\n   ```\n9. Build for production.\n   ```JS\n   npm run build\n   ```\n\n\u003c!-- CONTRIBUTING --\u003e\n\n## Contributing\n\nContributions are welcome!\n\n1. Fork the project.\n2. Create your feature branch (`git checkout -b feature/MyFeature`).\n3. Commit your changes (`git commit -m 'Add my feature'`).\n4. Push to the branch (`git push origin feature/MyFeature`).\n5. Open a pull request.\n\n\u003c!-- LICENSE --\u003e\n\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003c!-- CONTACT --\u003e\n\n## Contact\n\nAvraham (Avi) Mamenko - avimamenko@gmail.com\n\nProject Link: [https://github.com/amamenko/inky-doodle](https://github.com/amamenko/inky-doodle)\n\n\u003c!-- ACKNOWLEDGEMENTS --\u003e\n\n## Acknowledgements\n\n- Alex Jaloza\n- [Contentful](https://www.contentful.com/)\n- [NES.css](https://github.com/nostalgic-css/NES.css)\n- [react-select-nes-css-theme](https://www.npmjs.com/package/react-select-nes-css-theme)\n- [Vercel](https://vercel.com)\n- [Heroku](https://www.heroku.com)\n- [AWS](https://aws.amazon.com)\n- [instagram-web-api](https://www.npmjs.com/package/instagram-web-api)\n- [Jimp](https://www.npmjs.com/package/jimp)\n- [React Icons](https://react-icons.github.io/react-icons)\n- [Getform.io](https://getform.io/)\n- [React Spinners](https://www.npmjs.com/package/react-spinners)\n- [Best-README-Template](https://github.com/othneildrew/Best-README-Template)\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n\n[license-shield]: https://img.shields.io/github/license/othneildrew/Best-README-Template.svg?style=for-the-badge\n[license-url]: https://github.com/amamenko/inky-doodle/blob/master/LICENSE.txt\n[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge\u0026logo=linkedin\u0026colorB=555\n[linkedin-url]: https://www.linkedin.com/in/avrahammamenko\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famamenko%2Finky-doodle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famamenko%2Finky-doodle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famamenko%2Finky-doodle/lists"}