├── .eslintrc
├── .gitignore
├── .osfg-dir-config.js
├── .setup-symlinks.sh
├── LICENSE.md
├── README.md
├── docs
├── asset-manifest.json
├── conference-for-good
│ └── index.html
├── favicon.ico
├── index.html
├── league-for-good
│ └── index.html
├── mail-for-good
│ └── index.html
├── manifest.json
├── meeting-for-good
│ └── index.html
├── nonprofits.css
├── open-source-for-good-directory
│ └── index.html
├── pantry-for-good
│ └── index.html
└── static
│ ├── css
│ ├── main.0515109c.css
│ └── main.0515109c.css.map
│ └── js
│ ├── main.d4eb4b9c.js
│ └── main.d4eb4b9c.js.map
├── package.json
├── public
├── conference-for-good
├── favicon.ico
├── index.html
├── league-for-good
├── mail-for-good
├── manifest.json
├── meeting-for-good
├── nonprofits.css
├── open-source-for-good-directory
└── pantry-for-good
├── repo-list.json
├── src
├── actions
│ └── index.js
├── assets
│ └── fcc-logo-white.png
├── components
│ ├── Card.js
│ ├── Header.js
│ ├── Main.js
│ ├── Search.js
│ ├── SortMenu.js
│ ├── Testimonial.js
│ └── Title.js
├── containers
│ └── App.js
├── helpers
│ └── index.js
├── index.css
├── index.js
└── reducers
│ └── index.js
└── yarn.lock
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "react-app",
3 | "parserOption": {
4 | "ecmaVersion": 6,
5 | "ecmaFeatures": {
6 | "jsx": true
7 | }
8 | },
9 | "env": {
10 | "es6": true,
11 | "browser": true,
12 | "mocha": true,
13 | "node": true
14 | },
15 | "parser": "babel-eslint",
16 | "plugins": [
17 | "react",
18 | "import",
19 | "prefer-object-spread"
20 | ],
21 | "settings": {
22 | "import/ignore": [
23 | "node_modules",
24 | "\\.json$"
25 | ],
26 | "import/extensions": [
27 | ".js",
28 | ".jsx"
29 | ]
30 | },
31 | "globals": {
32 | "Promise": true,
33 | "window": true,
34 | "$": true,
35 | "ga": true,
36 | "jQuery": true,
37 | "router": true
38 | },
39 | "rules": {
40 | "block-scoped-var": 0,
41 | "brace-style": [ 2, "1tbs", { "allowSingleLine": true } ],
42 | "camelcase": 2,
43 | "comma-dangle": 2,
44 | "comma-spacing": [ 2, { "before": false, "after": true } ],
45 | "comma-style": [ 2, "last" ],
46 | "complexity": 0,
47 | "consistent-return": 2,
48 | "consistent-this": 0,
49 | "curly": 2,
50 | "default-case": 2,
51 | "dot-notation": 0,
52 | "eol-last": 2,
53 | "eqeqeq": 2,
54 | "func-names": 0,
55 | "func-style": 0,
56 | "guard-for-in": 2,
57 | "handle-callback-err": 2,
58 | "jsx-quotes": [ 2, "prefer-single" ],
59 | "key-spacing": [ 2, { "beforeColon": false, "afterColon": true } ],
60 | "keyword-spacing": [ 2 ],
61 | "max-depth": 0,
62 | "max-len": [ 2, 80, 2 ],
63 | "max-nested-callbacks": 0,
64 | "max-params": 0,
65 | "max-statements": 0,
66 | "new-cap": 0,
67 | "new-parens": 2,
68 | "no-alert": 2,
69 | "no-array-constructor": 2,
70 | "no-bitwise": 2,
71 | "no-caller": 2,
72 | "no-catch-shadow": 2,
73 | "no-cond-assign": 2,
74 | "no-console": 0,
75 | "no-constant-condition": 2,
76 | "no-control-regex": 2,
77 | "no-debugger": 2,
78 | "no-delete-var": 2,
79 | "no-div-regex": 2,
80 | "no-dupe-keys": 2,
81 | "no-else-return": 0,
82 | "no-empty": 2,
83 | "no-empty-character-class": 2,
84 | "no-eq-null": 2,
85 | "no-eval": 2,
86 | "no-ex-assign": 2,
87 | "no-extend-native": 2,
88 | "no-extra-bind": 2,
89 | "no-extra-boolean-cast": 2,
90 | "no-extra-parens": 0,
91 | "no-extra-semi": 2,
92 | "no-fallthrough": 2,
93 | "no-floating-decimal": 2,
94 | "no-func-assign": 2,
95 | "no-implied-eval": 2,
96 | "no-inline-comments": 2,
97 | "no-inner-declarations": 2,
98 | "no-invalid-regexp": 2,
99 | "no-irregular-whitespace": 2,
100 | "no-iterator": 2,
101 | "no-label-var": 2,
102 | "no-labels": 2,
103 | "no-lone-blocks": 2,
104 | "no-lonely-if": 2,
105 | "no-loop-func": 2,
106 | "no-mixed-requires": 0,
107 | "no-mixed-spaces-and-tabs": 2,
108 | "no-multi-spaces": 2,
109 | "no-multi-str": 2,
110 | "no-multiple-empty-lines": [ 2, { "max": 2 } ],
111 | "no-native-reassign": 2,
112 | "no-negated-in-lhs": 2,
113 | "no-nested-ternary": 2,
114 | "no-new": 2,
115 | "no-new-func": 2,
116 | "no-new-object": 2,
117 | "no-new-require": 2,
118 | "no-new-wrappers": 2,
119 | "no-obj-calls": 2,
120 | "no-octal": 2,
121 | "no-octal-escape": 2,
122 | "no-path-concat": 2,
123 | "no-plusplus": 0,
124 | "no-process-env": 0,
125 | "no-process-exit": 2,
126 | "no-proto": 2,
127 | "no-redeclare": 2,
128 | "no-regex-spaces": 2,
129 | "no-reserved-keys": 0,
130 | "no-restricted-modules": 0,
131 | "no-return-assign": 2,
132 | "no-script-url": 2,
133 | "no-self-compare": 2,
134 | "no-sequences": 2,
135 | "no-shadow": 0,
136 | "no-shadow-restricted-names": 2,
137 | "no-spaced-func": 2,
138 | "no-sparse-arrays": 2,
139 | "no-sync": 0,
140 | "no-ternary": 0,
141 | "no-trailing-spaces": 2,
142 | "no-undef": 2,
143 | "no-undef-init": 2,
144 | "no-undefined": 2,
145 | "no-underscore-dangle": 0,
146 | "no-unreachable": 2,
147 | "no-unused-expressions": 2,
148 | "no-unused-vars": 2,
149 | "no-use-before-define": 0,
150 | "no-void": 0,
151 | "no-warning-comments": [ 2, { "terms": [ "fixme" ], "location": "start" } ],
152 | "no-with": 2,
153 | "one-var": 0,
154 | "operator-assignment": 0,
155 | "padded-blocks": 0,
156 | "quote-props": [ 2, "as-needed" ],
157 | "quotes": [ 2, "single", "avoid-escape" ],
158 | "radix": 2,
159 | "semi": [ 2, "always" ],
160 | "semi-spacing": [ 2, { "before": false, "after": true } ],
161 | "sort-vars": 0,
162 | "space-before-blocks": [ 2, "always" ],
163 | "space-before-function-paren": [ 2, "never" ],
164 | "space-in-brackets": 0,
165 | "space-in-parens": 0,
166 | "space-infix-ops": 2,
167 | "space-unary-ops": [ 2, { "words": true, "nonwords": false } ],
168 | "spaced-comment": [ 2, "always", { "exceptions": [ "-" ] } ],
169 | "strict": 0,
170 | "use-isnan": 2,
171 | "valid-jsdoc": 2,
172 | "valid-typeof": 2,
173 | "vars-on-top": 0,
174 | "wrap-iife": [ 2, "any" ],
175 | "wrap-regex": 2,
176 | "yoda": 0,
177 |
178 | "react/display-name": 2,
179 | "react/jsx-boolean-value": [ 2, "always" ],
180 | "react/jsx-closing-bracket-location": [ 2, { "selfClosing": "line-aligned", "nonEmpty": "props-aligned" } ],
181 | "react/jsx-no-undef": 2,
182 | "react/jsx-sort-props": [ 2, { "ignoreCase": true } ],
183 | "react/jsx-uses-react": 2,
184 | "react/jsx-uses-vars": 2,
185 | "react/jsx-wrap-multilines": 2,
186 | "react/no-did-mount-set-state": 2,
187 | "react/no-did-update-set-state": 2,
188 | "react/no-multi-comp": [ 2, { "ignoreStateless": true } ],
189 | "react/no-unknown-property": 2,
190 | "react/prop-types": 2,
191 | "react/react-in-jsx-scope": 2,
192 | "react/self-closing-comp": 2,
193 | "react/sort-prop-types": 2,
194 |
195 | "import/default": 2,
196 | "import/export": 2,
197 | "import/extensions": [ 0, "always" ],
198 | "import/first": 2,
199 | "import/named": 2,
200 | "import/namespace": 2,
201 | "import/newline-after-import": 2,
202 | "import/no-duplicates": 2,
203 | "import/no-unresolved": 2,
204 | "import/unambiguous": 2,
205 |
206 | "prefer-object-spread/prefer-object-spread": 2
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | # Webpack build
40 | build
41 |
42 | # Jekyll build files
43 | *.gem
44 | docs/_site
45 | docs/.sass-cache
46 | docs/bundle
47 | docs/vendor
48 |
49 | # macOS store
50 | .DS_Store
51 |
52 | # VS Code Configuration files
53 | .vscode/
54 |
55 | # .env Confi Files
56 | .env
57 |
58 | # Create React App Build folder
59 | build
60 |
61 |
--------------------------------------------------------------------------------
/.osfg-dir-config.js:
--------------------------------------------------------------------------------
1 | /*
2 | OPEN SOURCE FOR GOOD DIRECTORY SAMPLE CONFIG FILE
3 |
4 | title: Displayed at the top and as the webpage title
5 | demoVideo: the YouTube video address
6 | liveDemo: the address of the project's homepage
7 | description: an ES6 template string that contains GitHub-flavored Markdown.
8 | Keep this relatively short - a paragraph tops
9 | body: an ES6 template string with GitHub-flavored Markdown.
10 | Please include the open source license, with the freeCodeCamp copyright at the end.
11 |
12 | If the 'liveDemo' or the 'demoVideo' aren't yet available, you can exclued them.
13 | They just won't be added to the project's page.
14 | */
15 |
16 | module.exports = {
17 | title: 'Mail for Good',
18 | demoVideo: 'https://www.youtube.com/watch?v=_7U03GVD4a8',
19 | liveDemo: 'https://meeting.freecodecamp.com/',
20 | description: `An app for sending millions of emails as cheaply as possible. Mail for Good uses AWS Simple Email Service to send bulk emails at $0.10 per 1000 emails.
21 |
22 | Mail for Good is fast and memory efficient, currently sending over 100 emails per second on a 1gb Digital Ocean VPS.
23 |
24 | We've used Mail for Good to deliver newsletters to hundreds of thousands of campers per week.
25 | `,
26 | body: `## What does Mail for Good do?
27 |
28 | With Mail for Good you can:
29 |
30 | - Send email campaigns of unlimited size.
31 | - Import emails saved in CSV format.
32 | - Create templates to reuse for convenience when sending email campaigns.
33 | - Track bounce rate and other standard metrics. You can also insert tracking pixels and unsubcribe links a click of a button.
34 | - Add custom fields to imported email lists such as names or cities.
35 | - Grant other users (limited or otherwise) permissions to use your account on your behalf.
36 | - Add embedded HTML newsletter sign up forms to your site. These are snippets of code that will let your users sign up with you at the click of a button.
37 |
38 | ### Performance
39 |
40 | We're currently sending weekly email blasts of over 700,000 emails in 3-4 hours on a $10 per month Digital Ocean VPS with 1gb memory and 1 core processor.
41 |
42 | Mail for Good is fast and scales to the rate limit enforced by AWS.
43 |
44 | ### Why are we doing this?
45 |
46 | We want to help nonprofits manage their email campaigns as inexpensively as possible, and have full control over their data.
47 |
48 |
49 | ### License
50 |
51 | This computer software is licensed under the Open Source [BSD-3-Clause](https://github.com/freeCodeCamp/Mail-for-Good/blob/master/LICENSE.md).
52 |
53 | Copyright (c) 2017, freeCodeCamp.
54 | `
55 | };
56 |
--------------------------------------------------------------------------------
/.setup-symlinks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Script for creating Symlinks inside the "public/" folder
4 | # that point to versions inside the "docs/" folder. This
5 | # process is done to enable the NonProfit view during development.
6 | # Only works for Unix like systems (MacOS, Linux).
7 |
8 | # Deleting Old Symlinks inside public
9 | cd public
10 | for f in *; do
11 | if [[ -L "$f" ]]; then
12 | rm $f
13 | echo "Deleted $f old Symlink file"
14 | fi
15 | done
16 |
17 | # Creating the New Symlinks
18 | for f in ../docs/*; do
19 | if [[ -d $f && $f != "../docs/static" && ! -L "$f" ]]; then
20 | ln -s $f .
21 | echo "Created new ${f: 8} Symlink file"
22 | fi
23 | done
24 |
25 | cd ..
26 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, freeCodeCamp
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Open Source for Good Directory
2 |
3 | A directory for freeCodeCamp's Open Source for Good Apps - Solutions for Nonprofits.
4 |
5 | ## Instructions for adding a Non-Profit Project
6 |
7 | There are two steps to add an Open Source for Good Project to the directory:
8 |
9 | 1. Add the file `.osfg-dir-config.js` to the **root of the Project**.
10 | * This will trigger an automatic build of the Project's page inside the directory.
11 | * Please **verify** that an **update** by CamperBot to `docs/[project-name]` has occurred in the master branch of the directory.
12 | * Fields:
13 | * **title:** Displayed at the top and as the webpage title
14 | * **demoVideo:** the YouTube video address
15 | * **liveDemo:** the address of the project's homepage
16 | * **description:** an ES6 template string that contains GitHub-flavored Markdown. Keep this relatively short - a paragraph tops.
17 | * **body:** an ES6 template string with GitHub-flavored Markdown. Please include the open source license, with the freeCodeCamp copyright at the end.
18 | * If the `liveDemo` or the `demoVideo` aren't yet available, you can exclued them. They just won't be added to the project's page.
19 |
20 | * You can see a [**sample config file**](https://github.com/freeCodeCamp/open-source-for-good-directory/blob/master/.osfg-dir-config.js) at the root of this repository.
21 |
22 | 2. Edit the file `repo-list.json` at the root of the directory to include the project.
23 | * This file will tell the directory app to fetch the corresponding GitHub data and include a card for the project.
24 | * If you don't yet have permissions to update this repo, please **request the edit** from one of the project's maintainers.
25 | * Instructions for the file:
26 | * Please keep this file **alphabetically sorted** by repo name
27 | * **Everything** should be in **lower case**. This is critical to our search functionality
28 | * **name:** the GitHub repo's name in lower case (without the preceeding freecodecamp/)
29 | * **icon:** the Image to be displayed in the project's card. This string contains a
30 | [Font Awesome icon HTML class](http://fontawesome.io/icons/).
31 | * **tags:** tags will be visible to users who aren't authenticated (we assume these users are people at nonprofits)
32 | * **status:** choose between `'dev'` and `'prod'`. Projects in `'dev'` won't be displayed to nonprofits (unauthenticated users).
33 |
34 | Please be paitient and while GitHub updates the directory - it will take a few minutes before the changes are reflected.
35 |
36 |
37 | ## Installation
38 |
39 | Make sure you have installed a recent version of [NodeJS](https://nodejs.org/) and **npm**.
40 |
41 | Open the folder you wish to install the project in using your terminal, and run:
42 |
43 | `git clone https://github.com/freeCodeCamp/open-source-for-good-directory`
44 |
45 | `cd` into the `open-source-for-good-directory` project that command created, then run `npm i` to install all the project dependencies.
46 |
47 | You'll need symbolic links inside the `public` folder that point to the corresponding `docs/[project-name]` directory. The bash script in the root of this repo. We've created a script to automate this process. Make sure the script is executable by running: `chmod +x .setup-symlinks.sh`. Then run `./.setup-symlinks.sh`.
48 |
49 | For Windows users wanting to use the script, you'll probably need the [Linux Subsystem](https://msdn.microsoft.com/en-us/commandline/wsl/about). We haven't tested this, so if you get this working, let us know how you did so, and we can add those steps to this guide.
50 |
51 | This directory is built using [Create React App](https://github.com/facebookincubator/create-react-app), so you can look for more info there if you run into trouble.
52 |
53 | To deploy the directory, run `yarn build` or `npm run build`. Then commit the changes to Github.
54 |
55 | ## Server
56 | The directory depends on a remote server to perform an automated webpage build for each project that requires it. The server works in the following way:
57 |
58 | 1. A Github WebHook registers push events for all the freeCodeCamp repos. It sends a POST request (URL/event) to a server hosted in Glitch.com (Specified on the WebHook configuration)
59 | 1. If there is an update to the configuration file `.osfg-dir-config.js`, it downloads the file and builds an HTML file.
60 | 1. The file is pushed to **this repo** inside the `docs` folder.
61 | 1. Everything inside the `docs` folder is automatically deployed to GitHub Pages, which in turn are linked to the directory's website.
62 |
63 | You can find the code for the server in [this repository](https://github.com/freeCodeCamp/osfg-dir-server)
64 |
65 | ### License
66 |
67 | This computer software is licensed under the open source [BSD-3-Clause](https://github.com/freeCodeCamp/open-source-for-good-directory/blob/master/LICENSE.md).
68 |
69 | Copyright (c) 2017, [freeCodeCamp](https://www.freecodecamp.org).
70 |
--------------------------------------------------------------------------------
/docs/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "main.css": "static/css/main.0515109c.css",
3 | "main.css.map": "static/css/main.0515109c.css.map",
4 | "main.js": "static/js/main.d4eb4b9c.js",
5 | "main.js.map": "static/js/main.d4eb4b9c.js.map"
6 | }
--------------------------------------------------------------------------------
/docs/conference-for-good/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Conference for Good
12 |
13 |
14 |
This is a free, open-source web application designed to help sports leagues track their player and team stats, and simplify the other day-to-day tasks involved with team management. It was designed to accommodate many popular sports.
An app for sending millions of emails as cheaply as possible. Mail for Good uses AWS Simple Email Service to send bulk emails at $0.10 per 1000 emails.
24 |
Mail for Good is fast and memory efficient, currently sending over 100 emails per second on a 1gb Digital Ocean VPS.
25 |
We've used Mail for Good to deliver newsletters to hundreds of thousands of campers per week.
Create templates to reuse for convenience when sending email campaigns.
47 |
Track bounce rate and other standard metrics. You can also insert tracking pixels and unsubcribe links a click of a button.
48 |
Add custom fields to imported email lists such as names or cities.
49 |
Grant other users (limited or otherwise) permissions to use your account on your behalf.
50 |
Add embedded HTML newsletter sign up forms to your site. These are snippets of code that will let your users sign up with you at the click of a button.
51 |
52 |
Performance
53 |
We're currently sending weekly email blasts of over 700,000 emails in 3-4 hours on a $10 per month Digital Ocean VPS with 1gb memory and 1 core processor.
54 |
Mail for Good is fast and scales to the rate limit enforced by AWS.
55 |
Why are we doing this?
56 |
We want to help nonprofits manage their email campaigns as inexpensively as possible, and have full control over their data.
57 |
License
58 |
This computer software is licensed under the Open Source BSD-3-Clause.
An app for sending millions of emails as cheaply as possible. Mail for Good uses AWS Simple Email Service to send bulk emails at $0.10 per 1000 emails.
25 |
Mail for Good is fast and memory efficient, currently sending over 100 emails per second on a 1gb Digital Ocean VPS.
26 |
We've used Mail for Good to deliver newsletters to hundreds of thousands of campers per week.
Create templates to reuse for convenience when sending email campaigns.
52 |
Track bounce rate and other standard metrics. You can also insert tracking pixels and unsubcribe links a click of a button.
53 |
Add custom fields to imported email lists such as names or cities.
54 |
Grant other users (limited or otherwise) permissions to use your account on your behalf.
55 |
Add embedded HTML newsletter sign up forms to your site. These are snippets of code that will let your users sign up with you at the click of a button.
56 |
57 |
Performance
58 |
We're currently sending weekly email blasts of over 700,000 emails in 3-4 hours on a $10 per month Digital Ocean VPS with 1gb memory and 1 core processor.
59 |
Mail for Good is fast and scales to the rate limit enforced by AWS.
60 |
Why are we doing this?
61 |
We want to help nonprofits manage their email campaigns as inexpensively as possible, and have full control over their data.
62 |
License
63 |
This computer software is licensed under the Open Source BSD-3-Clause.
17 | With Free Code Camp's valuable contribution, we were able to
18 | improve all of our systems and processes as part of our Wonder Women
19 | Eastern Indonesia program, and make sure that even more life changing
20 | technologies get to where they are needed most.
21 |
22 |
23 | Ewa Wojkowska - Kopernik
24 |
25 |
26 |
27 |
31 |
32 | We have been blown away by the professional quality of the work that
33 | has been produced by the campers working on our projects. Free Code
34 | Camp has been an invaluable partner and we are grateful for their
35 | support.
36 |
37 |
38 | Jennifer McDowell - Child First Authority
39 |
40 |
41 |
42 |
46 |
47 | We had the pleasure to work with two very talented campers who went
48 | above and beyond to create a web-based app for us. I would highly
49 | recommend that nonprofits apply to Free Code Camp with their custom
50 | solution needs!
51 |