Skip to content

Commit d941d46

Browse files
committed
Update docs, add blog post
1 parent 01c0be1 commit d941d46

10 files changed

+106
-199
lines changed

blog/2019-05-28-hola.md

-11
This file was deleted.

blog/2019-05-29-hello-world.md

-17
This file was deleted.

blog/2019-05-30-welcome.md

-13
This file was deleted.
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
slug: why-codeamigo
3+
title: Why I Created Codeamigo
4+
author: Philip London
5+
author_title: Founder @ codeamigo.dev
6+
author_url: https://github.com/plondon
7+
author_image_url: https://avatars.githubusercontent.com/u/5640772?v=4
8+
tags: [codeamigo, about, education]
9+
---
10+
11+
I've applied to work at [Codecademy](https://www.codecademy.com/) three times, once in 2014, again in 2015, and most recently in 2020. I've been rejected all three times. A few weeks after the most recent rejection I decided to build my own version of Codecademy. I was living in Spain so I thought codeamigo would be a good name. Here's why I created [codeamigo.dev](https://codeamigo.dev) and what I've learned so far.
12+
13+
I love the interactive learning experience of Codecademy. Of all the mediums I've used to learn how to code, YouTube, blog posts, tutorials, etc., Codecademy always stood out. I loved feeling a sense of accomplishment after finishing a step or lesson, or reaching my streak goal for the week. When I was first learning to code, I visited Codecademy everyday. I wouldn't be a developer without it.
14+
15+
What _bothered_ me about the platform was that I didn't know my teachers. I wanted to connect with members of my community and learn from them, instead of just digesting information from a black box. Watching [MKBHD](https://www.youtube.com/user/marquesbrownlee) on YouTube made this clear. I don't watch everyone of his videos because I'm interested in each and every piece of tech, I'm interested in him, and how he presents his material.
16+
17+
I thought if I could bring that concept to coding lessons and tutorials people would be able to learn from and follow peers they liked learning from. Building the platform was a lot of fun and quite challenging.
18+
19+
## Compiling Code on The Fly
20+
21+
Without a doubt the most challenging aspect of building codeamigo.dev was the code compilation. There are not a ton of examples of it in the wild. In fact, [Amjad Masad](https://twitter.com/amasad), who built repl.it, also wrote the code for Codecademy. Anyway, I decided to start with just languages the browser can understand natively, so HTML, CSS, and JS. [Ives Van Hoorne](https://twitter.com/compuives) and the [codesandbox](https://codesandbox.io) team were a great inspiration.
22+
23+
### Attempt 1: babel-standalone
24+
25+
Based on talks given by Ives I figued that [babel-standalone](https://babeljs.io/docs/en/babel-standalone) would be a good first step. Everytime a file changed I would post a message to an iframe that was listening for files, transpile them with babel, and then append the generated output to a script tag. I had special logic for if the file was HTML or CSS. It was very primitive, messy, and slow. I was happy it worked but it would sometimes take 5-6 seconds to render a change.
26+
27+
### Attempt 2: parcel
28+
29+
After scouring the internet for other solutions I came across [parcel](https://github.com/parcel-bundler/parcel/issues/1253) and thought this might be a good approach. In fact, they even had their own [REPL project](https://parcel-repl.vercel.app/) that mirrored the functionality I wanted. This worked well for awhile and was what the project was using when I posted it to [Hacker News originally](https://news.ycombinator.com/item?id=26464998). However, it would often use too many webworkers and cause the site to crash. Plus, I knew it wouldn't be able to scale past browser based languages.
30+
31+
### Attempt 3: repl.it approach
32+
33+
Next up I tried [recreating repl.it's approach](https://cloud.google.com/customers/repl-it). But it thoguht it would be too complex of an endeavor considering I have yet to find product-market-fit.
34+
35+
### Attempt 4: Codesandbox To the Rescue!
36+
37+
A few months ago, codesandbox released [sandpack](https://github.com/codesandbox/sandpack), which is exactly what I was looking for. A super fast, super scalable browser bundler. I would still like to dive deeper into Attempt 3, but only once I have more users and interest.
38+
39+
## Learning New Tools
40+
41+
I've loved the process of recreating Codecademy. I've loved owning all aspects of the project, the backend, frontend, and design, I've been able to implement features quickly and deploy them easily and automatically through [vercel](https://vercel.com). I've gotten to use and love [linear](https://linear.app) for issue management and [plausible](https://plausible.io/) for analytics.
42+
43+
### Backend
44+
45+
codeamigo.dev's backend uses NodeJS to serve an Apollo Server GraphQL API. Everytime you take a lesson, the backend creates codeModules specific to your user, so that it can save your progress. Of course it also tracks what step you are on and which checkpoints you've completed. When and if you decide to create a lesson, codeamigo will provide you with templates to get you started on React.js, Angular, or VanillaJS/TS projects.
46+
47+
### Frontend
48+
49+
The frontend is a NextJS app using apollo-client to manage state and tailwindcss for styling.
50+
51+
### How It Works
52+
53+
codeamigo.dev provides you with a platform to create Codecademy style lessons. Each lesson is made up of Steps, and each Step is made up of Checkpoints. A Step can have many or no Checkpoints. Each Checkpoint points to a test you must write that a user must pass. You can read more about testing [here](https://docs.codeamigo.dev/docs/).
54+
I hope that this project helps people learn new topics, either through teaching them or taking lessons!

docs/writing-tests/angular.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Be sure to add `@testing-library/angular: 10.9.0` to package.json
2+
3+
### Test a component is rendered
4+
5+
```ts
6+
import { TestBed } from "@angular/core/testing";
7+
import { render, screen, fireEvent } from "@testing-library/angular";
8+
import { CounterComponent } from "./counter.component";
9+
import {
10+
BrowserDynamicTestingModule,
11+
platformBrowserDynamicTesting
12+
} from "@angular/platform-browser-dynamic/testing";
13+
14+
describe("Counter", () => {
15+
beforeEach(() => {
16+
TestBed.resetTestEnvironment(); // new
17+
TestBed.initTestEnvironment(
18+
BrowserDynamicTestingModule,
19+
platformBrowserDynamicTesting()
20+
);
21+
22+
TestBed.configureTestingModule({
23+
declarations: [CounterComponent]
24+
}).compileComponents();
25+
});
26+
27+
it("should render counter", async () => {
28+
await render(CounterComponent, {
29+
componentProperties: { counter: 5 }
30+
});
31+
32+
expect(screen.getByText("Current Count: 5")).toBeDefined();
33+
});
34+
});
35+
36+
```

docs/writing-tests.md docs/writing-tests/react.md

-44
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
---
2-
title: Writing Tests
3-
---
4-
5-
## React
61
Be sure to add `@testing-library/react: 12.0.0` to package.json
72

83
### Check that the textContent is correct
@@ -77,43 +72,4 @@ describe('Board, handleClick', () => {
7772
expect(getByText('X')).toBeDefined()
7873
})
7974
})
80-
```
81-
82-
## Angular
83-
84-
Be sure to add `@testing-library/angular: 10.9.0` to package.json
85-
86-
### Test a component is rendered
87-
88-
```ts
89-
import { TestBed } from "@angular/core/testing";
90-
import { render, screen, fireEvent } from "@testing-library/angular";
91-
import { CounterComponent } from "./counter.component";
92-
import {
93-
BrowserDynamicTestingModule,
94-
platformBrowserDynamicTesting
95-
} from "@angular/platform-browser-dynamic/testing";
96-
97-
describe("Counter", () => {
98-
beforeEach(() => {
99-
TestBed.resetTestEnvironment(); // new
100-
TestBed.initTestEnvironment(
101-
BrowserDynamicTestingModule,
102-
platformBrowserDynamicTesting()
103-
);
104-
105-
TestBed.configureTestingModule({
106-
declarations: [CounterComponent]
107-
}).compileComponents();
108-
});
109-
110-
it("should render counter", async () => {
111-
await render(CounterComponent, {
112-
componentProperties: { counter: 5 }
113-
});
114-
115-
expect(screen.getByText("Current Count: 5")).toBeDefined();
116-
});
117-
});
118-
11975
```

docusaurus.config.js

+10-14
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ module.exports = {
1414
title: 'codeamigo',
1515
logo: {
1616
alt: 'codeamigo Logo',
17-
src: 'img/logo.svg',
17+
src: 'img/logo.png',
1818
},
1919
items: [
2020
{
21-
to: 'docs/',
21+
to: 'docs/writing-tests/react',
2222
activeBasePath: 'docs',
2323
label: 'Docs',
2424
position: 'left',
@@ -38,30 +38,26 @@ module.exports = {
3838
title: 'Docs',
3939
items: [
4040
{
41-
label: 'Getting Started',
42-
to: 'docs/',
41+
label: 'Writing Tests',
42+
to: 'docs/writing-tests/react',
4343
},
4444
],
4545
},
4646
{
4747
title: 'Community',
4848
items: [
49-
{
50-
label: 'Stack Overflow',
51-
href: 'https://stackoverflow.com/questions/tagged/docusaurus',
52-
},
53-
{
54-
label: 'Discord',
55-
href: 'https://discordapp.com/invite/docusaurus',
56-
},
5749
{
5850
label: 'Twitter',
59-
href: 'https://twitter.com/docusaurus',
51+
href: 'https://twitter.com/codeamigo_dev',
6052
},
53+
{
54+
label: 'GitHub',
55+
href: 'https://github.com/codeamigo'
56+
}
6157
],
6258
},
6359
],
64-
copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`,
60+
copyright: `Copyright © ${new Date().getFullYear()} codeamigo LLC, Built with Docusaurus.`,
6561
},
6662
},
6763
presets: [

sidebars.js

+3-8
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@ module.exports = {
22
docs: [
33
{
44
type: 'category',
5-
label: 'Codeamigo Docs',
5+
label: 'Writing Tests',
66
items: [
7-
'writing-tests',
7+
'writing-tests/react',
8+
'writing-tests/angular',
89
],
910
},
1011
{
1112
type: 'category',
1213
label: 'Docusaurus Tutorial',
1314
items: [
14-
'getting-started',
15-
'create-a-page',
16-
'create-a-document',
17-
'create-a-blog-post',
18-
'markdown-features',
19-
'thank-you',
2015
],
2116
},
2217
],

src/pages/index.js

+3-92
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,6 @@
11
import React from 'react';
2-
import clsx from 'clsx';
3-
import Layout from '@theme/Layout';
4-
import Link from '@docusaurus/Link';
5-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
6-
import useBaseUrl from '@docusaurus/useBaseUrl';
7-
import styles from './styles.module.css';
8-
9-
const features = [
10-
{
11-
title: 'Easy to Use',
12-
imageUrl: 'img/undraw_docusaurus_mountain.svg',
13-
description: (
14-
<>
15-
Docusaurus was designed from the ground up to be easily installed and
16-
used to get your website up and running quickly.
17-
</>
18-
),
19-
},
20-
{
21-
title: 'Focus on What Matters',
22-
imageUrl: 'img/undraw_docusaurus_tree.svg',
23-
description: (
24-
<>
25-
Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
26-
ahead and move your docs into the <code>docs</code> directory.
27-
</>
28-
),
29-
},
30-
{
31-
title: 'Powered by React',
32-
imageUrl: 'img/undraw_docusaurus_react.svg',
33-
description: (
34-
<>
35-
Extend or customize your website layout by reusing React. Docusaurus can
36-
be extended while reusing the same header and footer.
37-
</>
38-
),
39-
},
40-
];
41-
42-
function Feature({imageUrl, title, description}) {
43-
const imgUrl = useBaseUrl(imageUrl);
44-
return (
45-
<div className={clsx('col col--4', styles.feature)}>
46-
{imgUrl && (
47-
<div className="text--center">
48-
<img className={styles.featureImage} src={imgUrl} alt={title} />
49-
</div>
50-
)}
51-
<h3>{title}</h3>
52-
<p>{description}</p>
53-
</div>
54-
);
55-
}
2+
import { Redirect } from 'react-router-dom';
563

574
export default function Home() {
58-
const context = useDocusaurusContext();
59-
const {siteConfig = {}} = context;
60-
return (
61-
<Layout
62-
title={`Hello from ${siteConfig.title}`}
63-
description="Description will go into a meta tag in <head />">
64-
<header className={clsx('hero hero--primary', styles.heroBanner)}>
65-
<div className="container">
66-
<h1 className="hero__title">{siteConfig.title}</h1>
67-
<p className="hero__subtitle">{siteConfig.tagline}</p>
68-
<div className={styles.buttons}>
69-
<Link
70-
className={clsx(
71-
'button button--outline button--secondary button--lg',
72-
styles.getStarted,
73-
)}
74-
to={useBaseUrl('docs/')}>
75-
Get Started
76-
</Link>
77-
</div>
78-
</div>
79-
</header>
80-
<main>
81-
{features && features.length > 0 && (
82-
<section className={styles.features}>
83-
<div className="container">
84-
<div className="row">
85-
{features.map((props, idx) => (
86-
<Feature key={idx} {...props} />
87-
))}
88-
</div>
89-
</div>
90-
</section>
91-
)}
92-
</main>
93-
</Layout>
94-
);
95-
}
5+
return <Redirect to='/docs/writing-tests/react' />;
6+
}

static/img/logo.png

14.6 KB
Loading

0 commit comments

Comments
 (0)