{"id":16884430,"url":"https://github.com/yerkopalma/full-stack","last_synced_at":"2025-10-19T13:56:41.018Z","repository":{"id":72770477,"uuid":"94825513","full_name":"YerkoPalma/full-stack","owner":"YerkoPalma","description":":crystal_ball: full-stack project template","archived":false,"fork":false,"pushed_at":"2017-07-26T16:27:39.000Z","size":17,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-20T05:30:52.598Z","etag":null,"topics":["framework","full-stack"],"latest_commit_sha":null,"homepage":"","language":null,"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/YerkoPalma.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}},"created_at":"2017-06-19T22:16:17.000Z","updated_at":"2017-07-02T22:45:31.000Z","dependencies_parsed_at":"2023-05-12T02:30:26.067Z","dependency_job_id":null,"html_url":"https://github.com/YerkoPalma/full-stack","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/YerkoPalma/full-stack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YerkoPalma%2Ffull-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YerkoPalma%2Ffull-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YerkoPalma%2Ffull-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YerkoPalma%2Ffull-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YerkoPalma","download_url":"https://codeload.github.com/YerkoPalma/full-stack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YerkoPalma%2Ffull-stack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270850057,"owners_count":24656443,"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-08-17T02:00:09.016Z","response_time":129,"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":["framework","full-stack"],"created_at":"2024-10-13T16:27:58.199Z","updated_at":"2025-10-19T13:56:40.946Z","avatar_url":"https://github.com/YerkoPalma.png","language":null,"readme":"# full-stack\n\n\u003e full-stack project template\n\n## Features\n\n- Exposes a REST API prefixed with `'api/:version'`, like `api/v1`.\n- Use merry to serve the api, and bankai for assets.\n- Handle environment variables through .env file (remember not to commit the file).\n- Use leveldb as database (memdb in development, leveldown in production).\n- Use `npm scripts` as task runner.\n\n## Usage\n\nTo use it, copy the [savior][savior] script somewhere in your path, then clone \nmy [templates][templates], and set the `TEMPLATES` environment variable to the \npath where you cloned the templates. After that, run:\n\n```bash\n$ savior full-stack \u003cyour-app-name\u003e\n```\n\n## How it works\n\nThere are two main frames in this stack, the client (frontend) and the api \n(backend).\n\n### Api\n\nThe api files remain in the `/api` folder. The folder structure is the following\n\n```\napi/\n├── lib/\n│   ├── factory.js\n│   └── resource.js\n├── models/\n└── index.js\n```\n\nGenerally, you don't need to modify anything in the `lib` foler, \nthe files in there will help you to generate your model instance and the REST \nroutes for that model. We will get to that later.\n\nThe `models` folder contains your models schemas as json files, just that. \nBe aware that the name of your model file, must be the same that you use later \nto get your model instance.\n\nThe `index.js` file is the entry point of your api. It MUST expose (exports) a \n[merry][merry] instance, that will be served by the root index file (the server). \nHere is where you use the lib folder files. First create your models, which are \n[rest-parser][rest-parser] instances with the `factory.js` file, like this:\n\n```js\nvar Model = require('./lib/factory')\nvar Post = Model(db, 'post')\n```\n\nIn the above snippet, `Post` is your model, and `db` is a [levelup][levelup] \ninstance (in this example [memdb][memdb] for development and [level][level] for\nproduction). After you define that model, define the REST routes for that model\n\n```js\nvar Resource = require('./lib/resource')\nvar merry = require('merry')\n\nvar app = merry()\nvar resource = Resource(app)\n\nresource(Post, opt)\n```\n\nAs you can see, the `Resource` function expect a merry instance, and returns a \nfunction that will attach REST routes to your app, by providing a model (`Post` \nin the above example) and a set of options, which can/must be:\n\n- version: can be anything, if not defined will default to 1.\n- path: MUST be provided, and be exactly the same that the name of your model \nscheme file\n- only: an array of strings, specifying that you only need support for those \nactions, possible actions are: `'create', 'show', 'index', 'update', 'delete'`\n\nNow you are ready to expose a simple, but fully featured REST api. If you need \nspecific logic for certain routes, just define them as you would with any other \nmerry app.\n\n### client\n\nThe client source code of the app lives in the `/src` folder, the folder \nstructure is the following:\n\n```\nsrc/\n├── assets/\n├── store/\n│   ├── actions.js\n│   └── reducer.js\n├── views/\n└── index.js\n```\n\nMost of the client is handled by [singleton-router][singleton-router] and \n[redux][redux]. `views/` folder contains views, which are files that expose a \nfunction that gets as argument the `params` and the redux `store`, and, using \n[bel][bel], return an HTML element. To comunicate with the backend (api), you \nshould use the actions from the `store` folder, there is a helper function \n`makeRequest` which use the http module from node to make an xhr request \n(thanks to browserify), anyway, you can replace it for any other xhr/ajax \nlibrary\n\n## FAQ\n\n### How should I handle authentication stuff?\n\nYou should use middlewares. In the api, you can pass a [nanostack][nanostack] \ninstance to the resource library in your `/api/index.js` file, like this:\n\n```js\nvar app = merry()\nvar stack = Nanostack()\n// push to middleware\nvar resource = Resource(app, stack)\n```\n\nThat's the way to go with middlewares.\n\n### What about production?\n\nFor production you can build with `npm run build`, that would use [bankai][bankai] \nto build your frontend, then run your app with the `ENV` variable set to \n`production` like `ENV=production node index.js`. So what's different?\n\n- No loggin in production, only for errors.\n- Use level in production instead of memdb.\n- All your frontend is minified, thanks to bankai.\n\n### Do you use components?\n\nComponents doesn't get included here. If you want components, you should use \n[microcomponent][microcomponent] library.\n\n### And server side rendering?\n\nLet's say you have a component or something you want to server render, then you \nshould define it normally in your client and then in your main index file, take \nit and respond with it as a stream when there is an html request, for example:\n\n```js\nvar fromString = require('from2-string')\nvar nav = require('./components/nav')\nvar hyperstream = require('hyperstream')\nvar http = require('http')\nvar path = require('path')\nvar fs = require('fs')\n\nvar server = http.createServer(handler)\nserver.listen(port, ip)\n\nfunction handler (req, res) {\n  var url = req.url\n  if (url === '/') {\n    serveHtml(res, index)\n  }\n}\n\nfunction serveHtml (res, html) {\n  htmlStream = fs.createReadStream(path.resolve(__dirname, html))\n  navStream = hyperstream({\n    'header': fromString(nav.toString())\n  })\n  htmlStream.pipe(navStream).pipe(res)\n}\n```\n\nThe above snippet take the nav component (a `bel` component) and make a stream \nof it with [from-string][from-string]. Then it uses [hyperstream][hyperstream] to \nmake an html stream and pipe it to the response stream.\n\n## Example\n\nIn the example folder, there are some sub projects with their own description.\n\n## License\n\n[MIT](/license)\n\n[savior]: https://gist.github.com/YerkoPalma/c9814be639efb165e8445667f36b901e\n[templates]: https://github.com/YerkoPalma/templates\n[rest-parser]: https://github.com/karissa/node-rest-parser\n[memdb]: https://github.com/juliangruber/memdb\n[levelup]: https://github.com/level/levelup\n[level]: https://github.com/level/level\n[singleton-router]: https://github.com/YerkoPalma/singleton-router\n[redux]: https://github.com/reactjs/redux\n[nanostack]: https://github.com/yoshuawuyts/nanostack\n[microcomponent]: https://github.com/yoshuawuyts/microcomponent\n[from-string]: https://github.com/yoshuawuyts/from2-string\n[hyperstream]: https://github.com/substack/hyperstream\n[merry]: https://github.com/shipharbor/merry\n[bankai]: https://github.com/yoshuawuyts/bankai\n[bel]: https://github.com/shama/bel","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyerkopalma%2Ffull-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyerkopalma%2Ffull-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyerkopalma%2Ffull-stack/lists"}