]>
Commit | Line | Data |
---|---|---|
cce07b52 BB |
1 | # Problem |
2 | ||
3 | Feed reader users should be able to subscribe to the blog | |
4 | ||
5 | # Background | |
6 | ||
7 | As of this writing, the blog is served as HTML which is appropriate for | |
8 | web browsers but maybe not for other mechanisms like feed readers. | |
9 | ||
10 | Feed readers have different formats that they support: | |
11 | * h-feed is a microformat built into the page | |
12 | * rss and atom are XML based publishing formats | |
13 | * JSON feed is a JSON based publishing format | |
14 | * rss 3.0 is a text based pblishing format :P | |
15 | ||
16 | Currently the blog contains a single generator function that copies | |
17 | assets and generates HTML out of markdown files. This is good enough for | |
18 | the current setup, but if it were to generate more it would get messy | |
19 | real quick. | |
20 | ||
21 | Given the constraints listed below, some formats are not recommended: | |
22 | * RSS 3.0 is not a good candidate at the moment as it would require | |
23 | us to parse the markdown to extract the title. | |
24 | * Atom would work, however, given the requirement for an id, title, and | |
25 | date this would require more effort than a more lenient format. | |
26 | * RSS 2.0 fits the constraints as we wouldn't need to specify anything | |
27 | for the item. | |
28 | * JSON Feed would work, however given the requirement for an id, thtis | |
29 | would require more effort than a more lenient format. | |
30 | ||
31 | It is unclear whether the current constraints are good enough for feed | |
32 | readers. If this causes issues, it's likely we will have to include date, | |
33 | id or title as required in the other formats. | |
34 | ||
35 | After reviewing the functionality of existing readers, it has been found | |
36 | that an id and publication date would be needed for readers to behave | |
37 | correctly. This means that ATOM and JSON Feed would be equally valid | |
38 | as solutions than RSS 2.0 | |
39 | ||
40 | The current generator function depends on knowing a source for the post | |
41 | being generated, and a target on where the assets will be placed. | |
42 | ||
43 | # Hypothesis | |
44 | ||
45 | Given we serve the blog in a feed reader friendly format, users will be able to subscribe. | |
46 | ||
47 | # Test of Hypothesis | |
48 | ||
49 | Given I add the blog to a feed reader service like Reeder or Feedly, I will be able to see the entries. | |
50 | Given I add a new entry to the blog, the entries will be updated. | |
51 | ||
52 | # Assumptions | |
53 | ||
54 | * We can generate a valid feed with just the entries themselves and the existing | |
55 | blog data. | |
56 | * We can: Validated by generating an example file. | |
57 | * Including just a list of items with the whole content is good enough for | |
58 | feed readers. | |
59 | * We can't: It seems like we'll require at least a guid. The old reader | |
60 | behaves correctly with just the guid. It's unclear whether feedly | |
61 | does since it has caching. Will leave grok running. | |
62 | * It isn't required to link back, and we can include the whole text. | |
63 | * This is correct, however it might make sense to just link to the | |
64 | blog itself. | |
65 | ||
66 | # Constraints | |
67 | ||
68 | * We won't be parsing the markdown to generate feed items. | |
69 | * We won't be adding any sort of frontmatter to the entries. | |
70 | * The blog will remain ephemeral, and we won't introduce permalinks. | |
71 | * We won't have configurable templating or options to add/remove | |
72 | output types. | |
73 | ||
74 | # Solution Proposal | |
75 | ||
ae442b8f BB |
76 | We will add a new step in the creation process to create metadata for the |
77 | post that will allow each post to be uniquely identified, as well as | |
78 | having a publish date related to them. | |
cce07b52 BB |
79 | |
80 | We will split the current generator function into generators, and create | |
81 | a new generator that will generate an RSS 2.0 file | |
82 | ||
83 | # Blackbox | |
84 | ||
85 | ``` | |
ae442b8f BB |
86 | ╔══════════════════════╗ |
87 | ║ When Adding a Post ║ | |
88 | ╚══════════════════════╝ | |
89 | ┌───────────────┐ ┌───────────────┐ | |
90 | │ │ │ │ | |
91 | ┌────────────────▶│ writeMetadata │─────────▶│ Metadata File │ | |
92 | │ │ │ │ │ | |
93 | │ └───────────────┘ └───────────────┘ | |
94 | │ | |
95 | │ | |
96 | │ ╔════════════════════════╗ | |
97 | │ ║ When Generating Output ║ | |
98 | │ ╚════════════════════════╝ | |
99 | │ ┌─────────────────┐ ┌───────────────┐ | |
100 | │ │ │ │ │ | |
101 | │ ┌─────▶│ StaticGenerator │───────▶│ Static Assets │ | |
102 | │ │ │ │ │ │ | |
103 | │ │ └─────────────────┘ └───────────────┘ | |
104 | ┌───────┐ │ ┌───────────────┐ ┌───────────┐ | |
105 | │ │ │ │ │ │ │ | |
106 | │ Blog │──────┼─────▶│ HTMLGenerator │─────────▶│ HTML File │ | |
107 | │ │ │ │ │ │ │ | |
108 | └───────┘ │ └───────────────┘ └───────────┘ | |
109 | │ ┌──────────────┐ ┌──────────┐ | |
110 | │ │ │ │ │ | |
111 | └─────▶│ RSSGenerator │──────────▶│ RSS File │ | |
112 | │ │ │ │ | |
113 | └──────────────┘ └──────────┘ | |
cce07b52 BB |
114 | ``` |
115 | ||
116 | # Theory of Operation | |
117 | ||
ae442b8f BB |
118 | ## When Adding a Post |
119 | ||
120 | When the add function of the blog is triggered, it will shift the posts | |
d2dd1134 | 121 | as it currently does and then will generate a new unique ID and take the |
ae442b8f BB |
122 | current timestamp. This will be saved in a JSON file in the output |
123 | directory called "metadata.json" | |
124 | ||
125 | ## When Generating Output | |
126 | ||
127 | When the generate function of the blog is triggered, it will iterate | |
128 | over every post. For each of them it will parse the markdown content, | |
129 | and the metadata, creating an object of type `tPost` and pushing it | |
130 | to an array. | |
131 | ||
132 | Next, it will iterate from a list of generator functions and call them | |
133 | with the source and target directories, and an array containing the `tPost` | |
134 | objects. Each generator function will do its work, throwing an exception | |
135 | if they encounter an error. | |
cce07b52 BB |
136 | |
137 | When the static generator is called, it will remove the current assets | |
138 | directory in the target directory, and recursively copy the assets from | |
139 | the source directory. | |
140 | ||
141 | When the HTML generator is called, it will parse an `html` template, using | |
142 | the posts as the context, and will place the resulting file in the target | |
143 | directory. | |
144 | ||
145 | When the RSS generator is called, it will parse an `rss` template, using | |
146 | the posts as the context, and will place the resulting file in the target | |
147 | directory. | |
148 | ||
149 | # Technical Specification | |
150 | ||
ae442b8f BB |
151 | ## The Post Data Structure |
152 | ||
153 | This spec introduces a data structure to help generate output. | |
154 | ||
155 | ``` | |
156 | tPost <Object> | |
157 | +html <String> // The markup of the post | |
158 | +publishedOn <Number> // The timestamp when this post was added | |
d2dd1134 | 159 | +id <String> // The Unique ID for this post |
ae442b8f BB |
160 | ``` |
161 | ||
d2dd1134 BB |
162 | Given that posts won't come in at a high enough rate, and that the |
163 | purpouse is only to help feed readers identify each unique piece of | |
164 | content, for this version the `id` will be the same number as the | |
165 | `publishedOn`. | |
166 | ||
cce07b52 BB |
167 | ## The Generator Interface |
168 | ||
169 | Every generator must implement this interface in order to work with | |
170 | Blog. | |
171 | ||
172 | * Generators MUST be a function | |
173 | * Generators SHOULD read the source, destination, and posts parameters to | |
174 | write files. | |
175 | * Generators MUST NOT write anything into the source directory | |
176 | * Generators MUST return a promise | |
177 | * Generators SHOULD NOT resolve the promise with any information, as it will | |
178 | be discarded | |
179 | * Generators MUST throw exceptions if they encounter an unrecoverable error | |
180 | ||
181 | ``` | |
182 | IGenerator(source<String>, destination<String>, posts<Array<String>>) => Promise | |
183 | ``` | |
184 | ||
185 | ## New Generators | |
186 | ||
187 | ### Static Generator | |
188 | ||
189 | This generator will have the logic to move static assets around. It will | |
190 | re-use the current asset logic in the `#_generate` method in Blog. | |
191 | ||
192 | ``` | |
193 | StaticGenerator <IGenerator> | |
194 | ``` | |
195 | ||
196 | ### HTML Generator | |
197 | ||
198 | This generator will have the logic to generate an HTML file. It will | |
199 | re-use the current HTML logic in the `#_generate` method in Blog. | |
200 | ||
201 | ``` | |
202 | HTMLGenerator <IGenerator> | |
203 | ``` | |
204 | ||
205 | ### RSS Generator | |
206 | ||
207 | This generator will have the logic to generate an RSS file. It will | |
208 | re-use the current HTML logic in the `#_generate` method in Blog, | |
209 | however, instead of using the `index.html` template it will use a | |
210 | `feed.xml` template that generates a valid RSS 2.0 feed document. | |
211 | ||
212 | ``` | |
213 | RSSGenerator <IGenerator> | |
214 | ``` | |
215 | ||
216 | ## Modifications to existing parts of the code | |
217 | ||
218 | The `#_generate` function will be modified so it will now parse the | |
219 | post markdown, and then iterate over the generators, calling them | |
220 | so they create the appropriatet files. | |
221 | ||
222 | ## Important Metrics | |
223 | ||
224 | Given we're only processing 3 blog posts, and this is a compile time | |
225 | activity and not runtime, there are no recommended metrics in terms | |
226 | of file throughput performance or runtime performance. | |
227 | ||
228 | This should change if this would ever handle a higher volume, or would | |
229 | be expected to run this process runtime. | |
230 | ||
231 | ## Furhter Improvements | |
232 | ||
233 | It's recommended to eventually put more effort in assigning a unique ID | |
234 | to each post so we can use more feed formats. | |
235 | ||
236 | For more compatibility and future proofing, the same solution for | |
237 | RSS could be used to generate other feed formats, just adding | |
238 | a new generator | |
239 | ||
240 | This same solution could be extended to serve the blog in different formats | |
241 | (eg. a .txt that is easy to read in terminals) |