{"id":10647,"date":"2026-09-22T16:15:06","date_gmt":"2026-09-22T16:15:06","guid":{"rendered":"https:\/\/djangostars.com\/blog\/?p=10647"},"modified":"2026-09-22T16:25:17","modified_gmt":"2026-09-22T16:25:17","slug":"web-data-portal-development","status":"publish","type":"post","link":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/","title":{"rendered":"From Folders of Spreadsheets to a Web Data Portal"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">Someone asks your team for a subset of your data. A particular region, a particular set of years, a particular set of measurements.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The request is reasonable. The data exists. But answering it means opening several files, remembering which version is current, checking whether those particular records can be shared, filtering by hand, and sending back a spreadsheet. It takes forty minutes if the person doing it knows the data well.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">And it is always the same person.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Somewhere else, in a different kind of organization, a quarterly report is being assembled. The monitoring data goes back eight years. Every quarter, someone pulls the numbers together by hand, and every quarter it is built from scratch, because last time&#8217;s version does not fit this time&#8217;s question.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is the same problem. Not missing data, and not bad data. Data that exists is valuable and is reachable only by going through a human being.<\/span><\/p>\n<p><b>A note on why I am writing this.<\/b><span style=\"font-weight: 400;\"> I should say where I am standing while I write this. I did a PhD in economics before I moved into software, and I spent a lot of it on the wrong side of this exact problem\u2014pulling figures out of Excel files exported from several different platforms, none of which agreed on how a field should be named or what a missing value meant. The analysis was the small part. Getting the data into a state where analysis was possible was most of the work, and it was work nobody counted, funded, or saw.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I am now building out this direction at DjangoStars\u2014data platforms for research and monitoring organizations\u2014and it is the part of our work I have made my own. That means the conversations before a project exists: working out what a group actually has, what they need it to do, and whether we are the right people for it at all. The platforms described further down are the work of our engineers rather than mine. My contribution is the problem, not the code: understanding it precisely enough that what gets built answers the real question instead of the one that was easiest to write into a brief.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I talk to universities, research institutes, and organizations across Switzerland, Germany, Austria, and the Nordics about this every week, and what surprised me is how little it varies. Different countries, different disciplines, very different budgets\u2014the same folder of spreadsheets, and the same one person who knows where things are. Often the honest answer is that a group does not need a platform at all, and the sections below on when not to build one come out of those conversations as much as out of the ones that became projects.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Why every data request lands on the same person<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">If your organization has been collecting data for more than a few years, you probably recognize some version of this:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">One person knows where everything is and how the older files differ from the newer ones. When they are on leave, data requests wait.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">People outside your team ask for data by email\u2014researchers, partners, journalists, and member organizations. Every request is handled manually.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The same figures get reassembled by hand for each report, each funder update, and each quarter.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Data collected under a project that ended is technically still on a server and practically gone. Nobody remembers the naming convention.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">You cannot open the data publicly, because some of it is restricted, and separating the two would take work nobody has budgeted for.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">The work you have done is real and almost invisible to anyone who was not in the room.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">The common thread is not technical debt. Access to your data is mediated by a person, and that person&#8217;s time is finite. Every additional user worsens the bottleneck, which quietly creates a reason not to promote the data at all.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Evidence suggests this ends badly if left alone. <a href=\"https:\/\/pubmed.ncbi.nlm.nih.gov\/24361065\/\">A study<\/a> of 516 datasets from papers published over two decades found that the odds of a dataset still being available fell by roughly 17% per year after publication. Data kept by individuals often becomes unreachable as hardware, formats, and staff change. The same decay applies to any dataset whose custody depends on one person remembering. Separately, <a href=\"https:\/\/www.splunk.com\/en_us\/form\/the-state-of-dark-data.html\">Splunk&#8217;s<\/a> survey of over 1,300 business and IT leaders found that 55% of an organization&#8217;s data is &#8220;dark&#8221;\u2014data they either do not know exists or cannot find, prepare, or use.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What this looks like across different kinds of organizations<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">We have had versions of this conversation with teams in many different places, and the striking thing is how little the sector changes the story.<\/span><\/p>\n<h4><b>Universities and research centers<\/b><span style=\"font-weight: 400;\">\u00a0<\/span><\/h4>\n<p><span style=\"font-weight: 400;\">Years of measurements across projects and field campaigns, held in folders that follow a naming convention someone invented in 2014. External researchers ask for slices of it. A funder asks what the impact was.<\/span><\/p>\n<h4><b>NGOs and monitoring agencies<\/b><span style=\"font-weight: 400;\">\u00a0<\/span><\/h4>\n<p><span style=\"font-weight: 400;\">Program and monitoring data going back a decade, collected by field teams on forms that changed twice along the way. Quarterly reporting is a manual assembly job. The impact is real and almost impossible to show to a donor without a week of preparation.<\/span><\/p>\n<h4><b>Energy and utilities<\/b><span style=\"font-weight: 400;\">\u00a0<\/span><\/h4>\n<p><span style=\"font-weight: 400;\">Asset registers, inspection records, meter and consumption histories, often spread across a GIS layer, a maintenance system, and a set of spreadsheets that reconcile the two. Long asset lifetimes mean the historical series is genuinely valuable and genuinely awkward\u2014formats and standards changed several times across it.<\/span><\/p>\n<h4><strong>Logistics operators and freight brokers<\/strong><\/h4>\n<p><span style=\"font-weight: 400;\">Years of shipments, routes, lanes, carrier performance, and rates. Analysts build the same lane performance and seasonality views over and over, and the forecasting model lives in a workbook one person maintains while everyone else waits.<\/span><\/p>\n<p><b>Public bodies, environmental agencies, port and water authorities, industry associations, archives, and museums.<\/b><span style=\"font-weight: 400;\"> Same pattern again: a long series, a mandate to make it available, and a bottleneck made of one person&#8217;s time.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The details differ. The shape does not:<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10646\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2.png\" alt=\"\" width=\"1440\" height=\"1132\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2-300x236.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2-1024x805.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2-768x604.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-2-191x150.png 191w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">There is a reason to take the spreadsheet layer seriously rather than treating it as a harmless interim step. Field audits of operational spreadsheets have consistently found errors in the vast majority of those examined\u2014in the most methodologically careful audits, at least 86%. <\/span><a href=\"https:\/\/arxiv.org\/pdf\/0804.0941\"><span style=\"font-weight: 400;\">The finding<\/span><\/a><span style=\"font-weight: 400;\"> worth sitting with is the confidence gap. When developers were asked to estimate the probability that their own spreadsheet contained an error, the average estimate was 18%, while the actual rate in the same group was 86% .<sup><a id=\"ref1\" href=\"#fn1\">1<\/a><\/sup> <\/span><span style=\"font-weight: 400;\"> The problem is not that people are careless with spreadsheets. It is that nobody, including the author, can tell by looking.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">That is the argument for moving the calculation into a tested, version-controlled system, and it holds whether the output is a public data portal or an internal view for six analysts.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">This is for you if you have said any of these out loud<\/span><\/h2>\n<p><b>From universities and research centers:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;We have fifteen years of measurements. They are in a few hundred Excel files, and one person on the team can actually find things in them.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;Outside researchers email us for data. Every request gets handled by hand, and it eats the week.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;We collected data nobody else has. It is barely cited. The next funder will ask what the impact was, and I do not have a good answer.&#8221;<\/span><\/p>\n<p><b>From NGOs and monitoring organizations:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;We have eight years of monitoring data. It sits in tables, and nobody outside the team ever sees it.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;Every quarter we build the donor report from scratch. It takes four days, and it is the same four days each time.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;The impact is real. Showing it to a funder takes a week of preparation, so mostly we do not show it.&#8221;<\/span><\/p>\n<p><b>From energy and utilities:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;The asset history lives in three systems plus a spreadsheet that reconciles them, and the reconciliation is manual.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;We have twenty years of inspection records. The recording format changed twice. Nobody is confident the old ones are comparable to the new ones.&#8221;<\/span><\/p>\n<p><b>From logistics operators and freight brokers:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;Our analysts rebuild the same lane performance view every month.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;The forecasting model is a workbook. One person maintains it, and everyone else waits for him.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;Carriers ask us for their own performance numbers, and we pull them by hand, one at a time.&#8221;<\/span><\/p>\n<p><b>From public bodies and archives:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;We are required to make this available. In practice &#8216;available&#8217; means people email us and we send them a file.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">&#8220;Someone built a good internal tool for this once. They left.&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If one of these is a sentence you have said out loud, the rest of this article is about what to do with it\u2014including the parts most vendors will not tell you.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If none of them are, you may not have this problem yet, and a section below explains when building a portal is the wrong move.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Do you actually need a data portal?<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">It\u2019s worth being honest, because the answer is sometimes no. You probably do have it if:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">More than two or three groups outside your team want your data.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Requests arrive in a form you cannot automate: different regions, different variables, and different time windows each time.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Your data comes from multiple collection efforts, and the structures do not match.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Some records are restricted and some are open, and the distinction currently lives in someone&#8217;s head or in a column only one person understands.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Data keeps arriving\u2014from collaborators, field teams, and partner organizations\u2014and someone merges it by hand.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reports for funders, boards, or regulators are built from scratch each cycle rather than generated.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">A funder, board, or evaluation has asked what the impact of years of data collection actually was\u2014or your next reporting cycle requires that answer, and producing it means a week of manual work.\u00a0<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">If instead you have one reasonably clean dataset, a stable structure, and a handful of internal users, you do not need a platform. Skip to the section on when not to build one.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The short version:<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10648\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3.png\" alt=\"\" width=\"1440\" height=\"988\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3-300x206.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3-1024x703.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3-768x527.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-3-219x150.png 219w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Two rows are prerequisites, not signals: if nobody will own the data, or the structure still changes monthly, fix that first\u2014no number of rows on the left compensates. For the remaining rows, one on the right does not disqualify you; four or more does.\u00a0<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What is a data portal, and how do dashboards fit into it?<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">A data portal is the whole system: one structured database, plus a website where people filter, view, and export. Dashboards are part of it\u2014the ready-made views that sit alongside the ability to build your own.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The word people usually reach for is &#8220;dashboard,&#8221; and that is a reasonable place to start\u2014most of these platforms end up with dashboards in them. It\u2019s not the whole thing, and scoping the project as only that is where estimates go wrong.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">A dashboard is a set of prepared views: this chart, this map, and this summary kept up to date. Very useful, and often exactly what your internal team wants. But the person who emails you for data wants something a dashboard cannot give them\u2014to define their own subset, check it closely enough to trust it, and take it away in a format their own tools read. A portal does both. The dashboard is the top layer; the querying and export underneath it are what make the dashboard worth maintaining, because they mean the same data serves people whose questions you did not anticipate.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The work decomposes into five layers, and they are not equally hard.<\/span><\/p>\n<ol>\n<li><b> Consolidation.<\/b><span style=\"font-weight: 400;\"> Scattered spreadsheets, tables, and databases merged into one structured, documented model. This is where most of the real effort goes, and where most estimates are wrong.<\/span><\/li>\n<li><b> Access.<\/b><span style=\"font-weight: 400;\"> Users open a web page: no installation, no credentials request, no email to your team.<\/span><\/li>\n<li><b> Querying.<\/b><span style=\"font-weight: 400;\"> Users select the variables they want and set filters: a numeric range, a category, and a flag. They see how many records match before committing, which can confirm whether the query is working as intended.<\/span><\/li>\n<li><b> Visualization, including dashboards.<\/b><span style=\"font-weight: 400;\"> Maps for anything with coordinates, time series for monitoring data, and breakdowns for survey results and indicators\u2014both as prepared dashboard views for recurring questions and as charts users generate from their own selection. The point is not decoration. A coordinate error or a unit inconsistency is invisible in a table of 20,000 rows and obvious on a map.<\/span><\/li>\n<li><b> Export and reporting.<\/b><span style=\"font-weight: 400;\"> The subset leaves in a format the recipient&#8217;s workflow accepts. For research data, that usually means more than CSV: XLSX, a serialized dataframe, a GIS shapefile, and netCDF. For organizations reporting to funders or boards, it more often means a generated report in a fixed template\u2014the same output currently rebuilt by hand every cycle.<\/span><\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10649\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4.png\" alt=\"\" width=\"1440\" height=\"744\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4-300x155.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4-1024x529.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4-768x397.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-4-250x129.png 250w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><i><span style=\"font-weight: 400;\">The five layers are not equally hard. Consolidation is where the cost is.<\/span><\/i><\/p>\n<h2><span style=\"font-weight: 400;\">In plain terms: what goes in and what people get out<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">If the rest of this article is more detail than you need right now, this section is the whole idea.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">You have data. We turn it into one structured database and put a website on top of it. People then find what they need, look at it, and download it\u2014without emailing anyone.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10650\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5.png\" alt=\"\" width=\"1440\" height=\"708\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5-300x148.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5-1024x503.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5-768x378.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-5-250x123.png 250w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><i><span style=\"font-weight: 400;\">The person who used to answer every data request by hand is no longer in the loop.<\/span><\/i><\/p>\n<p><span style=\"font-weight: 400;\">Concretely, here is what &#8220;people find what they need themselves&#8221; means. The examples are from the two platforms described later in this article.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10651\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6.png\" alt=\"\" width=\"1440\" height=\"1828\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6-236x300.png 236w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6-807x1024.png 807w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6-768x975.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6-1210x1536.png 1210w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-6-118x150.png 118w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><b>On download formats,<\/b><span style=\"font-weight: 400;\"> the short answer is: whatever your users actually work in. CSV and Excel always. For anything with coordinates, use a GIS shapefile or GeoJSON. For scientific and climate data, use netCDF. For people working in Python, a ready-made dataframe that removes an entire parsing step on their end. For reporting, a generated PDF or Word document in your own template. Each format is small work individually and awkward to add after the fact, so decide the list early.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Not everything above belongs in every project. A portal for program indicators may need place, time, category, a map, and Excel export, and nothing else. The point of the list is that these are the pieces, and you choose from them.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What is this thing called? A terminology map<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The same project gets a different name depending on who describes it, which is why organisations with identical problems struggle to find each other&#8217;s solutions\u2014and why quotes for the same work arrive with wildly different assumptions attached.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10652\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7.png\" alt=\"\" width=\"1440\" height=\"1960\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7-220x300.png 220w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7-752x1024.png 752w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7-768x1045.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7-1128x1536.png 1128w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-7-110x150.png 110w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Two practical uses for this table.<\/span><\/p>\n<p><b>If you are writing a tender or a brief,<\/b><span style=\"font-weight: 400;\"> the most precise phrase is usually the least fashionable one. &#8220;A web front-end to our existing PostgreSQL database, with a graphical query builder and export&#8221; tells a bidder exactly what to price. <\/span><b>&#8220;An interactive data visualization dashboard <\/b><span style=\"font-weight: 400;\">does not, and you will receive quotes that differ by a factor of three because each bidder guessed differently.<\/span><\/p>\n<p><b>If you are searching for who can do this,<\/b><span style=\"font-weight: 400;\"> try more than one vocabulary. A team that describes its work as building data portals and a team that describes it as building web front-ends for scientific databases may be doing identical work. We usually show up under &#8220;dashboards&#8221; and &#8220;data visualization,&#8221; and the tender that describes the same project most accurately calls it a web front-end with a query builder.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Where data portal projects actually break<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">This is the part worth reading if you are deciding whether to commission this kind of work, because these problems show up in month two and are not in anyone&#8217;s initial requirements.<\/span><\/p>\n<p><b>Sources that disagree with each other.<\/b><span style=\"font-weight: 400;\"> Two collection efforts recorded the same measurement under different names, in different units, with different precision. One used decimal degrees, the other degrees and minutes. One recorded a detection limit, the other left the cell blank, and &#8220;blank&#8221; means &#8220;below detection&#8221; in one file and &#8220;not measured&#8221; in the other. Reconciling this is not a data-cleaning task you can hand to a script. It requires deciding what the harmonized model means, and those decisions need domain people in the room. Budget for that as design work, not as data entry.<\/span><\/p>\n<p><b>Metadata that was never recorded.<\/b><span style=\"font-weight: 400;\"> A number without its method, instrument, sampling depth, or collection protocol is not reusable by anyone outside the team that produced it\u2014they cannot tell whether it is comparable to their own. The same is true of a monitoring figure with no note on how it was counted or a survey response with no record of which version of the questionnaire was used. Building a portal exposes exactly how much context lives in people&#8217;s memory rather than in the data. You will have to decide what to do about records you cannot fully describe. Discarding them is usually wrong; publishing them without qualification is also wrong.<\/span><\/p>\n<p><b>Restricted and open data in the same tables.<\/b><span style=\"font-weight: 400;\"> This is the single most common reason organizations do not open their data, and it is solvable. It needs an explicit restriction status on records, roles that determine what each kind of user can see, and a default for anonymous visitors that is open data only. The engineering is straightforward. The hard part is deciding the policy\u2014what is embargoed until publication, what is confidential to a partner, and what can be shown in aggregate but not per record\u2014and that decision belongs to you, not to your developer. Get it settled before development starts, because it shapes the data model.<\/span><\/p>\n<p><b>Data about people.<\/b><span style=\"font-weight: 400;\"> If your records describe individuals\u2014survey respondents, program participants, patients, beneficiaries\u2014this is not the same problem as restricted access, and treating it as such is the most expensive mistake available. Role-based permissions control who sees a record. They do not make a record safe to publish. Before anyone designs the schema, you need to decide which fields are personal data at all, what the lawful basis for holding them is, what the smallest unit you are willing to expose publicly is, and whether aggregation at that level can be reversed by combining it with something else. A monitoring dataset with location, date, and demographic detail can identify someone even with the name removed. These answers determine the data model, the aggregation layer, and what the export can contain. Retrofitting them means rebuilding all three. Under GDPR, the cost of getting this wrong is not only a rebuild.<\/span><\/p>\n<p><b>Indicators that changed definition partway through.<\/b><span style=\"font-weight: 400;\"> You measured something one way for six years, then improved the methodology. In a time series, it shows up as a step change that looks like a real finding but is not. Someone has to decide whether that is one indicator or two, whether the older values can be restated, and what a portal user is told when they cross the boundary. This is not an engineering decision, and if nobody makes it explicitly, the platform will publish a misleading chart with complete confidence. The same applies to changed geographic boundaries, changed category lists, and any survey question whose wording moved.<\/span><\/p>\n<p><b>Incoming data from the field.<\/b><span style=\"font-weight: 400;\"> If contributors send you data\u2014collaborating researchers, field teams, partner organizations\u2014uploads are not a file drop. A usable ingest path validates field names and types, range-checks numeric values so that an impossible latitude is caught immediately, and, the part people forget, checks whether the incoming rows already exist. Matching on location and date with a configurable tolerance surfaces three cases: this row is already there, this row could complete an existing record, or this row is new. Show the candidate and the existing record side by side with the differences highlighted, and let a person decide. Automatic merging destroys trust the first time it gets one wrong.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10653\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8.png\" alt=\"\" width=\"1440\" height=\"688\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8-300x143.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8-1024x489.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8-768x367.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-8-250x119.png 250w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><i><span style=\"font-weight: 400;\">A contribution path that people trust ends in a human decision, not an automatic merge.<\/span><\/i><\/p>\n<p><b>Versioning and citability.<\/b><span style=\"font-weight: 400;\"> If people publish analyses based on your data, the version they used must remain retrievable, or their results won\u2019t be reproducible. Deciding how versions are cut and cited is a design question with real consequences, and it is much cheaper to answer at the start than to retrofit.<\/span><\/p>\n<p><b>Who owns this in three years.<\/b><span style=\"font-weight: 400;\"> Portals built as a project deliverable, with no named owner, afterward stop being updated and then stop being trusted. This is the most reliable predictor of whether the platform will still matter after the funding period. Two practical requirements follow: the code must be readable and documented well enough for someone else to pick up, and structural changes to the data must be possible without a developer on retainer.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">When you should not build a data portal<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">A custom portal is the wrong answer when your data is already clean and stable, when nobody will own it after launch, or when an existing repository or off-the-shelf catalogue would do the same job for free.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An honest list, because commissioning this work when you do not need it is expensive and demoralizing.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Your data fits one well-maintained file and has a few internal users.<\/b><span style=\"font-weight: 400;\"> A portal solves a coordination problem you do not have.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Nobody will own the data after launch.<\/b><span style=\"font-weight: 400;\"> Fix this first. Without an owner, the platform decays into a misleading snapshot, which is worse than a spreadsheet someone maintains.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>The structure is still changing every month.<\/b><span style=\"font-weight: 400;\"> Wait until the model is stable enough to build against, or you will pay for the same work twice.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>An existing repository would do.<\/b><span style=\"font-weight: 400;\"> For depositing and citing datasets, institutional repositories, Zenodo, Dataverse, or a domain data center are designed for that and cost nothing to build. General-purpose data portal software such as CKAN handles cataloging and publishing well. Custom development earns its cost when users need to query across a structured, domain-specific model, when contributors need a validated ingest path, or when access rules are more complicated than public-or-not. If none of those apply, use the off-the-shelf option and spend the money elsewhere.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>All you want is internal reporting over data that is already clean and in one place.<\/b><span style=\"font-weight: 400;\">Then a BI tool does it, and you should buy one rather than build. Custom work earns its cost when the data has to be consolidated first, when external users self-serve, or when access rules are more complicated than public-or-not.<\/span><\/li>\n<\/ul>\n<h2><span style=\"font-weight: 400;\">What this looks like in practice: two data portals<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">We have built two of these for sediment geochemistry databases: same domain, different problem in each.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">A global database where the whole point was harmonization<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">MOSAIC\u2014the Modern Ocean Sediment Archive and Inventory of Carbon, held at ETH Z\u00fcrich\u2014compiles organic carbon data from marine sediments worldwide, along with isotopic composition and associated sedimentological parameters. The data comes from individual studies conducted by different groups over decades, using different methods and reporting conventions. Version 2.0 includes data from more than 21,000 individual sediment cores from continental margins globally, expanding the original database\u2019s spatiotemporal coverage by more than 400%.<sup><a id=\"ref2\" href=\"#fn2\">2<\/a><\/sup> <\/span><\/p>\n<p><span style=\"font-weight: 400;\">The hard requirement was not visualization. It was that a researcher who did not collect any of this data should be able to find the subset relevant to their question and trust it. That means the harmonization has to be visible: which method produced this number and what it is comparable to.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We built the interactive map interface on top of the harmonized database, with filtering across geochemical parameters. One requirement shaped the design more than any other: the team maintaining it are researchers, not developers, and they needed to add new filters as the database grew without engineering involvement. The database is continuously expanding, and contributors submit new data using a template workbook\u2014so anything that required a developer in the loop would have become a bottleneck within a year.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10658\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-scaled.png\" alt=\"\" width=\"2560\" height=\"1283\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-scaled.png 2560w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-300x150.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-1024x513.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-768x385.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-1536x770.png 1536w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-2048x1026.png 2048w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/Screenshot-2026-09-22-at-18.59.36-1-250x125.png 250w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/><\/p>\n<p><i><span style=\"font-weight: 400;\">Every sample location in the database and the filters that narrow them down. Ranges for coordinates and depths, dropdowns for variables and sampling methods. This is what &#8220;define your own subset&#8221; looks like in practice\u2014and the dropdowns are the part that lets the research team extend it without a developer.<\/span><\/i><\/p>\n<p><span style=\"font-weight: 400;\">Three engineers, from 2023. Dr. Sarah Paradis at ETH Z\u00fcrich, who leads MOSAIC, has spoken publicly about working with us.<\/span><\/p>\n<p><b>If your objection is &#8220;our data is too inconsistent to build anything on&#8221;<\/b><span style=\"font-weight: 400;\">\u2014that was the starting condition here, and harmonizing it was the deliverable, not a prerequisite.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">An Arctic database where the problem was access and contribution<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">CASCADE, the Circum-Arctic Sediment Carbon Database, is an international collaboration curating data from across the Arctic Ocean: organic carbon, nitrogen, carbon isotopes, and biomarkers. It is openly available through the Bolin Centre Database, with a companion paper published in Earth System Science Data by Martens et al. (2021). Stockholm University&#8217;s Department of Environmental Science curates it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The data was already public. The problem was that extracting a specific subset for a specific scientific question still required someone who knew the database structure. As the collection kept expanding, that dependency got worse, not better. Two things had to be solved at once: letting any scientist extract what they need without help and letting collaborators contribute data without someone merging spreadsheets by hand.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">What we built on Django and Python over the existing PostgreSQL database:<\/span><\/p>\n<p><b>A graphical query builder.<\/b><span style=\"font-weight: 400;\"> The database is presented as a tree of tables and their fields, each with a checkbox for inclusion in the output and a filter appropriate to its type\u2014a numeric range, a category, or a boolean flag. As the query is built, the user sees a live record count, sample locations plotted on a North Pole map view, and a scrollable preview of matching rows. Clicking a location on the map highlights its row in the preview. This is the difference between a query interface people trust and one they abandon: you can tell whether your filters are doing what you intended before you export.<\/span><\/p>\n<p><b>Exports in the formats the work actually needs.<\/b><span style=\"font-weight: 400;\"> CSV, XLSX, a pickled pandas DataFrame, GIS shapefile, and netCDF.<\/span><\/p>\n<p><b>A validated contribution path.<\/b><span style=\"font-weight: 400;\"> Uploaded CSV data is checked against the database&#8217;s field names and types, and numeric values are range-checked\u2014a latitude outside \u221290 to +90 is caught immediately. Then each incoming row is matched against existing records by latitude, longitude, and date, with configurable tolerances, and classified as already fully present, able to complete an existing record, or entirely new. Candidates are shown side by side with the existing record, differences highlighted, and a person makes the final call. No automatic merging.<\/span><\/p>\n<p><b>Three levels of access.<\/b><span style=\"font-weight: 400;\"> An anonymous visitor can use the query builder, but only against public data; the public\/embargoed distinction is a flag on the records themselves. Registered users can query across both. A subset of those users have editor permission, which unlocks the upload path.<\/span><\/p>\n<p><b>If your objection is &#8220;we can&#8217;t open this because some of it is restricted&#8221;<\/b><span style=\"font-weight: 400;\">\u2014this is the shape of the answer. The restriction lives in the data, the roles enforce it, and the default for an anonymous visitor is open data only.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Why these two are relevant if you are not a research institute<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Both examples are geochemistry, because that is where we have public reference projects. The mechanics are not specific to it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Swap the sediment cores for monitoring records, survey responses, or program indicators, and every component maps across. A tree of tables and fields becomes a picker over your own variables. Range filters and a live record count work the same on dates and demographics as on depths and latitudes. The map becomes whatever your data has a shape in\u2014sites, districts, catchments. The public-versus-restricted flag becomes your own disclosure policy. The upload path with duplicate detection becomes how a partner organisation submits a quarter of data without anyone merging spreadsheets by hand.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">What genuinely differs is what we set out in the breakage section: if your records describe people, the aggregation and disclosure layer is real work these two projects did not need. Do not let anyone quote it as if it were free.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Do we integrate this into your existing site or build it standalone?<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Almost every organisation asking this question already has a website, usually on a CMS\u2014WordPress, Drupal, TYPO3, or Wagtail are the common ones in European institutions. The reasonable question that follows is whether the portal becomes part of it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Usually not inside it and usually visually continuous with it. A CMS is built to manage pages. It is not built to filter two hundred thousand records and serve an export, and forcing it to do so produces something slow that breaks on the next CMS upgrade. What people actually want from &#8220;integrated&#8221; is that it looks like one site, is accessible from the main navigation, and does not require a second login. All three are achievable without the portal living inside the CMS.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">There are five delivery shapes, and they differ mostly in how much already exists on your side.<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10659\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1.png\" alt=\"\" width=\"1440\" height=\"952\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1-300x198.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1-1024x677.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1-768x508.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-9-1-227x150.png 227w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">A few things worth knowing before you choose.<\/span><\/p>\n<p><b>A subdomain is fine.<\/b><span style=\"font-weight: 400;\"> Search engines handle <\/span><span style=\"font-weight: 400;\">data.yourorg.org<\/span><span style=\"font-weight: 400;\"> perfectly well, and for a platform with its own navigation and audience, it is often the cleaner choice. If the portal is meant to strengthen the main site&#8217;s standing in search, a subfolder is the marginally stronger option. Do not let this decide the architecture; the difference is small, and the maintenance implications are not.<\/span><\/p>\n<p><b>Single sign-on is a separate question from where the portal lives.<\/b><span style=\"font-weight: 400;\"> If your institution has an identity provider, connecting to it is normally straightforward and worth doing. Decide it early, because it affects the role model.<\/span><\/p>\n<p><b>&#8220;Turnkey&#8221; mostly means we do the consolidation.<\/b><span style=\"font-weight: 400;\"> That is the layer where the cost sits, and it is also the layer that cannot be outsourced entirely, because deciding what a harmonised field means requires the people who know the data. Expect to be involved in whichever model you choose. Any quote that promises consolidation with no time from your team is underestimating it.<\/span><\/p>\n<p><b>If you already have a database, say so early and precisely.<\/b><span style=\"font-weight: 400;\"> A front-end over a working, documented database is a fundamentally different project from consolidation plus a front-end\u2014different cost, different duration, different risk. Bidders who do not know which one they are quoting for will price the bigger one or discover it later.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Where does the data actually live?<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Every one of these conversations reaches this question, and it is worth answering plainly, because the answer affects cost more than almost any other technical choice.<\/span><\/p>\n<p><b>If you already have a database, that is the best possible starting point.<\/b><span style=\"font-weight: 400;\"> A front-end over a working PostgreSQL database is the cheapest version of this project\u2014CASCADE above is exactly that pattern. Say so in your first email to any vendor.<\/span><\/p>\n<p><b>If your &#8220;database&#8221; is a set of pandas scripts and Excel exports, that is also fine<\/b><span style=\"font-weight: 400;\"> and more common than people admit. It means the schema exists in someone&#8217;s head and in code rather than in a system, which is recoverable. It means that consolidation is part of the project rather than something you have already done.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">What we would normally use, and why:<\/span><\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-10660\" src=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1.png\" alt=\"\" width=\"1440\" height=\"1228\" srcset=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1.png 1440w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1-300x256.png 300w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1-1024x873.png 1024w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1-768x655.png 768w, https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-10-1-176x150.png 176w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">The pattern worth noticing is one database, extended where needed. A surprising number of proposals arrive with a warehouse, a search cluster, a cache layer, and a message queue for a dataset of two hundred thousand rows. That is not architecture; it is an invoice.<\/span><\/p>\n<p><b>A licensing note, because it matters for public bodies.<\/b><span style=\"font-weight: 400;\"> Open source is not one thing. PostgreSQL and Django are permissively licensed with no obligations attached. PostGIS is GPL\u2014used as a database extension, it does not make your own application code a derivative work, but if your procurement rules mention copyleft, flag it. CKAN, the widely used open-data portal platform, is AGPL-3.0, and its community treats extensions as derivative works that must also be AGPL. That is entirely fine if you are publishing open data, which is what it was built for. It is a real constraint if you intend to build proprietary extensions or fold it into a closed system. Tenders that say &#8220;no proprietary or costly licesnes&#8221; usually mean &#8220;no license fees&#8221; and do not consider copyleft at all. Be explicit about which you mean\u2014and ask your own legal people rather than taking a vendor&#8217;s word for it, including ours.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What stops happening once it is live<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The honest way to describe the outcome is not a percentage. It is a list of things that stop being part of anyone&#8217;s week.<\/span><\/p>\n<p><b>The data request stops being a task.<\/b><span style=\"font-weight: 400;\"> Anyone who wants a standard slice of open data gets it themselves, with no one from your team in the loop. What remains is governance\u2014approving accounts where you choose to, reviewing contributed data. Hours per month instead of hours per request.\u00a0<\/span><\/p>\n<p><b>The report stops being rebuilt.<\/b><span style=\"font-weight: 400;\"> The quarterly assembly job becomes a set of parameters and a generated output. The four days go back to the people who were spending them.<\/span><\/p>\n<p><b>&#8220;Which version is current&#8221; stops being a question you ask a person.<\/b><span style=\"font-weight: 400;\"> There is one place, and it is the answer.<\/span><\/p>\n<p><b>The single point of failure in access is no longer a person.<\/b><span style=\"font-weight: 400;\"> When the one who knows the files goes on leave, changes role, or leaves the organisation, the data, the schema, and the documentation stay. The single point of failure in stewardship remains\u2014someone must still own the data. For organisations whose data outlives their staff turnover\u2014which is most of them\u2014this is the durable part of the value, and the hardest to feel until it is tested.<\/span><\/p>\n<p><b>Showing your work stops no longer requires a week of preparation.<\/b><span style=\"font-weight: 400;\"> A founder, a board, a regulator, or a journalist can be sent a link. What was previously invisible because it was expensive to demonstrate becomes something you can point to. One that lives in a spreadsheet can only be checked by a manual audit that, in practice, never happens\u2014which is why nobody, including its author, can tell whether it is right by looking.<\/span><\/p>\n<p><b>Errors become findable.<\/b><span style=\"font-weight: 400;\"> A calculation that lives in code can be tested, reviewed, and version-controlled. One that lives in a spreadsheet cannot be, which is why nobody, including its author, can tell whether it is right.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">What does not change: someone still has to own the data. The platform removes the manual work, not the responsibility.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What you actually own at the end<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">This matters more than it sounds, because the difference between a platform you own and a platform you rent from whoever built it shows up three years later, when the original team has moved on and you need one thing changed.<\/span><\/p>\n<p><b>A working platform and the ability to change it.<\/b><span style=\"font-weight: 400;\"> Mainstream framework, no exotic dependencies, readable code with comments in English. The practical test is whether a competent developer who has never met us can pick it up and make a change. That is what keeps you from being locked in\u2014to us or to anyone.<\/span><\/p>\n<p><b>The harmonized data model.<\/b><span style=\"font-weight: 400;\"> Often the most valuable thing produced, and the part that outlives the interface. The decisions about what a field means, which units are canonical, and how sources reconcile are the hard intellectual work of the project. Once made and documented, they belong to you, and they remain useful even if the platform is rebuilt on something else one day.<\/span><\/p>\n<p><b>Documentation written for two different readers.<\/b><span style=\"font-weight: 400;\"> One for the people using the portal, one for whoever maintains it next. The second is the one vendors skip and the one that determines whether the platform survives.<\/span><\/p>\n<p><b>A deployment path your own people can run.<\/b><span style=\"font-weight: 400;\"> Environment setup, deployment steps, backup and restore. If a release requires us, you do not own it.<\/span><\/p>\n<p><b>The ability to extend the data without a developer.<\/b><span style=\"font-weight: 400;\"> Structural changes to the database should be possible outside the application, with the front-end adapting rather than needing a rewrite. In practice this is the difference between a platform that grows with your collection and one that freezes on the day we hand it over.<\/span><\/p>\n<p><b>Training and a support period with defined response times.<\/b><span style=\"font-weight: 400;\"> Sessions are recorded, so the people who join next year get them too.<\/span><\/p>\n<p><b>No license bill you did not agree to.<\/b><span style=\"font-weight: 400;\"> Built on open components, so there is no proprietary dependency quietly attached to your operating budget.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The underlying principle: you should be able to stop working with us and be fine. Agencies that make this difficult are protecting revenue at your expense, and the thing to check in any proposal is not whether the word &#8220;handover&#8221; appears, but whether the documentation and deployment path are named deliverables with their own line in the estimate.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">What to specify in a tender for a data portal<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The points below are what make competing bids comparable. Leaving them out is the usual reason quotes for the same project differ by a factor of three.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Points worth specifying, because leaving them out is what produces bids that are not comparable:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Licensing.<\/b><span style=\"font-weight: 400;\"> State whether proprietary or paid-license components are acceptable. If they are not, say so, or you will receive quotes that assume they are.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Code and documentation.<\/b><span style=\"font-weight: 400;\"> Require readable, commented code and documentation for both users and developers, in a named language. This is what makes the platform maintainable by someone other than the original vendor.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Access model.<\/b><span style=\"font-weight: 400;\"> Specify how restricted and open data are distinguished, what an unauthenticated visitor may see, and\u2014if your records describe individuals\u2014the smallest unit you are prepared to expose publicly.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Export formats.<\/b><span style=\"font-weight: 400;\"> List them. They are cheap to build in from the start and awkward to add later.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Deployment.<\/b><span style=\"font-weight: 400;\"> State what your existing environment is and who is responsible for changes to it.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Accessibility.<\/b><span style=\"font-weight: 400;\"> If WCAG compliance applies to your institution, name the level.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Handover.<\/b><span style=\"font-weight: 400;\"> Ask for a delivery estimate for a minimum viable version and separately for ongoing support options so you can see what maintenance actually costs before you commit.<\/span><\/li>\n<\/ul>\n<h2><span style=\"font-weight: 400;\">Next step<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Show us your data, even if it is a folder of spreadsheets with inconsistent column names. Under NDA, on a short call, we will tell you what could realistically be built from it, what we\u2019d need to decide before anyone writes code, and where we would start. Not a demo.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">DjangoStars has built Python and Django platforms since 2008.<\/span><\/p>\n<div class=\"dj-main-article-faq\" style=\"padding-top: 0px;\">\n\t\t<div class=\"dj-main-article-faq-title\">\n\t\tFrequently Asked Questions\n\t\t<\/div>\n\t\t<div class=\"dj-main-article-faq-items\">\n\t\t\t<div class=\"dj-main-article-faq-accordeon accordeon\"><dl>\n\t\t\t\t<dt>Is this a dashboard? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>It includes one. Dashboards\u2014prepared views for the questions you already know people ask\u2014are normally part of a data portal and often the part your own team uses most. Underneath is the queryable interface: users define their own subset and export it. Both usually belong in the project. The expensive mistake is scoping only the dashboard layer, then discovering that every unanticipated question still comes back to a person.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>We already have a database or a data repository. Does that change things? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Substantially, and in your favour. A front-end over an existing, documented PostgreSQL database is the cheapest version of this project. Even an informal setup\u2014pandas scripts, a stack of Excel exports, a database somebody built for one project\u2014is a real head start, because the structure exists somewhere even if it has not been written down. Tell any vendor what you have in the first conversation; it is the single biggest factor in the estimate.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>How long does it take? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd><p>Roughly three weeks at the simple end, up to three months for a full build. The simple end means an existing clean database serving external, self-serving users: a handful of filters, a table view, and a CSV export. If the users are a few internal analysts, see the section on when not to build \u2014 that is a BI-tool purchase, not a project.<\/p>  <p>Three months means consolidating several sources, mapping and interactive geography, role-based access, multiple export formats, and a contribution path.<\/p>  <p>What moves the number, in rough order of impact:<\/p>  <ul>   <li><strong>How many sources have to be reconciled<\/strong>, and how much they disagree. This dominates everything else.<\/li>   <li><strong>Whether a database already exists<\/strong> and whether it is documented.<\/li>   <li><strong>Mapping.<\/strong> Whether there is geography at all, and whether it needs to be interactive or static.<\/li>   <li><strong>Volume.<\/strong> Two hundred thousand rows and two hundred million are different engineering problems.<\/li>   <li><strong>Filters.<\/strong> How many, and whether your team must be able to add more without a developer.<\/li>   <li><strong>Export formats.<\/strong> CSV is trivial. Shapefile, netCDF, and generated reports are not.<\/li>   <li><strong>Access rules.<\/strong> Open to everyone is simple. Roles, approval workflows, and restricted records are not.<\/li>   <li><strong>Personal data.<\/strong> If records describe individuals, add the disclosure and aggregation work described above.<\/li> <\/ul><\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>Can our own team maintain it afterward? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>That depends on choices made during development, not after. Use a mainstream framework, avoid exotic dependencies, keep the code documented, and make structural data changes possible without touching application code. Make it a written requirement.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>Our data includes personal information. Can it still go in a portal?  \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Yes, but the design question comes first, not the permissions. You decide what the smallest publishable unit is and whether aggregation at that level is reversible; the platform is then built around that. This is work, and it is the part most quotes leave out\u2014so ask explicitly whether an estimate includes it.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>We do not want this open to everyone. What are the options? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Access is not binary, and these options can be combined. Fully open, with no account needed. Open data is visible to anyone, while restricted data requires a login. Self-registration is limited to specified email domains, so only people at partner institutions can create an account. Registration is open, but an administrator approves each account before granting access\u2014useful when you want to know who is using the data and why, which funders increasingly ask for. Or invitation-only. A common and sensible arrangement is open data for anonymous visitors, domain-restricted self-registration for partners, manual approval for everyone else, and a small number of accounts additionally holding permission to upload.<\/dd>\n\t\t\t<\/dl><dl>\n\t\t\t\t<dt>We cannot share our data\u2014can we still get an assessment? \n\t\t\t\t<div class=\"cross\">\n\t\t\t\t<span><\/span>\n\t\t\t\t<span><\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<\/dt>\n\t\t\t\t<dd>Yes, under NDA. In practice, a look at the real files, however messy, tells us more in an hour than a specification does in a week.<\/dd>\n\t\t\t<\/dl><\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n<hr \/>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li id=\"fn1\">Panko, R.R. and Halverson, R.P. (2001), reported in Panko, &#8220;Reducing Overconfidence in Spreadsheet Development.&#8221; Individual developers estimated an 18% probability that their spreadsheet contained an error; the measured rate for the same group was 86%.\u201d <a href=\"#ref1\">\u21a9<\/a><\/li>\n<li id=\"fn2\">Paradis, S. et al. (2023). \u201cThe Modern Ocean Sediment Archive and Inventory of Carbon (MOSAIC): version 2.0.\u201d <em>Earth System Science Data<\/em> 15: 4105\u20134125. doi:10.5194\/essd-15-4105-2023. See also van der Voort, T.S. et al. (2021), <em>Earth System Science Data<\/em> 13: 2135\u20132146, doi:10.5194\/essd-13-2135-2021.<br \/>\n<a href=\"#ref2\">\u21a9<\/a><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Someone asks your team for a subset of your data. A particular region, a particular set of years, a particular set of measurements. The request is reasonable. The data exists. But answering it means opening several files, remembering which version is current, checking whether those particular records can be shared, filtering by hand, and sending [&hellip;]<\/p>\n","protected":false},"author":56,"featured_media":10645,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[85],"tags":[96],"class_list":["post-10647","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-solutions","tag-ai-solutions"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Software Development Blog &amp; IT Tech Insights | Django Stars<\/title>\n<meta name=\"description\" content=\"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.\" \/>\n<link rel=\"canonical\" href=\"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/10647\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"eb Data Portal Development: From Spreadsheets to Self-Serve\" \/>\n<meta property=\"og:description\" content=\"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/djangostars.com\/blog\/web-data-portal-development\/\" \/>\n<meta property=\"og:site_name\" content=\"Software Development Blog &amp; IT Tech Insights | Django Stars\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/djangostars\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-22T16:15:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-22T16:25:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-1024x638.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"638\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Roksoliana Liubachivska\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@djangostars\" \/>\n<meta name=\"twitter:site\" content=\"@djangostars\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Roksoliana Liubachivska\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"31 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/\"},\"author\":{\"name\":\"Roksoliana Liubachivska\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d27085a56a2f9a661c69dde1b6709d9\"},\"headline\":\"From Folders of Spreadsheets to a Web Data Portal\",\"datePublished\":\"2026-09-22T16:15:06+00:00\",\"dateModified\":\"2026-09-22T16:25:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/\"},\"wordCount\":6436,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/MSO-3609-1-1-scaled.png\",\"keywords\":[\"AI solutions\"],\"articleSection\":[\"AI Solutions &amp; Development Insights for Intelligent Products\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/\",\"url\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/\",\"name\":\"eb Data Portal Development: From Spreadsheets to Self-Serve\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/MSO-3609-1-1-scaled.png\",\"datePublished\":\"2026-09-22T16:15:06+00:00\",\"dateModified\":\"2026-09-22T16:25:17+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d27085a56a2f9a661c69dde1b6709d9\"},\"description\":\"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#primaryimage\",\"url\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/MSO-3609-1-1-scaled.png\",\"contentUrl\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/MSO-3609-1-1-scaled.png\",\"width\":2560,\"height\":1594},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/web-data-portal-development\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"From Folders of Spreadsheets to a Web Data Portal\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/\",\"name\":\"Software Development Blog &amp; IT Tech Insights | Django Stars\",\"description\":\"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/#\\\/schema\\\/person\\\/8d27085a56a2f9a661c69dde1b6709d9\",\"name\":\"Roksoliana Liubachivska\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g\",\"caption\":\"Roksoliana Liubachivska\"},\"description\":\"Has three years of experience at Django Stars, where she gained insights into startup needs, including technology integration, market positioning, and scaling strategies. She holds a PhD, has authored over 18 academic articles on environmental sustainability, and specializes in crafting grant proposals for renewable energy.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/roksoliana-liubachivska\\\/\"],\"url\":\"https:\\\/\\\/djangostars.com\\\/blog\\\/author\\\/roksoliana-liubachivskadjangostars-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.","canonical":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/10647","og_locale":"en_US","og_type":"article","og_title":"eb Data Portal Development: From Spreadsheets to Self-Serve","og_description":"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.","og_url":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/","og_site_name":"Software Development Blog &amp; IT Tech Insights | Django Stars","article_publisher":"https:\/\/www.facebook.com\/djangostars\/","article_published_time":"2026-09-22T16:15:06+00:00","article_modified_time":"2026-09-22T16:25:17+00:00","og_image":[{"width":1024,"height":638,"url":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-1024x638.png","type":"image\/png"}],"author":"Roksoliana Liubachivska","twitter_card":"summary_large_image","twitter_creator":"@djangostars","twitter_site":"@djangostars","twitter_misc":{"Written by":"Roksoliana Liubachivska","Est. reading time":"31 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#article","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/"},"author":{"name":"Roksoliana Liubachivska","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/8d27085a56a2f9a661c69dde1b6709d9"},"headline":"From Folders of Spreadsheets to a Web Data Portal","datePublished":"2026-09-22T16:15:06+00:00","dateModified":"2026-09-22T16:25:17+00:00","mainEntityOfPage":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/"},"wordCount":6436,"commentCount":0,"image":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-scaled.png","keywords":["AI solutions"],"articleSection":["AI Solutions &amp; Development Insights for Intelligent Products"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/djangostars.com\/blog\/web-data-portal-development\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/","url":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/","name":"eb Data Portal Development: From Spreadsheets to Self-Serve","isPartOf":{"@id":"https:\/\/djangostars.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#primaryimage"},"image":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#primaryimage"},"thumbnailUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-scaled.png","datePublished":"2026-09-22T16:15:06+00:00","dateModified":"2026-09-22T16:25:17+00:00","author":{"@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/8d27085a56a2f9a661c69dde1b6709d9"},"description":"Web data portal development explained: what it costs, where projects break, and when not to build one. Two real portals, and what to specify in a tender.","breadcrumb":{"@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/djangostars.com\/blog\/web-data-portal-development\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#primaryimage","url":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-scaled.png","contentUrl":"https:\/\/djangostars.com\/blog\/wp-content\/uploads\/2026\/09\/MSO-3609-1-1-scaled.png","width":2560,"height":1594},{"@type":"BreadcrumbList","@id":"https:\/\/djangostars.com\/blog\/web-data-portal-development\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/djangostars.com\/blog\/"},{"@type":"ListItem","position":2,"name":"From Folders of Spreadsheets to a Web Data Portal"}]},{"@type":"WebSite","@id":"https:\/\/djangostars.com\/blog\/#website","url":"https:\/\/djangostars.com\/blog\/","name":"Software Development Blog &amp; IT Tech Insights | Django Stars","description":"Welcome behind the scenes of software product development. We share our best practices, tech solutions, management tips, and every useful insight we\u2018ve got while working on our projects.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/djangostars.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/djangostars.com\/blog\/#\/schema\/person\/8d27085a56a2f9a661c69dde1b6709d9","name":"Roksoliana Liubachivska","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f6a90af034d260bf621c72d40b729e2846c0abf51ec12941bfc804aae774f33b?s=96&d=mm&r=g","caption":"Roksoliana Liubachivska"},"description":"Has three years of experience at Django Stars, where she gained insights into startup needs, including technology integration, market positioning, and scaling strategies. She holds a PhD, has authored over 18 academic articles on environmental sustainability, and specializes in crafting grant proposals for renewable energy.","sameAs":["https:\/\/www.linkedin.com\/in\/roksoliana-liubachivska\/"],"url":"https:\/\/djangostars.com\/blog\/author\/roksoliana-liubachivskadjangostars-com\/"}]}},"_links":{"self":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/10647","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/users\/56"}],"replies":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/comments?post=10647"}],"version-history":[{"count":6,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/10647\/revisions"}],"predecessor-version":[{"id":10665,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/posts\/10647\/revisions\/10665"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media\/10645"}],"wp:attachment":[{"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/media?parent=10647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/categories?post=10647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/djangostars.com\/blog\/wp-json\/wp\/v2\/tags?post=10647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}