{"id":18409979,"url":"https://github.com/snowdogapps/wombat","last_synced_at":"2025-04-07T09:34:21.125Z","repository":{"id":33661184,"uuid":"159418589","full_name":"SnowdogApps/wombat","owner":"SnowdogApps","description":"Flat file headless CMS for building configurable API","archived":false,"fork":false,"pushed_at":"2022-06-01T17:30:37.000Z","size":328,"stargazers_count":62,"open_issues_count":4,"forks_count":3,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-10-31T17:45:44.639Z","etag":null,"topics":["hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/SnowdogApps.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}},"created_at":"2018-11-28T00:16:45.000Z","updated_at":"2023-06-26T07:44:36.000Z","dependencies_parsed_at":"2022-07-25T19:02:27.130Z","dependency_job_id":null,"html_url":"https://github.com/SnowdogApps/wombat","commit_stats":null,"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SnowdogApps%2Fwombat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SnowdogApps%2Fwombat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SnowdogApps%2Fwombat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SnowdogApps%2Fwombat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SnowdogApps","download_url":"https://codeload.github.com/SnowdogApps/wombat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223277053,"owners_count":17118461,"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":["hacktoberfest"],"created_at":"2024-11-06T03:28:22.886Z","updated_at":"2024-11-06T03:28:26.151Z","avatar_url":"https://github.com/SnowdogApps.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo.svg\" height=\"200\"\u003e\n\u003c/p\u003e\n\n# Wombat\nSimple open-source flat-file serverless Content Management Framework (headless-CMS) to build powerful API effortlessly.\n\n## Features\n- **Simple** - Designed to replace Wordpress in building simple company / product / event pages\n- **Fast and lightweight** - Serverless oriented, no framework, no database or other system-wide requirements\n- **Two types of data** - Unlike Contentful or Strapi, offers not only items collection, but also single entities, that can be used to build pages or store configuration\n- **Full internationalization** - Every piece content is assigned to one language, so you have complete freedom in customizing it\n- **No strict schema** - Do you need each item within a content type to do be different and have a different structure for each language? No problem, sky is the limit!\n- **No Admin Panel** - You are not limited by the UI or poor UX, just you and bunch of JSON and Markdown files\n- **Front-end agnostic** - Simple REST API can be used by any application\n\n\n## Setup\n1. Add Wombat as dependecy `yarn add @snowdog/wombat`\n2. Create content following [Content structure](#content-structure) description.\n3. Create `wombat.config.json` file. Can be just `{}` if you are okay with default setting.\n4. Add `\"dev\": \"wombat dev\"` to `package.json` scripts section\n5. Run `yarn dev` and enjoy working with your new API\n\n## Serverless deployment\nThis guide is for [ZEIT Now](https://zeit.co/docs/v2/deployments/official-builders/node-js-now-node/), but setting up any other serverless env looks simillar.\n\n1. In `package.json` add automatic DB building after installing dependecies\n   ```\n    \"scripts\": {\n      \"now-build\": \"wombat build\",\n      \"dev\": \"wombat dev\"\n    }\n   ```\n2. Define new builds and routes in `now.json` acording to [the example](./examples/now/now.json)\n3. Copy [collection.js](./examples/now/collection.js) and [entity.js](./examples/now/entity.js) from examples\n4. Deploy your app via `now`\n\n## Config options\n```js\n{\n  \"defaultLang\": \"en\", // Fallback language when request is send without `lang` query param.\n  \"allowedOrigins\": [], // List of domains used to set Access-Control-Allow-Origin (CORS) response header\n  \"wombatUrl\": \"http://api.your.app\", // String to replace all occurences of {{wombatUrl}} with given URL.\n  \"dev\": {\n    \"port\": \"3000\", // Port used by the dev web server to listen for requests\n    \"build\": true // Determines if new \"database\" file should be build from files before dev server will be started.\n  }\n}\n```\n\n## Content structure\nAll content is kept in `/content` directory.\nInside you need to define supported languages. For example, we want to have content just in English, so it will be `/content/en`.\n\nWombat supports two data types:\n### Collections\nDesigned to store sets of similar data, like blog posts, authors, job offers etc.\n- Collections are stored in `collection` directory inside each language.\n- Each collection and item of collection needs to be added as a directory.\n- Every property of an item collection needs to be a separate JSON or Markdown file.\n\n### Entities\nCreated to keep a single object like a landing page content or global configuration.\n- Entities are stored in `entity` directory inside each language.\n- Each entity needs to be added as a directory.\n- Every property of entity needs to be a separate JSON or Markdown file.\n- You can define the relation between entity and collection.\n\n### The Query object\nThe core of Wombat. It's the key to get data from collection and to supply entities with colection data.\n\n```js\n{\n  \"query\": {\n    \"name\": \"collectionName\", // (required) collection name\n    \"sortBy\": \"title\", // prop name used for sorting\n    \"sort\": \"desc\", // `asc` (default), `desc` or `shuffle` - `sortBy` required to use it\n    \"shuffle\": true, // Shuffle returned items\n    \"limit\": 2, // limit numer of returned items\n    \"page\": 1, // page number\n    \"perPage\": 100, // numer of items per page\n    \"items\": [\"award\", \"about\", \"partner\"], // Array of collection items IDs. Items order is preserved.\n    \"props\": [\"id\", \"content\"] // return only selected object props\n    \"filter\": {\n      \"prop\": \"published\", // name of collection item property used to filtering\n      \"type\": \"date\", // `value`, `number` or `date - type of the filtering\n      \"value\": \"2019-01-01\", // value used for filtering, can be also array\n      \"from\": \"2019-01-01\", // range start for `number` or `date` type\n      \"to\": \"2019-03-01\" // range end for `number` or `date` type\n    }\n  }\n}\n```\n\n### Example content tree\n```\ncontent\n└── en\n    ├── collection\n    |   └── blog\n    |       └── why-wombat-poop-is-cube\n    |       |   ├── content.md\n    |       |   ├── featured-image.json\n    |       |   └── title.json\n    |       └── things-you-dont-know-about-wombats\n    |           ├── content.md\n    |           ├── featured-image.json\n    |           ├── form-config.json\n    |           └── title.json\n    └── entity\n        └── home\n            ├── blog-posts.json\n            ├── about.md\n            └── hero-banner.json\n```\n## API\n### `/entity`\nRetrieve an entity item.\n\n**Example:**\nTo get `home` entity send request to `/entity?name=home`.\n\n**URL params:**\n- `name` - (required) Name of entity\n- `lang` - Return content in given lang.\n\n### `/collection`\nRetrieve the whole collection as array.\n\n**Examples:**\n#### Whole collection\n```\n/collection?name=blog\n```\n\n#### Whole collection, but only title and content\n```\n/collection?name=blog\u0026props=title,content\n```\n\n#### Only items selected by ID\n```\n/collection?name=blog\u0026items=why-wombat-poop-is-cube,things-you-dont-know-about-wombats\n```\n\n#### Two items from collection sorted by title descending\n```\n/collection?name=blog\u0026limit=2\u0026sortBy=title\u0026sort=desc\n```\n\n#### Items from second page, up to five per page\n```\n/collection?name=blog\u0026page=2\u0026perPage=5\n```\n\n**URL params:**\n- `name` - (required) Name of collection.\n- `lang` - Return content in given lang.\n- `sortBy` - Prop name used for sorting.\n- `sort` - `asc` (default) or `desc`- `sortBy` required to use it.\n- `shuffle` - Shuffle returned items.\n- `limit` - Limit numer of returned items.\n- `page` - Page number.\n- `perPage` - Numer of items per page.\n- `items` - Comma separated list of collection items IDs. Items order is preserved.\n- `props` - Comma separated list of selected object props, GraphQL-like.\n- `filter` - Filtering config in form of stringified JSON object\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowdogapps%2Fwombat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnowdogapps%2Fwombat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowdogapps%2Fwombat/lists"}